├── .gitignore ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── pages └── home.page.js ├── playwright.config.js ├── tests-examples └── demo-todo-app.spec.js └── tests ├── cart └── addItemToCart.spec.js ├── compareProducts ├── expertCompare.spec.js ├── interceptAddToCompare.spec.js └── simpleCompare.spec.js ├── gearSection └── heroArea2.spec.js ├── homePage ├── HotSellersSection.spec.js ├── headerPart1.spec.js ├── homePageHeader.spec.js └── homePageHeader2.spec.js ├── initialSetupTests ├── Alex.spec.js ├── Claudiu.spec.js ├── Mirel.spec.js └── Radu.spec.js └── search └── search.spec.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | /test-results/ 3 | /playwright-report/ 4 | /blob-report/ 5 | /playwright/.cache/ 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Adrian Maciuc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Break IT - a playwright with javascript project 2 | 3 | ## Table of Contents 4 | - [Introduction](#introduction) 5 | - [Contributors](#contributors) 6 | - [Project Description](#project-description) 7 | - [Playwright and JavaScript](#playwright-and-javascript) 8 | - [Page Object Model Pattern](#page-object-model-pattern) 9 | - [GitHub Actions](#github-actions) 10 | 11 | ## Introduction 12 | This is a project created by the members of Bug Hunter discord server. 13 | We estimate that our project will be done in about 2-3 months. 14 | 15 | ## Contributors 16 | - [Alex Stefan](https://github.com/AlexStefan17) 17 | - [Levi - Simon Levente-Attila](https://github.com/simonleventeattila) 18 | - [Radu Moldovan](https://github.com/RaduMoldovan30) 19 | - [Adrian Maciuc](https://github.com/adrianmaciuc) 20 | - [Dan Popescu](https://github.com/PopDan23) 21 | - [Claudiu Iacob](https://github.com/iclaudiu98) 22 | - [Adrian Ciuciui](https://github.com/AdrianCiuciui) 23 | - [Mirel Palii](https://github.com/pmirel) 24 | 25 | ## Project Description 26 | The purpose of this project is to polish our quality assurance automation skills on [Playwright](https://playwright.dev/) and Javascript, as well as understanding and following best practices in workflows and coding. 27 | 28 | ## Playwright and JavaScript 29 | This project utilizes [Playwright](https://playwright.dev/), a tool for automating browsers, written in JavaScript. It allows us to perform end-to-end testing, mimicking user interactions and validating the behavior of web applications. 30 | 31 | ## Page Object Model Pattern 32 | We follow the Page Object Model [(POM)](https://playwright.dev/docs/pom) pattern to maintain our tests. POM helps in creating an abstraction of the UI elements, making tests more maintainable and reducing duplication by separating page-specific locators and actions into reusable modules. 33 | 34 | ## GitHub Actions 35 | This project uses GitHub Actions for continuous integration. Tests are automatically run using GitHub Actions upon each push or pull request. The configuration for running Playwright tests in GitHub Actions can be found in the `.github/workflows` directory. 36 | 37 | ## Application Under Test 38 | https://magento.softwaretestingboard.com/ 39 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "break-it-playwright-javascript-project", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "break-it-playwright-javascript-project", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "@playwright/test": "^1.40.0", 13 | "@types/node": "^20.9.3" 14 | } 15 | }, 16 | "node_modules/@playwright/test": { 17 | "version": "1.40.0", 18 | "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.40.0.tgz", 19 | "integrity": "sha512-PdW+kn4eV99iP5gxWNSDQCbhMaDVej+RXL5xr6t04nbKLCBwYtA046t7ofoczHOm8u6c+45hpDKQVZqtqwkeQg==", 20 | "dev": true, 21 | "dependencies": { 22 | "playwright": "1.40.0" 23 | }, 24 | "bin": { 25 | "playwright": "cli.js" 26 | }, 27 | "engines": { 28 | "node": ">=16" 29 | } 30 | }, 31 | "node_modules/@types/node": { 32 | "version": "20.9.3", 33 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.3.tgz", 34 | "integrity": "sha512-nk5wXLAXGBKfrhLB0cyHGbSqopS+nz0BUgZkUQqSHSSgdee0kssp1IAqlQOu333bW+gMNs2QREx7iynm19Abxw==", 35 | "dev": true, 36 | "dependencies": { 37 | "undici-types": "~5.26.4" 38 | } 39 | }, 40 | "node_modules/fsevents": { 41 | "version": "2.3.2", 42 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 43 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 44 | "dev": true, 45 | "hasInstallScript": true, 46 | "optional": true, 47 | "os": [ 48 | "darwin" 49 | ], 50 | "engines": { 51 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 52 | } 53 | }, 54 | "node_modules/playwright": { 55 | "version": "1.40.0", 56 | "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.40.0.tgz", 57 | "integrity": "sha512-gyHAgQjiDf1m34Xpwzaqb76KgfzYrhK7iih+2IzcOCoZWr/8ZqmdBw+t0RU85ZmfJMgtgAiNtBQ/KS2325INXw==", 58 | "dev": true, 59 | "dependencies": { 60 | "playwright-core": "1.40.0" 61 | }, 62 | "bin": { 63 | "playwright": "cli.js" 64 | }, 65 | "engines": { 66 | "node": ">=16" 67 | }, 68 | "optionalDependencies": { 69 | "fsevents": "2.3.2" 70 | } 71 | }, 72 | "node_modules/playwright-core": { 73 | "version": "1.40.0", 74 | "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.40.0.tgz", 75 | "integrity": "sha512-fvKewVJpGeca8t0ipM56jkVSU6Eo0RmFvQ/MaCQNDYm+sdvKkMBBWTE1FdeMqIdumRaXXjZChWHvIzCGM/tA/Q==", 76 | "dev": true, 77 | "bin": { 78 | "playwright-core": "cli.js" 79 | }, 80 | "engines": { 81 | "node": ">=16" 82 | } 83 | }, 84 | "node_modules/undici-types": { 85 | "version": "5.26.5", 86 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", 87 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", 88 | "dev": true 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "break-it-playwright-javascript-project", 3 | "version": "1.0.0", 4 | "description": "- [Introduction](#introduction)\r - [Contributors](#contributors)\r - [Project Description](#project-description)\r - [Playwright and JavaScript](#playwright-and-javascript)\r - [Page Object Model Pattern](#page-object-model-pattern)\r - [GitHub Actions](#github-actions)", 5 | "main": "index.js", 6 | "scripts": {}, 7 | "keywords": [], 8 | "author": "", 9 | "license": "ISC", 10 | "devDependencies": { 11 | "@playwright/test": "^1.40.0", 12 | "@types/node": "^20.9.3" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /pages/home.page.js: -------------------------------------------------------------------------------- 1 | export class HomePage { 2 | 3 | constructor(page) { 4 | this.page = page; 5 | this.homePageUrl = 'https://magento.softwaretestingboard.com/'; 6 | } 7 | 8 | // locators 9 | whatIsNewBTN = () => this.page.locator("#ui-id-3") 10 | 11 | async navigateToHomePage() { 12 | await this.page.goto(this.homePageUrl); 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /playwright.config.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | const { defineConfig, devices } = require("@playwright/test"); 3 | 4 | /** 5 | * @see https://playwright.dev/docs/test-configuration 6 | */ 7 | module.exports = defineConfig({ 8 | testDir: "./tests", 9 | /* Run tests in files in parallel */ 10 | fullyParallel: true, 11 | /* Fail the build on CI if you accidentally left test.only in the source code. */ 12 | forbidOnly: !!process.env.CI, 13 | /* Retry on CI only */ 14 | retries: process.env.CI ? 2 : 0, 15 | /* Opt out of parallel tests on CI. */ 16 | workers: process.env.CI ? 1 : undefined, 17 | /* Reporter to use. See https://playwright.dev/docs/test-reporters */ 18 | reporter: "html", 19 | /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ 20 | use: { 21 | /* Base URL to use in actions like `await page.goto('/')`. */ 22 | // baseURL: 'http://127.0.0.1:3000', 23 | 24 | /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ 25 | trace: "on-first-retry", 26 | testIdAttribute: "id", 27 | }, 28 | 29 | /* Configure projects for major browsers */ 30 | projects: [ 31 | { 32 | name: "chromium", 33 | use: { ...devices["Desktop Chrome"] }, 34 | }, 35 | ], 36 | }); 37 | -------------------------------------------------------------------------------- /tests-examples/demo-todo-app.spec.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | const { test, expect } = require('@playwright/test'); 3 | 4 | test.beforeEach(async ({ page }) => { 5 | await page.goto('https://demo.playwright.dev/todomvc'); 6 | }); 7 | 8 | const TODO_ITEMS = [ 9 | 'buy some cheese', 10 | 'feed the cat', 11 | 'book a doctors appointment' 12 | ]; 13 | 14 | test.describe('New Todo', () => { 15 | test('should allow me to add todo items', async ({ page }) => { 16 | // create a new todo locator 17 | const newTodo = page.getByPlaceholder('What needs to be done?'); 18 | 19 | // Create 1st todo. 20 | await newTodo.fill(TODO_ITEMS[0]); 21 | await newTodo.press('Enter'); 22 | 23 | // Make sure the list only has one todo item. 24 | await expect(page.getByTestId('todo-title')).toHaveText([ 25 | TODO_ITEMS[0] 26 | ]); 27 | 28 | // Create 2nd todo. 29 | await newTodo.fill(TODO_ITEMS[1]); 30 | await newTodo.press('Enter'); 31 | 32 | // Make sure the list now has two todo items. 33 | await expect(page.getByTestId('todo-title')).toHaveText([ 34 | TODO_ITEMS[0], 35 | TODO_ITEMS[1] 36 | ]); 37 | 38 | await checkNumberOfTodosInLocalStorage(page, 2); 39 | }); 40 | 41 | test('should clear text input field when an item is added', async ({ page }) => { 42 | // create a new todo locator 43 | const newTodo = page.getByPlaceholder('What needs to be done?'); 44 | 45 | // Create one todo item. 46 | await newTodo.fill(TODO_ITEMS[0]); 47 | await newTodo.press('Enter'); 48 | 49 | // Check that input is empty. 50 | await expect(newTodo).toBeEmpty(); 51 | await checkNumberOfTodosInLocalStorage(page, 1); 52 | }); 53 | 54 | test('should append new items to the bottom of the list', async ({ page }) => { 55 | // Create 3 items. 56 | await createDefaultTodos(page); 57 | 58 | // create a todo count locator 59 | const todoCount = page.getByTestId('todo-count') 60 | 61 | // Check test using different methods. 62 | await expect(page.getByText('3 items left')).toBeVisible(); 63 | await expect(todoCount).toHaveText('3 items left'); 64 | await expect(todoCount).toContainText('3'); 65 | await expect(todoCount).toHaveText(/3/); 66 | 67 | // Check all items in one call. 68 | await expect(page.getByTestId('todo-title')).toHaveText(TODO_ITEMS); 69 | await checkNumberOfTodosInLocalStorage(page, 3); 70 | }); 71 | }); 72 | 73 | test.describe('Mark all as completed', () => { 74 | test.beforeEach(async ({ page }) => { 75 | await createDefaultTodos(page); 76 | await checkNumberOfTodosInLocalStorage(page, 3); 77 | }); 78 | 79 | test.afterEach(async ({ page }) => { 80 | await checkNumberOfTodosInLocalStorage(page, 3); 81 | }); 82 | 83 | test('should allow me to mark all items as completed', async ({ page }) => { 84 | // Complete all todos. 85 | await page.getByLabel('Mark all as complete').check(); 86 | 87 | // Ensure all todos have 'completed' class. 88 | await expect(page.getByTestId('todo-item')).toHaveClass(['completed', 'completed', 'completed']); 89 | await checkNumberOfCompletedTodosInLocalStorage(page, 3); 90 | }); 91 | 92 | test('should allow me to clear the complete state of all items', async ({ page }) => { 93 | const toggleAll = page.getByLabel('Mark all as complete'); 94 | // Check and then immediately uncheck. 95 | await toggleAll.check(); 96 | await toggleAll.uncheck(); 97 | 98 | // Should be no completed classes. 99 | await expect(page.getByTestId('todo-item')).toHaveClass(['', '', '']); 100 | }); 101 | 102 | test('complete all checkbox should update state when items are completed / cleared', async ({ page }) => { 103 | const toggleAll = page.getByLabel('Mark all as complete'); 104 | await toggleAll.check(); 105 | await expect(toggleAll).toBeChecked(); 106 | await checkNumberOfCompletedTodosInLocalStorage(page, 3); 107 | 108 | // Uncheck first todo. 109 | const firstTodo = page.getByTestId('todo-item').nth(0); 110 | await firstTodo.getByRole('checkbox').uncheck(); 111 | 112 | // Reuse toggleAll locator and make sure its not checked. 113 | await expect(toggleAll).not.toBeChecked(); 114 | 115 | await firstTodo.getByRole('checkbox').check(); 116 | await checkNumberOfCompletedTodosInLocalStorage(page, 3); 117 | 118 | // Assert the toggle all is checked again. 119 | await expect(toggleAll).toBeChecked(); 120 | }); 121 | }); 122 | 123 | test.describe('Item', () => { 124 | 125 | test('should allow me to mark items as complete', async ({ page }) => { 126 | // create a new todo locator 127 | const newTodo = page.getByPlaceholder('What needs to be done?'); 128 | 129 | // Create two items. 130 | for (const item of TODO_ITEMS.slice(0, 2)) { 131 | await newTodo.fill(item); 132 | await newTodo.press('Enter'); 133 | } 134 | 135 | // Check first item. 136 | const firstTodo = page.getByTestId('todo-item').nth(0); 137 | await firstTodo.getByRole('checkbox').check(); 138 | await expect(firstTodo).toHaveClass('completed'); 139 | 140 | // Check second item. 141 | const secondTodo = page.getByTestId('todo-item').nth(1); 142 | await expect(secondTodo).not.toHaveClass('completed'); 143 | await secondTodo.getByRole('checkbox').check(); 144 | 145 | // Assert completed class. 146 | await expect(firstTodo).toHaveClass('completed'); 147 | await expect(secondTodo).toHaveClass('completed'); 148 | }); 149 | 150 | test('should allow me to un-mark items as complete', async ({ page }) => { 151 | // create a new todo locator 152 | const newTodo = page.getByPlaceholder('What needs to be done?'); 153 | 154 | // Create two items. 155 | for (const item of TODO_ITEMS.slice(0, 2)) { 156 | await newTodo.fill(item); 157 | await newTodo.press('Enter'); 158 | } 159 | 160 | const firstTodo = page.getByTestId('todo-item').nth(0); 161 | const secondTodo = page.getByTestId('todo-item').nth(1); 162 | const firstTodoCheckbox = firstTodo.getByRole('checkbox'); 163 | 164 | await firstTodoCheckbox.check(); 165 | await expect(firstTodo).toHaveClass('completed'); 166 | await expect(secondTodo).not.toHaveClass('completed'); 167 | await checkNumberOfCompletedTodosInLocalStorage(page, 1); 168 | 169 | await firstTodoCheckbox.uncheck(); 170 | await expect(firstTodo).not.toHaveClass('completed'); 171 | await expect(secondTodo).not.toHaveClass('completed'); 172 | await checkNumberOfCompletedTodosInLocalStorage(page, 0); 173 | }); 174 | 175 | test('should allow me to edit an item', async ({ page }) => { 176 | await createDefaultTodos(page); 177 | 178 | const todoItems = page.getByTestId('todo-item'); 179 | const secondTodo = todoItems.nth(1); 180 | await secondTodo.dblclick(); 181 | await expect(secondTodo.getByRole('textbox', { name: 'Edit' })).toHaveValue(TODO_ITEMS[1]); 182 | await secondTodo.getByRole('textbox', { name: 'Edit' }).fill('buy some sausages'); 183 | await secondTodo.getByRole('textbox', { name: 'Edit' }).press('Enter'); 184 | 185 | // Explicitly assert the new text value. 186 | await expect(todoItems).toHaveText([ 187 | TODO_ITEMS[0], 188 | 'buy some sausages', 189 | TODO_ITEMS[2] 190 | ]); 191 | await checkTodosInLocalStorage(page, 'buy some sausages'); 192 | }); 193 | }); 194 | 195 | test.describe('Editing', () => { 196 | test.beforeEach(async ({ page }) => { 197 | await createDefaultTodos(page); 198 | await checkNumberOfTodosInLocalStorage(page, 3); 199 | }); 200 | 201 | test('should hide other controls when editing', async ({ page }) => { 202 | const todoItem = page.getByTestId('todo-item').nth(1); 203 | await todoItem.dblclick(); 204 | await expect(todoItem.getByRole('checkbox')).not.toBeVisible(); 205 | await expect(todoItem.locator('label', { 206 | hasText: TODO_ITEMS[1], 207 | })).not.toBeVisible(); 208 | await checkNumberOfTodosInLocalStorage(page, 3); 209 | }); 210 | 211 | test('should save edits on blur', async ({ page }) => { 212 | const todoItems = page.getByTestId('todo-item'); 213 | await todoItems.nth(1).dblclick(); 214 | await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill('buy some sausages'); 215 | await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).dispatchEvent('blur'); 216 | 217 | await expect(todoItems).toHaveText([ 218 | TODO_ITEMS[0], 219 | 'buy some sausages', 220 | TODO_ITEMS[2], 221 | ]); 222 | await checkTodosInLocalStorage(page, 'buy some sausages'); 223 | }); 224 | 225 | test('should trim entered text', async ({ page }) => { 226 | const todoItems = page.getByTestId('todo-item'); 227 | await todoItems.nth(1).dblclick(); 228 | await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill(' buy some sausages '); 229 | await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Enter'); 230 | 231 | await expect(todoItems).toHaveText([ 232 | TODO_ITEMS[0], 233 | 'buy some sausages', 234 | TODO_ITEMS[2], 235 | ]); 236 | await checkTodosInLocalStorage(page, 'buy some sausages'); 237 | }); 238 | 239 | test('should remove the item if an empty text string was entered', async ({ page }) => { 240 | const todoItems = page.getByTestId('todo-item'); 241 | await todoItems.nth(1).dblclick(); 242 | await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill(''); 243 | await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Enter'); 244 | 245 | await expect(todoItems).toHaveText([ 246 | TODO_ITEMS[0], 247 | TODO_ITEMS[2], 248 | ]); 249 | }); 250 | 251 | test('should cancel edits on escape', async ({ page }) => { 252 | const todoItems = page.getByTestId('todo-item'); 253 | await todoItems.nth(1).dblclick(); 254 | await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill('buy some sausages'); 255 | await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Escape'); 256 | await expect(todoItems).toHaveText(TODO_ITEMS); 257 | }); 258 | }); 259 | 260 | test.describe('Counter', () => { 261 | test('should display the current number of todo items', async ({ page }) => { 262 | // create a new todo locator 263 | const newTodo = page.getByPlaceholder('What needs to be done?'); 264 | 265 | // create a todo count locator 266 | const todoCount = page.getByTestId('todo-count') 267 | 268 | await newTodo.fill(TODO_ITEMS[0]); 269 | await newTodo.press('Enter'); 270 | await expect(todoCount).toContainText('1'); 271 | 272 | await newTodo.fill(TODO_ITEMS[1]); 273 | await newTodo.press('Enter'); 274 | await expect(todoCount).toContainText('2'); 275 | 276 | await checkNumberOfTodosInLocalStorage(page, 2); 277 | }); 278 | }); 279 | 280 | test.describe('Clear completed button', () => { 281 | test.beforeEach(async ({ page }) => { 282 | await createDefaultTodos(page); 283 | }); 284 | 285 | test('should display the correct text', async ({ page }) => { 286 | await page.locator('.todo-list li .toggle').first().check(); 287 | await expect(page.getByRole('button', { name: 'Clear completed' })).toBeVisible(); 288 | }); 289 | 290 | test('should remove completed items when clicked', async ({ page }) => { 291 | const todoItems = page.getByTestId('todo-item'); 292 | await todoItems.nth(1).getByRole('checkbox').check(); 293 | await page.getByRole('button', { name: 'Clear completed' }).click(); 294 | await expect(todoItems).toHaveCount(2); 295 | await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); 296 | }); 297 | 298 | test('should be hidden when there are no items that are completed', async ({ page }) => { 299 | await page.locator('.todo-list li .toggle').first().check(); 300 | await page.getByRole('button', { name: 'Clear completed' }).click(); 301 | await expect(page.getByRole('button', { name: 'Clear completed' })).toBeHidden(); 302 | }); 303 | }); 304 | 305 | test.describe('Persistence', () => { 306 | test('should persist its data', async ({ page }) => { 307 | // create a new todo locator 308 | const newTodo = page.getByPlaceholder('What needs to be done?'); 309 | 310 | for (const item of TODO_ITEMS.slice(0, 2)) { 311 | await newTodo.fill(item); 312 | await newTodo.press('Enter'); 313 | } 314 | 315 | const todoItems = page.getByTestId('todo-item'); 316 | const firstTodoCheck = todoItems.nth(0).getByRole('checkbox'); 317 | await firstTodoCheck.check(); 318 | await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); 319 | await expect(firstTodoCheck).toBeChecked(); 320 | await expect(todoItems).toHaveClass(['completed', '']); 321 | 322 | // Ensure there is 1 completed item. 323 | await checkNumberOfCompletedTodosInLocalStorage(page, 1); 324 | 325 | // Now reload. 326 | await page.reload(); 327 | await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); 328 | await expect(firstTodoCheck).toBeChecked(); 329 | await expect(todoItems).toHaveClass(['completed', '']); 330 | }); 331 | }); 332 | 333 | test.describe('Routing', () => { 334 | test.beforeEach(async ({ page }) => { 335 | await createDefaultTodos(page); 336 | // make sure the app had a chance to save updated todos in storage 337 | // before navigating to a new view, otherwise the items can get lost :( 338 | // in some frameworks like Durandal 339 | await checkTodosInLocalStorage(page, TODO_ITEMS[0]); 340 | }); 341 | 342 | test('should allow me to display active items', async ({ page }) => { 343 | const todoItem = page.getByTestId('todo-item'); 344 | await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); 345 | 346 | await checkNumberOfCompletedTodosInLocalStorage(page, 1); 347 | await page.getByRole('link', { name: 'Active' }).click(); 348 | await expect(todoItem).toHaveCount(2); 349 | await expect(todoItem).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); 350 | }); 351 | 352 | test('should respect the back button', async ({ page }) => { 353 | const todoItem = page.getByTestId('todo-item'); 354 | await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); 355 | 356 | await checkNumberOfCompletedTodosInLocalStorage(page, 1); 357 | 358 | await test.step('Showing all items', async () => { 359 | await page.getByRole('link', { name: 'All' }).click(); 360 | await expect(todoItem).toHaveCount(3); 361 | }); 362 | 363 | await test.step('Showing active items', async () => { 364 | await page.getByRole('link', { name: 'Active' }).click(); 365 | }); 366 | 367 | await test.step('Showing completed items', async () => { 368 | await page.getByRole('link', { name: 'Completed' }).click(); 369 | }); 370 | 371 | await expect(todoItem).toHaveCount(1); 372 | await page.goBack(); 373 | await expect(todoItem).toHaveCount(2); 374 | await page.goBack(); 375 | await expect(todoItem).toHaveCount(3); 376 | }); 377 | 378 | test('should allow me to display completed items', async ({ page }) => { 379 | await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); 380 | await checkNumberOfCompletedTodosInLocalStorage(page, 1); 381 | await page.getByRole('link', { name: 'Completed' }).click(); 382 | await expect(page.getByTestId('todo-item')).toHaveCount(1); 383 | }); 384 | 385 | test('should allow me to display all items', async ({ page }) => { 386 | await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); 387 | await checkNumberOfCompletedTodosInLocalStorage(page, 1); 388 | await page.getByRole('link', { name: 'Active' }).click(); 389 | await page.getByRole('link', { name: 'Completed' }).click(); 390 | await page.getByRole('link', { name: 'All' }).click(); 391 | await expect(page.getByTestId('todo-item')).toHaveCount(3); 392 | }); 393 | 394 | test('should highlight the currently applied filter', async ({ page }) => { 395 | await expect(page.getByRole('link', { name: 'All' })).toHaveClass('selected'); 396 | 397 | //create locators for active and completed links 398 | const activeLink = page.getByRole('link', { name: 'Active' }); 399 | const completedLink = page.getByRole('link', { name: 'Completed' }); 400 | await activeLink.click(); 401 | 402 | // Page change - active items. 403 | await expect(activeLink).toHaveClass('selected'); 404 | await completedLink.click(); 405 | 406 | // Page change - completed items. 407 | await expect(completedLink).toHaveClass('selected'); 408 | }); 409 | }); 410 | 411 | async function createDefaultTodos(page) { 412 | // create a new todo locator 413 | const newTodo = page.getByPlaceholder('What needs to be done?'); 414 | 415 | for (const item of TODO_ITEMS) { 416 | await newTodo.fill(item); 417 | await newTodo.press('Enter'); 418 | } 419 | } 420 | 421 | /** 422 | * @param {import('@playwright/test').Page} page 423 | * @param {number} expected 424 | */ 425 | async function checkNumberOfTodosInLocalStorage(page, expected) { 426 | return await page.waitForFunction(e => { 427 | return JSON.parse(localStorage['react-todos']).length === e; 428 | }, expected); 429 | } 430 | 431 | /** 432 | * @param {import('@playwright/test').Page} page 433 | * @param {number} expected 434 | */ 435 | async function checkNumberOfCompletedTodosInLocalStorage(page, expected) { 436 | return await page.waitForFunction(e => { 437 | return JSON.parse(localStorage['react-todos']).filter(i => i.completed).length === e; 438 | }, expected); 439 | } 440 | 441 | /** 442 | * @param {import('@playwright/test').Page} page 443 | * @param {string} title 444 | */ 445 | async function checkTodosInLocalStorage(page, title) { 446 | return await page.waitForFunction(t => { 447 | return JSON.parse(localStorage['react-todos']).map(i => i.title).includes(t); 448 | }, title); 449 | } 450 | -------------------------------------------------------------------------------- /tests/cart/addItemToCart.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | const HomePageUrl = 'https://magento.softwaretestingboard.com/'; 3 | 4 | test('Add item to cart', async ({ page }) => { 5 | await page.goto(HomePageUrl); 6 | await page.waitForTimeout(1000); 7 | await page.getByTestId('ui-id-5').hover(); 8 | await page.getByTestId('ui-id-17').hover(); 9 | await page.getByTestId('ui-id-21').click(); 10 | 11 | await page.waitForTimeout(1000); 12 | await expect(page.url()).toEqual( 13 | 'https://magento.softwaretestingboard.com/men/tops-men/tees-men.html' 14 | ); 15 | 16 | await page.getByRole('tab', { name: 'Color' }).click(); 17 | await page.locator('#narrow-by-list [option-id="53"]').click(); 18 | await expect(page.locator('.product-item')).toHaveCount(4); 19 | await page 20 | .getByAltText('Atomic Endurance Running Tee (V-neck)-XS-Green') 21 | .click(); 22 | 23 | await expect(page.url()).toEqual( 24 | 'https://magento.softwaretestingboard.com/atomic-endurance-running-tee-v-neck.html' 25 | ); 26 | 27 | const selectOptionsForProduct = async (size, color, quantity) => { 28 | await page.getByLabel(size).click(); 29 | await page.getByLabel(color).click(); 30 | await page.getByTestId('qty').fill(quantity); 31 | }; 32 | 33 | await selectOptionsForProduct('XL', 'Green', '3'); 34 | await page.getByTitle('Add to Cart').click(); 35 | const response = await page.waitForResponse('**/customer/section/load/*'); 36 | const respBody = await response.json(); 37 | const productId = respBody.cart.items[0].product_id; 38 | 39 | await expect(productId).toEqual('494'); 40 | }); 41 | -------------------------------------------------------------------------------- /tests/compareProducts/expertCompare.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from "@playwright/test"; 2 | 3 | test("Expert compare", async ({ page }) => { 4 | const gearPage = "https://magento.softwaretestingboard.com/gear/watches.html"; 5 | const watches = ".product-item"; 6 | const addToCompareButton = "Add to Compare"; 7 | const name = ".product-item-name"; 8 | const addToCompareMessage = "Compare Products"; 9 | const compareMessage = ".message-success.success.message"; 10 | const price = ".price-box.price-final_price"; 11 | const id = "data-product-id"; 12 | 13 | await page.goto(gearPage); 14 | const allWatches = await page.locator(watches).all(); 15 | 16 | // Get random watch 17 | const randomWatchIndex = Math.floor(Math.random() * allWatches.length); 18 | const randomWatch = allWatches[randomWatchIndex]; 19 | await randomWatch.hover(); 20 | await page.waitForTimeout(1000); 21 | 22 | // Get watch name and id 23 | const watchName = await randomWatch.locator(name).innerText(); 24 | const watchPrice = await randomWatch.locator(price); 25 | const watchId = await watchPrice.getAttribute(id); 26 | 27 | await page.waitForTimeout(1000); 28 | await randomWatch.getByTitle(addToCompareButton).click(); 29 | 30 | // Intercept call 31 | const response = await page.waitForResponse("**/customer/section/load/*"); 32 | const responseBody = await response.json(); 33 | await expect(responseBody["compare-products"]["items"][0]["id"]).toBe( 34 | watchId 35 | ); 36 | 37 | // Check comparasion list message 38 | await expect(page.getByTitle(addToCompareMessage)).toBeVisible(); 39 | const message = await page.locator(compareMessage).innerText(); 40 | await expect(message).toContain( 41 | `You added product ${watchName} to the comparison list.` 42 | ); 43 | }); 44 | -------------------------------------------------------------------------------- /tests/compareProducts/interceptAddToCompare.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from "@playwright/test"; 2 | 3 | test("intercept", async ({ page }) => { 4 | await page.goto("https://magento.softwaretestingboard.com/gear/watches.html"); 5 | 6 | await page.locator('[class="item product product-item"]').first().hover(); 7 | await page.waitForTimeout(1000); 8 | 9 | await page.getByTitle("Add to Compare").first().click(); 10 | const response = await page.waitForResponse("**/customer/section/load/*"); 11 | 12 | const responseAsObject = await response.json(); 13 | const ItemId = responseAsObject["compare-products"].items[0].id; 14 | await expect(ItemId).toBe("44"); 15 | 16 | await page.waitForSelector('[data-ui-id="message-success"]'); 17 | await expect(page.locator('[data-ui-id="message-success"]')).toContainText( 18 | "You added product Didi Sport Watch to the comparison list" 19 | ); 20 | }); 21 | -------------------------------------------------------------------------------- /tests/compareProducts/simpleCompare.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from "@playwright/test"; 2 | 3 | test("Simple Compare 2 items", async ({ page }) => { 4 | await page.goto("https://magento.softwaretestingboard.com/gear/bags.html"); 5 | 6 | // Function to randomly select a product and remove it from the list 7 | function selectRandomProduct(itemList) { 8 | const randomIndex = Math.floor(Math.random() * itemList.length); 9 | return itemList[randomIndex]; 10 | } 11 | 12 | // Function to hover over the product and click the compare button 13 | async function hoverAndCompare(product) { 14 | await product.hover(); 15 | await page.waitForTimeout(1500); 16 | await product.getByTitle("Add to Compare").click(); 17 | } 18 | 19 | const allProducts = await page.locator(".product-item").all(); 20 | 21 | // Select the first product to compare 22 | const selectedProduct1 = await selectRandomProduct(allProducts); 23 | const selectedProduct1Details = await selectedProduct1 24 | .locator(".product-item-name") 25 | .textContent(); 26 | await hoverAndCompare(selectedProduct1); 27 | 28 | // Select the second product to compare 29 | const selectedProduct2 = await selectRandomProduct(allProducts); 30 | const selectedProduct2Details = await selectedProduct2 31 | .locator(".product-item-name") 32 | .textContent(); 33 | await hoverAndCompare(selectedProduct2); 34 | 35 | // check if products are added to compare 36 | await expect(page.getByTitle("Compare Products")).toBeVisible(); 37 | await expect(page.getByTitle("Compare Products")).toContainText("2"); 38 | await page.getByTitle("Compare Products").click(); 39 | 40 | // verify that items in compare have the same details as initial selection 41 | const itemsInComparePage = await page 42 | .locator(".product-item-name") 43 | .allTextContents(); 44 | await expect(itemsInComparePage).toContain(selectedProduct1Details); 45 | await expect(itemsInComparePage).toContain(selectedProduct2Details); 46 | }); 47 | -------------------------------------------------------------------------------- /tests/gearSection/heroArea2.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from "@playwright/test"; 2 | 3 | test("Gear section hero images-1", async ({ page }) => { 4 | await page.goto("https://magento.softwaretestingboard.com/gear.html"); 5 | await page.locator(".block-promo.gear-category-equipment").click(); 6 | await expect(page.url()).toContain("/gear/fitness-equipment.htm"); 7 | }); 8 | 9 | test("Gear section hero images-2", async ({ page }) => { 10 | await page.goto("https://magento.softwaretestingboard.com/gear.html"); 11 | await page.locator(".block-promo.gear-category-watches").click(); 12 | await expect(page.locator(".base")).toHaveText("Watches"); 13 | }); 14 | -------------------------------------------------------------------------------- /tests/homePage/HotSellersSection.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from "@playwright/test"; 2 | 3 | test("Six items displayed at hot sellers", async ({ page }) => { 4 | await page.goto("https://magento.softwaretestingboard.com/"); 5 | const productItems = await page.$$(".product-item"); 6 | expect(productItems).toHaveLength(6); 7 | }); 8 | 9 | test("Item redirects correctly on home page", async ({ page }) => { 10 | await page.goto("https://magento.softwaretestingboard.com/"); 11 | 12 | const productItems = await page.$$(".product-item"); 13 | const priceItems = await page.locator(".price").allTextContents(); 14 | const nameItems = await page.locator(".product-item-link").allInnerTexts(); 15 | 16 | for (let item in productItems) { 17 | // Re-fetch the elements inside the loop to ensure they are still attached to the DOM 18 | const updatedProductItems = await page.$$(".product-item"); 19 | 20 | // Go to item`s page 21 | await updatedProductItems[item].click(); 22 | 23 | // Get the name of the item 24 | const nameItemsPage = await page.locator("span.base").innerText(); 25 | 26 | // Get the price of the item 27 | const priceItemPage = await page.locator(".product-info-main .price"); 28 | 29 | expect(nameItemsPage).toContain(nameItems[item]); 30 | expect(priceItemPage).toHaveText(priceItems[item]); 31 | 32 | await page.goto("https://magento.softwaretestingboard.com/"); 33 | } 34 | }); 35 | -------------------------------------------------------------------------------- /tests/homePage/headerPart1.spec.js: -------------------------------------------------------------------------------- 1 | //@ts-check 2 | const { test, expect } = require("@playwright/test"); 3 | 4 | test("Check redirect to what-is-new page", async ({ page }) => { 5 | await page.goto("https://magento.softwaretestingboard.com/"); 6 | await page.getByTestId("ui-id-3").click(); 7 | await expect(page).toHaveURL(/what-is-new/); 8 | }); 9 | 10 | test("Check redirect to women page", async ({ page }) => { 11 | await page.goto("https://magento.softwaretestingboard.com/"); 12 | await page.getByTestId("ui-id-4").click(); 13 | await expect(page).toHaveURL(/women/); 14 | }); 15 | test("Check redirect to men page", async ({ page }) => { 16 | await page.goto("https://magento.softwaretestingboard.com/"); 17 | await page.getByTestId("ui-id-5").click(); 18 | await expect(page).toHaveURL(/men/); 19 | }); 20 | 21 | test("Check redirect to gear page", async ({ page }) => { 22 | await page.goto("https://magento.softwaretestingboard.com/"); 23 | await page.getByTestId("ui-id-6").click(); 24 | await expect(page).toHaveURL(/gear/); 25 | }); 26 | 27 | test("Check redirect to training page", async ({ page }) => { 28 | await page.goto("https://magento.softwaretestingboard.com/"); 29 | await page.getByTestId("ui-id-7").click(); 30 | await expect(page).toHaveURL(/training/); 31 | }); 32 | 33 | test("Check redirect to sale page", async ({ page }) => { 34 | await page.goto("https://magento.softwaretestingboard.com/"); 35 | await page.getByTestId("ui-id-8").click(); 36 | await expect(page).toHaveURL(/sale/); 37 | }); 38 | -------------------------------------------------------------------------------- /tests/homePage/homePageHeader.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | import { HomePage } from '../../pages/home.page'; 3 | 4 | test("Test redirect to what is new page", async ({ page }) => { 5 | const homePage = new HomePage(page) 6 | await homePage.navigateToHomePage() 7 | await homePage.whatIsNewBTN().click() 8 | await expect(page.url()).toContain("/what-is-new"); 9 | }); 10 | 11 | test("Test redirect to women page", async ({ page }) => { 12 | await page.goto("https://magento.softwaretestingboard.com/"); 13 | await page.locator("#ui-id-4").click(); 14 | await expect(page.url()).toContain("/women"); 15 | }); 16 | 17 | test("Test redirect to Men page", async ({ page }) => { 18 | await page.goto("https://magento.softwaretestingboard.com/"); 19 | await page.locator("#ui-id-5").click(); 20 | await expect(page.url()).toContain("/men"); 21 | }); 22 | 23 | test("Test redirect to Gear page", async ({ page }) => { 24 | await page.goto("https://magento.softwaretestingboard.com/"); 25 | await page.locator("#ui-id-6").click(); 26 | await expect(page.url()).toContain("/gear"); 27 | }) 28 | 29 | test("Test redirect to Training page", async ({ page }) => { 30 | await page.goto("https://magento.softwaretestingboard.com/"); 31 | await page.locator("#ui-id-7").click(); 32 | await expect(page.url()).toContain("/training"); 33 | }) 34 | 35 | test("Test redirect to Sale page", async ({ page }) => { 36 | await page.goto("https://magento.softwaretestingboard.com/"); 37 | await page.locator("#ui-id-8").click(); 38 | await expect(page.url()).toContain("/sale"); 39 | }) -------------------------------------------------------------------------------- /tests/homePage/homePageHeader2.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | 3 | const HomePageUrl = 'https://magento.softwaretestingboard.com/'; 4 | 5 | test('Search suggestion in header', async ({ page }) => { 6 | await page.goto(HomePageUrl); 7 | await expect(page).toHaveTitle('Home Page'); 8 | 9 | await page.getByTestId('search').pressSequentially('jackets', { delay: 100 }); 10 | await page.waitForTimeout(1000); 11 | 12 | const parentLocator = page.getByTestId('search_autocomplete'); 13 | const childLocator = parentLocator.locator('[role="option"]'); 14 | 15 | const lenghtEl = await childLocator.count(); 16 | await expect(lenghtEl).toEqual(8); 17 | 18 | for (let i = 0; i < lenghtEl; i++) { 19 | await expect(childLocator.nth(i)).toContainText('jacket', { 20 | ignoreCase: true, 21 | }); 22 | } 23 | }); 24 | 25 | test('Logo click redirect home page', async ({ page }) => { 26 | await page.goto(HomePageUrl); 27 | await page.getByLabel('store logo').click(); 28 | expect(page.url()).toEqual(HomePageUrl); 29 | }); 30 | 31 | test('Click on cart is empty', async ({ page }) => { 32 | await page.goto(HomePageUrl); 33 | 34 | await page.waitForTimeout(1000); 35 | 36 | await page.locator('[data-block="minicart"] .action.showcart').click(); 37 | await expect(page.getByTestId('minicart-content-wrapper')).toContainText( 38 | 'You have no items in your shopping cart.' 39 | ); 40 | }); 41 | 42 | test('Search functionality with result', async ({ page }) => { 43 | await page.goto(HomePageUrl); 44 | await page.getByTestId('search').fill('jackets'); 45 | 46 | await page.keyboard.press('Enter'); 47 | const listItem = await page.locator('.product-item'); 48 | await expect(listItem).toHaveCount(1); 49 | 50 | const cardText = ( 51 | await page.locator('[class="product name product-item-name"]>a').innerText() 52 | ).trim(); 53 | 54 | await expect(cardText).toEqual('Jade Yoga Jacket'); 55 | }); 56 | -------------------------------------------------------------------------------- /tests/initialSetupTests/Alex.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from "@playwright/test"; 2 | 3 | test("has title", async ({ page }) => { 4 | await page.goto("https://www.ajokeaday.com/"); 5 | 6 | // Expect a title "to contain" a substring. 7 | await expect(page).toHaveTitle(/Joke of the Day/); 8 | }); 9 | -------------------------------------------------------------------------------- /tests/initialSetupTests/Claudiu.spec.js: -------------------------------------------------------------------------------- 1 | const { test, expect } = require("@playwright/test"); 2 | 3 | test("Verify if only four lumas items are listed on whats new page", async ({ 4 | page, 5 | }) => { 6 | await page.goto("https://magento.softwaretestingboard.com/what-is-new.html"); 7 | const products = page.locator(".product-image-photo"); 8 | await expect(products).toHaveCount(4); 9 | }); 10 | 11 | test("Verify if by Clicking on Stellar Solar Jacket the page is redirect to the clicked product", async ({ 12 | page, 13 | }) => { 14 | await page.goto("https://magento.softwaretestingboard.com/what-is-new.html"); 15 | await page.getByText("Stellar Solar Jacket").click(); 16 | await expect(page).toHaveURL( 17 | "https://magento.softwaretestingboard.com/stellar-solar-jacket.html" 18 | ); 19 | }); 20 | -------------------------------------------------------------------------------- /tests/initialSetupTests/Mirel.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from "@playwright/test"; 2 | 3 | test("Verify that has the correct title", async ({ page }) => { 4 | await page.goto("https://magento.softwaretestingboard.com/"); 5 | 6 | await expect(page).toHaveTitle("Home Page"); 7 | }); 8 | -------------------------------------------------------------------------------- /tests/initialSetupTests/Radu.spec.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | import { test, expect } from "@playwright/test"; 3 | 4 | test("Check if the user is on the Home Page", async ({ page }) => { 5 | await page.goto("https://magento.softwaretestingboard.com/"); 6 | await expect(page).toHaveURL("https://magento.softwaretestingboard.com/"); 7 | await expect(page).toHaveTitle("Home Page"); 8 | }); 9 | 10 | test("Count products on the home page", async ({ page }) => { 11 | await page.goto("https://magento.softwaretestingboard.com/"); 12 | const numberOfProducts = await page.locator(".product-item").count(); 13 | await expect(numberOfProducts).toBe(6); 14 | }); 15 | 16 | test("Select random products from home page", async ({ page }) => { 17 | await page.goto("https://magento.softwaretestingboard.com/"); 18 | const numberOfProducts = await page.locator(".product-item").all(); 19 | const randomProduct = 20 | numberOfProducts[Math.floor(Math.random() * numberOfProducts.length)]; 21 | const pageTitles = await page.locator(".product-item-link").allInnerTexts(); 22 | await randomProduct.click(); 23 | const pageTitle = await page.locator(".product-info-main .base").innerText(); 24 | await expect(pageTitles).toContain(pageTitle); 25 | }); 26 | -------------------------------------------------------------------------------- /tests/search/search.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from "@playwright/test"; 2 | 3 | const homePageUrl = "https://magento.softwaretestingboard.com/"; 4 | const searchBar = "Search entire store here..."; 5 | const elementsList = "ul[role='listbox']"; 6 | const searchItems = ".qs-option-name"; 7 | const amount = ".amount"; 8 | const products = ".product-item"; 9 | const pagination = ".items.pages-items"; 10 | 11 | test("Search in header for pants", async ({ page }) => { 12 | await page.goto(homePageUrl); 13 | 14 | await page 15 | .getByPlaceholder(searchBar) 16 | .pressSequentially("pants", { delay: 300 }); 17 | await expect(page.locator(elementsList)).toBeVisible(); 18 | const sugestionList = await page.locator(searchItems).allInnerTexts(); 19 | 20 | await expect(sugestionList).toContain("pants for women"); 21 | 22 | const optionPantsForWomen = await page 23 | .getByRole("option", { 24 | hasText: "pants for women", 25 | }) 26 | .locator(amount) 27 | .allInnerTexts(); 28 | await expect(optionPantsForWomen).toContain("25"); 29 | }); 30 | 31 | test("Search in header for tees for man", async ({ page }) => { 32 | await page.goto(homePageUrl); 33 | 34 | await page 35 | .getByPlaceholder(searchBar) 36 | .pressSequentially("tee", { delay: 300 }); 37 | 38 | await page.locator(searchItems).getByText("tee for man").click(); 39 | 40 | await expect(await page.locator(products)).toHaveCount(12); 41 | 42 | const pagesCount = await page 43 | .locator(pagination) 44 | .first() 45 | .locator(".item .page") 46 | .all(); 47 | await expect(pagesCount).toHaveLength(4); 48 | }); 49 | 50 | test("Search in header for tees", async ({ page }) => { 51 | await page.goto(homePageUrl); 52 | 53 | await page 54 | .getByPlaceholder(searchBar) 55 | .pressSequentially("tee", { delay: 300 }); 56 | 57 | await page.locator(searchItems).getByText("tees").first().click(); 58 | await page.waitForTimeout(1000); 59 | 60 | await expect(await page.locator(products).all()).toHaveLength(3); 61 | await expect(await page.locator(pagination)).not.toBeVisible(); 62 | }); 63 | --------------------------------------------------------------------------------