From f0858e9b4efaf6f8ce7620add9149bb61108a811 Mon Sep 17 00:00:00 2001 From: shray sharma Date: Tue, 18 Jun 2024 21:37:48 +0200 Subject: [PATCH 01/19] update dependencies --- package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 6b74c45..dd5e998 100644 --- a/package.json +++ b/package.json @@ -17,15 +17,15 @@ "plop": "plop" }, "dependencies": { - "gatsby": "^5.13.3", - "gatsby-adapter-netlify": "^1.1.3", - "react": "^18.2.0", - "react-dom": "^18.2.0", + "gatsby": "^5.13.6", + "gatsby-adapter-netlify": "^1.1.6", + "react": "^18.3.1", + "react-dom": "^18.3.1", "react-helmet": "^6.1.0", "react-slick": "^0.30.2" }, "devDependencies": { - "plop": "^3.0.5", - "prettier": "^3.2.5" + "plop": "^4.0.1", + "prettier": "^3.3.2" } } From 2238509690809d965fa88c3f08434856becf3946 Mon Sep 17 00:00:00 2001 From: shray sharma Date: Wed, 19 Jun 2024 16:58:31 +0200 Subject: [PATCH 02/19] Playwright init, tests --- tests/package-lock.json | 125 ++++++ tests/package.json | 19 + tests/playwright.config.ts | 77 ++++ tests/tests-examples/demo-todo-app.spec.ts | 437 +++++++++++++++++++++ tests/tests/ui.spec.ts | 81 ++++ 5 files changed, 739 insertions(+) create mode 100644 tests/package-lock.json create mode 100644 tests/package.json create mode 100644 tests/playwright.config.ts create mode 100644 tests/tests-examples/demo-todo-app.spec.ts create mode 100644 tests/tests/ui.spec.ts diff --git a/tests/package-lock.json b/tests/package-lock.json new file mode 100644 index 0000000..afecb40 --- /dev/null +++ b/tests/package-lock.json @@ -0,0 +1,125 @@ +{ + "name": "tests", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "tests", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "install": "^0.13.0", + "or": "^0.2.0", + "yarn": "^1.22.22" + }, + "devDependencies": { + "@playwright/test": "^1.44.1", + "@types/node": "^20.14.5" + } + }, + "node_modules/@playwright/test": { + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.44.1.tgz", + "integrity": "sha512-1hZ4TNvD5z9VuhNJ/walIjvMVvYkZKf71axoF/uiAqpntQJXpG64dlXhoDXE3OczPuTuvjf/M5KWFg5VAVUS3Q==", + "dev": true, + "dependencies": { + "playwright": "1.44.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@types/node": { + "version": "20.14.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.5.tgz", + "integrity": "sha512-aoRR+fJkZT2l0aGOJhuA8frnCSoNX6W7U2mpNq63+BxBIj5BQFt8rHy627kijCmm63ijdSdwvGgpUsU6MBsZZA==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/install": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/install/-/install-0.13.0.tgz", + "integrity": "sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/or": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/or/-/or-0.2.0.tgz", + "integrity": "sha512-BHB8VZq2isxkyRaCBZ6CZCbQBzCT+gy8LPiqdbMH1+Fd6biFj3v8ebjeYzzL51PbsApsPYnGegGTO6KLQMxxDw==", + "engines": { + "node": "*" + } + }, + "node_modules/playwright": { + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.44.1.tgz", + "integrity": "sha512-qr/0UJ5CFAtloI3avF95Y0L1xQo6r3LQArLIg/z/PoGJ6xa+EwzrwO5lpNr/09STxdHuUoP2mvuELJS+hLdtgg==", + "dev": true, + "dependencies": { + "playwright-core": "1.44.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.44.1.tgz", + "integrity": "sha512-wh0JWtYTrhv1+OSsLPgFzGzt67Y7BE/ZS3jEqgGBlp2ppp1ZDj8c+9IARNW4dwf1poq5MgHreEM2KV/GuR4cFA==", + "dev": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/yarn": { + "version": "1.22.22", + "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.22.22.tgz", + "integrity": "sha512-prL3kGtyG7o9Z9Sv8IPfBNrWTDmXB4Qbes8A9rEzt6wkJV8mUvoirjU0Mp3GGAU06Y0XQyA3/2/RQFVuK7MTfg==", + "hasInstallScript": true, + "bin": { + "yarn": "bin/yarn.js", + "yarnpkg": "bin/yarn.js" + }, + "engines": { + "node": ">=4.0.0" + } + } + } +} diff --git a/tests/package.json b/tests/package.json new file mode 100644 index 0000000..8a796c1 --- /dev/null +++ b/tests/package.json @@ -0,0 +1,19 @@ +{ + "name": "tests", + "version": "1.0.0", + "main": "index.js", + "scripts": {}, + "keywords": [], + "author": "", + "license": "ISC", + "description": "", + "devDependencies": { + "@playwright/test": "^1.44.1", + "@types/node": "^20.14.5" + }, + "dependencies": { + "install": "^0.13.0", + "or": "^0.2.0", + "yarn": "^1.22.22" + } +} diff --git a/tests/playwright.config.ts b/tests/playwright.config.ts new file mode 100644 index 0000000..301801e --- /dev/null +++ b/tests/playwright.config.ts @@ -0,0 +1,77 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './tests', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + // baseURL: 'http://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // url: 'http://127.0.0.1:3000', + // reuseExistingServer: !process.env.CI, + // }, +}); diff --git a/tests/tests-examples/demo-todo-app.spec.ts b/tests/tests-examples/demo-todo-app.spec.ts new file mode 100644 index 0000000..2fd6016 --- /dev/null +++ b/tests/tests-examples/demo-todo-app.spec.ts @@ -0,0 +1,437 @@ +import { test, expect, type Page } from '@playwright/test'; + +test.beforeEach(async ({ page }) => { + await page.goto('https://demo.playwright.dev/todomvc'); +}); + +const TODO_ITEMS = [ + 'buy some cheese', + 'feed the cat', + 'book a doctors appointment' +]; + +test.describe('New Todo', () => { + test('should allow me to add todo items', async ({ page }) => { + // create a new todo locator + const newTodo = page.getByPlaceholder('What needs to be done?'); + + // Create 1st todo. + await newTodo.fill(TODO_ITEMS[0]); + await newTodo.press('Enter'); + + // Make sure the list only has one todo item. + await expect(page.getByTestId('todo-title')).toHaveText([ + TODO_ITEMS[0] + ]); + + // Create 2nd todo. + await newTodo.fill(TODO_ITEMS[1]); + await newTodo.press('Enter'); + + // Make sure the list now has two todo items. + await expect(page.getByTestId('todo-title')).toHaveText([ + TODO_ITEMS[0], + TODO_ITEMS[1] + ]); + + await checkNumberOfTodosInLocalStorage(page, 2); + }); + + test('should clear text input field when an item is added', async ({ page }) => { + // create a new todo locator + const newTodo = page.getByPlaceholder('What needs to be done?'); + + // Create one todo item. + await newTodo.fill(TODO_ITEMS[0]); + await newTodo.press('Enter'); + + // Check that input is empty. + await expect(newTodo).toBeEmpty(); + await checkNumberOfTodosInLocalStorage(page, 1); + }); + + test('should append new items to the bottom of the list', async ({ page }) => { + // Create 3 items. + await createDefaultTodos(page); + + // create a todo count locator + const todoCount = page.getByTestId('todo-count') + + // Check test using different methods. + await expect(page.getByText('3 items left')).toBeVisible(); + await expect(todoCount).toHaveText('3 items left'); + await expect(todoCount).toContainText('3'); + await expect(todoCount).toHaveText(/3/); + + // Check all items in one call. + await expect(page.getByTestId('todo-title')).toHaveText(TODO_ITEMS); + await checkNumberOfTodosInLocalStorage(page, 3); + }); +}); + +test.describe('Mark all as completed', () => { + test.beforeEach(async ({ page }) => { + await createDefaultTodos(page); + await checkNumberOfTodosInLocalStorage(page, 3); + }); + + test.afterEach(async ({ page }) => { + await checkNumberOfTodosInLocalStorage(page, 3); + }); + + test('should allow me to mark all items as completed', async ({ page }) => { + // Complete all todos. + await page.getByLabel('Mark all as complete').check(); + + // Ensure all todos have 'completed' class. + await expect(page.getByTestId('todo-item')).toHaveClass(['completed', 'completed', 'completed']); + await checkNumberOfCompletedTodosInLocalStorage(page, 3); + }); + + test('should allow me to clear the complete state of all items', async ({ page }) => { + const toggleAll = page.getByLabel('Mark all as complete'); + // Check and then immediately uncheck. + await toggleAll.check(); + await toggleAll.uncheck(); + + // Should be no completed classes. + await expect(page.getByTestId('todo-item')).toHaveClass(['', '', '']); + }); + + test('complete all checkbox should update state when items are completed / cleared', async ({ page }) => { + const toggleAll = page.getByLabel('Mark all as complete'); + await toggleAll.check(); + await expect(toggleAll).toBeChecked(); + await checkNumberOfCompletedTodosInLocalStorage(page, 3); + + // Uncheck first todo. + const firstTodo = page.getByTestId('todo-item').nth(0); + await firstTodo.getByRole('checkbox').uncheck(); + + // Reuse toggleAll locator and make sure its not checked. + await expect(toggleAll).not.toBeChecked(); + + await firstTodo.getByRole('checkbox').check(); + await checkNumberOfCompletedTodosInLocalStorage(page, 3); + + // Assert the toggle all is checked again. + await expect(toggleAll).toBeChecked(); + }); +}); + +test.describe('Item', () => { + + test('should allow me to mark items as complete', async ({ page }) => { + // create a new todo locator + const newTodo = page.getByPlaceholder('What needs to be done?'); + + // Create two items. + for (const item of TODO_ITEMS.slice(0, 2)) { + await newTodo.fill(item); + await newTodo.press('Enter'); + } + + // Check first item. + const firstTodo = page.getByTestId('todo-item').nth(0); + await firstTodo.getByRole('checkbox').check(); + await expect(firstTodo).toHaveClass('completed'); + + // Check second item. + const secondTodo = page.getByTestId('todo-item').nth(1); + await expect(secondTodo).not.toHaveClass('completed'); + await secondTodo.getByRole('checkbox').check(); + + // Assert completed class. + await expect(firstTodo).toHaveClass('completed'); + await expect(secondTodo).toHaveClass('completed'); + }); + + test('should allow me to un-mark items as complete', async ({ page }) => { + // create a new todo locator + const newTodo = page.getByPlaceholder('What needs to be done?'); + + // Create two items. + for (const item of TODO_ITEMS.slice(0, 2)) { + await newTodo.fill(item); + await newTodo.press('Enter'); + } + + const firstTodo = page.getByTestId('todo-item').nth(0); + const secondTodo = page.getByTestId('todo-item').nth(1); + const firstTodoCheckbox = firstTodo.getByRole('checkbox'); + + await firstTodoCheckbox.check(); + await expect(firstTodo).toHaveClass('completed'); + await expect(secondTodo).not.toHaveClass('completed'); + await checkNumberOfCompletedTodosInLocalStorage(page, 1); + + await firstTodoCheckbox.uncheck(); + await expect(firstTodo).not.toHaveClass('completed'); + await expect(secondTodo).not.toHaveClass('completed'); + await checkNumberOfCompletedTodosInLocalStorage(page, 0); + }); + + test('should allow me to edit an item', async ({ page }) => { + await createDefaultTodos(page); + + const todoItems = page.getByTestId('todo-item'); + const secondTodo = todoItems.nth(1); + await secondTodo.dblclick(); + await expect(secondTodo.getByRole('textbox', { name: 'Edit' })).toHaveValue(TODO_ITEMS[1]); + await secondTodo.getByRole('textbox', { name: 'Edit' }).fill('buy some sausages'); + await secondTodo.getByRole('textbox', { name: 'Edit' }).press('Enter'); + + // Explicitly assert the new text value. + await expect(todoItems).toHaveText([ + TODO_ITEMS[0], + 'buy some sausages', + TODO_ITEMS[2] + ]); + await checkTodosInLocalStorage(page, 'buy some sausages'); + }); +}); + +test.describe('Editing', () => { + test.beforeEach(async ({ page }) => { + await createDefaultTodos(page); + await checkNumberOfTodosInLocalStorage(page, 3); + }); + + test('should hide other controls when editing', async ({ page }) => { + const todoItem = page.getByTestId('todo-item').nth(1); + await todoItem.dblclick(); + await expect(todoItem.getByRole('checkbox')).not.toBeVisible(); + await expect(todoItem.locator('label', { + hasText: TODO_ITEMS[1], + })).not.toBeVisible(); + await checkNumberOfTodosInLocalStorage(page, 3); + }); + + test('should save edits on blur', async ({ page }) => { + const todoItems = page.getByTestId('todo-item'); + await todoItems.nth(1).dblclick(); + await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill('buy some sausages'); + await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).dispatchEvent('blur'); + + await expect(todoItems).toHaveText([ + TODO_ITEMS[0], + 'buy some sausages', + TODO_ITEMS[2], + ]); + await checkTodosInLocalStorage(page, 'buy some sausages'); + }); + + test('should trim entered text', async ({ page }) => { + const todoItems = page.getByTestId('todo-item'); + await todoItems.nth(1).dblclick(); + await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill(' buy some sausages '); + await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Enter'); + + await expect(todoItems).toHaveText([ + TODO_ITEMS[0], + 'buy some sausages', + TODO_ITEMS[2], + ]); + await checkTodosInLocalStorage(page, 'buy some sausages'); + }); + + test('should remove the item if an empty text string was entered', async ({ page }) => { + const todoItems = page.getByTestId('todo-item'); + await todoItems.nth(1).dblclick(); + await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill(''); + await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Enter'); + + await expect(todoItems).toHaveText([ + TODO_ITEMS[0], + TODO_ITEMS[2], + ]); + }); + + test('should cancel edits on escape', async ({ page }) => { + const todoItems = page.getByTestId('todo-item'); + await todoItems.nth(1).dblclick(); + await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill('buy some sausages'); + await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Escape'); + await expect(todoItems).toHaveText(TODO_ITEMS); + }); +}); + +test.describe('Counter', () => { + test('should display the current number of todo items', async ({ page }) => { + // create a new todo locator + const newTodo = page.getByPlaceholder('What needs to be done?'); + + // create a todo count locator + const todoCount = page.getByTestId('todo-count') + + await newTodo.fill(TODO_ITEMS[0]); + await newTodo.press('Enter'); + + await expect(todoCount).toContainText('1'); + + await newTodo.fill(TODO_ITEMS[1]); + await newTodo.press('Enter'); + await expect(todoCount).toContainText('2'); + + await checkNumberOfTodosInLocalStorage(page, 2); + }); +}); + +test.describe('Clear completed button', () => { + test.beforeEach(async ({ page }) => { + await createDefaultTodos(page); + }); + + test('should display the correct text', async ({ page }) => { + await page.locator('.todo-list li .toggle').first().check(); + await expect(page.getByRole('button', { name: 'Clear completed' })).toBeVisible(); + }); + + test('should remove completed items when clicked', async ({ page }) => { + const todoItems = page.getByTestId('todo-item'); + await todoItems.nth(1).getByRole('checkbox').check(); + await page.getByRole('button', { name: 'Clear completed' }).click(); + await expect(todoItems).toHaveCount(2); + await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); + }); + + test('should be hidden when there are no items that are completed', async ({ page }) => { + await page.locator('.todo-list li .toggle').first().check(); + await page.getByRole('button', { name: 'Clear completed' }).click(); + await expect(page.getByRole('button', { name: 'Clear completed' })).toBeHidden(); + }); +}); + +test.describe('Persistence', () => { + test('should persist its data', async ({ page }) => { + // create a new todo locator + const newTodo = page.getByPlaceholder('What needs to be done?'); + + for (const item of TODO_ITEMS.slice(0, 2)) { + await newTodo.fill(item); + await newTodo.press('Enter'); + } + + const todoItems = page.getByTestId('todo-item'); + const firstTodoCheck = todoItems.nth(0).getByRole('checkbox'); + await firstTodoCheck.check(); + await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); + await expect(firstTodoCheck).toBeChecked(); + await expect(todoItems).toHaveClass(['completed', '']); + + // Ensure there is 1 completed item. + await checkNumberOfCompletedTodosInLocalStorage(page, 1); + + // Now reload. + await page.reload(); + await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); + await expect(firstTodoCheck).toBeChecked(); + await expect(todoItems).toHaveClass(['completed', '']); + }); +}); + +test.describe('Routing', () => { + test.beforeEach(async ({ page }) => { + await createDefaultTodos(page); + // make sure the app had a chance to save updated todos in storage + // before navigating to a new view, otherwise the items can get lost :( + // in some frameworks like Durandal + await checkTodosInLocalStorage(page, TODO_ITEMS[0]); + }); + + test('should allow me to display active items', async ({ page }) => { + const todoItem = page.getByTestId('todo-item'); + await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); + + await checkNumberOfCompletedTodosInLocalStorage(page, 1); + await page.getByRole('link', { name: 'Active' }).click(); + await expect(todoItem).toHaveCount(2); + await expect(todoItem).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); + }); + + test('should respect the back button', async ({ page }) => { + const todoItem = page.getByTestId('todo-item'); + await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); + + await checkNumberOfCompletedTodosInLocalStorage(page, 1); + + await test.step('Showing all items', async () => { + await page.getByRole('link', { name: 'All' }).click(); + await expect(todoItem).toHaveCount(3); + }); + + await test.step('Showing active items', async () => { + await page.getByRole('link', { name: 'Active' }).click(); + }); + + await test.step('Showing completed items', async () => { + await page.getByRole('link', { name: 'Completed' }).click(); + }); + + await expect(todoItem).toHaveCount(1); + await page.goBack(); + await expect(todoItem).toHaveCount(2); + await page.goBack(); + await expect(todoItem).toHaveCount(3); + }); + + test('should allow me to display completed items', async ({ page }) => { + await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); + await checkNumberOfCompletedTodosInLocalStorage(page, 1); + await page.getByRole('link', { name: 'Completed' }).click(); + await expect(page.getByTestId('todo-item')).toHaveCount(1); + }); + + test('should allow me to display all items', async ({ page }) => { + await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); + await checkNumberOfCompletedTodosInLocalStorage(page, 1); + await page.getByRole('link', { name: 'Active' }).click(); + await page.getByRole('link', { name: 'Completed' }).click(); + await page.getByRole('link', { name: 'All' }).click(); + await expect(page.getByTestId('todo-item')).toHaveCount(3); + }); + + test('should highlight the currently applied filter', async ({ page }) => { + await expect(page.getByRole('link', { name: 'All' })).toHaveClass('selected'); + + //create locators for active and completed links + const activeLink = page.getByRole('link', { name: 'Active' }); + const completedLink = page.getByRole('link', { name: 'Completed' }); + await activeLink.click(); + + // Page change - active items. + await expect(activeLink).toHaveClass('selected'); + await completedLink.click(); + + // Page change - completed items. + await expect(completedLink).toHaveClass('selected'); + }); +}); + +async function createDefaultTodos(page: Page) { + // create a new todo locator + const newTodo = page.getByPlaceholder('What needs to be done?'); + + for (const item of TODO_ITEMS) { + await newTodo.fill(item); + await newTodo.press('Enter'); + } +} + +async function checkNumberOfTodosInLocalStorage(page: Page, expected: number) { + return await page.waitForFunction(e => { + return JSON.parse(localStorage['react-todos']).length === e; + }, expected); +} + +async function checkNumberOfCompletedTodosInLocalStorage(page: Page, expected: number) { + return await page.waitForFunction(e => { + return JSON.parse(localStorage['react-todos']).filter((todo: any) => todo.completed).length === e; + }, expected); +} + +async function checkTodosInLocalStorage(page: Page, title: string) { + return await page.waitForFunction(t => { + return JSON.parse(localStorage['react-todos']).map((todo: any) => todo.title).includes(t); + }, title); +} diff --git a/tests/tests/ui.spec.ts b/tests/tests/ui.spec.ts new file mode 100644 index 0000000..03995c3 --- /dev/null +++ b/tests/tests/ui.spec.ts @@ -0,0 +1,81 @@ +import { test, expect } from '@playwright/test'; + +test('has title', async ({ page }) => { + await page.goto('localhost:5000'); + + // TODO + // > set title for app + // await expect(page).toHaveTitle(/Playwright/); +}); + +test('shipping text exist', async ({ page }) => { + await page.goto('localhost:5000'); + + const UpperText = "Free shipping worldwide"; + + const loc = await page.getByText(UpperText); + + await expect(loc).toBeVisible(); +}); + +test('Brand logo should be present', async ({ page }) => { + await page.goto('localhost:5000'); + + // Check if the logo exists + const brandLogo = page.locator('.Brand-module--root--7bb0e'); + await expect(brandLogo).toBeVisible(); +}); + +test('Header exist', async ({ page }) => { + await page.goto('localhost:5000'); + + const HeaderTextShop = "Shop"; + const HeaderTextJournal = "journal"; + const HeaderTextAbout = "About"; + + const HeaderShop = await page.getByText(HeaderTextShop); + const HeaderJournal = await page.getByText(HeaderTextJournal); + const HeaderAbout = await page.getByText(HeaderTextAbout); + + await expect(HeaderShop).toBeTruthy(); + await expect(HeaderJournal).toBeTruthy(); + await expect(HeaderAbout).toBeTruthy(); +}); + +test('All header elements should be present', async ({ page }) => { + await page.goto('localhost:5000'); + + // brand logo + const brandLogo = page.locator('.Brand-module--root--7bb0e'); + await expect(brandLogo).toBeVisible(); + + // search button + const searchButton = page.locator('.Header-module--iconButton--db197[aria-label="Search"]'); + await expect(searchButton).toBeVisible(); + + // favorites link + const favoritesLink = page.locator('.Header-module--iconContainer--8ecbb[aria-label="Favorites"]'); + await expect(favoritesLink).toBeVisible(); + + // orders link + const ordersLink = page.locator('.Header-module--iconContainer--8ecbb[aria-label="Orders"]'); + await expect(ordersLink).toBeVisible(); + + // cart button + const cartButton = page.locator('.Header-module--iconButton--db197[aria-label="Cart"]'); + await expect(cartButton).toBeVisible(); +}); + +test('Hero section "Essentials for a cold winter" should have a background image', async ({ page }) => { + await page.goto('localhost:5000'); + + // Select the specific hero section by using the text content + const heroSection = page.locator('.Hero-module--root--39580:has-text("Essentials for a cold winter")'); + + // Check if the background image is set correctly + const backgroundImage = await heroSection.evaluate((element) => { + return window.getComputedStyle(element).getPropertyValue('background-image'); + }); + + expect(backgroundImage).toContain('/banner1.png?imgcdn=true'); +}); \ No newline at end of file From 93ef1607d3da38fcbbbcb1d283e42fbb92e49378 Mon Sep 17 00:00:00 2001 From: shray sharma Date: Fri, 21 Jun 2024 22:45:44 +0200 Subject: [PATCH 03/19] Home page links tests --- tests/tests/ui.spec.ts | 85 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/tests/tests/ui.spec.ts b/tests/tests/ui.spec.ts index 03995c3..057cfff 100644 --- a/tests/tests/ui.spec.ts +++ b/tests/tests/ui.spec.ts @@ -78,4 +78,89 @@ test('Hero section "Essentials for a cold winter" should have a background image }); expect(backgroundImage).toContain('/banner1.png?imgcdn=true'); +}); + + + +test('Hero section "Essentials for a cold winter" should have a background image', async ({ page }) => { + await page.goto('localhost:5000'); + + // Select the specific hero section by using the text content + const heroSection = page.locator('.Hero-module--root--39580:has-text("Essentials for a cold winter")'); + + // Check if the background image is set correctly + const backgroundImage = await heroSection.evaluate((element) => { + return window.getComputedStyle(element).getPropertyValue('background-image'); + }); + + expect(backgroundImage).toContain('/banner1.png?imgcdn=true'); +}); + +test('click on shop now button and verify redirection', async ({ page }) => { + await page.goto('http://localhost:5000'); + + // Click on the button + await page.click('button.Button-module--button--c17ef.Button-module--primary--2e17d.Hero-module--ctaButton--06285'); + + await page.waitForNavigation(); + + expect(page.url()).toBe('http://localhost:5000/shop/'); +}); + +test('click on shop now button and redirection', async ({ page }) => { + await page.goto('http://localhost:5000'); + + await page.click('button.Button-module--button--c17ef.Button-module--primary--2e17d.Hero-module--ctaButton--06285'); + + await page.waitForNavigation(); + + expect(page.url()).toBe('http://localhost:5000/shop/'); +}); + + +test('Home page text exist', async ({ page }) => { + await page.goto('localhost:5000'); + + const Text = "This is a demonstration of the Sydney theme for verse by"; + const NewCollection = "New Collection"; + + const HeaderShop = await page.getByText(Text); + const newCollectionExist = await page.getByText(NewCollection); + + await expect(HeaderShop).toBeTruthy(); + await expect(newCollectionExist).toBeTruthy(); +}); + +test('click on SHOP NOW and verify redirection', async ({ page }) => { + await page.goto('http://localhost:5000'); + + await page.click('span.ProductCollection-module--text--79158'); + + await page.waitForNavigation(); + + expect(page.url()).toBe('http://localhost:5000/shop/'); +}); + +test('click on Women and verify redirection', async ({ page }) => { + await page.goto('http://localhost:5000'); + + await page.click('span.ProductCollection-module--title--b48e6'); + + await page.waitForNavigation(); + + expect(page.url()).toBe('http://localhost:5000/shop/'); +}); + +test('New Arrivals exist and redirect on shop page', async ({ page }) => { + await page.goto('http://localhost:5000'); + + const TextHeaderExist = "New Arrivals"; + let Header = await page.getByText(TextHeaderExist); + + await expect(Header).toBeVisible(); + await page.click('div.ProductCard-module--imageContainer--00924'); + + await page.waitForNavigation(); + + expect(page.url()).toBe('http://localhost:5000/product/sample/'); }); \ No newline at end of file From 5a8b0f27816cbf2c2721d6862be8009f8d7ae35c Mon Sep 17 00:00:00 2001 From: shray sharma Date: Sat, 22 Jun 2024 13:29:15 +0200 Subject: [PATCH 04/19] About page tests --- tests/tests/about.spec.ts | 119 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 tests/tests/about.spec.ts diff --git a/tests/tests/about.spec.ts b/tests/tests/about.spec.ts new file mode 100644 index 0000000..c4fa630 --- /dev/null +++ b/tests/tests/about.spec.ts @@ -0,0 +1,119 @@ +import { test, expect } from '@playwright/test'; + +test('About page | Header text exists', async ({ page }) => { + await page.goto('localhost:5000/about/'); + + const HeaderText = `Sydney \n A British brand since 1860`; + + const Header = await page.getByText(HeaderText); + + await expect(Header).toBeVisible(); +}); + +test('About page | page navigate buttons exists', async ({ page }) => { + await page.goto('http://localhost:5000/about/'); + + const HistoryButtonText = "History"; + const ValuesButtonText = "Values"; + const SustainabilityButtonText = "Sustainability"; + + // specify the exact element type and text + const HistoryButton = await page.getByRole('link', { name: HistoryButtonText }); + const ValuesButton = await page.getByRole('link', { name: ValuesButtonText }); + const SustainabilityButton = await page.getByRole('link', { name: SustainabilityButtonText }); + + await expect(HistoryButton).toBeVisible(); + await expect(ValuesButton).toBeVisible(); + await expect(SustainabilityButton).toBeVisible(); +}); + + +test('About page | History text exists', async ({ page }) => { + await page.goto('http://localhost:5000/about/'); + + const Text1 = "Founded in 1860, Sydney is an innovative British brand with a contemporary edge. We make timeless everyday luxury clothing."; + const Text2 = "We created some of the world's first T-shirts and spent decades perfecting the feel of the cotton. Today we are the only brand that makes T-shirts in its own factory in the UK. And we do this in the same factory we have occupied since 1937."; + + const ExtractText1 = await page.getByText(Text1); + const ExtractText2 = await page.getByText(Text2); + + await expect(ExtractText1).toBeVisible(); + await expect(ExtractText2).toBeVisible(); +}); + + +test('About page | Check if Values image and text exists', async ({ page }) => { + await page.goto('http://localhost:5000/about/'); + + const imageSelector = '.about-module--imageContainer--42d10 img'; + const imgAltText = 'founder'; + const imgSrc = '/about2.png?imgcdn=true'; + const imageSelectorBottom = `img[alt="${imgAltText}"][src="${imgSrc}"]`; + + const ValuesText = `Sunspel produced some of the world's earliest T-shirts. In the late 1800s the business made luxury tunics and undershirts from lightweight Sea Island cotton for export to the Far East and other warm climates. While these garments initially had silk buttoned plackets, these were removed in the early 1900s and replaced with simple bound necks to reduce manufacturing costs - creating the T-shirt. We've supplied the world as the T-shirt has evolved from underwear to outerwear, from symbol of youthful rebellion to everyday wardrobe staple, and we've spent decades refining its every last aspect.`; + const TextEcowear = "Be an ecowear"; + const TextSophisticated = "Sophisticated and not mass-produced"; + const TextMaterials = "Only natural materials"; + + const imageElement = await page.$(imageSelector); + const imageElementBottom = await page.$(imageSelectorBottom); + + const ExtractValuesText = await page.getByText(ValuesText); + const ExtractEcowearText = await page.getByText(TextEcowear); + const ExtractSophisticated = await page.getByText(TextSophisticated); + const ExtractMaterials = await page.getByText(TextMaterials); + + await expect(imageElement).not.toBeNull(); + await expect(imageElementBottom).not.toBeNull(); + + await expect(ExtractValuesText).toBeVisible(); + await expect(ExtractEcowearText).toBeVisible(); + await expect(ExtractSophisticated).toBeVisible(); + await expect(ExtractMaterials).toBeVisible(); +}); + +test('About page | Check if Sustainability image and text exists', async ({ page }) => { + await page.goto('http://localhost:5000/about/'); + + const imageContainerClass = '.about-module--imageContainer--42d10'; + + const imgAltText = 'shirt backwards'; + const imgSrc = '/about3.png?imgcdn=true'; + + const imageSelector = `${imageContainerClass} img[alt="${imgAltText}"][src="${imgSrc}"]`; + const imageElement = await page.$(imageSelector); + + + const Text1 = "Our founder, Thomas Hill, had both an eye for quality and a desire to innovate. As well as using the finest fibres such as Sea Island cotton, cashmere and silk, he invented his own fabrics. Sunspel continues this commitment to innovation today and our unique fabrics include: Q100 Sea Island cotton, Q82 Supima cotton, Q75 warp knit mesh cotton and Q14 warp knit cellular cotton. The technology behind these fabrics remains unchanged today and all Sunspel products use the finest cottons, wools and fibres."; + const Text2 = "Made in Long Eaton, England and crafted from our luxurious long staple Supima cotton for unparalleled softness, comfort and durability, the Sunspel T-shirt has a classic fit and only the most essential details."; + const Text3 = "With over 100 years spent perfecting fabric, fit and style, the Sunspel Classic T-shirt is recognised as the finest in the world."; + + const ExtractText1 = await page.getByText(Text1); + const ExtractText2 = await page.getByText(Text2); + const ExtractText3 = await page.getByText(Text3); + + await expect(imageElement).not.toBeNull(); + await expect(ExtractText1).toBeVisible(); + await expect(ExtractText2).toBeVisible(); + await expect(ExtractText3).toBeVisible(); +}); + + +test('Check if clicking on link changes URL to specific section', async ({ page }) => { + await page.goto('http://localhost:5000/about'); + + // link element + const linkSelectorHistory = 'div[role="presentation"] .ThemeLink-module--link--f3867[href="/about/#history"]'; + const linkSelectorValues = 'div[role="presentation"] .ThemeLink-module--link--f3867[href="/about/#values"]'; + const linkSelectorSustainability = 'div[role="presentation"] .ThemeLink-module--link--f3867[href="/about/#sustainability"]'; + + // Verify that the URL changes to the specific section + await page.click(linkSelectorHistory); + await expect(page).toHaveURL('http://localhost:5000/about/#history'); + + await page.click(linkSelectorValues); + await expect(page).toHaveURL('http://localhost:5000/about/#values'); + + await page.click(linkSelectorSustainability); + await expect(page).toHaveURL('http://localhost:5000/about/#sustainability'); +}); \ No newline at end of file From b1d3c8de1d17f4e66888107054548aeed41012c0 Mon Sep 17 00:00:00 2001 From: shray sharma Date: Tue, 25 Jun 2024 13:51:16 +0200 Subject: [PATCH 05/19] blog page tests --- tests/tests/about.spec.ts | 43 ++++++++++++ tests/tests/blog.spec.ts | 144 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 tests/tests/blog.spec.ts diff --git a/tests/tests/about.spec.ts b/tests/tests/about.spec.ts index c4fa630..c95b488 100644 --- a/tests/tests/about.spec.ts +++ b/tests/tests/about.spec.ts @@ -1,5 +1,48 @@ import { test, expect } from '@playwright/test'; + +test('About page | Header elements exist', async ({ page }) => { + await page.goto('http://localhost:5000'); + + // Find the main container with a more specific locator + const mainContainer = page.locator('div.Container-module--container--6761c >> nth=0'); + await expect(mainContainer).toBeVisible(); + + // Check the header + const header = mainContainer.locator('div.Header-module--header--aa06a'); + await expect(header).toBeVisible(); + + // Check the navigation links + const navLinks = header.locator('nav a.Header-module--navLink--2a5b8'); + await expect(navLinks.nth(0)).toHaveText('Shop'); + await expect(navLinks.nth(1)).toHaveText('journal'); + await expect(navLinks.nth(2)).toHaveText('About'); + + // Check the burger icon / page resolution + // const burgerIcon = header.locator('div.Header-module--burgerIcon--813a8'); + // await expect(burgerIcon).toBeVisible(); + + // Check the brand logo + const brandLogo = header.locator('div.Brand-module--root--7bb0e'); + await expect(brandLogo).toBeVisible(); + + // Check the search button + const searchButton = header.locator('button[aria-label="Search"]'); + await expect(searchButton).toBeVisible(); + + // Check the favorites link + const favoritesLink = header.locator('a[aria-label="Favorites"]'); + await expect(favoritesLink).toBeVisible(); + + // Check the orders link + const ordersLink = header.locator('a[aria-label="Orders"]'); + await expect(ordersLink).toBeVisible(); + + // Check the cart button + const cartButton = header.locator('button[aria-label="Cart"]'); + await expect(cartButton).toBeVisible(); + }); + test('About page | Header text exists', async ({ page }) => { await page.goto('localhost:5000/about/'); diff --git a/tests/tests/blog.spec.ts b/tests/tests/blog.spec.ts new file mode 100644 index 0000000..cdcbf14 --- /dev/null +++ b/tests/tests/blog.spec.ts @@ -0,0 +1,144 @@ +import { test, expect } from '@playwright/test'; + +test('Blog page | Header elements exist', async ({ page }) => { + await page.goto('http://localhost:5000'); + + // Find the main container with a more specific locator + const mainContainer = page.locator('div.Container-module--container--6761c >> nth=0'); + await expect(mainContainer).toBeVisible(); + + // Check the header + const header = mainContainer.locator('div.Header-module--header--aa06a'); + await expect(header).toBeVisible(); + + // Check the navigation links + const navLinks = header.locator('nav a.Header-module--navLink--2a5b8'); + await expect(navLinks.nth(0)).toHaveText('Shop'); + await expect(navLinks.nth(1)).toHaveText('journal'); + await expect(navLinks.nth(2)).toHaveText('About'); + + // Check the burger icon / page resolution + // const burgerIcon = header.locator('div.Header-module--burgerIcon--813a8'); + // await expect(burgerIcon).toBeVisible(); + + // Check the brand logo + const brandLogo = header.locator('div.Brand-module--root--7bb0e'); + await expect(brandLogo).toBeVisible(); + + // Check the search button + const searchButton = header.locator('button[aria-label="Search"]'); + await expect(searchButton).toBeVisible(); + + // Check the favorites link + const favoritesLink = header.locator('a[aria-label="Favorites"]'); + await expect(favoritesLink).toBeVisible(); + + // Check the orders link + const ordersLink = header.locator('a[aria-label="Orders"]'); + await expect(ordersLink).toBeVisible(); + + // Check the cart button + const cartButton = header.locator('button[aria-label="Cart"]'); + await expect(cartButton).toBeVisible(); + }); + + test('Blog page | Verify all elements in the nav container exist and are visible', async ({ page }) => { + await page.goto('http://localhost:5000/blog/'); + + const navContainerSelector = '.index-module--navContainer--b967e'; + const expectedLinks = [ + 'All Posts', + 'Design', + 'Collaboration', + 'Interview', + 'News' + ]; + + // Wait for the container to be visible + const navContainer = page.locator(navContainerSelector); + await navContainer.waitFor({ state: 'visible' }); + + // Loop through each expected link text and assert its existence and visibility + for (const linkText of expectedLinks) { + const linkLocator = navContainer.locator(`a.ThemeLink-module--link--f3867:has-text("${linkText}")`); + + await expect(linkLocator).toBeVisible(); + } + }); + + + test('Blog page | Verify all elements in the blog preview grid exist and are visible', async ({ page }) => { + await page.goto('http://localhost:5000/blog/'); + + const gridContainerSelector = '.BlogPreviewGrid-module--root--84743'; + + // Wait for the container to be visible + const gridContainer = page.locator(gridContainerSelector); + await gridContainer.waitFor({ state: 'visible' }); + + // Define the expected blog previews data + const blogPreviews = [ + { + imgSrc: '/blogs/blog1.png?imgcdn=true', + category: 'design', + title: 'The new standard of Opening and Closing', + excerpt: 'London-based seasonal British flowers and UK producers in her beautiful and sustainable creations. This season, we worked with Flora to style Sunspel stores for Christmas, for which she produced eye-catching sustainably sourced wreaths.' + }, + { + imgSrc: '/blogs/blog2.png?imgcdn=true', + category: 'design', + title: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.', + excerpt: 'London-based seasonal British flowers and UK producers in her beautiful and sustainable creations. This season, we worked with Flora to style Sunspel stores for Christmas, for which she produced eye-catching sustainably sourced wreaths.' + }, + { + imgSrc: '/blogs/blog3.png?imgcdn=true', + category: 'design', + title: 'It is a long established fact that a reader by the readable', + excerpt: 'London-basedsonal British flowers and UK producers in her beautiful and sustainable creations. This season, we worked with Flora to style Sunspel stores for Christmas, for which she produced eye-catching sustainably sourced wreaths.' + }, + { + imgSrc: '/blogs/blog3.png?imgcdn=true', + category: 'design', + title: 'It is a long establishable', + excerpt: 'London-based floral designer Flora Fricker champions seasonal British flowers and UK producers in her beautiful and sustainable creations. This season, we worked with Flora to style Sunspel stores for Christmas, for which she produced eye-catching sustainably sourced wreaths.' + }, + { + imgSrc: '/blogs/blog2.png?imgcdn=true', + category: 'design', + title: 'It is a long estab the readable', + excerpt: 'Loproducers in her beautiful and sustainable creations. This season, we worked with Flora to style Sunspel stores for Christmas, for which she produced eye-catching sustainably sourced wreaths.' + }, + { + imgSrc: '/blogs/blog1.png?imgcdn=true', + category: 'design', + title: 'The new standard of Opening and Closing', + excerpt: 'London-based floral tish flowers and UK producers in her beautiful and sustainable creations. This season, we worked with Flora to style Sunspel stores for Christmas, for which she produced eye-catching sustainably sourced wreaths.' + } + ]; + + // Loop through each expected blog preview and assert its existence and visibility + for (let i = 0; i < blogPreviews.length; i++) { + const preview = blogPreviews[i]; + const previewSelector = `${gridContainerSelector} > div:nth-child(${i + 1})`; + + // Check image + const imageLocator = page.locator(`${previewSelector} img.BlogPreview-module--blogPreviewImage--3dd51`); + await expect(imageLocator).toHaveAttribute('src', preview.imgSrc); + await expect(imageLocator).toBeVisible(); + + // Check category + const categoryLocator = page.locator(`${previewSelector} span.BlogPreview-module--category--ad951`); + await expect(categoryLocator).toHaveText(preview.category); + await expect(categoryLocator).toBeVisible(); + + // Check title + const titleLocator = page.locator(`${previewSelector} h4.BlogPreview-module--title--67522 a`); + await expect(titleLocator).toHaveText(preview.title); + await expect(titleLocator).toBeVisible(); + + // Check excerpt + const excerptLocator = page.locator(`${previewSelector} p.BlogPreview-module--excerpt--be3c5`); + await expect(excerptLocator).toHaveText(preview.excerpt); + await expect(excerptLocator).toBeVisible(); + } + }); \ No newline at end of file From 61b2e92939393709eba15b6ca4ac9b05b0692539 Mon Sep 17 00:00:00 2001 From: shray sharma Date: Wed, 26 Jun 2024 12:18:03 +0200 Subject: [PATCH 06/19] blog/sample tests --- tests/tests/design.spec.ts | 145 +++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 tests/tests/design.spec.ts diff --git a/tests/tests/design.spec.ts b/tests/tests/design.spec.ts new file mode 100644 index 0000000..4f77af1 --- /dev/null +++ b/tests/tests/design.spec.ts @@ -0,0 +1,145 @@ +import { test, expect } from '@playwright/test'; + + + +test('blog/sample/ | Header elements exist', async ({ page }) => { + await page.goto('http://localhost:5000/blog/sample/'); + + // Find the main container with a more specific locator + const mainContainer = page.locator('div.Container-module--container--6761c >> nth=0'); + await expect(mainContainer).toBeVisible(); + + // Check the header + const header = mainContainer.locator('div.Header-module--header--aa06a'); + await expect(header).toBeVisible(); + + // Check the navigation links + const navLinks = header.locator('nav a.Header-module--navLink--2a5b8'); + await expect(navLinks.nth(0)).toHaveText('Shop'); + await expect(navLinks.nth(1)).toHaveText('journal'); + await expect(navLinks.nth(2)).toHaveText('About'); + + // Check the burger icon / page resolution + // const burgerIcon = header.locator('div.Header-module--burgerIcon--813a8'); + // await expect(burgerIcon).toBeVisible(); + + // Check the brand logo + const brandLogo = header.locator('div.Brand-module--root--7bb0e'); + await expect(brandLogo).toBeVisible(); + + // Check the search button + const searchButton = header.locator('button[aria-label="Search"]'); + await expect(searchButton).toBeVisible(); + + // Check the favorites link + const favoritesLink = header.locator('a[aria-label="Favorites"]'); + await expect(favoritesLink).toBeVisible(); + + // Check the orders link + const ordersLink = header.locator('a[aria-label="Orders"]'); + await expect(ordersLink).toBeVisible(); + + // Check the cart button + const cartButton = header.locator('button[aria-label="Cart"]'); + await expect(cartButton).toBeVisible(); + }); + + test('blog/sample/ | Check all elements exist', async ({ page }) => { + await page.goto('http://localhost:5000/blog/sample/'); + + // root element + await expect(page.locator('.Blog-module--root--35094')).toBeVisible(); + + // category span + await expect(page.locator('.Blog-module--category--6dcd0')).toHaveText('design'); + + // the title + await expect(page.locator('.Blog-module--title--0f7d6')).toHaveText('Friends of Sydney: Flora Fricker'); + + // the image container and the image + await expect(page.locator('.Blog-module--imageContainer--3e280 img')).toHaveAttribute('src', '/blogFeatured.png?imgcdn=true'); + + // first content div + await expect(page.locator('.sample-module--content--ec8b1').first()).toBeVisible(); + + // all paragraphs within the content + await expect(page.locator('.sample-module--excerpt--53842')).toBeVisible(); + await expect(page.locator('.sample-module--blogParagraph--54e81')).toHaveCount(6); + + // the images container + await expect(page.locator('.sample-module--imagesContainer--f1361')).toBeVisible(); + + // two images within the images container + await expect(page.locator('.sample-module--imageContainer--78ea7 img')).toHaveCount(2); + await expect(page.locator('.sample-module--imageContainer--78ea7 img').first()).toHaveAttribute('src', '/cloth.png?imgcdn=true'); + await expect(page.locator('.sample-module--imageContainer--78ea7 img').nth(1)).toHaveAttribute('src', '/collections/collection1.png?imgcdn=true'); + + // the blog subheader + await expect(page.locator('.sample-module--blogSubHeader--e3d3b')).toHaveText('2. Lorem ipsum'); + + await expect(page.locator('.sample-module--content--ec8b1').nth(1)).toBeVisible(); + + // the footer container + await expect(page.locator('.Blog-module--footerContainer--4a957')).toBeVisible(); + + // the "Share with:" text + await expect(page.locator('.Blog-module--footerContainer--4a957 span')).toHaveText('Share with:'); + + // social media icons + await expect(page.locator('.Blog-module--socialMediaIconContainer--32487')).toHaveCount(3); + + // "back to blog" button + await expect(page.locator('text=back to blog')).toBeVisible(); + }); + + + test('blog/sample/ | Check all elements in the footer exist', async ({ page }) => { + await page.goto('http://localhost:5000/blog/sample/'); + + // footer container + const footerContainer = page.locator('.Footer-module--content--2aeb3'); + await expect(footerContainer).toBeVisible({ timeout: 10000 }); + + //footer content top + const footerContentTop = footerContainer.locator('.Footer-module--contentTop--729c1'); + await expect(footerContentTop).toBeVisible(); + + // "Info" section + const infoSection = footerContentTop.locator('.Footer-module--footerLinkContainer--34ce1').nth(0); + await expect(infoSection).toBeVisible(); + await expect(infoSection.locator('.Footer-module--linkTitle--fa138')).toHaveText('Info'); + + //"Info" links + const infoLinks = infoSection.locator('.Footer-module--linkList--6f95b li a'); + await expect(infoLinks).toHaveCount(6); + await expect(infoLinks.nth(0)).toHaveText('About Us'); + await expect(infoLinks.nth(1)).toHaveText('Journal'); + await expect(infoLinks.nth(2)).toHaveText('Privacy Policy'); + + // "Support" section + const supportSection = footerContentTop.locator('.Footer-module--footerLinkContainer--34ce1').nth(1); + await expect(supportSection).toBeVisible(); + await expect(supportSection.locator('.Footer-module--linkTitle--fa138')).toHaveText('Support'); + + // "Support" links + const supportLinks = supportSection.locator('.Footer-module--linkList--6f95b li a'); + await expect(supportLinks).toHaveCount(8); + await expect(supportLinks.nth(0)).toHaveText('FAQ'); + await expect(supportLinks.nth(1)).toHaveText('Contact Us'); + await expect(supportLinks.nth(2)).toHaveText('Shipping & Returns'); + await expect(supportLinks.nth(3)).toHaveText('How to use this theme'); + + // newsletter section + const newsletterSection = footerContainer.locator('.Footer-module--newsLetter--91500'); + await expect(newsletterSection).toBeVisible(); + await expect(newsletterSection.locator('.Footer-module--newsLetterContent--e10ad')).toBeVisible(); + await expect(newsletterSection.locator('.Footer-module--linkTitle--fa138')).toHaveText('Newsletter'); + await expect(newsletterSection.locator('.Footer-module--promoMessage--b609e')).toHaveText('Get 15% off your first purchase! Plus, be the first to know about sales, new product launches and exclusive offers!'); + + // newsletter input form + await expect(newsletterSection.locator('.Footer-module--newsLetterForm--11787 input[name="newsLetterInput"]')).toBeVisible(); + + // social media icons in the footer + const socialIcons = newsletterSection.locator('.Footer-module--socialIconContainer--ac360'); + await expect(socialIcons).toHaveCount(4); + }); \ No newline at end of file From 9e804f2f691fde80502b69ce355e11767edf3f9c Mon Sep 17 00:00:00 2001 From: shray sharma Date: Thu, 27 Jun 2024 07:47:46 +0200 Subject: [PATCH 07/19] using page tests --- tests/tests/using.spec.ts | 200 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 tests/tests/using.spec.ts diff --git a/tests/tests/using.spec.ts b/tests/tests/using.spec.ts new file mode 100644 index 0000000..5defec2 --- /dev/null +++ b/tests/tests/using.spec.ts @@ -0,0 +1,200 @@ +import { test, expect } from '@playwright/test'; + + +test('how-to-use page | check all elements in navContainer exist', async ({ page }) => { + await page.goto('http://localhost:5000/how-to-use/'); + + // Check that the navContainer exists + const navContainer = await page.$('.about-module--navContainer--d8791'); + expect(navContainer).not.toBeNull(); + + const selectors = [ + 'a.ThemeLink-module--link--f3867[href="/how-to-use/#builtby"]', + 'a.ThemeLink-module--link--f3867[href="/how-to-use/#tools"]' + ]; + + for (const selector of selectors) { + const element = await page.$(selector); + expect(element).not.toBeNull(); + } + }); + + test('how-to-use page | check elements in #builtBy container exist', async ({ page }) => { + await page.goto('http://localhost:5000/how-to-use/'); + + const textContents = [ + "This theme is proudly brought to you by the team at", + "Matter Design & Digital", + "The Sydney theme is built for Netlify as an ecommerce theme suitable for JAMStack architecture.", + "Matter. has pre-built connections to microservices available through its JAMM.™ solution.", + "Read more about JAMM.™" + ]; + + for (const text of textContents) { + // console.log(`text content: ${text}`); + const element = await page.locator(`text=${text}`).first(); + expect(element).not.toBeNull(); + } + + const image = await page.locator('img[alt="JAMM Detail"][src="/how-to-use/jamm-sydney-1upd@2x.png?imgcdn=true"]'); + expect(image).not.toBeNull(); + }); + + test('how-to-use page | check links in #builtBy container redirect to correct sites', async ({ page, context }) => { + await page.goto('http://localhost:5000/how-to-use/'); + + const links = [ + { selector: 'a[href="https://matterdesign.com.au/"]', url: 'https://matterdesign.com.au/' }, + { selector: 'a[href="https://jamm.matter.design/"]', url: 'https://matterdesign.com.au/news/headless-jamm-framework/' } + ]; + + for (const link of links) { + // capture the redirection + const newPagePromise = context.waitForEvent('page'); + + await page.click(link.selector); + + const newPage = await newPagePromise; + await newPage.waitForLoadState(); + + const url = newPage.url(); + // console.log(`Checking URL: ${url}`); + expect(url).toBe(link.url); + + await newPage.close(); + } + }); + + test('how-to-use page | check text content in #tools container exist', async ({ page }) => { + await page.goto('http://localhost:5000/how-to-use/'); + + const textContents = [ + "Headless architecture enables Composable Commerce. What this means is that you can ‘compose’ a suite of best of breed tools together to create an agile ecommerce system. This approach is the opposite end of the spectrum from a traditional ‘Monolithic’ architecture where all the functionality and data comes from one source.", + "Why go with Composable Commerce? History has shown, technology innovation comes from new specialised solutions that find better ways to do things. By creating an architecture that taps into this innovation, you are getting a system that is innovating faster than monolithic solutions giving you a competitive advantage.", + "Matter. has been innovating since 2003, and we have aligned with companies that do it best. The following technologies are either currently available or are on our roadmap for JAMM.™.", + "BigCommerce", + "VTEX (roadmap)", + "Commercetools (roadmap)", + "Contentful", + "WordPress", + "Sanity", + "Builder.io", + "Algolia", + "Searchspring (roadmap)", + "XO (roadmap)", + "Syte (roadmap)", + "Akeneo", + "Klaviyo", + "Ortto", + "Dot Digital", + "Omnisend", + "Gorgias", + "Zendesk", + "Yotpo", + "Trustpilot", + "Reviews.io", + "Localisr.io", + "Our team are fanatical about site speed and the agility of a composable commerce approach. If you need help to setup a Headless architecture, we’d love to hear from you.", + "Contact the team at Matter." + ]; + + for (const text of textContents) { + const element = await page.locator(`text=${text}`).first(); + expect(element).not.toBeNull(); + } + }); + + +test('how-to-use page | Header elements exist', async ({ page }) => { + await page.goto('http://localhost:5000/how-to-use/'); + + // Find the main container with a more specific locator + const mainContainer = page.locator('div.Container-module--container--6761c >> nth=0'); + await expect(mainContainer).toBeVisible(); + + // Check the header + const header = mainContainer.locator('div.Header-module--header--aa06a'); + await expect(header).toBeVisible(); + + // Check the navigation links + const navLinks = header.locator('nav a.Header-module--navLink--2a5b8'); + await expect(navLinks.nth(0)).toHaveText('Shop'); + await expect(navLinks.nth(1)).toHaveText('journal'); + await expect(navLinks.nth(2)).toHaveText('About'); + + // Check the burger icon / page resolution + // const burgerIcon = header.locator('div.Header-module--burgerIcon--813a8'); + // await expect(burgerIcon).toBeVisible(); + + // Check the brand logo + const brandLogo = header.locator('div.Brand-module--root--7bb0e'); + await expect(brandLogo).toBeVisible(); + + // Check the search button + const searchButton = header.locator('button[aria-label="Search"]'); + await expect(searchButton).toBeVisible(); + + // Check the favorites link + const favoritesLink = header.locator('a[aria-label="Favorites"]'); + await expect(favoritesLink).toBeVisible(); + + // Check the orders link + const ordersLink = header.locator('a[aria-label="Orders"]'); + await expect(ordersLink).toBeVisible(); + + // Check the cart button + const cartButton = header.locator('button[aria-label="Cart"]'); + await expect(cartButton).toBeVisible(); + }); + + + test('how-to-use page | Check all elements in the footer exist', async ({ page }) => { + await page.goto('http://localhost:5000/how-to-use/'); + + // footer container + const footerContainer = page.locator('.Footer-module--content--2aeb3'); + await expect(footerContainer).toBeVisible({ timeout: 10000 }); + + //footer content top + const footerContentTop = footerContainer.locator('.Footer-module--contentTop--729c1'); + await expect(footerContentTop).toBeVisible(); + + // "Info" section + const infoSection = footerContentTop.locator('.Footer-module--footerLinkContainer--34ce1').nth(0); + await expect(infoSection).toBeVisible(); + await expect(infoSection.locator('.Footer-module--linkTitle--fa138')).toHaveText('Info'); + + //"Info" links + const infoLinks = infoSection.locator('.Footer-module--linkList--6f95b li a'); + await expect(infoLinks).toHaveCount(6); + await expect(infoLinks.nth(0)).toHaveText('About Us'); + await expect(infoLinks.nth(1)).toHaveText('Journal'); + await expect(infoLinks.nth(2)).toHaveText('Privacy Policy'); + + // "Support" section + const supportSection = footerContentTop.locator('.Footer-module--footerLinkContainer--34ce1').nth(1); + await expect(supportSection).toBeVisible(); + await expect(supportSection.locator('.Footer-module--linkTitle--fa138')).toHaveText('Support'); + + // "Support" links + const supportLinks = supportSection.locator('.Footer-module--linkList--6f95b li a'); + await expect(supportLinks).toHaveCount(8); + await expect(supportLinks.nth(0)).toHaveText('FAQ'); + await expect(supportLinks.nth(1)).toHaveText('Contact Us'); + await expect(supportLinks.nth(2)).toHaveText('Shipping & Returns'); + await expect(supportLinks.nth(3)).toHaveText('How to use this theme'); + + // newsletter section + const newsletterSection = footerContainer.locator('.Footer-module--newsLetter--91500'); + await expect(newsletterSection).toBeVisible(); + await expect(newsletterSection.locator('.Footer-module--newsLetterContent--e10ad')).toBeVisible(); + await expect(newsletterSection.locator('.Footer-module--linkTitle--fa138')).toHaveText('Newsletter'); + await expect(newsletterSection.locator('.Footer-module--promoMessage--b609e')).toHaveText('Get 15% off your first purchase! Plus, be the first to know about sales, new product launches and exclusive offers!'); + + // newsletter input form + await expect(newsletterSection.locator('.Footer-module--newsLetterForm--11787 input[name="newsLetterInput"]')).toBeVisible(); + + // social media icons in the footer + const socialIcons = newsletterSection.locator('.Footer-module--socialIconContainer--ac360'); + await expect(socialIcons).toHaveCount(4); + }); \ No newline at end of file From a63ead27dc0e509a496b8d1eccea3383364626e9 Mon Sep 17 00:00:00 2001 From: shray sharma Date: Mon, 1 Jul 2024 21:22:13 +0200 Subject: [PATCH 08/19] shop page tests --- tests/tests/shop.spec.ts | 111 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 tests/tests/shop.spec.ts diff --git a/tests/tests/shop.spec.ts b/tests/tests/shop.spec.ts new file mode 100644 index 0000000..b2a526a --- /dev/null +++ b/tests/tests/shop.spec.ts @@ -0,0 +1,111 @@ +import { test, expect } from '@playwright/test'; + + +test('Shop page | Header elements exist', async ({ page }) => { + await page.goto('http://localhost:5000/shop'); + + // Find the main container with a more specific locator + const mainContainer = page.locator('div.Container-module--container--6761c >> nth=0'); + await expect(mainContainer).toBeVisible(); + + // Check the header + const header = mainContainer.locator('div.Header-module--header--aa06a'); + await expect(header).toBeVisible(); + + // Check the navigation links + const navLinks = header.locator('nav a.Header-module--navLink--2a5b8'); + await expect(navLinks.nth(0)).toHaveText('Shop'); + await expect(navLinks.nth(1)).toHaveText('journal'); + await expect(navLinks.nth(2)).toHaveText('About'); + + // Check the burger icon / page resolution + // const burgerIcon = header.locator('div.Header-module--burgerIcon--813a8'); + // await expect(burgerIcon).toBeVisible(); + + // Check the brand logo + const brandLogo = header.locator('div.Brand-module--root--7bb0e'); + await expect(brandLogo).toBeVisible(); + + // Check the search button + const searchButton = header.locator('button[aria-label="Search"]'); + await expect(searchButton).toBeVisible(); + + // Check the favorites link + const favoritesLink = header.locator('a[aria-label="Favorites"]'); + await expect(favoritesLink).toBeVisible(); + + // Check the orders link + const ordersLink = header.locator('a[aria-label="Orders"]'); + await expect(ordersLink).toBeVisible(); + + // Check the cart button + const cartButton = header.locator('button[aria-label="Cart"]'); + await expect(cartButton).toBeVisible(); +}); + +test('Shop page | check elements existence', async ({ page }) => { + await page.goto('localhost:5000/shop/'); + + // Check for the span with class 'shop-module--itemCount--b09b3' + const itemCount = await page.locator('span.shop-module--itemCount--b09b3'); + await expect(itemCount).toHaveText('476 items'); + + // Check for the div with class 'shop-module--controllerContainer--a756d' + const controllerContainer = await page.locator('div.shop-module--controllerContainer--a756d'); + await expect(controllerContainer).toBeVisible(); + + // Check for the first div with class 'shop-module--iconContainer--4dc3e' containing the Filters text + const filtersIconContainer = await page.locator('div.shop-module--iconContainer--4dc3e >> text=Filters'); + await expect(filtersIconContainer).toBeVisible(); + + // Check for the second div with class 'shop-module--iconContainer--4dc3e shop-module--sortContainer--b6d9e' containing the Sort by text + const sortByIconContainer = await page.locator('div.shop-module--iconContainer--4dc3e.shop-module--sortContainer--b6d9e >> text=Sort by'); + await expect(sortByIconContainer).toBeVisible(); + }); + + + test.describe('Chip Module Elements Existence Tests', () => { + test('check chip XS element existence', async ({ page }) => { + await page.goto('localhost:5000/shop/'); + + //'Chip-module--root--b4116' containing the XS text + const chipXS = await page.locator('div.Chip-module--root--b4116').filter({ hasText: 'XS' }); + await expect(chipXS).toBeVisible(); + }); + + test('check chip S element existence', async ({ page }) => { + await page.goto('localhost:5000/shop/'); + + //'Chip-module--root--b4116' containing the S text + const chipS = await page.locator('div.Chip-module--root--b4116').filter({ hasText: /^S$/ }); + await expect(chipS).toBeVisible(); + }); + }); + + test('Shop page | Check for ProductCard elements', async ({ page }) => { + await page.goto('localhost:5000/shop/'); + + const imageContainer = page.locator('.ProductCard-module--imageContainer--00924').first(); + await expect(imageContainer).toBeVisible(); + + const bagContainer = imageContainer.locator('.ProductCard-module--bagContainer--39254'); + await expect(bagContainer).toBeVisible(); + + const heartContainer = imageContainer.locator('.ProductCard-module--heartContainer--f2a71'); + await expect(heartContainer).toBeVisible(); + + // first product name + const productName = page.locator('.ProductCard-module--productName--e6c17').first(); + await expect(productName).toBeVisible(); + await expect(productName).toHaveText('Relaxed-fit graphic T-shirt'); + + // product price + const productPrice = page.locator('.ProductCard-module--prices--cd435').first(); + await expect(productPrice).toBeVisible(); + await expect(productPrice).toHaveText('$13.90'); + + // information + const metaInfo = page.locator('.ProductCard-module--meta--07643').first(); + await expect(metaInfo).toBeVisible(); + await expect(metaInfo).toHaveText('+ 2 colors'); + }); \ No newline at end of file From e7000cd91f10dc38d1ce1c2464b4603f7a27b7ef Mon Sep 17 00:00:00 2001 From: shray sharma Date: Tue, 2 Jul 2024 12:25:22 +0200 Subject: [PATCH 09/19] Login page tests --- tests/tests/login.spec.ts | 145 ++++++++++++++++++++++++++++++++++++++ tests/tests/shop.spec.ts | 53 +++++++++++++- 2 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 tests/tests/login.spec.ts diff --git a/tests/tests/login.spec.ts b/tests/tests/login.spec.ts new file mode 100644 index 0000000..da71234 --- /dev/null +++ b/tests/tests/login.spec.ts @@ -0,0 +1,145 @@ +import { test, expect } from '@playwright/test'; + +test('Login page | Header elements exist', async ({ page }) => { + await page.goto('http://localhost:5000/login'); + + const mainContainer = page.locator('div.Container-module--container--6761c >> nth=0'); + await expect(mainContainer).toBeVisible(); + + // Header + const header = mainContainer.locator('div.Header-module--header--aa06a'); + await expect(header).toBeVisible(); + + // Navigation links + const navLinks = header.locator('nav a.Header-module--navLink--2a5b8'); + await expect(navLinks.nth(0)).toHaveText('Shop'); + await expect(navLinks.nth(1)).toHaveText('journal'); + await expect(navLinks.nth(2)).toHaveText('About'); + + const brandLogo = header.locator('div.Brand-module--root--7bb0e'); + await expect(brandLogo).toBeVisible(); + + const searchButton = header.locator('button[aria-label="Search"]'); + await expect(searchButton).toBeVisible(); + + const favoritesLink = header.locator('a[aria-label="Favorites"]'); + await expect(favoritesLink).toBeVisible(); + + const ordersLink = header.locator('a[aria-label="Orders"]'); + await expect(ordersLink).toBeVisible(); + + const cartButton = header.locator('button[aria-label="Cart"]'); + await expect(cartButton).toBeVisible(); +}); + + +test('Login page | Check all elements exist on login page', async ({ page }) => { + await page.goto('http://localhost:5000/login'); + + const loginTitle = page.locator('h1.login-module--loginTitle--fd184'); + await expect(loginTitle).toHaveText('Login'); + + const subtitle = page.locator('span.login-module--subtitle--63321'); + await expect(subtitle).toHaveText('Please enter your e-mail and password'); + + const emailLabel = page.locator('label[for="email"].FormInputField-module--label--df295'); + await expect(emailLabel).toHaveText('Email'); + const emailInput = page.locator('input#email[name="email"].FormInputField-module--input--8de56'); + await expect(emailInput).toBeVisible(); + + const passwordLabel = page.locator('label[for="password"].FormInputField-module--label--df295'); + await expect(passwordLabel).toHaveText('Password'); + const passwordInput = page.locator('input#password[name="password"].FormInputField-module--input--8de56'); + await expect(passwordInput).toBeVisible(); + + const forgotPasswordLink = page.locator('a.login-module--forgotLink--0d638[href="/forgot/"]'); + await expect(forgotPasswordLink).toHaveText('Forgot Password'); + + const loginButton = page.locator('button.Button-module--button--c17ef.Button-module--primary--2e17d.Button-module--fullWidth--737a0[type="submit"]'); + await expect(loginButton).toHaveText('LOG IN'); + + const newCustomerText = page.locator('span.login-module--createLink--314d0'); + await expect(newCustomerText).toHaveText('New Customer?'); + + const createAccountButton = page.locator('button.Button-module--button--c17ef.Button-module--secondary--e788d.Button-module--fullWidth--737a0[type="button"]'); + await expect(createAccountButton).toHaveText('create an account'); + + await createAccountButton.click(); + + await page.goto('http://localhost:5000/signup'); + }); + + + test('Login page | Attribute elements exist', async ({ page }) => { + await page.goto('http://localhost:5000/login'); + + const freeDeliveryRoot = page.locator('div.Attribute-module--root--d11a4:nth-child(1)'); + const freeDeliveryIcon = freeDeliveryRoot.locator('div.Attribute-module--iconContainer--81ef8 svg'); + const freeDeliveryTitle = freeDeliveryRoot.locator('span.Attribute-module--title--afe18'); + const freeDeliverySubtitle = freeDeliveryRoot.locator('span.Attribute-module--subtitle--6e815'); + + await expect(freeDeliveryIcon).toBeVisible(); + await expect(freeDeliveryTitle).toHaveText('free delivery worldwide'); + await expect(freeDeliverySubtitle).toHaveText('Click to learn more'); + + const returnsRoot = page.locator('div.Attribute-module--root--d11a4:nth-child(2)'); + const returnsIcon = returnsRoot.locator('div.Attribute-module--iconContainer--81ef8 svg'); + const returnsTitle = returnsRoot.locator('span.Attribute-module--title--afe18'); + const returnsSubtitle = returnsRoot.locator('span.Attribute-module--subtitle--6e815'); + + await expect(returnsIcon).toBeVisible(); + await expect(returnsTitle).toHaveText('returns'); + await expect(returnsSubtitle).toHaveText('Return goods in 30 days'); + + const securedPaymentRoot = page.locator('div.Attribute-module--root--d11a4:nth-child(3)'); + const securedPaymentIcon = securedPaymentRoot.locator('div.Attribute-module--iconContainer--81ef8 svg'); + const securedPaymentTitle = securedPaymentRoot.locator('span.Attribute-module--title--afe18'); + const securedPaymentSubtitle = securedPaymentRoot.locator('span.Attribute-module--subtitle--6e815'); + + await expect(securedPaymentIcon).toBeVisible(); + await expect(securedPaymentTitle).toHaveText('secured payment'); + await expect(securedPaymentSubtitle).toHaveText('Shop safely'); + }); + + + test('Login page | Footer exist', async ({ page }) => { + await page.goto('http://localhost:5000/login/'); + + const footerContainer = page.locator('.Footer-module--content--2aeb3'); + await expect(footerContainer).toBeVisible({ timeout: 10000 }); + + const footerContentTop = footerContainer.locator('.Footer-module--contentTop--729c1'); + await expect(footerContentTop).toBeVisible(); + + const infoSection = footerContentTop.locator('.Footer-module--footerLinkContainer--34ce1').nth(0); + await expect(infoSection).toBeVisible(); + await expect(infoSection.locator('.Footer-module--linkTitle--fa138')).toHaveText('Info'); + + const infoLinks = infoSection.locator('.Footer-module--linkList--6f95b li a'); + await expect(infoLinks).toHaveCount(6); + await expect(infoLinks.nth(0)).toHaveText('About Us'); + await expect(infoLinks.nth(1)).toHaveText('Journal'); + await expect(infoLinks.nth(2)).toHaveText('Privacy Policy'); + + const supportSection = footerContentTop.locator('.Footer-module--footerLinkContainer--34ce1').nth(1); + await expect(supportSection).toBeVisible(); + await expect(supportSection.locator('.Footer-module--linkTitle--fa138')).toHaveText('Support'); + + const supportLinks = supportSection.locator('.Footer-module--linkList--6f95b li a'); + await expect(supportLinks).toHaveCount(8); + await expect(supportLinks.nth(0)).toHaveText('FAQ'); + await expect(supportLinks.nth(1)).toHaveText('Contact Us'); + await expect(supportLinks.nth(2)).toHaveText('Shipping & Returns'); + await expect(supportLinks.nth(3)).toHaveText('How to use this theme'); + + const newsletterSection = footerContainer.locator('.Footer-module--newsLetter--91500'); + await expect(newsletterSection).toBeVisible(); + await expect(newsletterSection.locator('.Footer-module--newsLetterContent--e10ad')).toBeVisible(); + await expect(newsletterSection.locator('.Footer-module--linkTitle--fa138')).toHaveText('Newsletter'); + await expect(newsletterSection.locator('.Footer-module--promoMessage--b609e')).toHaveText('Get 15% off your first purchase! Plus, be the first to know about sales, new product launches and exclusive offers!'); + + await expect(newsletterSection.locator('.Footer-module--newsLetterForm--11787 input[name="newsLetterInput"]')).toBeVisible(); + + const socialIcons = newsletterSection.locator('.Footer-module--socialIconContainer--ac360'); + await expect(socialIcons).toHaveCount(4); + }); \ No newline at end of file diff --git a/tests/tests/shop.spec.ts b/tests/tests/shop.spec.ts index b2a526a..f52de5c 100644 --- a/tests/tests/shop.spec.ts +++ b/tests/tests/shop.spec.ts @@ -108,4 +108,55 @@ test('Shop page | check elements existence', async ({ page }) => { const metaInfo = page.locator('.ProductCard-module--meta--07643').first(); await expect(metaInfo).toBeVisible(); await expect(metaInfo).toHaveText('+ 2 colors'); - }); \ No newline at end of file + }); + + test('Shop page | Check all elements in the footer exist', async ({ page }) => { + await page.goto('http://localhost:5000/shop/'); + + // footer container + const footerContainer = page.locator('.Footer-module--content--2aeb3'); + await expect(footerContainer).toBeVisible({ timeout: 10000 }); + + //footer content top + const footerContentTop = footerContainer.locator('.Footer-module--contentTop--729c1'); + await expect(footerContentTop).toBeVisible(); + + // "Info" section + const infoSection = footerContentTop.locator('.Footer-module--footerLinkContainer--34ce1').nth(0); + await expect(infoSection).toBeVisible(); + await expect(infoSection.locator('.Footer-module--linkTitle--fa138')).toHaveText('Info'); + + //"Info" links + const infoLinks = infoSection.locator('.Footer-module--linkList--6f95b li a'); + await expect(infoLinks).toHaveCount(6); + await expect(infoLinks.nth(0)).toHaveText('About Us'); + await expect(infoLinks.nth(1)).toHaveText('Journal'); + await expect(infoLinks.nth(2)).toHaveText('Privacy Policy'); + + // "Support" section + const supportSection = footerContentTop.locator('.Footer-module--footerLinkContainer--34ce1').nth(1); + await expect(supportSection).toBeVisible(); + await expect(supportSection.locator('.Footer-module--linkTitle--fa138')).toHaveText('Support'); + + // "Support" links + const supportLinks = supportSection.locator('.Footer-module--linkList--6f95b li a'); + await expect(supportLinks).toHaveCount(8); + await expect(supportLinks.nth(0)).toHaveText('FAQ'); + await expect(supportLinks.nth(1)).toHaveText('Contact Us'); + await expect(supportLinks.nth(2)).toHaveText('Shipping & Returns'); + await expect(supportLinks.nth(3)).toHaveText('How to use this theme'); + + // newsletter section + const newsletterSection = footerContainer.locator('.Footer-module--newsLetter--91500'); + await expect(newsletterSection).toBeVisible(); + await expect(newsletterSection.locator('.Footer-module--newsLetterContent--e10ad')).toBeVisible(); + await expect(newsletterSection.locator('.Footer-module--linkTitle--fa138')).toHaveText('Newsletter'); + await expect(newsletterSection.locator('.Footer-module--promoMessage--b609e')).toHaveText('Get 15% off your first purchase! Plus, be the first to know about sales, new product launches and exclusive offers!'); + + // newsletter input form + await expect(newsletterSection.locator('.Footer-module--newsLetterForm--11787 input[name="newsLetterInput"]')).toBeVisible(); + + // social media icons in the footer + const socialIcons = newsletterSection.locator('.Footer-module--socialIconContainer--ac360'); + await expect(socialIcons).toHaveCount(4); + }); \ No newline at end of file From abe5083fbfe070c1e82c9bbd5c3957f0adb3a013 Mon Sep 17 00:00:00 2001 From: shray sharma Date: Wed, 3 Jul 2024 06:07:21 +0200 Subject: [PATCH 10/19] Product page tests --- tests/tests/product.spec.ts | 118 ++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 tests/tests/product.spec.ts diff --git a/tests/tests/product.spec.ts b/tests/tests/product.spec.ts new file mode 100644 index 0000000..fd32941 --- /dev/null +++ b/tests/tests/product.spec.ts @@ -0,0 +1,118 @@ +import { test, expect } from '@playwright/test'; + +test('Product page | Header elements exist', async ({ page }) => { + await page.goto('http://localhost:5000/product/sample/'); + + const mainContainer = page.locator('div.Container-module--container--6761c >> nth=0'); + await expect(mainContainer).toBeVisible(); + + // Header + const header = mainContainer.locator('div.Header-module--header--aa06a'); + await expect(header).toBeVisible(); + + // Navigation links + const navLinks = header.locator('nav a.Header-module--navLink--2a5b8'); + await expect(navLinks.nth(0)).toHaveText('Shop'); + await expect(navLinks.nth(1)).toHaveText('journal'); + await expect(navLinks.nth(2)).toHaveText('About'); + + const brandLogo = header.locator('div.Brand-module--root--7bb0e'); + await expect(brandLogo).toBeVisible(); + + const searchButton = header.locator('button[aria-label="Search"]'); + await expect(searchButton).toBeVisible(); + + const favoritesLink = header.locator('a[aria-label="Favorites"]'); + await expect(favoritesLink).toBeVisible(); + + const ordersLink = header.locator('a[aria-label="Orders"]'); + await expect(ordersLink).toBeVisible(); + + const cartButton = header.locator('button[aria-label="Cart"]'); + await expect(cartButton).toBeVisible(); +}); + + +test('Product page | Check links', async ({ page }) => { + await page.goto('http://localhost:5000/product/sample/'); + + const homeLink = page.locator('a.BreadCrumbs-module--crumb--3257d', { hasText: 'Home' }); + await expect(homeLink).toBeVisible(); + await homeLink.click(); + await expect(page).toHaveURL('http://localhost:5000/'); + + await page.goto('http://localhost:5000/product/sample/'); + + const menLink = page.locator('a.BreadCrumbs-module--crumb--3257d', { hasText: 'Men' }); + await expect(menLink).toBeVisible(); + await menLink.click(); + await expect(page).toHaveURL(/http:\/\/localhost:5000\/shop\/?/); + + await page.goto('http://localhost:5000/product/sample/'); + + const sweaterLink = page.locator('a.BreadCrumbs-module--crumb--3257d', { hasText: 'Sweater' }); + await expect(sweaterLink).toBeVisible(); + await sweaterLink.click(); + await expect(page).toHaveURL(/http:\/\/localhost:5000\/shop\/?/); + + await page.goto('http://localhost:5000/product/sample/'); + + const jumperText = page.locator('span.BreadCrumbs-module--crumb--3257d'); + await expect(jumperText).toBeVisible(); + await expect(jumperText).toHaveText('Lambswool Crew Neck Jumper'); + }); + + + test('Product page | Check product images exist', async ({ page }) => { + await page.goto('http://localhost:5000/product/sample/'); + + const img1 = page.locator('div.Gallery-module--imageContainer--ae68e img[alt="pdp description 1"]').first(); + await expect(img1).toBeVisible(); + await expect(img1).toHaveAttribute('src', '/products/pdp1.jpeg?imgcdn=true'); + + const img2 = page.locator('div.Gallery-module--imageContainer--ae68e img[alt="pdp description 2"]').first(); + await expect(img2).toBeVisible(); + await expect(img2).toHaveAttribute('src', '/products/pdp2.jpeg?imgcdn=true'); + + const img3 = page.locator('div.Gallery-module--imageContainer--ae68e img[alt="pdp description 3"]').first(); + await expect(img3).toBeVisible(); + await expect(img3).toHaveAttribute('src', '/products/pdp3.jpeg?imgcdn=true'); + + const img4 = page.locator('div.Gallery-module--imageContainer--ae68e img[alt="pdp description 4"]').first(); + await expect(img4).toBeVisible(); + await expect(img4).toHaveAttribute('src', '/products/pdp4.jpeg?imgcdn=true'); + }); + + +test('Check product page elements exist', async ({ page }) => { + await page.goto('http://localhost:5000/product/sample/'); + + const vendorName = page.locator('span.sample-module--vendor--de5dc', { hasText: 'by Sunspel' }); + await expect(vendorName).toBeVisible(); + + const priceContainer = page.locator('div.sample-module--priceContainer--eeab5'); + await expect(priceContainer).toBeVisible(); + await expect(priceContainer.locator('span').first()).toHaveText('$'); + await expect(priceContainer.locator('span').nth(1)).toHaveText('75.00'); + + const colorSwatchSection = page.locator('div.SwatchList-module--root--8d12e'); + const colorSwatchLabel = colorSwatchSection.locator('span.SwatchList-module--label--b12be').nth(0); + await expect(colorSwatchLabel).toBeVisible(); + const colorSwatches = colorSwatchSection.locator('div.SwatchList-module--swatchSelection--a95b1 button'); + await expect(colorSwatches).toHaveCount(6); + await expect(colorSwatches.nth(0)).toHaveClass(/Swatch-module--isActive--3d559/); + await expect(colorSwatches.nth(1)).toHaveClass(/Swatch-module--root--b289f/); + await expect(colorSwatches.nth(2)).toHaveClass(/Swatch-module--root--b289f/); + + const sizeContainer = page.locator('div.SizeList-module--root--d1877'); + const sizeLabel = sizeContainer.locator('span.SizeList-module--label--44881').nth(0); + await expect(sizeLabel).toBeVisible(); + + const sizeOptions = sizeContainer.locator('div.SizeList-module--sizeSelection--45655 div.BoxOption-module--root--49993'); + await expect(sizeOptions).toHaveCount(10); + await expect(sizeOptions.nth(0)).toHaveText('xs'); + await expect(sizeOptions.nth(1)).toHaveText('s'); + await expect(sizeOptions.nth(2)).toHaveText('m'); + await expect(sizeOptions.nth(3)).toHaveText('l'); + await expect(sizeOptions.nth(4)).toHaveText('xl'); +}); \ No newline at end of file From 146e3f86462b6339a78188cae77b38fde192dc41 Mon Sep 17 00:00:00 2001 From: shray sharma Date: Thu, 4 Jul 2024 16:25:24 +0200 Subject: [PATCH 11/19] Signup page tests --- tests/tests/signup.spec.ts | 116 +++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 tests/tests/signup.spec.ts diff --git a/tests/tests/signup.spec.ts b/tests/tests/signup.spec.ts new file mode 100644 index 0000000..e02986a --- /dev/null +++ b/tests/tests/signup.spec.ts @@ -0,0 +1,116 @@ +import { test, expect } from '@playwright/test'; + +test('Signup page | Header elements exist', async ({ page }) => { + await page.goto('http://localhost:5000/signup'); + + const mainContainer = page.locator('div.Container-module--container--6761c >> nth=0'); + await expect(mainContainer).toBeVisible(); + + // Header + const header = mainContainer.locator('div.Header-module--header--aa06a'); + await expect(header).toBeVisible(); + + // Navigation links + const navLinks = header.locator('nav a.Header-module--navLink--2a5b8'); + await expect(navLinks.nth(0)).toHaveText('Shop'); + await expect(navLinks.nth(1)).toHaveText('journal'); + await expect(navLinks.nth(2)).toHaveText('About'); + + const brandLogo = header.locator('div.Brand-module--root--7bb0e'); + await expect(brandLogo).toBeVisible(); + + const searchButton = header.locator('button[aria-label="Search"]'); + await expect(searchButton).toBeVisible(); + + const favoritesLink = header.locator('a[aria-label="Favorites"]'); + await expect(favoritesLink).toBeVisible(); + + const ordersLink = header.locator('a[aria-label="Orders"]'); + await expect(ordersLink).toBeVisible(); + + const cartButton = header.locator('button[aria-label="Cart"]'); + await expect(cartButton).toBeVisible(); +}); + +test('Signup page | Elements on the signup page exists', async ({ page }) => { + await page.goto('http://localhost:5000/signup'); + + // title + const title = page.locator('h1.signup-module--title--8132f'); + await expect(title).toHaveText('Create Account'); + + // subtitle + const subtitle = page.locator('span.signup-module--subtitle--d1f2c'); + await expect(subtitle).toHaveText('Please enter your the information below:'); + + // first name input field + const firstNameLabel = page.locator('label[for="firstName"]'); + const firstNameInput = page.locator('input#firstName'); + await expect(firstNameLabel).toHaveText('First Name '); + await expect(firstNameInput).toBeVisible(); + + // last name input field + const lastNameLabel = page.locator('label[for="lastName"]'); + const lastNameInput = page.locator('input#lastName'); + await expect(lastNameLabel).toHaveText('Last Name '); + await expect(lastNameInput).toBeVisible(); + + // email input field + const emailLabel = page.locator('label[for="email"]'); + const emailInput = page.locator('input#email'); + await expect(emailLabel).toHaveText('Email '); + await expect(emailInput).toBeVisible(); + + // password input field + const passwordLabel = page.locator('label[for="password"]'); + const passwordInput = page.locator('input#password'); + await expect(passwordLabel).toHaveText('Password '); + await expect(passwordInput).toBeVisible(); + + //create account button + const createAccountButton = page.locator('button[type="submit"]'); + await expect(createAccountButton).toHaveText('create account'); + + // reminder text + const reminderText = page.locator('span.signup-module--reminder--9f649'); + await expect(reminderText).toHaveText('Have an account?'); + + // log in button + const logInButton = page.locator('button', { hasText: 'log in' }); + await expect(logInButton).toHaveText('log in'); +}); + + +test('Signup page | log in button redirects to login page', async ({ page }) => { + await page.goto('http://localhost:5000/signup/'); + + await page.click('button.Button-module--button--c17ef.Button-module--secondary--e788d.Button-module--fullWidth--737a0'); + + await page.waitForURL('**/login/'); + + await expect(page).toHaveURL(/\/login\/$/); +}); + +test('Signup page | Footer elements', async ({ page }) => { + await page.goto('http://localhost:5000/signup/'); + + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/about/"]')).toBeVisible(); + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/blog/"]')).toBeVisible(); + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/support/#policy"]')).toBeVisible(); + + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/faq/"]')).toBeVisible(); + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/support/#contact"]')).toBeVisible(); + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/support/#returns"]')).toBeVisible(); + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/how-to-use/"]')).toBeVisible(); + + // newsletter section + await expect(page.locator('input[name="newsLetterInput"]')).toBeVisible(); + await expect(page.locator('.Footer-module--promoMessage--b609e')).toBeVisible(); + + // social media icons + const socialIcons = page.locator('.Footer-module--socialIconContainer--ac360'); + await expect(socialIcons.nth(0)).toBeVisible(); + await expect(socialIcons.nth(1)).toBeVisible(); + await expect(socialIcons.nth(2)).toBeVisible(); + await expect(socialIcons.nth(3)).toBeVisible(); +}); From 3074a02e6f1fa16207538c06ca4bea974b846aac Mon Sep 17 00:00:00 2001 From: shray sharma Date: Mon, 8 Jul 2024 19:05:50 +0200 Subject: [PATCH 12/19] Favorite page tests --- tests/tests/favorites.spec.ts | 100 ++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 tests/tests/favorites.spec.ts diff --git a/tests/tests/favorites.spec.ts b/tests/tests/favorites.spec.ts new file mode 100644 index 0000000..d434ad4 --- /dev/null +++ b/tests/tests/favorites.spec.ts @@ -0,0 +1,100 @@ +import { test, expect } from '@playwright/test'; + + +test('account/favorites/ | My Bag element', async ({ page }) => { + await page.goto('http://localhost:5000/account/favorites/'); + + // Click the cart button + const cartButton = await page.locator('button[aria-label="Cart"]'); + await cartButton.click(); + + const myBagElement = await page.locator('h4:has-text("My Bag")'); + await expect(myBagElement).toBeVisible(); +}); + + +test('account/favorites/ | click the cart button and check all Mini Cart item elements exist', async ({ page }) => { + + await page.goto('http://localhost:5000/account/favorites/'); + + // cart button + const cartButton = await page.locator('button[aria-label="Cart"]'); + await cartButton.click(); + + // Cart item elements exist + const miniCartItemRoot = await page.locator('.MiniCartItem-module--root--9bda7'); + const imageContainer = await page.locator('.MiniCartItem-module--imageContainer--3cdb5'); + const productImage = await page.locator('.MiniCartItem-module--imageContainer--3cdb5 img'); + const detailsContainer = await page.locator('.MiniCartItem-module--detailsContainer--ad9e6'); + const productName = await page.locator('.MiniCartItem-module--name--e5c89'); + const priceContainer = await page.locator('.MiniCartItem-module--priceContainer--64de1'); + const priceSymbol = await page.locator('.MiniCartItem-module--priceContainer--64de1 span').nth(0); + const priceValue = await page.locator('.MiniCartItem-module--priceContainer--64de1 span').nth(1); + const productMetaColor = await page.locator('.MiniCartItem-module--meta--12c6d:has-text("Color: Anthracite Melange")'); + const productMetaSize = await page.locator('.MiniCartItem-module--meta--12c6d:has-text("Size:")'); + const productSize = await page.locator('.MiniCartItem-module--size--7489d'); + const adjustItemContainer = await page.locator('.MiniCartItem-module--adjustItemContainer--ff32a'); + const adjustItemRoot = await page.locator('.AdjustItem-module--root--c19b7'); + const minusIconContainer = await page.locator('.AdjustItem-module--iconContainer--a2f36').nth(0); + const quantityInput = await page.locator('.AdjustItem-module--inputContainer--9d8ec input'); + const plusIconContainer = await page.locator('.AdjustItem-module--iconContainer--a2f36').nth(1); + const closeContainer = await page.locator('.MiniCartItem-module--closeContainer--1dcaa'); + const removeItemRoot = await page.locator('.RemoveItem-module--root--ed714'); + + await expect(miniCartItemRoot).toBeVisible(); + await expect(imageContainer).toBeVisible(); + await expect(productImage).toBeVisible(); + await expect(detailsContainer).toBeVisible(); + await expect(productName).toBeVisible(); + await expect(priceContainer).toBeVisible(); + await expect(priceSymbol).toBeVisible(); + await expect(priceValue).toBeVisible(); + await expect(productMetaColor).toBeVisible(); + await expect(productMetaSize).toBeVisible(); + await expect(productSize).toBeVisible(); + await expect(adjustItemContainer).toBeVisible(); + await expect(adjustItemRoot).toBeVisible(); + await expect(minusIconContainer).toBeVisible(); + await expect(quantityInput).toBeVisible(); + await expect(plusIconContainer).toBeVisible(); + await expect(closeContainer).toBeVisible(); + await expect(removeItemRoot).toBeVisible(); +}); + + +test('account/favorites/ | Header elements exist', async ({ page }) => { + await page.goto('http://localhost:5000/account/favorites/'); + + const mainContainer = page.locator('div.Container-module--container--6761c >> nth=0'); + await expect(mainContainer).toBeVisible(); + + // Check the header + const header = mainContainer.locator('div.Header-module--header--aa06a'); + await expect(header).toBeVisible(); + + // Check the navigation links + const navLinks = header.locator('nav a.Header-module--navLink--2a5b8'); + await expect(navLinks.nth(0)).toHaveText('Shop'); + await expect(navLinks.nth(1)).toHaveText('journal'); + await expect(navLinks.nth(2)).toHaveText('About'); + + // Check the brand logo + const brandLogo = header.locator('div.Brand-module--root--7bb0e'); + await expect(brandLogo).toBeVisible(); + + // Check the search button + const searchButton = header.locator('button[aria-label="Search"]'); + await expect(searchButton).toBeVisible(); + + // Check the favorites link + const favoritesLink = header.locator('a[aria-label="Favorites"]'); + await expect(favoritesLink).toBeVisible(); + + // Check the orders link + const ordersLink = header.locator('a[aria-label="Orders"]'); + await expect(ordersLink).toBeVisible(); + + // Check the cart button + const cartButton = header.locator('button[aria-label="Cart"]'); + await expect(cartButton).toBeVisible(); + }); \ No newline at end of file From 3238c1b9782664bf2dd88d03f694e6e72e088dfb Mon Sep 17 00:00:00 2001 From: shray sharma Date: Tue, 9 Jul 2024 21:29:21 +0200 Subject: [PATCH 13/19] Cart page tests --- tests/tests/cart.spec.ts | 120 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 tests/tests/cart.spec.ts diff --git a/tests/tests/cart.spec.ts b/tests/tests/cart.spec.ts new file mode 100644 index 0000000..0bdad62 --- /dev/null +++ b/tests/tests/cart.spec.ts @@ -0,0 +1,120 @@ +import { test, expect } from '@playwright/test'; + +test('Cart page | All elements in header exist', async ({ page }) => { + await page.goto('http://localhost:5000/cart/'); + + const headerContainer = page.locator('div.cart-module--headerContainer--33826'); + await expect(headerContainer).toBeVisible(); + + const shoppingContainer = headerContainer.locator('div.cart-module--shoppingContainer--cdac8'); + await expect(shoppingContainer).toBeVisible(); + + const shopLink = shoppingContainer.locator('a.cart-module--shopLink--a0151'); + await expect(shopLink).toBeVisible(); + await expect(shopLink).toHaveAttribute('href', '/shop/'); + + const shopLinkSvg = shopLink.locator('svg'); + await expect(shopLinkSvg).toBeVisible(); + await expect(shopLinkSvg).toHaveAttribute('width', '15'); + await expect(shopLinkSvg).toHaveAttribute('height', '15'); + + const continueShoppingSpan = shopLink.locator('span.cart-module--continueShopping--f2529'); + await expect(continueShoppingSpan).toBeVisible(); + await expect(continueShoppingSpan).toHaveText('Continue Shopping'); + + const brandContainer = headerContainer.locator('div.Brand-module--root--7bb0e'); + await expect(brandContainer).toBeVisible(); + await expect(brandContainer).toHaveAttribute('role', 'presentation'); + + const brandSvg = brandContainer.locator('svg'); + await expect(brandSvg).toBeVisible(); + await expect(brandSvg).toHaveAttribute('width', '127'); + await expect(brandSvg).toHaveAttribute('height', '24'); + + const loginContainer = headerContainer.locator('div.cart-module--loginContainer--120bb'); + await expect(loginContainer).toBeVisible(); + + // Check for the login link + const loginLink = loginContainer.locator('a'); + await expect(loginLink).toBeVisible(); + await expect(loginLink).toHaveAttribute('href', '/login/'); + await expect(loginLink).toHaveText('Login'); + }); + + test('Cart page | Order Summary', async ({ page }) => { + await page.goto('http://localhost:5000/cart/'); + + const orderSummary = page.locator('div.OrderSummary-module--orderSummary--2151a'); + await expect(orderSummary).toBeVisible(); + + const orderSummaryTitle = orderSummary.locator('span.OrderSummary-module--title--ac4fb'); + await expect(orderSummaryTitle).toBeVisible(); + await expect(orderSummaryTitle).toHaveText('order summary'); + + const calculationContainer = orderSummary.locator('div.OrderSummary-module--calculationContainer--0cca1'); + await expect(calculationContainer).toBeVisible(); + + const labelContainers = calculationContainer.locator('div.OrderSummary-module--labelContainer--bdd63'); + await expect(labelContainers).toHaveCount(3); + + await expect(labelContainers.nth(0).locator('span').first()).toHaveText('Subtotal'); + await expect(labelContainers.nth(0).locator('span').nth(1)).toHaveText('$440.00'); + + await expect(labelContainers.nth(1).locator('span').first()).toHaveText('Shipping'); + await expect(labelContainers.nth(1).locator('span').nth(1)).toHaveText('---'); + + await expect(labelContainers.nth(2).locator('span').first()).toHaveText('Tax'); + await expect(labelContainers.nth(2).locator('span').nth(1)).toHaveText('$0.00'); + + const couponContainer = orderSummary.locator('div.OrderSummary-module--couponContainer--13bed'); + await expect(couponContainer).toBeVisible(); + + const couponCodeLabel = couponContainer.locator('span').nth(0); + await expect(couponCodeLabel).toBeVisible(); + await expect(couponCodeLabel).toHaveText('Coupon Code'); + + const couponInputField = couponContainer.locator('input#couponInput').nth(0); + await expect(couponInputField).toBeVisible(); + await expect(couponInputField).toHaveAttribute('name', 'couponInput'); + + const couponInputIcon = couponContainer.locator('div.FormInputField-module--iconContainer--9d2a4').nth(0).locator('svg'); + await expect(couponInputIcon).toBeVisible(); + await expect(couponInputIcon).toHaveAttribute('width', '15'); + await expect(couponInputIcon).toHaveAttribute('height', '15'); + + const giftCardLabel = couponContainer.locator('span').nth(1); + await expect(giftCardLabel).toBeVisible(); + await expect(giftCardLabel).toHaveText('Gift Card'); + + const giftCardInputField = couponContainer.locator('input#couponInput').nth(1); + await expect(giftCardInputField).toBeVisible(); + await expect(giftCardInputField).toHaveAttribute('name', 'couponInput'); + + const giftCardInputIcon = couponContainer.locator('div.FormInputField-module--iconContainer--9d2a4').nth(1).locator('svg'); + await expect(giftCardInputIcon).toBeVisible(); + await expect(giftCardInputIcon).toHaveAttribute('width', '15'); + await expect(giftCardInputIcon).toHaveAttribute('height', '15'); + + const totalContainer = orderSummary.locator('div.OrderSummary-module--totalContainer--491aa'); + await expect(totalContainer).toBeVisible(); + + const totalAmount = totalContainer.locator('span').nth(1); + await expect(totalAmount).toBeVisible(); + await expect(totalAmount).toHaveText('$440.00'); + }); + + + test('Cart page | checkout button redirect to confirm page', async ({ page }) => { + await page.goto('http://localhost:5000/cart/'); + + // Check for the checkout button + const checkoutButton = page.getByRole('button', { name: 'checkout' }) + await expect(checkoutButton).toBeVisible(); + + await Promise.all([ + page.waitForNavigation(), + checkoutButton.click() + ]); + + await page.goto('http://localhost:5000/orderConfirm/'); + }); \ No newline at end of file From 28116ab062fd4ff764253ead11f9a922781c52b9 Mon Sep 17 00:00:00 2001 From: shray sharma Date: Thu, 11 Jul 2024 08:19:07 +0200 Subject: [PATCH 14/19] Order confirm, faq page tests --- cart.spec.ts | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++ faq.spec.ts | 70 ++++++++++++++++++++ 2 files changed, 254 insertions(+) create mode 100644 cart.spec.ts create mode 100644 faq.spec.ts diff --git a/cart.spec.ts b/cart.spec.ts new file mode 100644 index 0000000..d84c953 --- /dev/null +++ b/cart.spec.ts @@ -0,0 +1,184 @@ +import { test, expect } from '@playwright/test'; + +test('Cart page | All elements in header exist', async ({ page }) => { + await page.goto('http://localhost:5000/cart/'); + + const headerContainer = page.locator('div.cart-module--headerContainer--33826'); + await expect(headerContainer).toBeVisible(); + + const shoppingContainer = headerContainer.locator('div.cart-module--shoppingContainer--cdac8'); + await expect(shoppingContainer).toBeVisible(); + + const shopLink = shoppingContainer.locator('a.cart-module--shopLink--a0151'); + await expect(shopLink).toBeVisible(); + await expect(shopLink).toHaveAttribute('href', '/shop/'); + + const shopLinkSvg = shopLink.locator('svg'); + await expect(shopLinkSvg).toBeVisible(); + await expect(shopLinkSvg).toHaveAttribute('width', '15'); + await expect(shopLinkSvg).toHaveAttribute('height', '15'); + + const continueShoppingSpan = shopLink.locator('span.cart-module--continueShopping--f2529'); + await expect(continueShoppingSpan).toBeVisible(); + await expect(continueShoppingSpan).toHaveText('Continue Shopping'); + + const brandContainer = headerContainer.locator('div.Brand-module--root--7bb0e'); + await expect(brandContainer).toBeVisible(); + await expect(brandContainer).toHaveAttribute('role', 'presentation'); + + const brandSvg = brandContainer.locator('svg'); + await expect(brandSvg).toBeVisible(); + await expect(brandSvg).toHaveAttribute('width', '127'); + await expect(brandSvg).toHaveAttribute('height', '24'); + + const loginContainer = headerContainer.locator('div.cart-module--loginContainer--120bb'); + await expect(loginContainer).toBeVisible(); + + // Check for the login link + const loginLink = loginContainer.locator('a'); + await expect(loginLink).toBeVisible(); + await expect(loginLink).toHaveAttribute('href', '/login/'); + await expect(loginLink).toHaveText('Login'); + }); + + test('Cart page | Order Summary', async ({ page }) => { + await page.goto('http://localhost:5000/cart/'); + + const orderSummary = page.locator('div.OrderSummary-module--orderSummary--2151a'); + await expect(orderSummary).toBeVisible(); + + const orderSummaryTitle = orderSummary.locator('span.OrderSummary-module--title--ac4fb'); + await expect(orderSummaryTitle).toBeVisible(); + await expect(orderSummaryTitle).toHaveText('order summary'); + + const calculationContainer = orderSummary.locator('div.OrderSummary-module--calculationContainer--0cca1'); + await expect(calculationContainer).toBeVisible(); + + const labelContainers = calculationContainer.locator('div.OrderSummary-module--labelContainer--bdd63'); + await expect(labelContainers).toHaveCount(3); + + await expect(labelContainers.nth(0).locator('span').first()).toHaveText('Subtotal'); + await expect(labelContainers.nth(0).locator('span').nth(1)).toHaveText('$440.00'); + + await expect(labelContainers.nth(1).locator('span').first()).toHaveText('Shipping'); + await expect(labelContainers.nth(1).locator('span').nth(1)).toHaveText('---'); + + await expect(labelContainers.nth(2).locator('span').first()).toHaveText('Tax'); + await expect(labelContainers.nth(2).locator('span').nth(1)).toHaveText('$0.00'); + + const couponContainer = orderSummary.locator('div.OrderSummary-module--couponContainer--13bed'); + await expect(couponContainer).toBeVisible(); + + const couponCodeLabel = couponContainer.locator('span').nth(0); + await expect(couponCodeLabel).toBeVisible(); + await expect(couponCodeLabel).toHaveText('Coupon Code'); + + const couponInputField = couponContainer.locator('input#couponInput').nth(0); + await expect(couponInputField).toBeVisible(); + await expect(couponInputField).toHaveAttribute('name', 'couponInput'); + + const couponInputIcon = couponContainer.locator('div.FormInputField-module--iconContainer--9d2a4').nth(0).locator('svg'); + await expect(couponInputIcon).toBeVisible(); + await expect(couponInputIcon).toHaveAttribute('width', '15'); + await expect(couponInputIcon).toHaveAttribute('height', '15'); + + const giftCardLabel = couponContainer.locator('span').nth(1); + await expect(giftCardLabel).toBeVisible(); + await expect(giftCardLabel).toHaveText('Gift Card'); + + const giftCardInputField = couponContainer.locator('input#couponInput').nth(1); + await expect(giftCardInputField).toBeVisible(); + await expect(giftCardInputField).toHaveAttribute('name', 'couponInput'); + + const giftCardInputIcon = couponContainer.locator('div.FormInputField-module--iconContainer--9d2a4').nth(1).locator('svg'); + await expect(giftCardInputIcon).toBeVisible(); + await expect(giftCardInputIcon).toHaveAttribute('width', '15'); + await expect(giftCardInputIcon).toHaveAttribute('height', '15'); + + const totalContainer = orderSummary.locator('div.OrderSummary-module--totalContainer--491aa'); + await expect(totalContainer).toBeVisible(); + + const totalAmount = totalContainer.locator('span').nth(1); + await expect(totalAmount).toBeVisible(); + await expect(totalAmount).toHaveText('$440.00'); + }); + + + test('Cart page | checkout button redirect to confirm page', async ({ page }) => { + await page.goto('http://localhost:5000/cart/'); + + // Check for the checkout button + const checkoutButton = page.getByRole('button', { name: 'checkout' }) + await expect(checkoutButton).toBeVisible(); + + await Promise.all([ + page.waitForNavigation(), + checkoutButton.click() + ]); + + await page.goto('http://localhost:5000/orderConfirm/'); + }); + + + test('Cart page | Order confirm page elements exist', async ({ page }) => { + + await page.goto('http://localhost:5000/orderConfirm/'); + + // root div + const rootDiv = page.locator('.accountSuccess-module--root--e132d'); + await expect(rootDiv).toBeVisible(); + + await expect(rootDiv.locator('h1')).toHaveText('Thank You!'); + + await expect(rootDiv.locator('p')).toHaveText('We are now processing your order. If you have any concerns feel free to email us at customerservice@example.com'); + + const actionContainer = rootDiv.locator('.accountSuccess-module--actionContainer--25abb'); + await expect(actionContainer).toBeVisible(); + + // ActionCard + const actionCards = actionContainer.locator('.ActionCard-module--root--0dba6'); + await expect(actionCards).toHaveCount(4); + + // Order Status + const orderStatusCard = actionCards.nth(0); + await expect(orderStatusCard.locator('.ActionCard-module--actionName--fe65b')).toHaveText('Order Status'); + await expect(orderStatusCard.locator('.ActionCard-module--link--94d11')).toHaveText('Check your order status'); + + // Shop ActionCard + const shopCard = actionCards.nth(1); + await expect(shopCard.locator('.ActionCard-module--actionName--fe65b')).toHaveText('Shop'); + await expect(shopCard.locator('.ActionCard-module--link--94d11')).toHaveText('Continue Shopping'); + + // FAQs + const faqsCard = actionCards.nth(2); + await expect(faqsCard.locator('.ActionCard-module--actionName--fe65b')).toHaveText('FAQs'); + await expect(faqsCard.locator('.ActionCard-module--link--94d11')).toHaveText('Check out FAQs page'); + + const contactUsCard = actionCards.nth(3); + await expect(contactUsCard.locator('.ActionCard-module--actionName--fe65b')).toHaveText('Contact Us'); + await expect(contactUsCard.locator('.ActionCard-module--link--94d11')).toHaveText('Reach out to us'); +}); + +test('Order Confirm page | Footer elements', async ({ page }) => { + await page.goto('http://localhost:5000/orderConfirm/'); + + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/about/"]')).toBeVisible(); + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/blog/"]')).toBeVisible(); + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/support/#policy"]')).toBeVisible(); + + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/faq/"]')).toBeVisible(); + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/support/#contact"]')).toBeVisible(); + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/support/#returns"]')).toBeVisible(); + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/how-to-use/"]')).toBeVisible(); + + // newsletter section + await expect(page.locator('input[name="newsLetterInput"]')).toBeVisible(); + await expect(page.locator('.Footer-module--promoMessage--b609e')).toBeVisible(); + + // social media icons + const socialIcons = page.locator('.Footer-module--socialIconContainer--ac360'); + await expect(socialIcons.nth(0)).toBeVisible(); + await expect(socialIcons.nth(1)).toBeVisible(); + await expect(socialIcons.nth(2)).toBeVisible(); + await expect(socialIcons.nth(3)).toBeVisible(); +}); diff --git a/faq.spec.ts b/faq.spec.ts new file mode 100644 index 0000000..9300111 --- /dev/null +++ b/faq.spec.ts @@ -0,0 +1,70 @@ +import { test, expect } from '@playwright/test'; + +test('Faq page | Footer elements', async ({ page }) => { + await page.goto('http://localhost:5000/faq/'); + + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/about/"]')).toBeVisible(); + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/blog/"]')).toBeVisible(); + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/support/#policy"]')).toBeVisible(); + + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/faq/"]')).toBeVisible(); + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/support/#contact"]')).toBeVisible(); + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/support/#returns"]')).toBeVisible(); + await expect(page.locator('.Footer-module--footerLinks--1a995 >> a[href="/how-to-use/"]')).toBeVisible(); + + // newsletter section + await expect(page.locator('input[name="newsLetterInput"]')).toBeVisible(); + await expect(page.locator('.Footer-module--promoMessage--b609e')).toBeVisible(); + + // social media icons + const socialIcons = page.locator('.Footer-module--socialIconContainer--ac360'); + await expect(socialIcons.nth(0)).toBeVisible(); + await expect(socialIcons.nth(1)).toBeVisible(); + await expect(socialIcons.nth(2)).toBeVisible(); + await expect(socialIcons.nth(3)).toBeVisible(); + }); + + + test('Faq page | FAQ banner', async ({ page }) => { + await page.goto('http://localhost:5000/faq/'); + + const timeout = 10000; + + const bannerRoot = page.locator('.Banner-module--root--d0b7f'); + await expect(bannerRoot).toBeVisible({ timeout }); + + const bannerContent = bannerRoot.locator('.Banner-module--content--07f4d'); + await expect(bannerContent).toBeVisible({ timeout }); + + await expect(bannerContent.locator('h2')).toHaveText('Frequently Asked Questions', { timeout }); + }); + +test('Shop page | Header elements exist', async ({ page }) => { + await page.goto('http://localhost:5000/faq/'); + + const mainContainer = page.locator('div.Container-module--container--6761c >> nth=0'); + await expect(mainContainer).toBeVisible(); + + const header = mainContainer.locator('div.Header-module--header--aa06a'); + await expect(header).toBeVisible(); + + const navLinks = header.locator('nav a.Header-module--navLink--2a5b8'); + await expect(navLinks.nth(0)).toHaveText('Shop'); + await expect(navLinks.nth(1)).toHaveText('journal'); + await expect(navLinks.nth(2)).toHaveText('About'); + + const brandLogo = header.locator('div.Brand-module--root--7bb0e'); + await expect(brandLogo).toBeVisible(); + + const searchButton = header.locator('button[aria-label="Search"]'); + await expect(searchButton).toBeVisible(); + + const favoritesLink = header.locator('a[aria-label="Favorites"]'); + await expect(favoritesLink).toBeVisible(); + + const ordersLink = header.locator('a[aria-label="Orders"]'); + await expect(ordersLink).toBeVisible(); + + const cartButton = header.locator('button[aria-label="Cart"]'); + await expect(cartButton).toBeVisible(); +}); From 3f3c72713a2ed49af73dacdb9b550a2aeccf2bb7 Mon Sep 17 00:00:00 2001 From: shray sharma Date: Fri, 12 Jul 2024 19:05:27 +0200 Subject: [PATCH 15/19] Support page test --- tests/tests/support.spec.ts | 105 ++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 tests/tests/support.spec.ts diff --git a/tests/tests/support.spec.ts b/tests/tests/support.spec.ts new file mode 100644 index 0000000..482b735 --- /dev/null +++ b/tests/tests/support.spec.ts @@ -0,0 +1,105 @@ +import { test, expect } from '@playwright/test'; + + +test('Support page | Header elements exist', async ({ page }) => { + await page.goto('http://localhost:5000/support/'); + + // banner + const bannerRoot = await page.$('.Banner-module--root--d0b7f'); + expect(bannerRoot).not.toBeNull(); + + if (bannerRoot) { + const bannerContent = await bannerRoot.$('.Banner-module--content--07f4d'); + expect(bannerContent).not.toBeNull(); + + if (bannerContent) { + const bannerHeading = await bannerContent.$('h2'); + expect(bannerHeading).not.toBeNull(); + + if (bannerHeading) { + expect(await bannerHeading.textContent()).toBe('Contact Us'); + } + } + } +}); + +test('Support page | All policy general text', async ({ page }) => { + await page.goto('http://localhost:5000/support/'); + + const policyRoot = await page.$('.Policy-module--root--be247'); + expect(policyRoot).not.toBeNull(); + + if (policyRoot) { + const section1 = await policyRoot.$('.Policy-module--section--8f61b:nth-child(1)'); + expect(section1).not.toBeNull(); + + if (section1) { + const heading1 = await section1.$('h3'); + expect(heading1).not.toBeNull(); + if (heading1) { + expect(await heading1.textContent()).toBe('1. Lorem Ipsum'); + } + + const paragraphs1 = await section1.$$('p'); + expect(paragraphs1.length).toBe(3); + } + + const section2 = await policyRoot.$('.Policy-module--section--8f61b:nth-child(2)'); + expect(section2).not.toBeNull(); + + if (section2) { + const heading2 = await section2.$('h3'); + expect(heading2).not.toBeNull(); + if (heading2) { + expect(await heading2.textContent()).toBe('2. Lorem Ipsum'); + } + + const paragraphs2 = await section2.$$('p'); + expect(paragraphs2.length).toBe(3); + } + + const section3 = await policyRoot.$('.Policy-module--section--8f61b:nth-child(3)'); + expect(section3).not.toBeNull(); + + if (section3) { + const heading3 = await section3.$('h3'); + expect(heading3).not.toBeNull(); + if (heading3) { + expect(await heading3.textContent()).toBe('3. Lorem Ipsum'); + } + + const paragraphs3 = await section3.$$('p'); + expect(paragraphs3.length).toBe(8); + } + } + }); + +test('Support page | Header elements', async ({ page }) => { + await page.goto('http://localhost:5000/support/'); + + const mainContainer = page.locator('div.Container-module--container--6761c >> nth=0'); + await expect(mainContainer).toBeVisible(); + + const header = mainContainer.locator('div.Header-module--header--aa06a'); + await expect(header).toBeVisible(); + + const navLinks = header.locator('nav a.Header-module--navLink--2a5b8'); + await expect(navLinks.nth(0)).toHaveText('Shop'); + await expect(navLinks.nth(1)).toHaveText('journal'); + await expect(navLinks.nth(2)).toHaveText('About'); + + const brandLogo = header.locator('div.Brand-module--root--7bb0e'); + await expect(brandLogo).toBeVisible(); + + const searchButton = header.locator('button[aria-label="Search"]'); + await expect(searchButton).toBeVisible(); + + const favoritesLink = header.locator('a[aria-label="Favorites"]'); + await expect(favoritesLink).toBeVisible(); + + const ordersLink = header.locator('a[aria-label="Orders"]'); + await expect(ordersLink).toBeVisible(); + + const cartButton = header.locator('button[aria-label="Cart"]'); + await expect(cartButton).toBeVisible(); + }); \ No newline at end of file From afcc615a96e2f7ada14b40e3b39a0eefed77e0c8 Mon Sep 17 00:00:00 2001 From: shray sharma Date: Mon, 15 Jul 2024 10:35:05 +0200 Subject: [PATCH 16/19] shop, account page tests --- tests/tests/account.spec.ts | 45 ++++++++++++++++++++++++++ tests/tests/shopv2.spec.ts | 64 +++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 tests/tests/account.spec.ts create mode 100644 tests/tests/shopv2.spec.ts diff --git a/tests/tests/account.spec.ts b/tests/tests/account.spec.ts new file mode 100644 index 0000000..9d4d941 --- /dev/null +++ b/tests/tests/account.spec.ts @@ -0,0 +1,45 @@ +import { test, expect } from '@playwright/test'; + +test('Account orders | Orders elements', async ({ page }) => { + await page.goto('http://localhost:5000/account/orders/'); + + const orderDetailsSelector = '.OrderItem-module--orderHeader--56952'; + const orderDetails = await page.$(orderDetailsSelector); + expect(orderDetails).not.toBeNull(); + + if (orderDetails) { + const orderId = await orderDetails.$('.OrderItem-module--orderId--a589c'); + const orderTotal = await orderDetails.$('.OrderItem-module--total--3ff20'); + const orderDate = await orderDetails.$('.OrderItem-module--orderDate--117f4'); + const orderStatus = await orderDetails.$('.OrderItem-module--status--d134a'); + + expect(orderId).not.toBeNull(); + expect(orderTotal).not.toBeNull(); + expect(orderDate).not.toBeNull(); + expect(orderStatus).not.toBeNull(); + + if (orderId) { + const orderIdText = await orderId.textContent(); + expect(orderIdText).toMatch(/Order #\d+/); + } + } +}); + +test('Check footer elements exist', async ({ page }) => { + await page.goto('http://localhost:5000/account/orders/'); + + const footerSelector = '.Footer-module--content--2aeb3'; + const footer = await page.$(footerSelector); + expect(footer).not.toBeNull(); + + // Check for specific elements within the footer + const footerLinks = await page.$$('.Footer-module--footerLinkContainer--34ce1'); + // at least one footer link container exists + expect(footerLinks.length).toBeGreaterThan(0); + + const newsletterSection = await page.$('.Footer-module--newsLetter--91500'); + expect(newsletterSection).not.toBeNull(); + + const socialIcons = await page.$$('.Footer-module--socialIconContainer--ac360'); + expect(socialIcons.length).toBeGreaterThan(0); +}); \ No newline at end of file diff --git a/tests/tests/shopv2.spec.ts b/tests/tests/shopv2.spec.ts new file mode 100644 index 0000000..f35c982 --- /dev/null +++ b/tests/tests/shopv2.spec.ts @@ -0,0 +1,64 @@ +import { test, expect } from '@playwright/test'; + +test('ShopV2 api | Check main elements', async ({ page }) => { + await page.goto('http://localhost:5000/shopV2/'); + + const productCards = await page.$$('.ProductCard-module--root--d7fcc'); + + for (const card of productCards) { + const productNameElement = await card.$('.ProductCard-module--productName--e6c17'); + const pricesElement = await card.$('.ProductCard-module--prices--cd435'); + + if (productNameElement) { + const productName = await productNameElement.innerText(); + // console.log(`Product Name: ${productName}`); + } else { + console.log('Product Name element is null'); + } + + if (pricesElement) { + const priceText = await pricesElement.innerText(); + // console.log(`Price: ${priceText}`); + } else { + console.log('Prices element is null'); + } + } +}); + +test('Click on Product Card and check redirect', async ({ page }) => { + await page.goto('http://localhost:5000/shopV2/'); + + const productCardSelector = '.ProductCard-module--root--d7fcc'; + const productCard = await page.$(productCardSelector); + + expect(productCard).not.toBeNull(); + + if (productCard) { + await productCard.click(); + + await page.waitForNavigation(); + + expect(page.url()).toBe('http://localhost:5000/product/sample/'); + } else { + console.error('Product card not found!'); + } +}); + +test('Check footer elements exist', async ({ page }) => { + await page.goto('http://localhost:5000/shopV2/'); + + const footerSelector = '.Footer-module--content--2aeb3'; + const footer = await page.$(footerSelector); + expect(footer).not.toBeNull(); + + // Check for specific elements within the footer + const footerLinks = await page.$$('.Footer-module--footerLinkContainer--34ce1'); + // at least one footer link container exists + expect(footerLinks.length).toBeGreaterThan(0); + + const newsletterSection = await page.$('.Footer-module--newsLetter--91500'); + expect(newsletterSection).not.toBeNull(); + + const socialIcons = await page.$$('.Footer-module--socialIconContainer--ac360'); + expect(socialIcons.length).toBeGreaterThan(0); +}); \ No newline at end of file From c6fde9f075ab59b778cb45f16fef1990feec94a0 Mon Sep 17 00:00:00 2001 From: shray sharma Date: Wed, 17 Jul 2024 12:46:35 -0400 Subject: [PATCH 17/19] Login page input fields tests --- tests/tests/login.spec.ts | 75 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/tests/tests/login.spec.ts b/tests/tests/login.spec.ts index da71234..4adec84 100644 --- a/tests/tests/login.spec.ts +++ b/tests/tests/login.spec.ts @@ -142,4 +142,77 @@ test('Login page | Check all elements exist on login page', async ({ page }) => const socialIcons = newsletterSection.locator('.Footer-module--socialIconContainer--ac360'); await expect(socialIcons).toHaveCount(4); - }); \ No newline at end of file + }); + + + test('Login page | functionality test', async ({ page }) => { + await page.goto('http://localhost:5000/login/'); + + await expect(page.locator('h1.login-module--loginTitle--fd184')).toBeVisible(); + + // Fill in the email + await page.fill('input[name="email"]', 'test@example.com'); + + // Fill in the password + await page.fill('input[name="password"]', 'password123'); + + await Promise.all([ + page.waitForNavigation(), + page.click('button[type="submit"]') +]); + + // URL is correct after login + await expect(page).toHaveURL('http://localhost:5000/account/orders/'); +}); + +test('Login page | Create account button redirects to signup page', async ({ page }) => { + await page.goto('http://localhost:5000/login/'); + + // Click the "create an account" button + await Promise.all([ + page.waitForNavigation(), + page.click('button:has-text("create an account")') + ]); + + // Check that the URL is correct after clicking "create an account" + await expect(page).toHaveURL('http://localhost:5000/signup/'); +}); + + +test('Login page | Fill signup form and create an account', async ({ page }) => { + await page.goto('http://localhost:5000/signup'); + + // Fill in the signup form + await page.fill('input[name="firstName"]', 'John'); + await page.fill('input[name="lastName"]', 'Doe'); + await page.fill('input[name="email"]', 'ss@gmail.com'); + await page.fill('input[name="password"]', 'Password1'); + + await Promise.all([ + page.waitForNavigation(), + page.click('button:has-text("create account")') + ]); + + // URL is correct after creating an account + await expect(page).toHaveURL('http://localhost:5000/accountSuccess/'); +}); + +test('Check redirection on button clicks', async ({ page }) => { + await page.goto('http://localhost:5000/accountSuccess/'); + + const accountsButton = page.locator('.ActionCard-module--actionName--fe65b:has-text("Accounts")'); + await accountsButton.click(); + + await expect(page).toHaveURL('http://localhost:5000/login/'); + + await expect(page.locator('h1')).toHaveText('Login'); +}); + +test('Check redirection on Shop button click', async ({ page }) => { + await page.goto('http://localhost:5000/accountSuccess/'); + + const shopButton = page.locator('.ActionCard-module--actionName--fe65b:has-text("Shop")'); + await shopButton.click(); + + await expect(page).toHaveURL('http://localhost:5000/shop/'); +}); \ No newline at end of file From bf6ec41d5d71c171cb8a3ecf7895bb345d6e36d0 Mon Sep 17 00:00:00 2001 From: shray sharma Date: Thu, 18 Jul 2024 13:17:41 -0400 Subject: [PATCH 18/19] Cart menu tests actions --- tests/tests/actions.spec.ts | 102 ++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 tests/tests/actions.spec.ts diff --git a/tests/tests/actions.spec.ts b/tests/tests/actions.spec.ts new file mode 100644 index 0000000..77fe42a --- /dev/null +++ b/tests/tests/actions.spec.ts @@ -0,0 +1,102 @@ +import { test, expect } from '@playwright/test'; + +test('Header cart button open menu', async ({ page }) => { + await page.goto('http://localhost:5000'); + + const cartButton = await page.locator('button[aria-label="Cart"]'); + + // cart button exists + await expect(cartButton).toBeVisible(); + + await cartButton.click(); + + const miniCartPanel = page.locator('.MiniCart-module--root--1956d'); + + await expect(miniCartPanel).toBeVisible(); + + const quantityInput = page.locator('.AdjustItem-module--inputContainer--9d8ec input'); + + // Check the initial value + await expect(quantityInput).toHaveValue('1'); + + // Locate the increment and decrement buttons + const incrementButton = page.locator('.AdjustItem-module--iconContainer--a2f36').nth(1); + const decrementButton = page.locator('.AdjustItem-module--iconContainer--a2f36').nth(0); + + // Click the increment button + await incrementButton.click(); + await expect(quantityInput).toHaveValue('2'); + + // Click the decrement button + await decrementButton.click(); + await expect(quantityInput).toHaveValue('1'); + + + const checkoutButton = page.locator('button').filter({ hasText: 'checkout' }) + + await expect(checkoutButton).toBeVisible(); + + // Click the checkout button + await checkoutButton.click(); + + await page.waitForNavigation(); + + // Verify that the page URL has changed + await expect(page).toHaveURL('http://localhost:5000/cart/'); +}); + +test('Check click edit button actions', async ({ page }) => { + await page.goto('http://localhost:5000/cart/'); + + const editButton = page.locator('div').filter({ hasText: /^Edit$/ }).first() + + // edit button is visible + await expect(editButton).toBeVisible(); + + await editButton.click(); + + await page.waitForSelector('.QuickView-module--root--41109'); + + // Verify the content within the Quick View panel + const quickViewPanel = page.getByText('Select OptionsLambswool Crew').first() + + // Quick View panel is visible + await expect(quickViewPanel).toBeVisible(); + + const titleElement = await quickViewPanel.locator('h4'); + const titleText = await titleElement.innerText(); + expect(titleText).toContain('Select Options'); + + // product name inside the Quick View panel + const productNameElement = await quickViewPanel.locator('.QuickView-module--productName--d8aac'); + const productNameText = await productNameElement.innerText(); + expect(productNameText).toContain('Lambswool Crew Neck Jumper'); + + //price inside the Quick View panel + const priceElement = await quickViewPanel.locator('.QuickView-module--price--6d140'); + const priceText = await priceElement.innerText(); + expect(priceText).toContain('$75'); +}); + + +test('Check button for change colors', async ({ page }) => { + await page.goto('http://localhost:5000/cart/'); + + const editButton = page.locator('div').filter({ hasText: /^Edit$/ }).first() + + await expect(editButton).toBeVisible(); + + await editButton.click(); + const colorButton = await page.locator('button:nth-child(2)').first() + await colorButton.click(); + + // Wait for the color title to update + await page.waitForSelector('.SwatchList-module--label--b12be'); + + // Verify the updated color title + const colorTitleElement = await page.getByText('Select Colour: Pale Purple') + + const colorTitleText = await colorTitleElement.innerText(); + + expect(colorTitleText).toContain('Pale Purple'); +}); \ No newline at end of file From f2559e6454e920bec0e26a4a16b99ecc2d0ca9a8 Mon Sep 17 00:00:00 2001 From: shray sharma Date: Fri, 19 Jul 2024 12:37:18 -0400 Subject: [PATCH 19/19] actions tests2 --- tests/tests/actions.spec.ts | 123 ++++++++++++++++++++++++++++++++---- 1 file changed, 110 insertions(+), 13 deletions(-) diff --git a/tests/tests/actions.spec.ts b/tests/tests/actions.spec.ts index 77fe42a..3356423 100644 --- a/tests/tests/actions.spec.ts +++ b/tests/tests/actions.spec.ts @@ -7,7 +7,7 @@ test('Header cart button open menu', async ({ page }) => { // cart button exists await expect(cartButton).toBeVisible(); - + await cartButton.click(); const miniCartPanel = page.locator('.MiniCart-module--root--1956d'); @@ -18,15 +18,15 @@ test('Header cart button open menu', async ({ page }) => { // Check the initial value await expect(quantityInput).toHaveValue('1'); - + // Locate the increment and decrement buttons const incrementButton = page.locator('.AdjustItem-module--iconContainer--a2f36').nth(1); const decrementButton = page.locator('.AdjustItem-module--iconContainer--a2f36').nth(0); - + // Click the increment button await incrementButton.click(); await expect(quantityInput).toHaveValue('2'); - + // Click the decrement button await decrementButton.click(); await expect(quantityInput).toHaveValue('1'); @@ -35,12 +35,12 @@ test('Header cart button open menu', async ({ page }) => { const checkoutButton = page.locator('button').filter({ hasText: 'checkout' }) await expect(checkoutButton).toBeVisible(); - + // Click the checkout button await checkoutButton.click(); - + await page.waitForNavigation(); - + // Verify that the page URL has changed await expect(page).toHaveURL('http://localhost:5000/cart/'); }); @@ -52,9 +52,9 @@ test('Check click edit button actions', async ({ page }) => { // edit button is visible await expect(editButton).toBeVisible(); - + await editButton.click(); - + await page.waitForSelector('.QuickView-module--root--41109'); // Verify the content within the Quick View panel @@ -62,7 +62,7 @@ test('Check click edit button actions', async ({ page }) => { // Quick View panel is visible await expect(quickViewPanel).toBeVisible(); - + const titleElement = await quickViewPanel.locator('h4'); const titleText = await titleElement.innerText(); expect(titleText).toContain('Select Options'); @@ -85,7 +85,7 @@ test('Check button for change colors', async ({ page }) => { const editButton = page.locator('div').filter({ hasText: /^Edit$/ }).first() await expect(editButton).toBeVisible(); - + await editButton.click(); const colorButton = await page.locator('button:nth-child(2)').first() await colorButton.click(); @@ -97,6 +97,103 @@ test('Check button for change colors', async ({ page }) => { const colorTitleElement = await page.getByText('Select Colour: Pale Purple') const colorTitleText = await colorTitleElement.innerText(); - + expect(colorTitleText).toContain('Pale Purple'); -}); \ No newline at end of file +}); + + +test('Check navigation links and breadcrumbs existence', async ({ page }) => { + await page.goto('http://localhost:5000/account/orders/'); + + await expect(page.locator('a.AccountNav-module--webLink--22ce5[href="/account/orders/"]')).toBeVisible(); + await expect(page.locator('a.AccountNav-module--webLink--22ce5[href="/account/address/"]')).toBeVisible(); + await expect(page.locator('a.AccountNav-module--webLink--22ce5[href="/account/settings/"]')).toBeVisible(); + await expect(page.locator('a.AccountNav-module--webLink--22ce5[href="/account/viewed/"]')).toBeVisible(); + await expect(page.locator('span.AccountNav-module--webLink--22ce5:has-text("Logout")')).toBeVisible(); + + await expect(page.locator('div[data-breadcrumbs="true"]')).toBeVisible(); +}); + + +test('check that Filters panel is visible and contains expected elements', async ({ page }) => { + await page.goto('http://localhost:5000/shop/'); + + // Click the button to open the Filters panel + const filtersButton = page.locator('div').filter({ hasText: /^Filters$/ }); + await expect(filtersButton).toBeVisible(); + await filtersButton.click(); + + // Filters panel is visible + const filterPanel = page.locator('div.CardController-module--filterContainer--601b9'); + await expect(filterPanel).toBeVisible(); + + // Verify the presence of categories and checkboxes within the Filters panel + + // Check 'colour' category + await expect(filterPanel.getByText('colour').first()).toBeVisible(); + await expect(filterPanel.locator('input#Black')).toBeVisible(); + await expect(filterPanel.locator('input#Green')).toBeVisible(); + await expect(filterPanel.locator('input#Blue')).toBeVisible(); + await expect(filterPanel.locator('input#Grey')).toBeVisible(); + await expect(filterPanel.locator('input#Red')).toBeVisible(); + + // Check 'size' category + await expect(filterPanel.getByText('size', { exact: true }).first()).toBeVisible(); + await expect(filterPanel.locator('input#XXS')).toBeVisible(); + await expect(filterPanel.locator('input#XS')).toBeVisible(); + await expect(filterPanel.locator('input#S')).toBeVisible(); + await expect(filterPanel.locator('input#M')).toBeVisible(); + await expect(filterPanel.locator('input#L')).toBeVisible(); + await expect(filterPanel.locator('input#XL')).toBeVisible(); + await expect(filterPanel.locator('input#XXL')).toBeVisible(); + await expect(filterPanel.locator('input#Onesize')).toBeVisible(); + + // Check 'gender' category + await expect(filterPanel.getByText('gender').first()).toBeVisible(); + await expect(filterPanel.locator('input#Male')).toBeVisible(); + await expect(filterPanel.locator('input#Female')).toBeVisible(); + await expect(filterPanel.locator('input#Unisex')).toBeVisible(); + }); + + + test('click accordion button and check visibility of content', async ({ page }) => { + await page.goto('http://localhost:5000/product/sample/'); + + const accordionButton = page.locator('div').filter({ hasText: /^composition & care$/ }); + await expect(accordionButton).toBeVisible(); + + await accordionButton.click(); + + + const accordionContent = page.locator('div.Accordion-module--accordionContent--d4d65.Accordion-module--show--96114'); + await expect(accordionContent).toBeVisible(); + + await expect(accordionContent.locator('p.sample-module--information--29ab5')).toHaveText('This soft lambswool jumper is knitted in Scotland, using yarn from one of the world\'s oldest spinners based in Fife. Once knitted, the garment is washed in Scottish spring water to make it beautifully soft.'); + }); + + + test('check accordion section for "delivery & returns"', async ({ page }) => { + await page.goto('http://localhost:5000/product/sample/'); + + const accordionHeader = page.locator('div.Accordion-module--accordionHeader--fb950 >> text=delivery & returns'); + await expect(accordionHeader).toBeVisible(); + await accordionHeader.click(); + + const accordionContent = page.locator('div.Accordion-module--accordionContent--d4d65.Accordion-module--show--96114'); + await expect(accordionContent).toBeVisible(); + + await expect(accordionContent.locator('p.sample-module--information--29ab5')).toHaveText('This soft lambswool jumper is knitted in Scotland, using yarn from one of the world\'s oldest spinners based in Fife. Once knitted, the garment is washed in Scottish spring water to make it beautifully soft.'); + }); + + test('check accordion section for "help"', async ({ page }) => { + await page.goto('http://localhost:5000/product/sample/'); + + const accordionHeader = page.locator('div.Accordion-module--accordionHeader--fb950 >> text=help'); + await expect(accordionHeader).toBeVisible(); + await accordionHeader.click(); + + const accordionContent = page.locator('div.Accordion-module--accordionContent--d4d65.Accordion-module--show--96114'); + await expect(accordionContent).toBeVisible(); + + await expect(accordionContent.locator('p.sample-module--information--29ab5')).toHaveText('This soft lambswool jumper is knitted in Scotland, using yarn from one of the world\'s oldest spinners based in Fife. Once knitted, the garment is washed in Scottish spring water to make it beautifully soft.'); + }); \ No newline at end of file