├── tests ├── uploadFiles │ ├── testfile1.pdf │ └── testfile2.pdf ├── screenshots │ ├── 1688987907924HomePage.png │ ├── 1688988031210FullPage.png │ └── 1688988283663Macbook.png ├── MouseRightClick.spec.js ├── MouseHover.spec.js ├── Tracing.spec.js ├── recordvideo.spec.js ├── screenshot2.spec.js ├── ParallelTesting.spec.js ├── mytest.spec.js ├── MouseDoubleClick.spec.js ├── HomePageTest.spec.js ├── Tags.spec.js ├── BrowserContext.spec.js ├── HandleInnerFrames.spec.js ├── Reporters.spec.js ├── example.spec.js ├── Softassertions.spec.js ├── RadioButtons.spec.js ├── screenshot.spec.js ├── Inputbox.spec.js ├── AutoSuggestDropDown.spec.js ├── DragAndDrop.spec.js ├── KeyboardActions.spec.js ├── Pomtest.spec.js ├── HandleFrames.spec.js ├── LocatingMultipleElements.spec.js ├── APITests.spec.js ├── Locators.spec.js ├── Grouping.spec.js ├── MultiSelectDropdown.spec.js ├── Hooks2.spec.js ├── Hooks3.spec.js ├── HiddenDropDown.spec.js ├── Annotations.spec.js ├── BootstrapDropdown.spec.js ├── DatePicker.spec.js ├── Hooks1.spec.js ├── UploadFiles.spec.js ├── Locators_builtin.spec.js ├── Checkboxes.spec.js ├── HandlingWindows.spec.js ├── Alerts.spec.js ├── DropDowns.spec.js ├── MouseEvents.spec.js ├── Assertions.spec.js └── Table.spec.js ├── .gitignore ├── package.json ├── jenkinsfile ├── results.xml ├── pages ├── CartPage.js ├── LoginPage.js └── HomePage.js ├── playwright.config.js ├── results.json └── tests-examples └── demo-todo-app.spec.js /tests/uploadFiles/testfile1.pdf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/uploadFiles/testfile2.pdf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | /test-results/ 3 | /playwright-report/ 4 | /playwright/.cache/ 5 | -------------------------------------------------------------------------------- /tests/screenshots/1688987907924HomePage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavanoltraining/playwrightautomation/HEAD/tests/screenshots/1688987907924HomePage.png -------------------------------------------------------------------------------- /tests/screenshots/1688988031210FullPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavanoltraining/playwrightautomation/HEAD/tests/screenshots/1688988031210FullPage.png -------------------------------------------------------------------------------- /tests/screenshots/1688988283663Macbook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavanoltraining/playwrightautomation/HEAD/tests/screenshots/1688988283663Macbook.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "playwrightautomation", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": {}, 7 | "keywords": [], 8 | "author": "", 9 | "license": "ISC", 10 | "devDependencies": { 11 | "@playwright/test": "^1.34.2" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | 3 | stages { 4 | stage('Install dependencies') { 5 | steps { 6 | sh 'npm install' 7 | } 8 | } 9 | 10 | stage('Run tests') { 11 | steps { 12 | sh 'npx playwright test Pomtest.spec.js' 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/MouseRightClick.spec.js: -------------------------------------------------------------------------------- 1 | const {test, expect}= require('@playwright/test') 2 | 3 | test ('Mouse Right Click', async ({page})=>{ 4 | 5 | await page.goto('http://swisnl.github.io/jQuery-contextMenu/demo.html') 6 | 7 | const button=await page.locator('//span[normalize-space()="right click me"]') 8 | 9 | //right click action 10 | await button.click({button: 'right'}); 11 | 12 | await page.waitForTimeout(5000) 13 | 14 | 15 | }) -------------------------------------------------------------------------------- /tests/MouseHover.spec.js: -------------------------------------------------------------------------------- 1 | const {test, expect}= require('@playwright/test') 2 | 3 | test ('Mouse hover', async ({page})=>{ 4 | 5 | await page.goto('https://demo.opencart.com/') 6 | 7 | const desktops=await page.locator('//a[normalize-space()="Desktops"]') 8 | const macbook=await page.locator('//a[normalize-space()="Mac (1)"]') 9 | 10 | //mouse hover 11 | await desktops.hover() 12 | await macbook.hover() 13 | 14 | await page.waitForTimeout(5000) 15 | 16 | }) -------------------------------------------------------------------------------- /tests/Tracing.spec.js: -------------------------------------------------------------------------------- 1 | 2 | import { test, expect } from '@playwright/test'; 3 | 4 | test('test', async ({ page }) => { 5 | await page.goto('https://www.demoblaze.com/index.html'); 6 | await page.getByRole('link', { name: 'Log in' }).click(); 7 | await page.locator('#loginusername').fill('pavanol'); 8 | await page.locator('#loginpassword').fill('test@123'); 9 | await page.getByRole('button', { name: 'Log in' }).click(); 10 | await expect(page.locator('#logout')).toBeVisible() 11 | }); -------------------------------------------------------------------------------- /tests/recordvideo.spec.js: -------------------------------------------------------------------------------- 1 | 2 | import { test, expect } from '@playwright/test'; 3 | 4 | test('test', async ({ page }) => { 5 | await page.goto('https://www.demoblaze.com/index.html'); 6 | await page.getByRole('link', { name: 'Log in' }).click(); 7 | await page.locator('#loginusername').fill('pavanol'); 8 | await page.locator('#loginpassword').fill('test@123'); 9 | await page.getByRole('button', { name: 'Log in' }).click(); 10 | await expect(page.locator('#logout')).toBeVisible() 11 | }); -------------------------------------------------------------------------------- /tests/screenshot2.spec.js: -------------------------------------------------------------------------------- 1 | //using 2 | // screenshot: 'on' in config file 3 | 4 | import { test, expect } from '@playwright/test'; 5 | 6 | test('test', async ({ page }) => { 7 | 8 | await page.goto('https://www.demoblaze.com/index.html'); 9 | await page.getByRole('link', { name: 'Log in' }).click(); 10 | await page.locator('#loginusername').fill('pavanol'); 11 | await page.locator('#loginpassword').fill('test@123'); 12 | await page.getByRole('button', { name: 'Log in' }).click(); 13 | }); -------------------------------------------------------------------------------- /tests/ParallelTesting.spec.js: -------------------------------------------------------------------------------- 1 | const { test, expect } = require('@playwright/test'); 2 | test.describe.configure({mode: 'parallel'}); 3 | 4 | test.describe('Group1',()=>{ 5 | 6 | test('Test1', async({page})=>{ 7 | console.log('this is test 1....') 8 | }) 9 | 10 | test('Test2', async({page})=>{ 11 | console.log('this is test 2....') 12 | }) 13 | 14 | test('Test3', async({page})=>{ 15 | console.log('this is test 3....') 16 | }) 17 | 18 | 19 | }) 20 | 21 | -------------------------------------------------------------------------------- /tests/mytest.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | 3 | test('test', async ({ page }) => { 4 | await page.goto('https://www.demoblaze.com/index.html'); 5 | 6 | await page.getByRole('link', { name: 'Log in' }).click(); 7 | 8 | await page.locator('#loginusername').fill('pavanol'); 9 | 10 | await page.locator('#loginpassword').fill('test@123'); 11 | 12 | await page.getByRole('button', { name: 'Log in' }).click(); 13 | 14 | await expect(page.locator('#logout2')).toBeVisible() 15 | }); -------------------------------------------------------------------------------- /tests/MouseDoubleClick.spec.js: -------------------------------------------------------------------------------- 1 | const {test, expect}= require('@playwright/test') 2 | 3 | test ('Mouse Double Click', async ({page})=>{ 4 | 5 | await page.goto('https://testautomationpractice.blogspot.com/') 6 | 7 | const btnCopy=await page.locator('//button[normalize-space()="Copy Text"]') 8 | 9 | //double click 10 | await btnCopy.dblclick() 11 | 12 | const f2=await page.locator('#field2') 13 | 14 | await expect(f2).toHaveValue('Hello World!') 15 | 16 | await page.waitForTimeout(5000) 17 | 18 | }) -------------------------------------------------------------------------------- /results.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/HomePageTest.spec.js: -------------------------------------------------------------------------------- 1 | const { test, expect } = require('@playwright/test'); 2 | 3 | test('Home Page',async ({page})=>{ 4 | 5 | await page.goto('https://www.demoblaze.com/index.html'); 6 | 7 | const pageTitle=await page.title(); 8 | console.log('Page title is:', pageTitle); 9 | 10 | await expect(page).toHaveTitle('STORE'); 11 | 12 | const pageURL=await page.url(); 13 | console.log('Page URL is:',pageURL); 14 | 15 | await expect(page).toHaveURL('https://www.demoblaze.com/index.html'); 16 | 17 | await page.close(); 18 | 19 | } ) 20 | -------------------------------------------------------------------------------- /tests/Tags.spec.js: -------------------------------------------------------------------------------- 1 | const { test, expect } = require('@playwright/test') 2 | 3 | test('test1@sanity',async({page})=>{ 4 | console.log('this is my test1...') 5 | }) 6 | 7 | 8 | test('test2@sanity',async({page})=>{ 9 | console.log('this is my test2...') 10 | }) 11 | 12 | 13 | test('test3@reg',async({page})=>{ 14 | console.log('this is my test3...') 15 | }) 16 | 17 | 18 | test('test4@reg',async({page})=>{ 19 | console.log('this is my test4...') 20 | }) 21 | 22 | test('test5@sanity@reg',async({page})=>{ 23 | console.log('this is my test5...') 24 | }) -------------------------------------------------------------------------------- /tests/BrowserContext.spec.js: -------------------------------------------------------------------------------- 1 | import { chromium,test, expect } from '@playwright/test'; 2 | //const { chromium, test, expect } = require('@playwright/test') 3 | 4 | test("browse context test",async () => { 5 | const browser = await chromium.launch({ headless: false }); 6 | const context1 = await browser.newContext(); 7 | const context2 = await browser.newContext(); 8 | 9 | 10 | const page = await context.newPage(); 11 | await page.goto('https://www.demoblaze.com/index.html'); 12 | 13 | 14 | console.log(browser.contexts().length); 15 | 16 | await browser.close(); 17 | }); 18 | 19 | -------------------------------------------------------------------------------- /tests/HandleInnerFrames.spec.js: -------------------------------------------------------------------------------- 1 | const { test, expect } = require('@playwright/test'); 2 | 3 | test('Inner frames', async ({ page }) => { 4 | 5 | await page.goto('https://ui.vision/demo/webtest/frames/'); 6 | 7 | const frame3=await page.frame({url:'https://ui.vision/demo/webtest/frames/frame_3.html'}) 8 | //frame3.locator("input[name='mytext3']").fill('welcome') 9 | 10 | //nested frame 11 | const childFrames=await frame3.childFrames() 12 | await childFrames[0].locator("//*[@id='i5']/div[3]/div").check() // radio button 13 | 14 | 15 | await page.waitForTimeout(5000); 16 | 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /tests/Reporters.spec.js: -------------------------------------------------------------------------------- 1 | const { test, expect } = require('@playwright/test'); 2 | 3 | test('Test1', async ({ page }) => { 4 | await page.goto('https://www.demoblaze.com/index.html'); 5 | await expect(page).toHaveTitle('STORE'); 6 | }) 7 | 8 | test('Test2', async ({ page }) => { 9 | await page.goto('https://demo.opencart.com/'); 10 | await expect(page).toHaveTitle('Your Store'); 11 | }) 12 | 13 | 14 | test('Test3', async ({ page }) => { 15 | await page.goto('https://demo.nopcommerce.com/'); 16 | await expect(page).toHaveTitle('nopCommerce demo store'); 17 | }) 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tests/example.spec.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | const { test, expect } = require('@playwright/test'); 3 | 4 | test('has title', async ({ page }) => { 5 | await page.goto('https://playwright.dev/'); 6 | 7 | // Expect a title "to contain" a substring. 8 | await expect(page).toHaveTitle(/Playwright/); 9 | }); 10 | 11 | test('get started link', async ({ page }) => { 12 | await page.goto('https://playwright.dev/'); 13 | 14 | // Click the get started link. 15 | await page.getByRole('link', { name: 'Get started' }).click(); 16 | 17 | // Expects the URL to contain intro. 18 | await expect(page).toHaveURL(/.*intro/); 19 | }); 20 | -------------------------------------------------------------------------------- /pages/CartPage.js: -------------------------------------------------------------------------------- 1 | exports.CartPage = class CartPage { 2 | 3 | constructor(page) { 4 | this.page = page; 5 | this.noOfProducts= '//tbody[@id="tbodyid"]/tr/td[2]' 6 | 7 | } 8 | 9 | async checkProductInCart(productName) { 10 | const productsInCart=await this.page.$$(this.noOfProducts) 11 | for (const product of productsInCart) { 12 | console.log(await product.textContent()) 13 | if (productName === await product.textContent()) { 14 | return true; 15 | break; 16 | } 17 | } 18 | 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /tests/Softassertions.spec.js: -------------------------------------------------------------------------------- 1 | const {test, expect} =require('@playwright/test') 2 | 3 | 4 | test("Soft assertions",async ({page})=>{ 5 | 6 | await page.goto("https://www.demoblaze.com/index.html") 7 | 8 | //Hard assertions 9 | /* await expect(page).toHaveTitle('STORE123'); 10 | await expect(page).toHaveURL("https://www.demoblaze.com/index.html"); 11 | await expect(page.locator('.navbar-brand')).toBeVisible(); 12 | */ 13 | //Soft assertions 14 | await expect.soft(page).toHaveTitle('STORE123'); 15 | await expect.soft(page).toHaveURL("https://www.demoblaze.com/index.html"); 16 | await expect.soft(page.locator('.navbar-brand')).toBeVisible(); 17 | 18 | }) -------------------------------------------------------------------------------- /tests/RadioButtons.spec.js: -------------------------------------------------------------------------------- 1 | const {test, expect}=require('@playwright/test') 2 | 3 | test('handle radio button',async ({page})=>{ 4 | 5 | await page.goto('https://itera-qa.azurewebsites.net/home/automation'); 6 | 7 | //Radio button 8 | await page.locator("//input[@value='option2']").check(); //male 9 | //await page.check("//input[@value='option2']"); 10 | await expect(await page.locator("//input[@value='option2']")).toBeChecked(); 11 | await expect(await page.locator("//input[@value='option2']").isChecked()).toBeTruthy();//male 12 | 13 | await expect(await page.locator("//input[@value='option1']").isChecked()).toBeFalsy(); //female 14 | 15 | 16 | 17 | await page.waitForTimeout(5000); //pausing code 18 | 19 | }) -------------------------------------------------------------------------------- /tests/screenshot.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | 3 | test('page screenshot', async ({ page }) => { 4 | await page.goto('https://demo.opencart.com/') 5 | await page.screenshot({ path:'tests/screenshots/'+Date.now()+'HomePage.png'}) 6 | }); 7 | 8 | test('Full page screenshot', async ({ page }) => { 9 | await page.goto('https://demo.opencart.com/') 10 | await page.screenshot({ path:'tests/screenshots/'+Date.now()+'FullPage.png',fullPage:true}) 11 | }); 12 | 13 | test.only('Element screenshot', async ({ page }) => { 14 | await page.goto('https://demo.opencart.com/') 15 | await page.locator('//*[@id="content"]/div[2]/div[1]/form/div').screenshot({ path:'tests/screenshots/'+Date.now()+'Macbook.png'}) 16 | }); -------------------------------------------------------------------------------- /tests/Inputbox.spec.js: -------------------------------------------------------------------------------- 1 | const {test, expect}=require('@playwright/test') 2 | 3 | test('handle inputbox',async ({page})=>{ 4 | 5 | await page.goto('https://itera-qa.azurewebsites.net/home/automation'); 6 | 7 | //Inputbox - firstname 8 | await expect(await page.locator("//input[@id='name']")).toBeVisible(); 9 | await expect(await page.locator("//input[@id='name']")).toBeEmpty(); 10 | await expect(await page.locator("//input[@id='name']")).toBeEditable(); 11 | await expect(await page.locator("//input[@id='name']")).toBeEnabled(); 12 | 13 | 14 | //await page.locator("//input[@id='name']").fill("John") 15 | await page.fill("//input[@id='name']",'John'); 16 | 17 | await page.waitForTimeout(5000); //pausing code 18 | 19 | }) -------------------------------------------------------------------------------- /tests/AutoSuggestDropDown.spec.js: -------------------------------------------------------------------------------- 1 | const {test, expect}=require('@playwright/test') 2 | 3 | test('Auto suggest dropdown', async ({page}) =>{ 4 | await page.goto('https://www.redbus.in/') 5 | 6 | await page.locator('#src').fill('Delhi'); 7 | await page.waitForSelector("//li[contains(@class,'sc-iwsKbI')]/div/text[1]") 8 | 9 | const fromCityOptions=await page.$$("//li[contains(@class,'sc-iwsKbI')]/div/text[1]") 10 | 11 | for(let option of fromCityOptions) 12 | { 13 | const value=await option.textContent() 14 | //console.log(value); 15 | if(value.includes('Anand Vihar')) 16 | { 17 | await option.click() 18 | break; 19 | 20 | } 21 | } 22 | 23 | await page.waitForTimeout(5000); 24 | 25 | }) -------------------------------------------------------------------------------- /tests/DragAndDrop.spec.js: -------------------------------------------------------------------------------- 1 | const {test, expect}= require('@playwright/test') 2 | 3 | test ('Drag And Drop', async ({page})=>{ 4 | 5 | await page.goto('http://www.dhtmlgoodies.com/scripts/drag-drop-custom/demo-drag-drop-3.html') 6 | 7 | const rome=await page.locator('#box6') 8 | const italy=await page.locator('#box106') 9 | 10 | //Appraoch 1 11 | /*await rome.hover() 12 | await page.mouse.down() 13 | 14 | await italy.hover() 15 | await page.mouse.up() 16 | */ 17 | //Appraoch 2 18 | await rome.dragTo(italy) 19 | 20 | //WASHINGTON---> US 21 | const washington=await page.locator('#box3') 22 | const usa=await page.locator('#box103') 23 | 24 | await washington.dragTo(usa) 25 | 26 | 27 | await page.waitForTimeout(5000) 28 | 29 | }) -------------------------------------------------------------------------------- /pages/LoginPage.js: -------------------------------------------------------------------------------- 1 | exports.LoginPage = 2 | class LoginPage { 3 | 4 | constructor(page) { 5 | this.page = page; 6 | this.loginLink="#login2" 7 | this.usernameInput = '#loginusername'; 8 | this.passwordInput = '#loginpassword'; 9 | this.loginButton = '//button[normalize-space()="Log in"]'; 10 | } 11 | 12 | async gotoLoginPage(){ 13 | await this.page.goto('https://www.demoblaze.com/index.html'); 14 | } 15 | 16 | async login(username, password) { 17 | await this.page.locator(this.loginLink).click(); 18 | await this.page.locator(this.usernameInput).fill(username); 19 | await this.page.locator(this.passwordInput).fill(password); 20 | await this.page.locator(this.loginButton).click(); 21 | 22 | } 23 | } -------------------------------------------------------------------------------- /tests/KeyboardActions.spec.js: -------------------------------------------------------------------------------- 1 | const { test, expect } = require('@playwright/test'); 2 | 3 | test('Keyboard actions', async ({ page }) => { 4 | 5 | await page.goto("https://gotranscript.com/text-compare") 6 | 7 | //await page.locator('name="text1"').fill("welcome to autoamtion"); 8 | 9 | await page.type('[name="text1"]','welcome to automation') 10 | 11 | //Ctrl + A - Select the text 12 | await page.keyboard.press('Meta+A') 13 | 14 | //Ctrl + C - copy the text 15 | await page.keyboard.press('Meta+C') 16 | 17 | //Tab 18 | await page.keyboard.down('Tab') 19 | await page.keyboard.up('Tab') 20 | 21 | 22 | //Ctrl + V - paste the text 23 | await page.keyboard.press('Meta+V') 24 | 25 | await page.waitForTimeout(5000); 26 | 27 | }); 28 | 29 | 30 | -------------------------------------------------------------------------------- /tests/Pomtest.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | import { LoginPage } from '../pages/LoginPage'; 3 | import { HomePage } from '../pages/HomePage'; 4 | import { CartPage} from '../pages/CartPage'; 5 | 6 | 7 | test('test', async ({ page }) => { 8 | 9 | //Login 10 | const login=new LoginPage(page); 11 | await login.gotoLoginPage(); 12 | await login.login('pavanol','test@123') 13 | await page.waitForTimeout(3000) 14 | 15 | //Home 16 | const home=new HomePage(page) 17 | await home.addProductToCart("Nexus 6") 18 | await page.waitForTimeout(3000) 19 | await home.gotoCart(); 20 | 21 | //Cart 22 | const cart=new CartPage(page) 23 | await page.waitForTimeout(3000) 24 | const status=await cart.checkProductInCart('Nexus 6') 25 | expect(await status).toBe(true); 26 | }); -------------------------------------------------------------------------------- /tests/HandleFrames.spec.js: -------------------------------------------------------------------------------- 1 | const { test, expect } = require('@playwright/test'); 2 | 3 | test('frames', async ({ page }) => { 4 | 5 | await page.goto('https://ui.vision/demo/webtest/frames/'); 6 | 7 | //total frames 8 | const allframes=await page.frames() 9 | console.log("Number of frames:",allframes.length) 10 | 11 | //approach 1: using name or url 12 | //const var=await page.frame('name'); // if name is present 13 | //const frame1=await page.frame({url:'https://ui.vision/demo/webtest/frames/frame_1.html'}) 14 | //await frame1.fill("[name='mytext1']",'Hello'); 15 | 16 | 17 | //appraoch 2- using frame locator 18 | const inputbox=await page.frameLocator("frame[src='frame_1.html']").locator("[name='mytext1']") 19 | inputbox.fill("Hello") 20 | 21 | 22 | await page.waitForTimeout(5000); 23 | 24 | }); 25 | -------------------------------------------------------------------------------- /tests/LocatingMultipleElements.spec.js: -------------------------------------------------------------------------------- 1 | const { test, expect } = require('@playwright/test'); 2 | 3 | test('LocateElements', async ({ page }) => { 4 | 5 | await page.goto('https://www.demoblaze.com/index.html') 6 | 7 | // Locate and return all the links on the webpage 8 | /*const links = await page.$$('a'); 9 | 10 | for (const link of links) { 11 | const linktext = await link.textContent(); 12 | console.log(linktext); 13 | } 14 | */ 15 | 16 | //Locate all the products displayed on home page 17 | await page.waitForSelector("//div[@id='tbodyid']//h4/a"); 18 | 19 | const products = await page.$$("//div[@id='tbodyid']//h4/a") 20 | 21 | for (const product of products) { 22 | const prodName = await product.textContent(); 23 | console.log(prodName); 24 | } 25 | 26 | }); -------------------------------------------------------------------------------- /tests/APITests.spec.js: -------------------------------------------------------------------------------- 1 | import { expect, test } from "@playwright/test"; 2 | 3 | // Create 4 | test("Create user", async ({ request, baseURL }) => { 5 | const _response = await request.post(`${baseURL}`, { 6 | data: { 7 | "name": "xyz}", 8 | "gender": "male", 9 | "email": "xyzabc245faas@gmail.com", 10 | "status": "inactive" 11 | }, headers: { 12 | "Accept": "application/json" 13 | } 14 | }); 15 | expect(_response.status()).toBe(201); 16 | expect(_response.ok()).toBeTruthy(); 17 | console.log(await _response.json()); 18 | const res = await _response.json(); 19 | _number = res.result.task_effective_number; 20 | _sys_id = res.result.sys_id; 21 | 22 | // output as xml 23 | // console.log((await _response.body()).toString()); 24 | }) 25 | // test("", async ({ page }) => { 26 | // await page.request.get("") 27 | // }) 28 | -------------------------------------------------------------------------------- /pages/HomePage.js: -------------------------------------------------------------------------------- 1 | exports.HomePage = class HomePage { 2 | 3 | constructor(page) { 4 | this.page = page; 5 | this.productList= '//*[@id="tbodyid"]/div/div/div/h4/a'; 6 | this.addToCartbtn='//a[normalize-space()="Add to cart"]'; 7 | this.cart='#cartur' 8 | } 9 | 10 | 11 | async addProductToCart(productName) { 12 | const productList = await this.page.$$(this.productList); 13 | for (const product of productList) { 14 | if (productName === await product.textContent()) { 15 | await product.click() 16 | break; 17 | } 18 | } 19 | await this.page.on('dialog', async dialog=>{ 20 | if(dialog.message().includes('added')){ 21 | await dialog.accept(); 22 | } 23 | }) 24 | await this.page.locator(this.addToCartbtn).click(); 25 | } 26 | 27 | async gotoCart() { 28 | await this.page.locator(this.cart).click(); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /tests/Locators.spec.js: -------------------------------------------------------------------------------- 1 | //const {test, expect} = require('@playwright/test') 2 | import {test,expect} from '@playwright/test' 3 | 4 | test('Locators', async ({page})=>{ 5 | 6 | await page.goto("https://www.demoblaze.com/index.html") 7 | 8 | //click on login button - property 9 | //await page.locator('id=login2').click() 10 | await page.click('id=login2') 11 | 12 | //provide username - CSS 13 | //await page.locator('#loginusername').fill("pavanol") 14 | await page.fill('#loginusername','pavanol') 15 | //await page.type('#loginusername','pavanol) 16 | 17 | //provide password - CSS 18 | await page.fill("input[id='loginpassword']",'test@123') 19 | 20 | //Click on login button - XPath 21 | await page.click("//button[normalize-space()='Log in']") 22 | 23 | //verify logout link presence - XPath 24 | const logoutlink= await page.locator("//a[normalize-space()='Log out']") 25 | 26 | await expect(logoutlink).toBeVisible(); 27 | 28 | await page.close() 29 | 30 | }) -------------------------------------------------------------------------------- /tests/Grouping.spec.js: -------------------------------------------------------------------------------- 1 | //const { test, expect } = require('@playwright/test'); 2 | import {test, expect} from '@playwright/test' 3 | 4 | test.beforeAll(async()=>{ 5 | console.log('this is beforeAll Hook......') 6 | }) 7 | test.afterAll(async()=>{ 8 | console.log('this is aftereAll Hook......') 9 | }) 10 | 11 | test.beforeEach(async()=>{ 12 | console.log('this is beforeEach Hook......') 13 | }) 14 | 15 | test.afterEach(async()=>{ 16 | console.log('this is afterEach Hook......') 17 | }) 18 | 19 | test.describe.skip('Group1',()=>{ 20 | 21 | test('Test1', async({page})=>{ 22 | console.log('this is test 1....') 23 | }) 24 | 25 | test('Test2', async({page})=>{ 26 | console.log('this is test 2....') 27 | }) 28 | }) 29 | 30 | 31 | test.describe('Group 2', ()=>{ 32 | 33 | test('Test3', async({page})=>{ 34 | console.log('this is test 3....') 35 | }) 36 | 37 | 38 | test('Test4', async({page})=>{ 39 | console.log('this is test 4....') 40 | }) 41 | }) 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /tests/MultiSelectDropdown.spec.js: -------------------------------------------------------------------------------- 1 | const {test, expect}=require('@playwright/test') 2 | 3 | test("Handle dropdowns",async ({page})=>{ 4 | 5 | await page.goto('https://testautomationpractice.blogspot.com/'); 6 | 7 | //Select multiple options from multi select dropdown 8 | //await page.selectOption('#colors',['Blue', 'Red', 'Yellow']) 9 | 10 | //Assertions 11 | //1) check number of options in dropdown 12 | //const options=await page.locator('#colors option') 13 | //await expect(options).toHaveCount(5); 14 | 15 | //2) check number of options in dropdown using JS array 16 | //const options=await page.$$('#colors option') 17 | //console.log("Number of options:",options.length) 18 | //await expect(options.length).toBe(5); 19 | 20 | //3) check presence of value in the dropdown 21 | const content=await page.locator('#colors').textContent() 22 | //await expect(content.includes('Black')).toBeTruthy(); 23 | await expect(content.includes('Black')).toBeFalsy; 24 | 25 | 26 | await page.waitForTimeout(5000); 27 | 28 | }) -------------------------------------------------------------------------------- /tests/Hooks2.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | 3 | let page; 4 | 5 | test.beforeEach(async ({browser})=>{ 6 | page=await browser.newPage(); 7 | await page.goto('https://www.demoblaze.com/index.html') 8 | //Login 9 | await page.locator('#login2').click() 10 | await page.locator('#loginusername').fill('pavanol') 11 | await page.locator('#loginpassword').fill('test@123') 12 | await page.locator('//button[normalize-space()="Log in"]').click() 13 | }); 14 | 15 | test.afterEach(async()=>{ 16 | await page.locator('#logout2').click() 17 | } ) 18 | 19 | test('Home Page Test', async () => { 20 | const products=await page.$$('.hrefch') 21 | expect(products).toHaveLength(9) 22 | }); 23 | 24 | 25 | test('Add Product to cart Test', async () => { 26 | await page.locator('//a[normalize-space()="Samsung galaxy s6"]').click() 27 | await page.locator('//a[normalize-space()="Add to cart"]').click() 28 | 29 | page.on('dialog', async dialog=>{ 30 | expect(dialog.message()).toContain('Product added.') 31 | await dialog.accept() 32 | }) 33 | }); 34 | 35 | -------------------------------------------------------------------------------- /tests/Hooks3.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | 3 | let page; 4 | 5 | test.beforeAll(async ({browser})=>{ 6 | page=await browser.newPage(); 7 | await page.goto('https://www.demoblaze.com/index.html') 8 | //Login 9 | await page.locator('#login2').click() 10 | await page.locator('#loginusername').fill('pavanol') 11 | await page.locator('#loginpassword').fill('test@123') 12 | await page.locator('//button[normalize-space()="Log in"]').click() 13 | }); 14 | 15 | test.afterAll(async()=>{ 16 | await page.locator('#logout2').click() 17 | } ) 18 | 19 | test('Home Page Test', async () => { 20 | const products=await page.$$('.hrefch') 21 | expect(products).toHaveLength(9) 22 | }); 23 | 24 | 25 | test('Add Product to cart Test', async () => { 26 | await page.locator('//a[normalize-space()="Samsung galaxy s6"]').click() 27 | await page.locator('//a[normalize-space()="Add to cart"]').click() 28 | 29 | page.on('dialog', async dialog=>{ 30 | expect(dialog.message()).toContain('Product added.') 31 | await dialog.accept() 32 | }) 33 | }); 34 | 35 | -------------------------------------------------------------------------------- /tests/HiddenDropDown.spec.js: -------------------------------------------------------------------------------- 1 | const {test, expect}=require('@playwright/test') 2 | 3 | test('Hidden options dropdown', async ({page}) =>{ 4 | await page.goto('https://opensource-demo.orangehrmlive.com/web/index.php/auth/login') 5 | 6 | await page.locator("[name='username']").fill('Admin'); 7 | await page.locator("[name='password']").fill('admin123'); 8 | await page.locator("[type='submit']").click(); 9 | 10 | await page.locator("//span[normalize-space()='PIM']").click() 11 | 12 | //click on drop down 13 | await page.locator("//*[@id='app']/div[1]/div[2]/div[2]/div/div[1]/div[2]/form/div[1]/div/div[6]/div/div[2]/div/div/div[2]").click() 14 | 15 | //waiting for options 16 | await page.waitForTimeout(3000); 17 | 18 | const options=await page.$$("//div[@role='listbox']//span") 19 | 20 | for(let option of options) 21 | { 22 | const jobTitle=await option.textContent(); 23 | //console.log(jobTitle); 24 | if(jobTitle.includes('QA Engineer')) 25 | { 26 | await option.click(); 27 | break; 28 | } 29 | } 30 | await page.waitForTimeout(5000); 31 | 32 | 33 | }) -------------------------------------------------------------------------------- /tests/Annotations.spec.js: -------------------------------------------------------------------------------- 1 | const {test, expect}=require('@playwright/test') 2 | 3 | // only 4 | /*test.only('test1', async({page})=>{ 5 | console.log('this is test1') 6 | }) 7 | */ 8 | //skip 9 | /*test.skip('test2', async({page})=>{ 10 | console.log('this is test2') 11 | }) 12 | 13 | test('test3', async({page, browserName})=>{ 14 | console.log('this is test3') 15 | if(browserName==='chromium') 16 | { 17 | test.skip() 18 | } 19 | }) 20 | */ 21 | 22 | //Fixme 23 | /*test('test4', async({page})=>{ 24 | test.fixme() 25 | console.log('this is test 4..') 26 | 27 | }) 28 | */ 29 | 30 | // Fail 31 | 32 | /*test('test5', async({page})=>{ 33 | test.fail() //exp 34 | console.log('this is test5....') 35 | expect(1).toBe(2); //If both exp & Actual is failed then test pass 36 | }) 37 | 38 | test('test6', async({page, browserName})=>{ 39 | console.log('this is test6....') 40 | if(browserName==='firefox') 41 | { 42 | test.fail() //exp 43 | } 44 | }) 45 | */ 46 | 47 | // slow() 48 | 49 | test('test7', async({page})=>{ 50 | test.slow(); 51 | // test.setTimeout(5000) 52 | await page.goto('https://www.demoblaze.com/index.html') 53 | console.log('this is test 7..') 54 | }) 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /tests/BootstrapDropdown.spec.js: -------------------------------------------------------------------------------- 1 | const {test, expect}=require('@playwright/test') 2 | 3 | test('Boostrap dropdown', async ({page}) =>{ 4 | await page.goto('https://www.jquery-az.com/boots/demo.php?ex=63.0_2') 5 | 6 | await page.locator('.multiselect').click() // click on the dropdown 7 | 8 | //1 9 | //const options=await page.locator('ul>li label input') 10 | //await expect(options).toHaveCount(11); 11 | 12 | //2 13 | //const options=await page.$$('ul>li label input') 14 | //await expect(options.length).toBe(11) 15 | 16 | //3 select options from dropdown 17 | /*const options=await page.$$('ul>li label') 18 | for(let option of options) 19 | { 20 | const value=await option.textContent(); 21 | //console.log("value is",value) 22 | if(value.includes('Angular') || value.includes('Java')) 23 | { 24 | await option.click() 25 | } 26 | 27 | }*/ 28 | 29 | // delect options 30 | const options=await page.$$('ul>li label') 31 | for(let option of options) 32 | { 33 | const value=await option.textContent(); 34 | //console.log("value is",value) 35 | if(value.includes('HTML') || value.includes('CSS')) 36 | { 37 | await option.click() 38 | } 39 | 40 | } 41 | 42 | 43 | await page.waitForTimeout(5000); 44 | }) -------------------------------------------------------------------------------- /tests/DatePicker.spec.js: -------------------------------------------------------------------------------- 1 | const { test, expect } = require('@playwright/test'); 2 | 3 | test("Date Picker", async ({ page }) => { 4 | 5 | await page.goto('https://testautomationpractice.blogspot.com/') 6 | // await page.fill('#datepicker','03/15/2024') 7 | 8 | //date picker 9 | const year="2022" 10 | const month="March" 11 | const date="25" 12 | 13 | await page.click('#datepicker') // opens calender 14 | 15 | while(true) 16 | { 17 | const currentYear=await page.locator('.ui-datepicker-year').textContent() 18 | const currentMonth=await page.locator('.ui-datepicker-month').textContent() 19 | 20 | if(currentYear == year && currentMonth==month) 21 | { 22 | break; 23 | } 24 | 25 | // await page.locator('[title="Next"]').click() //Next 26 | await page.locator('[title="Prev"]').click() //Previous 27 | } 28 | 29 | const dates=await page.$$("//a[@class='ui-state-default']") 30 | 31 | //date selection using loop 32 | /* for(const dt of dates) 33 | { 34 | if(await dt.textContent()==date) 35 | { 36 | await dt.click(); 37 | break; 38 | } 39 | } 40 | */ 41 | 42 | //date selection - wihout loop 43 | await page.click(`//a[@class='ui-state-default'][text()='${date}']`) 44 | 45 | 46 | await page.waitForTimeout(5000); 47 | 48 | }); 49 | -------------------------------------------------------------------------------- /tests/Hooks1.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | 3 | test('Home Page Test', async ({ page }) => { 4 | await page.goto('https://www.demoblaze.com/index.html') 5 | //Login 6 | await page.locator('#login2').click() 7 | await page.locator('#loginusername').fill('pavanol') 8 | await page.locator('#loginpassword').fill('test@123') 9 | await page.locator('//button[normalize-space()="Log in"]').click() 10 | 11 | //Home Page 12 | const products=await page.$$('.hrefch') 13 | expect(products).toHaveLength(9) 14 | 15 | //Logout 16 | await page.locator('#logout2').click() 17 | }); 18 | 19 | 20 | test('Add Product to cart Test', async ({ page }) => { 21 | await page.goto('https://www.demoblaze.com/index.html') 22 | //Login 23 | await page.locator('#login2').click() 24 | await page.locator('#loginusername').fill('pavanol') 25 | await page.locator('#loginpassword').fill('test@123') 26 | await page.locator('//button[normalize-space()="Log in"]').click() 27 | 28 | //Add product to cart 29 | await page.locator('//a[normalize-space()="Samsung galaxy s6"]').click() 30 | await page.locator('//a[normalize-space()="Add to cart"]').click() 31 | 32 | page.on('dialog', async dialog=>{ 33 | expect(dialog.message()).toContain('Product added.') 34 | await dialog.accept() 35 | }) 36 | //Logout 37 | await page.locator('#logout2').click() 38 | 39 | }); 40 | 41 | -------------------------------------------------------------------------------- /tests/UploadFiles.spec.js: -------------------------------------------------------------------------------- 1 | // Reference : https://playwright.dev/docs/input#upload-files 2 | 3 | const {test, expect}=require('@playwright/test') 4 | 5 | test('Single File',async ({page})=>{ 6 | 7 | await page.goto('https://www.foundit.in/') 8 | 9 | await page.waitForSelector('.mqfihd-upload'); 10 | await page.locator('.mqfihd-upload').click() 11 | 12 | await page.locator('#file-upload').setInputFiles('tests/uploadFiles/testfile1.pdf') 13 | 14 | await page.waitForTimeout(5000) 15 | }) 16 | 17 | test.only('Multiple Files',async ({page})=>{ 18 | 19 | await page.goto('https://davidwalsh.name/demo/multiple-file-upload.php') 20 | 21 | await page.locator('#filesToUpload') 22 | .setInputFiles(['tests/uploadFiles/testfile1.pdf', 23 | 'tests/uploadFiles/testfile2.pdf']); 24 | 25 | await page.waitForTimeout(3000) 26 | expect (await page.locator('#fileList li:nth-child(1)')).toHaveText('testfile1.pdf') 27 | expect (await page.locator('#fileList li:nth-child(2)')).toHaveText('testfile2.pdf') 28 | 29 | await page.waitForTimeout(3000) 30 | 31 | //Removing files 32 | await page.locator('#filesToUpload').setInputFiles([]) 33 | await page.waitForTimeout(3000) 34 | 35 | expect(await page.locator('#fileList li:nth-child(1)')).toHaveText('No Files Selected') 36 | 37 | await page.waitForTimeout(3000) 38 | 39 | }) 40 | -------------------------------------------------------------------------------- /tests/Locators_builtin.spec.js: -------------------------------------------------------------------------------- 1 | /* 2 | page.getByAltText() - to locate an element, usually image, by its text alternative. 3 | page.getByPlaceholder() - to locate an input by placeholder. 4 | page.getByRole() to locate by explicit and implicit accessibility attributes. 5 | page.getByText() to locate by text content. 6 | 7 | page.getByLabel() to locate a form control by associated label's text. 8 | page.getByTitle() to locate an element by its title attribute. 9 | page.getByTestId() to locate an element based on its data-testid attribute (other attributes can be configured). 10 | 11 | */ 12 | 13 | const {test, expect} = require('@playwright/test') 14 | 15 | test('Built-inLocators',async({page})=>{ 16 | 17 | await page.goto('https://opensource-demo.orangehrmlive.com/web/index.php/auth/login') 18 | 19 | //page.getByAltText() - to locate an element, usually image, by its text alternative. 20 | const logo=await page.getByAltText('company-branding') 21 | await expect(logo).toBeVisible(); 22 | 23 | //page.getByPlaceholder() - to locate an input by placeholder. 24 | await page.getByPlaceholder('Username').fill("Admin") 25 | await page.getByPlaceholder('Password').fill("admin123") 26 | 27 | await page.getByRole('button', {type: 'submit'} ).click() 28 | 29 | const name=await page.locator('//p[@class="oxd-userdropdown-name"]').textContent() 30 | 31 | await expect(await page.getByText(name)).toBeVisible() 32 | 33 | }) -------------------------------------------------------------------------------- /tests/Checkboxes.spec.js: -------------------------------------------------------------------------------- 1 | const {test, expect}=require('@playwright/test') 2 | 3 | test("Handle checkboxes",async ({page})=>{ 4 | 5 | await page.goto('https://itera-qa.azurewebsites.net/home/automation'); 6 | 7 | //single checkbox 8 | await page.locator("//input[@id='monday' and @type='checkbox']").check(); 9 | //await page.check("//input[@id='monday' and @type='checkbox']"); 10 | 11 | expect(await page.locator("//input[@id='monday' and @type='checkbox']")).toBeChecked(); 12 | expect(await page.locator("//input[@id='monday' and @type='checkbox']").isChecked()).toBeTruthy(); 13 | expect(await page.locator("//input[@id='sunday' and @type='checkbox']").isChecked()).toBeFalsy(); 14 | 15 | //Multiple checkboxes 16 | const checkboxLocators=[ 17 | "//input[@id='monday' and @type='checkbox']", 18 | "//input[@id='sunday' and @type='checkbox']", 19 | "//input[@id='saturday' and @type='checkbox']" 20 | ]; 21 | 22 | for(const locator of checkboxLocators) // select multiple checkboxes 23 | { 24 | await page.locator(locator).check(); 25 | } 26 | 27 | await page.waitForTimeout(5000); 28 | 29 | 30 | for(const locator of checkboxLocators) // unselect multiple checkboxes which are already selected 31 | { 32 | if(await page.locator(locator).isChecked()) 33 | { 34 | await page.locator(locator).uncheck(); 35 | } 36 | } 37 | await page.waitForTimeout(5000); 38 | }) -------------------------------------------------------------------------------- /tests/HandlingWindows.spec.js: -------------------------------------------------------------------------------- 1 | const { test, expect, chromium } = require('@playwright/test'); 2 | 3 | test('Handle Pages/Windows', async () => { 4 | 5 | const browser=await chromium.launch() 6 | const context=await browser.newContext() 7 | 8 | const page1=await context.newPage() 9 | const page2=await context.newPage() 10 | 11 | const allPages=context.pages() 12 | console.log("No Of Pages created:",allPages.length) 13 | 14 | await page1.goto("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login") 15 | await expect(page1).toHaveTitle("OrangeHRM") 16 | 17 | await page2.goto("https://www.orangehrm.com/") 18 | await expect(page2).toHaveTitle("OrangeHRM HR Software | Free & Open Source HR Software | HRMS | HRIS | OrangeHRM") 19 | 20 | }) 21 | 22 | test.only('Handle Multiple Pages/Windows', async () => { 23 | 24 | const browser=await chromium.launch() 25 | const context=await browser.newContext() 26 | 27 | const page1=await context.newPage() 28 | await page1.goto("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login") 29 | await expect(page1).toHaveTitle("OrangeHRM") 30 | 31 | const pagePromise=context.waitForEvent('page') 32 | await page1.locator('//a[normalize-space()="OrangeHRM, Inc"]').click() 33 | 34 | const newPage= await pagePromise; 35 | await expect(newPage).toHaveTitle("OrangeHRM HR Software | Free & Open Source HR Software | HRMS | HRIS | OrangeHRM") 36 | 37 | await page1.waitForTimeout(3000) 38 | await newPage.waitForTimeout(3000) 39 | 40 | await browser.close() 41 | 42 | }) 43 | -------------------------------------------------------------------------------- /tests/Alerts.spec.js: -------------------------------------------------------------------------------- 1 | const { test, expect } = require('@playwright/test'); 2 | 3 | test.skip('Alert with OK', async ({ page }) => { 4 | await page.goto('https://testautomationpractice.blogspot.com/'); 5 | 6 | //Enabling Dilaog window handler 7 | page.on('dialog', async dialog=>{ 8 | expect(dialog.type()).toContain('alert') 9 | expect(dialog.message()).toContain('I am an alert box!') 10 | await dialog.accept(); 11 | 12 | }) 13 | await page.click('//button[normalize-space()="Alert"]'); 14 | await page.waitForTimeout(5000); 15 | 16 | }); 17 | 18 | test.skip('Confirmation Dialod-Alert with OK and cancel', async ({ page }) => { 19 | await page.goto('https://testautomationpractice.blogspot.com/'); 20 | 21 | //Enabling dialog window handler 22 | page.on('dialog', async dialog=>{ 23 | expect(dialog.type()).toContain('confirm') 24 | expect(dialog.message()).toContain('Press a button!') 25 | await dialog.accept(); // close by using OK button 26 | //await dialog.dismiss(); // close by using cancel 27 | 28 | }) 29 | await page.click('//button[normalize-space()="Confirm Box"]'); 30 | await expect(page.locator('//p[@id="demo"]')).toHaveText('You pressed OK!') 31 | 32 | await page.waitForTimeout(5000); 33 | 34 | }); 35 | 36 | test('Prompt Dialog', async ({ page }) => { 37 | await page.goto('https://testautomationpractice.blogspot.com/'); 38 | 39 | //Enabling dialog window handler 40 | page.on('dialog', async dialog=>{ 41 | expect(dialog.type()).toContain('prompt') 42 | expect(dialog.message()).toContain('Please enter your name:') 43 | expect(dialog.defaultValue()).toContain('Harry Potter') 44 | await dialog.accept('John'); 45 | 46 | }) 47 | await page.click('//button[normalize-space()="Prompt"]'); 48 | await expect(page.locator('//p[@id="demo"]')).toHaveText('Hello John! How are you today?') 49 | 50 | await page.waitForTimeout(5000); 51 | 52 | }); -------------------------------------------------------------------------------- /tests/DropDowns.spec.js: -------------------------------------------------------------------------------- 1 | const {test, expect}=require('@playwright/test') 2 | 3 | test("Handle dropdowns",async ({page})=>{ 4 | 5 | await page.goto('https://testautomationpractice.blogspot.com/'); 6 | 7 | //Multiple ways to select option from the dropdown 8 | //await page.locator("#country").selectOption({label:'India'}); //label/ visible text 9 | //await page.locator("#country").selectOption('India'); //visible text 10 | //await page.locator("#country").selectOption({value: 'uk'}); // by using value 11 | //await page.locator("#country").selectOption({index: 1}); // by using index 12 | //await page.selectOption("#country",'India'); //by text 13 | 14 | //Assertions 15 | //1) check number of options in dropdown - Approach1 16 | //const options=await page.locator('#country option') 17 | //await expect(options).toHaveCount(10); 18 | 19 | //2) check number of options in dropdown - Appraoch2 20 | //const options=await page.$$('#country option') 21 | //console.log("Number of options:", options.length) 22 | // await expect(options.length).toBe(10); 23 | 24 | //3) check presence of value in the dropdown - Appraoch1 25 | // const content=await page.locator('#country').textContent() 26 | //await expect(content.includes('India')).toBeTruthy(); 27 | 28 | //4) check presence of value in the dropdown - Approach 2 - using looping 29 | /*const options=await page.$$('#country option') 30 | let status=false; 31 | for(const option of options) 32 | { 33 | //console.log(await option.textContent()) 34 | let value=await option.textContent(); 35 | if(value.includes('France')) 36 | { 37 | status=true; 38 | break; 39 | } 40 | } 41 | expect(status).toBeTruthy(); 42 | */ 43 | 44 | 45 | //5) select option from dropdown using loop 46 | const options=await page.$$('#country option') 47 | for(const option of options) 48 | { 49 | let value=await option.textContent(); 50 | if(value.includes('France')) 51 | { 52 | await page.selectOption("#country", value); 53 | break; 54 | } 55 | } 56 | 57 | 58 | await page.waitForTimeout(5000); 59 | 60 | }) -------------------------------------------------------------------------------- /tests/MouseEvents.spec.js: -------------------------------------------------------------------------------- 1 | const { test, expect } = require('@playwright/test'); 2 | 3 | test('Mouse hover',async ({page})=>{ 4 | 5 | await page.goto('https://demo.opencart.com/'); 6 | 7 | const desktops = await page.locator('//a[normalize-space()="Desktops"]'); 8 | const macbook= await page.locator('//a[normalize-space()="Mac (1)"]'); 9 | 10 | // Mose hover 11 | await desktops.hover() 12 | await macbook.hover() 13 | 14 | await page.waitForTimeout(5000) 15 | 16 | } ) 17 | 18 | 19 | test.skip('Right Click',async ({page})=>{ 20 | 21 | await page.goto('http://swisnl.github.io/jQuery-contextMenu/demo.html'); 22 | 23 | // Wait for the button to be visible on the page 24 | const button = await page.locator('//span[normalize-space()="right click me"]'); 25 | 26 | // Right-click on the button 27 | await button.click({ button: 'right' }); 28 | await page.waitForTimeout(5000) 29 | 30 | } ) 31 | 32 | test.skip('Double Click',async ({page})=>{ 33 | 34 | await page.goto('https://testautomationpractice.blogspot.com/'); 35 | 36 | const btnCopy = await page.locator('//button[normalize-space()="Copy Text"]') 37 | 38 | // Double-click on the button 39 | await btnCopy.dblclick(); 40 | 41 | const f2= await page.locator('#field2') 42 | await expect(f2).toHaveValue('Hello World!') 43 | 44 | await page.waitForTimeout(5000) 45 | } ) 46 | 47 | test.skip('Drag and Drop',async ({page})=>{ 48 | 49 | await page.goto('http://www.dhtmlgoodies.com/scripts/drag-drop-custom/demo-drag-drop-3.html'); 50 | 51 | // Drag and Drop rome--> italy 52 | const rome = await page.locator('#box6'); 53 | const italy = await page.locator('#box106'); 54 | 55 | //Approach 1 56 | await rome.hover(); 57 | await page.mouse.down(); 58 | await italy.hover(); 59 | await page.mouse.up(); 60 | 61 | //Appraoch 2 - direct 62 | //await rome.dragTo(italy); 63 | 64 | // Drag and Drop Washingtom--> USA 65 | const washington = await page.locator('#box3'); 66 | const usa = await page.locator('#box103'); 67 | await washington.dragTo(usa); 68 | 69 | await page.waitForTimeout(5000) 70 | } ) 71 | 72 | -------------------------------------------------------------------------------- /tests/Assertions.spec.js: -------------------------------------------------------------------------------- 1 | const {test, expect}=require('@playwright/test') 2 | 3 | test('AssertionsTest',async ({page})=>{ 4 | 5 | //open app url 6 | await page.goto('https://demo.nopcommerce.com/register') 7 | 8 | //1) expect(page).toHaveURL() Page has URL 9 | await expect(page).toHaveURL('https://demo.nopcommerce.com/register') 10 | 11 | //2) expect(page).toHaveTitle() Page has title 12 | await expect(page).toHaveTitle('nopCommerce demo store. Register') 13 | 14 | //3) expect(locator).toBeVisible() Element is visible 15 | const logoElement=await page.locator('.header-logo') 16 | await expect(logoElement).toBeVisible() 17 | 18 | //4) expect(locator).toBeEnabled() Control is enabled 19 | const searchStoreBox=await page.locator('#small-searchterms') 20 | await expect(searchStoreBox).toBeEnabled() 21 | 22 | //5) expect(locator).toBeChecked() Radio/Checkbox is checked 23 | 24 | //radio button 25 | const maleRadioButton=await page.locator('#gender-male') 26 | await maleRadioButton.click() // select radio button 27 | await expect(maleRadioButton).toBeChecked() 28 | 29 | 30 | //check box 31 | const newsletterCheckbox=await page.locator('#Newsletter') 32 | await expect(newsletterCheckbox).toBeChecked() 33 | 34 | //6) expect(locator).toHaveAttribute() Element has attribute 35 | const regButton=await page.locator('#register-button') 36 | await expect(regButton).toHaveAttribute('type','submit') 37 | 38 | // 7) expect(locator).toHaveText() Element matches text 39 | 40 | await expect(await page.locator('.page-title h1')).toHaveText('Register') //full text 41 | 42 | 43 | // 8) expect(locator).toContainText() Element contains text 44 | await expect(await page.locator('.page-title h1')).toContainText('Reg') //partial text 45 | 46 | 47 | //9) expect(locator).toHaveValue(value) Input has a value 48 | const emailInput=await page.locator('#Email') 49 | await emailInput.fill('test@demo.com'); 50 | await expect(emailInput).toHaveValue('test@demo.com') 51 | 52 | // 10) expect(locator).toHaveCount() List of elements has given length 53 | const options= await page.locator('select[name="DateOfBirthMonth"] option') 54 | await expect(options).toHaveCount(13) 55 | }) 56 | -------------------------------------------------------------------------------- /tests/Table.spec.js: -------------------------------------------------------------------------------- 1 | const {test, expect}=require('@playwright/test') 2 | 3 | test("handling table",async ({page})=>{ 4 | 5 | await page.goto('https://testautomationpractice.blogspot.com/'); 6 | 7 | const table=await page.locator('#productTable') 8 | 9 | // 1) total number of rows & columns 10 | const columns= await table.locator('thead tr th') 11 | console.log('Number of columns:', await columns.count()) //4 12 | expect(await columns.count()).toBe(4) 13 | 14 | const rows=await table.locator('tbody tr') 15 | console.log('Number of rows:', await rows.count()) //5 16 | expect(await rows.count()).toBe(5) 17 | 18 | //2) select check box for product 4 19 | /* const machedRow= rows.filter({ 20 | has: page.locator('td'), 21 | hasText: 'Product 4' 22 | }) 23 | await machedRow.locator('input').check() 24 | */ 25 | 26 | //3) select multiple products by re-usable function 27 | // await selectProduct(rows,page,'Product 1') 28 | // await selectProduct(rows,page,'Product 3') 29 | // await selectProduct(rows,page,'Product 5') 30 | 31 | //4) print all product details using loop 32 | /* for(let i=0;i0) 52 | { 53 | await pages.nth(p).click() 54 | } 55 | for(let i=0;i { 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 | --------------------------------------------------------------------------------