├── .gitignore ├── Lambdainfo.txt ├── base └── pomFixture.ts ├── fixture ├── fixtest.test.ts └── myFixture.ts ├── jsonReports └── jsonReport.json ├── package-lock.json ├── package.json ├── pages ├── homePage.ts ├── loginPage.ts ├── registerPage.ts └── specialHotPage.ts ├── playwright.config.ts ├── pomtest ├── addToCart.test.ts └── addToCartUsingFixture.test.ts ├── readme.md ├── test-data └── addTocart-test-data.json ├── tests ├── alerts.test.ts ├── basicInteractions.test.ts ├── calendar.test.ts ├── dropdown.test.ts ├── frames.test.ts ├── login.test.ts ├── recorded.test.ts ├── uploadDownload.test.ts └── windows.test.ts └── uploadItems ├── apple.png └── mango.png /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | /test-results/ 3 | /playwright-report/ 4 | /playwright/.cache/ 5 | -------------------------------------------------------------------------------- /Lambdainfo.txt: -------------------------------------------------------------------------------- 1 | Like, Share, comment & subs -------------------------------------------------------------------------------- /base/pomFixture.ts: -------------------------------------------------------------------------------- 1 | import { chromium, test as baseTest } from "@playwright/test"; 2 | import RegisterPage from "../pages/registerPage" 3 | import LoginPage from "../pages/loginPage" 4 | import HomePage from "../pages/homePage" 5 | import SpecialHotPage from "../pages/specialHotPage" 6 | 7 | import path from "path" 8 | 9 | type pages = { 10 | registerPage: RegisterPage; 11 | loginPage: LoginPage; 12 | homePage: HomePage; 13 | specialPage: SpecialHotPage 14 | } 15 | 16 | // LambdaTest capabilities 17 | const capabilities = { 18 | browserName: "Chrome", // Browsers allowed: `Chrome`, `MicrosoftEdge`, `pw-chromium`, `pw-firefox` and `pw-webkit` 19 | browserVersion: "latest", 20 | "LT:Options": { 21 | platform: "Windows 10", 22 | build: "Playwright Test Build", 23 | name: "Playwright Test", 24 | user: '', 25 | accessKey: '', 26 | network: true, 27 | video: true, 28 | console: true, 29 | tunnel: false, // Add tunnel configuration if testing locally hosted webpage 30 | tunnelName: "", // Optional 31 | geoLocation: '', // country code can be fetched from https://www.lambdatest.com/capabilities-generator/ 32 | }, 33 | }; 34 | 35 | // Patching the capabilities dynamically according to the project name. 36 | const modifyCapabilities = (configName, testName) => { 37 | let config = configName.split("@lambdatest")[0]; 38 | let [browserName, browserVersion, platform] = config.split(":"); 39 | capabilities.browserName = browserName 40 | ? browserName 41 | : capabilities.browserName; 42 | capabilities.browserVersion = browserVersion 43 | ? browserVersion 44 | : capabilities.browserVersion; 45 | capabilities["LT:Options"]["platform"] = platform 46 | ? platform 47 | : capabilities["LT:Options"]["platform"]; 48 | capabilities["LT:Options"]["name"] = testName; 49 | }; 50 | 51 | const getErrorMessage = (obj, keys) => 52 | keys.reduce( 53 | (obj, key) => (typeof obj == "object" ? obj[key] : undefined), 54 | obj 55 | ); 56 | 57 | const testPages = baseTest.extend({ 58 | page: async ({ }, use, testInfo) => { 59 | let fileName = testInfo.file.split(path.sep).pop(); 60 | if (testInfo.project.name.match(/lambdatest/)) { 61 | modifyCapabilities( 62 | testInfo.project.name, 63 | `${testInfo.title} - ${fileName}` 64 | ); 65 | const browser = await chromium.connect(`wss://cdp.lambdatest.com/playwright?capabilities= 66 | ${encodeURIComponent(JSON.stringify(capabilities))}`); 67 | const context = await browser.newContext(testInfo.project.use); 68 | const ltPage = await context.newPage() 69 | await use(ltPage); 70 | const testStatus = { 71 | action: "setTestStatus", 72 | arguments: { 73 | status: testInfo.status, 74 | remark: getErrorMessage(testInfo, ["error", "message"]), 75 | }, 76 | }; 77 | await ltPage.evaluate(() => { }, 78 | `lambdatest_action: ${JSON.stringify(testStatus)}`); 79 | await ltPage.close(); 80 | await context.close(); 81 | await browser.close(); 82 | } else { 83 | const browser = await chromium.launch(); 84 | const context = await browser.newContext(); 85 | const page = await context.newPage() 86 | await use(page); 87 | } 88 | }, 89 | 90 | registerPage: async ({ page }, use) => { 91 | await use(new RegisterPage(page)); 92 | }, 93 | loginPage: async ({ page }, use) => { 94 | await use(new LoginPage(page)); 95 | }, 96 | homePage: async ({ page }, use) => { 97 | await use(new HomePage(page)); 98 | }, 99 | specialPage: async ({ page }, use) => { 100 | await use(new SpecialHotPage(page)); 101 | }, 102 | 103 | }) 104 | 105 | export const test = testPages; 106 | export const expect = testPages.expect; -------------------------------------------------------------------------------- /fixture/fixtest.test.ts: -------------------------------------------------------------------------------- 1 | import {test} from "./myFixture" 2 | 3 | test("fixture demo", async ({ age, email }) => { 4 | console.log(age+15, email.toUpperCase()); 5 | 6 | }) -------------------------------------------------------------------------------- /fixture/myFixture.ts: -------------------------------------------------------------------------------- 1 | import { test as myTest } from "@playwright/test"; 2 | 3 | // type koushik = { 4 | // age: number, 5 | // email: string 6 | // } 7 | 8 | const myFixtureTest = myTest.extend<{ 9 | age: number, 10 | email: string 11 | }>({ 12 | age: 27, 13 | email:"koushik350@gmail.com" 14 | }) 15 | 16 | export const test = myFixtureTest; -------------------------------------------------------------------------------- /jsonReports/jsonReport.json: -------------------------------------------------------------------------------- 1 | { 2 | "config": { 3 | "forbidOnly": false, 4 | "fullyParallel": false, 5 | "globalSetup": null, 6 | "globalTeardown": null, 7 | "globalTimeout": 0, 8 | "grep": {}, 9 | "grepInvert": null, 10 | "maxFailures": 0, 11 | "metadata": {}, 12 | "preserveOutput": "always", 13 | "projects": [ 14 | { 15 | "outputDir": "C:/Users/kouss/OneDrive/Desktop/learn-playwright/test-results", 16 | "repeatEach": 1, 17 | "retries": 0, 18 | "name": "chrome:latest:MacOS Catalina@lambdatest", 19 | "testDir": "C:/Users/kouss/OneDrive/Desktop/learn-playwright", 20 | "testIgnore": [], 21 | "testMatch": [ 22 | "pomtest/addToCartUsingFixture.test.ts" 23 | ], 24 | "timeout": 300000 25 | }, 26 | { 27 | "outputDir": "C:/Users/kouss/OneDrive/Desktop/learn-playwright/test-results", 28 | "repeatEach": 1, 29 | "retries": 0, 30 | "name": "chrome:latest:Windows 10@lambdatest", 31 | "testDir": "C:/Users/kouss/OneDrive/Desktop/learn-playwright", 32 | "testIgnore": [], 33 | "testMatch": [ 34 | "pomtest/addToCartUsingFixture.test.ts" 35 | ], 36 | "timeout": 300000 37 | }, 38 | { 39 | "outputDir": "C:/Users/kouss/OneDrive/Desktop/learn-playwright/test-results", 40 | "repeatEach": 1, 41 | "retries": 0, 42 | "name": "chrome", 43 | "testDir": "C:/Users/kouss/OneDrive/Desktop/learn-playwright", 44 | "testIgnore": [], 45 | "testMatch": [ 46 | "pomtest/addToCartUsingFixture.test.ts" 47 | ], 48 | "timeout": 300000 49 | }, 50 | { 51 | "outputDir": "C:/Users/kouss/OneDrive/Desktop/learn-playwright/test-results", 52 | "repeatEach": 1, 53 | "retries": 0, 54 | "name": "firefox", 55 | "testDir": "C:/Users/kouss/OneDrive/Desktop/learn-playwright", 56 | "testIgnore": [], 57 | "testMatch": [ 58 | "pomtest/addToCartUsingFixture.test.ts" 59 | ], 60 | "timeout": 300000 61 | } 62 | ], 63 | "reporter": [ 64 | [ 65 | "dot", 66 | null 67 | ], 68 | [ 69 | "json", 70 | { 71 | "outputFile": "jsonReports/jsonReport.json" 72 | } 73 | ], 74 | [ 75 | "html", 76 | { 77 | "open": "never" 78 | } 79 | ] 80 | ], 81 | "reportSlowTests": { 82 | "max": 5, 83 | "threshold": 15000 84 | }, 85 | "rootDir": "C:/Users/kouss/OneDrive/Desktop/learn-playwright", 86 | "quiet": false, 87 | "shard": null, 88 | "updateSnapshots": "missing", 89 | "version": "1.22.2", 90 | "workers": 4, 91 | "webServer": null, 92 | "_globalOutputDir": "C:\\Users\\kouss\\OneDrive\\Desktop\\learn-playwright", 93 | "_configDir": "C:\\Users\\kouss\\OneDrive\\Desktop\\learn-playwright", 94 | "_testGroupsCount": 1 95 | }, 96 | "suites": [ 97 | { 98 | "title": "pomtest\\addToCartUsingFixture.test.ts", 99 | "file": "pomtest/addToCartUsingFixture.test.ts", 100 | "line": 0, 101 | "column": 0, 102 | "specs": [], 103 | "suites": [ 104 | { 105 | "title": "Page object test demo", 106 | "file": "pomtest/addToCartUsingFixture.test.ts", 107 | "line": 8, 108 | "column": 6, 109 | "specs": [ 110 | { 111 | "title": "Register test_01", 112 | "ok": true, 113 | "tags": [], 114 | "tests": [ 115 | { 116 | "timeout": 300000, 117 | "annotations": [], 118 | "expectedStatus": "passed", 119 | "projectName": "chrome", 120 | "results": [ 121 | { 122 | "workerIndex": 0, 123 | "status": "passed", 124 | "duration": 7774, 125 | "stdout": [], 126 | "stderr": [], 127 | "retry": 0, 128 | "attachments": [ 129 | { 130 | "name": "screenshot", 131 | "contentType": "image/png", 132 | "path": "C:\\Users\\kouss\\OneDrive\\Desktop\\learn-playwright\\test-results\\pomtest-addToCartUsingFixture-Page-object-test-demo-Register-test-01-chrome\\test-finished-1.png" 133 | } 134 | ] 135 | } 136 | ], 137 | "status": "expected" 138 | } 139 | ], 140 | "file": "pomtest/addToCartUsingFixture.test.ts", 141 | "line": 10, 142 | "column": 5 143 | }, 144 | { 145 | "title": "Login test_02", 146 | "ok": true, 147 | "tags": [], 148 | "tests": [ 149 | { 150 | "timeout": 300000, 151 | "annotations": [], 152 | "expectedStatus": "passed", 153 | "projectName": "chrome", 154 | "results": [ 155 | { 156 | "workerIndex": 0, 157 | "status": "passed", 158 | "duration": 9160, 159 | "stdout": [], 160 | "stderr": [], 161 | "retry": 0, 162 | "attachments": [ 163 | { 164 | "name": "screenshot", 165 | "contentType": "image/png", 166 | "path": "C:\\Users\\kouss\\OneDrive\\Desktop\\learn-playwright\\test-results\\pomtest-addToCartUsingFixture-Page-object-test-demo-Login-test-02-chrome\\test-finished-1.png" 167 | }, 168 | { 169 | "name": "screenshot", 170 | "contentType": "image/png", 171 | "path": "C:\\Users\\kouss\\OneDrive\\Desktop\\learn-playwright\\test-results\\pomtest-addToCartUsingFixture-Page-object-test-demo-Login-test-02-chrome\\test-finished-2.png" 172 | } 173 | ] 174 | } 175 | ], 176 | "status": "expected" 177 | } 178 | ], 179 | "file": "pomtest/addToCartUsingFixture.test.ts", 180 | "line": 23, 181 | "column": 5 182 | }, 183 | { 184 | "title": "Add to cart test_03", 185 | "ok": true, 186 | "tags": [], 187 | "tests": [ 188 | { 189 | "timeout": 300000, 190 | "annotations": [], 191 | "expectedStatus": "passed", 192 | "projectName": "chrome", 193 | "results": [ 194 | { 195 | "workerIndex": 0, 196 | "status": "passed", 197 | "duration": 13035, 198 | "stdout": [], 199 | "stderr": [], 200 | "retry": 0, 201 | "attachments": [ 202 | { 203 | "name": "screenshot", 204 | "contentType": "image/png", 205 | "path": "C:\\Users\\kouss\\OneDrive\\Desktop\\learn-playwright\\test-results\\pomtest-addToCartUsingFixture-Page-object-test-demo-Add-to-cart-test-03-chrome\\test-finished-1.png" 206 | }, 207 | { 208 | "name": "screenshot", 209 | "contentType": "image/png", 210 | "path": "C:\\Users\\kouss\\OneDrive\\Desktop\\learn-playwright\\test-results\\pomtest-addToCartUsingFixture-Page-object-test-demo-Add-to-cart-test-03-chrome\\test-finished-2.png" 211 | }, 212 | { 213 | "name": "screenshot", 214 | "contentType": "image/png", 215 | "path": "C:\\Users\\kouss\\OneDrive\\Desktop\\learn-playwright\\test-results\\pomtest-addToCartUsingFixture-Page-object-test-demo-Add-to-cart-test-03-chrome\\test-finished-3.png" 216 | } 217 | ] 218 | } 219 | ], 220 | "status": "expected" 221 | } 222 | ], 223 | "file": "pomtest/addToCartUsingFixture.test.ts", 224 | "line": 31, 225 | "column": 5 226 | } 227 | ] 228 | } 229 | ] 230 | } 231 | ], 232 | "errors": [] 233 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learn-playwright", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "learn-playwright", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "@playwright/test": "^1.22.2", 13 | "moment": "^2.29.1" 14 | } 15 | }, 16 | "node_modules/@playwright/test": { 17 | "version": "1.22.2", 18 | "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.22.2.tgz", 19 | "integrity": "sha512-cCl96BEBGPtptFz7C2FOSN3PrTnJ3rPpENe+gYCMx4GNNDlN4tmo2D89y13feGKTMMAIVrXfSQ/UmaQKLy1XLA==", 20 | "dev": true, 21 | "dependencies": { 22 | "@types/node": "*", 23 | "playwright-core": "1.22.2" 24 | }, 25 | "bin": { 26 | "playwright": "cli.js" 27 | }, 28 | "engines": { 29 | "node": ">=14" 30 | } 31 | }, 32 | "node_modules/@types/node": { 33 | "version": "17.0.36", 34 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.36.tgz", 35 | "integrity": "sha512-V3orv+ggDsWVHP99K3JlwtH20R7J4IhI1Kksgc+64q5VxgfRkQG8Ws3MFm/FZOKDYGy9feGFlZ70/HpCNe9QaA==", 36 | "dev": true 37 | }, 38 | "node_modules/moment": { 39 | "version": "2.29.3", 40 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", 41 | "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==", 42 | "dev": true, 43 | "engines": { 44 | "node": "*" 45 | } 46 | }, 47 | "node_modules/playwright-core": { 48 | "version": "1.22.2", 49 | "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.22.2.tgz", 50 | "integrity": "sha512-w/hc/Ld0RM4pmsNeE6aL/fPNWw8BWit2tg+TfqJ3+p59c6s3B6C8mXvXrIPmfQEobkcFDc+4KirNzOQ+uBSP1Q==", 51 | "dev": true, 52 | "bin": { 53 | "playwright": "cli.js" 54 | }, 55 | "engines": { 56 | "node": ">=14" 57 | } 58 | } 59 | }, 60 | "dependencies": { 61 | "@playwright/test": { 62 | "version": "1.22.2", 63 | "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.22.2.tgz", 64 | "integrity": "sha512-cCl96BEBGPtptFz7C2FOSN3PrTnJ3rPpENe+gYCMx4GNNDlN4tmo2D89y13feGKTMMAIVrXfSQ/UmaQKLy1XLA==", 65 | "dev": true, 66 | "requires": { 67 | "@types/node": "*", 68 | "playwright-core": "1.22.2" 69 | } 70 | }, 71 | "@types/node": { 72 | "version": "17.0.36", 73 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.36.tgz", 74 | "integrity": "sha512-V3orv+ggDsWVHP99K3JlwtH20R7J4IhI1Kksgc+64q5VxgfRkQG8Ws3MFm/FZOKDYGy9feGFlZ70/HpCNe9QaA==", 75 | "dev": true 76 | }, 77 | "moment": { 78 | "version": "2.29.3", 79 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", 80 | "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==", 81 | "dev": true 82 | }, 83 | "playwright-core": { 84 | "version": "1.22.2", 85 | "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.22.2.tgz", 86 | "integrity": "sha512-w/hc/Ld0RM4pmsNeE6aL/fPNWw8BWit2tg+TfqJ3+p59c6s3B6C8mXvXrIPmfQEobkcFDc+4KirNzOQ+uBSP1Q==", 87 | "dev": true 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learn-playwright", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "npx playwright test --project=chrome", 8 | "test:lt": "npx playwright test --project=\"chrome:latest:MacOS Catalina@lambdatest\"" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "@playwright/test": "^1.22.2", 15 | "moment": "^2.29.1" 16 | } 17 | } -------------------------------------------------------------------------------- /pages/homePage.ts: -------------------------------------------------------------------------------- 1 | import { Page } from "@playwright/test"; 2 | 3 | export default class HomePage { 4 | 5 | 6 | constructor(public page: Page) { 7 | 8 | } 9 | 10 | async clickOnSpecialHotMenu() { 11 | await Promise.all([ 12 | this.page.waitForNavigation({ waitUntil: "networkidle" }), 13 | 14 | this.page.click("(//span[contains(text(),'Special')]/../..)[2]") 15 | ]) 16 | } 17 | } -------------------------------------------------------------------------------- /pages/loginPage.ts: -------------------------------------------------------------------------------- 1 | import { Page } from "@playwright/test"; 2 | export default class LoginPage { 3 | 4 | constructor(public page: Page) { } 5 | 6 | async login(email: string, password: string) { 7 | await this.enterEmail(email); 8 | await this.enterLoginPassword(password); 9 | await this.clickLoginBtn(); 10 | } 11 | 12 | async enterEmail(emailaddress: string) { 13 | await this.page.locator("input[name='email']") 14 | .type(emailaddress); 15 | } 16 | 17 | async enterLoginPassword(password: string) { 18 | await this.page.locator("input[name='password']") 19 | .type(password); 20 | } 21 | 22 | async clickLoginBtn() { 23 | await Promise.all([ 24 | this.page.waitForNavigation(), 25 | this.page.click("input[value='Login']") 26 | ]) 27 | } 28 | } -------------------------------------------------------------------------------- /pages/registerPage.ts: -------------------------------------------------------------------------------- 1 | import { Page } from "@playwright/test"; 2 | export default class RegisterPage { 3 | 4 | 5 | constructor(public page: Page) { } 6 | 7 | 8 | async enterFirstName(firstname: string) { 9 | await this.page.locator("#input-firstname") 10 | .type(firstname); 11 | } 12 | async enterLastName(lastname: string) { 13 | await this.page.locator("input[name='lastname']") 14 | .type(lastname); 15 | } 16 | async enterEmail(email: string) { 17 | await this.page.locator("input[name='email']") 18 | .type(email); 19 | } 20 | 21 | async enterTelephone(phone: string) { 22 | await this.page.locator("input[name='telephone']") 23 | .type(phone); 24 | } 25 | 26 | async enterPassword(password: string) { 27 | await this.page.locator("input[name='password']") 28 | .type(password); 29 | } 30 | 31 | async enterConfirmPassword(password: string) { 32 | await this.page.locator("input[name='confirm']") 33 | .type(password); 34 | } 35 | 36 | 37 | isSubscribeChecked() { 38 | return this.page.locator("#input-newsletter-no"); 39 | } 40 | 41 | async clickTermandConditon() { 42 | await this.page.click("//label[@for='input-agree']") 43 | } 44 | 45 | async clickContinueToRegister() { 46 | await Promise.all([ 47 | this.page.waitForNavigation({waitUntil:"networkidle"}), 48 | this.page.click("input[value='Continue']") 49 | ]) 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /pages/specialHotPage.ts: -------------------------------------------------------------------------------- 1 | import { Page } from "@playwright/test"; 2 | 3 | export default class SpecialHotPage{ 4 | 5 | 6 | constructor(public page: Page) { } 7 | 8 | async addFirstProductToTheCart() { 9 | await this.page.hover("//div[@class='image']/a", { 10 | strict: false 11 | }); 12 | await this.page.locator("(//button[@title='Add to Cart'])") 13 | .nth(0).click(); 14 | } 15 | async isToastVisible() { 16 | // await this.page.waitFor 17 | const toast = this.page.locator("//a[.='View Cart ']"); 18 | await toast.waitFor({state:"visible"}) 19 | return toast; 20 | } 21 | } -------------------------------------------------------------------------------- /playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { devices, PlaywrightTestConfig } from '@playwright/test'; 2 | 3 | // const capabilities = { 4 | // browserName: "Chrome", // Browsers allowed: `Chrome`, `MicrosoftEdge`, `pw-chromium`, `pw-firefox` and `pw-webkit` 5 | // browserVersion: "latest", 6 | // "LT:Options": { 7 | // platform: "Windows 10", 8 | // build: "Playwright Test from config", 9 | // name: "Playwright Test - 1", 10 | // user: '', 11 | // accessKey: '', 12 | // network: true, 13 | // video: true, 14 | // console: true, 15 | // tunnel: false, // Add tunnel configuration if testing locally hosted webpage 16 | // tunnelName: "", // Optional 17 | // geoLocation: '', // country code can be fetched from https://www.lambdatest.com/capabilities-generator/ 18 | // }, 19 | // }; 20 | const config: PlaywrightTestConfig = { 21 | projects: [ 22 | { 23 | name: "chrome:latest:MacOS Catalina@lambdatest", 24 | use: { 25 | viewport: { width: 1920, height: 1080 }, 26 | }, 27 | }, 28 | { 29 | name: "chrome:latest:Windows 10@lambdatest", 30 | use: { 31 | viewport: { width: 1280, height: 720 }, 32 | }, 33 | }, 34 | { 35 | name: "chrome", 36 | use: { 37 | ...devices["Desktop Chrome"] 38 | } 39 | }, 40 | { 41 | name: "firefox", 42 | use: { 43 | ...devices["Desktop Firefox"] 44 | } 45 | } 46 | ], 47 | 48 | testMatch: ["pomtest/addToCartUsingFixture.test.ts"], 49 | use: { 50 | // connectOptions: { 51 | // wsEndpoint: `wss://cdp.lambdatest.com/playwright?capabilities= 52 | // ${encodeURIComponent(JSON.stringify(capabilities))}` 53 | // }, 54 | baseURL: "https://ecommerce-playground.lambdatest.io/index.php?", 55 | headless: false, 56 | screenshot: "on", 57 | video: "on", 58 | launchOptions: { 59 | // slowMo: 1000 60 | }, 61 | }, 62 | timeout: 60 * 1000 * 5, 63 | retries: 0, 64 | reporter: [["dot"], ["json", { 65 | outputFile: "jsonReports/jsonReport.json" 66 | }], ["html", { 67 | open: "never" 68 | }]] 69 | }; 70 | 71 | export default config; 72 | -------------------------------------------------------------------------------- /pomtest/addToCart.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "@playwright/test"; 2 | import RegisterPage from "../pages/registerPage" 3 | import LoginPage from "../pages/loginPage" 4 | import HomePage from "../pages/homePage" 5 | import SpecialHotPage from "../pages/specialHotPage" 6 | 7 | const email = "Koushik03@mailinator.com"; 8 | const password = "Koushik@123"; 9 | test.describe("Page object test demo", async () => { 10 | 11 | // test.use({ 12 | // baseURL:"somsomos" 13 | // }) 14 | test("Register test_01", async ({ page, baseURL }, testInfo) => { 15 | console.log('TITLE: ' + testInfo.title); 16 | 17 | const register = new RegisterPage(page); 18 | await page.goto(`${baseURL}route=account/register`); 19 | await register.enterFirstName("Koushik"); 20 | await register.enterLastName("Chatterjee") 21 | await register.enterEmail(email); 22 | await register.enterTelephone("1234567890") 23 | await register.enterPassword(password); 24 | await register.enterConfirmPassword(password); 25 | expect(register.isSubscribeChecked()).toBeChecked(); 26 | await register.clickTermandConditon(); 27 | await register.clickContinueToRegister(); 28 | console.log('STATUS: ' + testInfo.status); 29 | 30 | 31 | }) 32 | 33 | test("Login test_02", async ({ page, baseURL }) => { 34 | const login = new LoginPage(page); 35 | await page.goto(`${baseURL}route=account/login`) 36 | await login.enterEmail(email); 37 | await login.enterLoginPassword(password); 38 | await login.clickLoginBtn(); 39 | expect(await page.title()).toBe("My Account"); 40 | }) 41 | 42 | test("Add to cart test_03", async ({ page, baseURL }) => { 43 | const login = new LoginPage(page); 44 | const homePage = new HomePage(page); 45 | const special = new SpecialHotPage(page); 46 | await page.goto(`${baseURL}route=account/login`) 47 | await login.login(email, password); 48 | await homePage.clickOnSpecialHotMenu(); 49 | await special.addFirstProductToTheCart(); 50 | const isCartVisible = await special.isToastVisible(); 51 | expect(isCartVisible).toBeVisible(); 52 | }) 53 | }) -------------------------------------------------------------------------------- /pomtest/addToCartUsingFixture.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "@playwright/test"; 2 | import { test } from "../base/pomFixture"; 3 | import * as data from "../test-data/addTocart-test-data.json" 4 | 5 | // test.use({ 6 | // browserName: "firefox" 7 | // }) 8 | test.describe("Page object test demo", async () => { 9 | 10 | test("Register test_01", async ({ page, baseURL, registerPage }) => { 11 | await page.goto(`${baseURL}route=account/register`); 12 | await registerPage.enterFirstName(data.fistname); 13 | await registerPage.enterLastName(data.lastname) 14 | await registerPage.enterEmail(data.email); 15 | await registerPage.enterTelephone(data.phone_number) 16 | await registerPage.enterPassword(data.password); 17 | await registerPage.enterConfirmPassword(data.password); 18 | expect(registerPage.isSubscribeChecked()).toBeChecked(); 19 | await registerPage.clickTermandConditon(); 20 | await registerPage.clickContinueToRegister(); 21 | }) 22 | 23 | test("Login test_02", async ({ page, baseURL, loginPage }) => { 24 | await page.goto(`${baseURL}route=account/login`) 25 | await loginPage.enterEmail(data.email); 26 | await loginPage.enterLoginPassword(data.password); 27 | await loginPage.clickLoginBtn(); 28 | expect(await page.title()).toBe("My Account"); 29 | }) 30 | 31 | test("Add to cart test_03", async ({ page, baseURL, loginPage, homePage, specialPage }) => { 32 | 33 | await page.goto(`${baseURL}route=account/login`) 34 | await loginPage.login(data.email, data.password); 35 | await homePage.clickOnSpecialHotMenu(); 36 | await specialPage.addFirstProductToTheCart(); 37 | const isCartVisible = await specialPage.isToastVisible(); 38 | expect(isCartVisible).toBeVisible(); 39 | }) 40 | }) -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Playwright Tutorial - Typescript 2 | 3 | ## What is Playwright? 4 | - The playwright is a Node.js library to automate Chromium, Firefox, and WebKit with a single API. Playwright is built to enable cross-browser web testing. 5 | - Playwright by Microsoft did start as a fork of Puppeteer Puppeteer is a node library to automate the chromium browsers with the JavaScript API 6 | ## How to use? 7 | - Clone the repository 8 | - open the project 9 | - From the terminal install all the dependencies using 'npm i' 10 | 11 | ## Required software 12 | - Node js -> v.14 or above 13 | - VS Code 14 | - Playwright Vs Code Extension 15 | 16 | ## Video list 17 | Please follow in a sequence: 18 | 19 | - [How To Setup Playwright Test Automation Framework | Playwright Tutorial🎭| Part I | LambdaTest](https://youtu.be/06HIhFcpBDo) 20 | - [How To Use Functions And Selectors | Playwright With Typescript Tutorial 🎭| Part II | LambdaTest](https://youtu.be/UWeXnulWfJs) 21 | - [Playwright Testing Features | Playwright With TypeScript Tutorial🎭| Part III | LambdaTest](https://youtu.be/1INdYpaXqLE) -------------------------------------------------------------------------------- /test-data/addTocart-test-data.json: -------------------------------------------------------------------------------- 1 | { 2 | "fistname":"Koushik", 3 | "lastname":"Chatterjee", 4 | "email": "Koushik04@mailinator.com", 5 | "password":"Koushik@123", 6 | "phone_number":"1254124874" 7 | } -------------------------------------------------------------------------------- /tests/alerts.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "@playwright/test"; 2 | 3 | 4 | test("handling alerts", async ({ page }) => { 5 | 6 | await page.goto("https://www.lambdatest.com/selenium-playground/javascript-alert-box-demo"); 7 | 8 | page.on("dialog", async (alert) => { 9 | const text = alert.defaultValue(); 10 | console.log(text);; 11 | await alert.accept("koushik"); 12 | }) 13 | await page.locator("button:has-text('Click Me')").nth(2).click(); 14 | // expect(page.locator("id=confirm-demo")).toContainText("Cancel!") 15 | expect(page.locator("id=prompt-demo")).toContainText("'koushik'"); 16 | 17 | }) 18 | 19 | test("Modal alert", async ({ page }) => { 20 | await page.goto("https://www.lambdatest.com/selenium-playground/bootstrap-modal-demo") 21 | await page.click("//button[@data-target='#myModal']") 22 | await page.click("(//button[text()='Save Changes'])[1]") 23 | }) -------------------------------------------------------------------------------- /tests/basicInteractions.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "@playwright/test"; 2 | 3 | test("Interaction with inputs", async ({ page }) => { 4 | 5 | await page.goto("https://www.lambdatest.com/selenium-playground/simple-form-demo"); 6 | const messageInput = page.locator("input#user-message"); 7 | await messageInput.scrollIntoViewIfNeeded(); 8 | console.log(await messageInput.getAttribute("placeholder")); 9 | expect(messageInput).toHaveAttribute("placeholder", "Please enter your Message") 10 | console.log('Before entering data: ' + await messageInput.inputValue()); 11 | await messageInput.type("Hi koushik"); 12 | console.log('After entering data: ' + await messageInput.inputValue()) 13 | 14 | 15 | }) 16 | 17 | test("Sum", async ({ page }) => { 18 | await page.goto("https://www.lambdatest.com/selenium-playground/simple-form-demo"); 19 | const sum1input = page.locator("#sum1") 20 | const sum2input = page.locator("#sum2") 21 | 22 | const getValuesBtn = page.locator("//button[text()='Get values']") 23 | let num1 = 121; 24 | let num2 = 546 25 | await sum1input.fill("" + num1); 26 | await sum2input.type("" + num2); 27 | await getValuesBtn.click() 28 | const result = page.locator("#addmessage") 29 | console.log(await result.textContent()); 30 | let expectedResult = num1 + num2; 31 | expect(result).toHaveText("" + expectedResult) 32 | 33 | }) 34 | 35 | test("Checkbox", async ({ page }) => { 36 | 37 | await page.goto("https://www.lambdatest.com/selenium-playground/checkbox-demo") 38 | const singleCheckbox = page.locator("id=isAgeSelected") 39 | expect(singleCheckbox).not.toBeChecked(); 40 | await singleCheckbox.check(); 41 | expect(singleCheckbox).toBeChecked(); 42 | 43 | 44 | }) -------------------------------------------------------------------------------- /tests/calendar.test.ts: -------------------------------------------------------------------------------- 1 | import { test } from "@playwright/test"; 2 | import moment from "moment"; 3 | 4 | // test("Calendar demo using fill function", async ({ page }) => { 5 | // await page.goto("https://www.lambdatest.com/selenium-playground/bootstrap-date-picker-demo"); 6 | // let date = "1994-12-04" 7 | 8 | // await page.fill("id=birthday", date); 9 | // await page.waitForTimeout(3000) 10 | // }) 11 | 12 | test("Calendar demo using moment", async ({ page }) => { 13 | 14 | await page.goto("https://www.lambdatest.com/selenium-playground/bootstrap-date-picker-demo"); 15 | 16 | await selectDate(12, "December 2017"); 17 | 18 | await page.reload(); 19 | 20 | await selectDate(5, "December 2023"); 21 | 22 | await page.reload(); 23 | 24 | await selectDate(2, "July 2022"); 25 | 26 | 27 | await page.waitForTimeout(3000) 28 | 29 | 30 | 31 | async function selectDate(date: number, dateToSelect: string) { 32 | await page.click("//input[@placeholder='Start date']") 33 | 34 | const mmYY = page.locator("(//table[@class='table-condensed']//th[@class='datepicker-switch'])[1]"); 35 | const prev = page.locator("(//table[@class='table-condensed']//th[@class='prev'])[1]"); 36 | const next = page.locator("(//table[@class='table-condensed']//th[@class='next'])[1]"); 37 | 38 | // let dateToSelect: string = "May 2019"; 39 | const thisMonth = moment(dateToSelect, "MMMM YYYY").isBefore(); 40 | console.log("this month? " + thisMonth); 41 | while (await mmYY.textContent() != dateToSelect) { 42 | if (thisMonth) { 43 | await prev.click(); 44 | } else { 45 | await next.click(); 46 | } 47 | } 48 | await page.click(`//td[@class='day'][text()='${date}']`); 49 | } 50 | }) -------------------------------------------------------------------------------- /tests/dropdown.test.ts: -------------------------------------------------------------------------------- 1 | import { test } from "@playwright/test"; 2 | 3 | 4 | test("handling dropdown", async ({ page }) => { 5 | 6 | 7 | await page.goto("https://www.lambdatest.com/selenium-playground/select-dropdown-demo"); 8 | await page.selectOption("#select-demo", { 9 | // label: "Tuesday" 10 | // value: "Friday" 11 | index: 5 12 | }) 13 | await page.waitForTimeout(3000); 14 | 15 | await page.selectOption("#multi-select", [ 16 | { 17 | label: "Texas" 18 | }, { 19 | index: 2 20 | }, { 21 | value: "Washington" 22 | } 23 | ]) 24 | }) 25 | 26 | test.only("Bootstrap dropdown", async ({ page }) => { 27 | await page.goto("https://www.lambdatest.com/selenium-playground/jquery-dropdown-search-demo"); 28 | await selectCountry("India"); 29 | await selectCountry("Denmark"); 30 | await selectCountry("South Africa"); 31 | // await page.waitForTimeout(3000) 32 | 33 | async function selectCountry(countryName) { 34 | await page.click("#country+span"); 35 | await page.locator("ul#select2-country-results") 36 | .locator("li", { 37 | hasText: countryName 38 | }).click(); 39 | } 40 | }) -------------------------------------------------------------------------------- /tests/frames.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "@playwright/test"; 2 | 3 | test("Interact with frames", async ({ page }) => { 4 | 5 | await page.goto("https://letcode.in/frame"); 6 | const allframes = page.frames(); 7 | console.log("No.of frames: " + allframes.length); 8 | 9 | const frame = page.frameLocator("#firstFr") 10 | await frame.locator("input[name='fname']").fill("Koushik"); 11 | await frame.locator("input[name='lname']").fill("Chatterjee"); 12 | 13 | const innerFrame = frame.frameLocator("iframe[src='innerFrame']") 14 | await innerFrame.locator("input[name='email']").fill("koushik@gmail.com") 15 | 16 | await frame.locator("input[name='fname']").fill("letcode"); 17 | 18 | // const myFrame = page.frame("firstFr") 19 | // // if (myFrame != null) { 20 | // // await myFrame.fill("", "") 21 | // // } 22 | // await myFrame?.fill("input[name='fname']", "koushik") 23 | // await myFrame?.fill("input[name='lname']", "chatterjee") 24 | 25 | // expect(await myFrame?.locator("p.has-text-info").textContent()).toContain("You have entered") 26 | 27 | 28 | await page.waitForTimeout(3000); 29 | 30 | 31 | 32 | 33 | 34 | }) -------------------------------------------------------------------------------- /tests/login.test.ts: -------------------------------------------------------------------------------- 1 | import { chromium, test, expect } from "@playwright/test" 2 | 3 | 4 | // LambdaTest capabilities 5 | const capabilities = { 6 | browserName: "Chrome", // Browsers allowed: `Chrome`, `MicrosoftEdge`, `pw-chromium`, `pw-firefox` and `pw-webkit` 7 | browserVersion: "latest", 8 | "LT:Options": { 9 | platform: "Windows 10", 10 | build: "Playwright Test Build", 11 | name: "Playwright Test", 12 | user: '', 13 | accessKey: '', 14 | network: true, 15 | video: true, 16 | console: true, 17 | tunnel: false, // Add tunnel configuration if testing locally hosted webpage 18 | tunnelName: "", // Optional 19 | geoLocation: '', // country code can be fetched from https://www.lambdatest.com/capabilities-generator/ 20 | }, 21 | }; 22 | test("Login test demo", async () => { 23 | 24 | const browser = await chromium.connect(`wss://cdp.lambdatest.com/playwright?capabilities= 25 | ${encodeURIComponent(JSON.stringify(capabilities))}`); 26 | const context = await browser.newContext(); 27 | const page = await context.newPage(); 28 | 29 | await page.goto("https://ecommerce-playground.lambdatest.io/") 30 | await page.hover("//a[@data-toggle='dropdown']//span[contains(.,'My account')]") 31 | // await page.click("text=Login") 32 | await page.click("'Login'") 33 | await page.fill("input[name='email']", "koushik350@gmail.com") 34 | await page.fill("input[name='password']", "Pass123$") 35 | await page.click("input[value='Login']"); 36 | 37 | await page.close(); 38 | await context.close(); 39 | await browser.close(); 40 | 41 | // await page.waitForTimeout(5000); 42 | 43 | // const newContext = await browser.newContext() 44 | 45 | // const newPage = await newContext.newPage(); 46 | // await newPage.goto("https://ecommerce-playground.lambdatest.io/index.php?route=account/login") 47 | 48 | // await newPage.waitForTimeout(5000); 49 | 50 | }) -------------------------------------------------------------------------------- /tests/recorded.test.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | 3 | test('test', async ({ page }) => { 4 | 5 | // Go to https://ecommerce-playground.lambdatest.io/ 6 | await page.goto('https://ecommerce-playground.lambdatest.io/'); 7 | 8 | // Click a:has-text("Login") 9 | await page.hover("//a[@data-toggle='dropdown']//span[contains(.,'My account')]") 10 | 11 | await page.locator('a:has-text("Login")').click(); 12 | await expect(page).toHaveURL('https://ecommerce-playground.lambdatest.io/index.php?route=account/login'); 13 | 14 | // Click [placeholder="E-Mail Address"] 15 | await page.locator('[placeholder="E-Mail Address"]').click(); 16 | 17 | // Fill [placeholder="E-Mail Address"] 18 | await page.locator('[placeholder="E-Mail Address"]').fill('koushik350@gmail.com'); 19 | 20 | // Press Tab 21 | await page.locator('[placeholder="E-Mail Address"]').press('Tab'); 22 | 23 | // Fill [placeholder="Password"] 24 | await page.locator('[placeholder="Password"]').fill('Pass123$'); 25 | 26 | // Click input:has-text("Login") 27 | await page.locator('input:has-text("Login")').click(); 28 | await expect(page).toHaveURL('https://ecommerce-playground.lambdatest.io/index.php?route=account/account'); 29 | 30 | // Click text=Edit your account information 31 | await page.locator('text=Edit your account information').click(); 32 | await expect(page).toHaveURL('https://ecommerce-playground.lambdatest.io/index.php?route=account/edit'); 33 | 34 | // Click [placeholder="First Name"] 35 | await page.locator('[placeholder="First Name"]').click(); 36 | 37 | // Fill [placeholder="First Name"] 38 | await page.locator('[placeholder="First Name"]').fill('koushik'); 39 | 40 | // Click text=Continue 41 | await page.locator('text=Continue').click(); 42 | await expect(page).toHaveURL('https://ecommerce-playground.lambdatest.io/index.php?route=account/account'); 43 | 44 | // Click span:has-text("Logout") 45 | await page.hover("//a[@data-toggle='dropdown']//span[contains(.,'My account')]") 46 | 47 | await page.locator('span:has-text("Logout")').click(); 48 | await expect(page).toHaveURL('https://ecommerce-playground.lambdatest.io/index.php?route=account/login'); 49 | 50 | }); -------------------------------------------------------------------------------- /tests/uploadDownload.test.ts: -------------------------------------------------------------------------------- 1 | import { test } from "@playwright/test"; 2 | 3 | 4 | test("Download files", async ({ page }) => { 5 | 6 | await page.goto("https://www.lambdatest.com/selenium-playground/generate-file-to-download-demo"); 7 | await page.type("#textbox", "Like, Share, comment & subs"); 8 | await page.click("id=create") 9 | const download = await Promise.all([ 10 | page.waitForEvent("download"), 11 | page.click("id=link-to-download") 12 | ]) 13 | const fileName = download[0].suggestedFilename() 14 | await download[0].saveAs(fileName); 15 | // const path = await download[0].path(); 16 | // console.log(path); 17 | 18 | }) 19 | 20 | test.only("Upload files", async ({ page }) => { 21 | await page.goto("https://blueimp.github.io/jQuery-File-Upload/") 22 | // await page.setInputFiles("input[type='file']", 23 | // ["uploadItems/apple.png", "uploadItems/mango.png"]); 24 | 25 | const [uploadFiles] = await Promise.all([ 26 | page.waitForEvent("filechooser"), 27 | page.click("input[type='file']") 28 | ]) 29 | const isMultiple = uploadFiles.isMultiple(); 30 | console.log(isMultiple); 31 | uploadFiles.setFiles( 32 | ["uploadItems/apple.png", 33 | "uploadItems/mango.png"] 34 | ) 35 | 36 | 37 | 38 | 39 | await page.waitForTimeout(3000); 40 | }) -------------------------------------------------------------------------------- /tests/windows.test.ts: -------------------------------------------------------------------------------- 1 | let facebookPage: Page; 2 | import { expect, Page, test } from "@playwright/test"; 3 | 4 | test("Interact with multiple tabs", async ({ page }) => { 5 | 6 | await page.goto("https://www.lambdatest.com/selenium-playground/window-popup-modal-demo"); 7 | 8 | // console.log(page.url()); 9 | 10 | 11 | const [multiPage] = await Promise.all([ 12 | page.waitForEvent("popup"), 13 | page.click("#followboth") 14 | ]) 15 | await multiPage.waitForLoadState(); 16 | 17 | const pages = multiPage.context().pages(); 18 | console.log('No.of tabs: ' + pages.length); 19 | 20 | pages.forEach(tab => { 21 | console.log(tab.url()); 22 | }) 23 | 24 | for (let index = 0; index < pages.length; index++) { 25 | const url = pages[index].url() 26 | if (url == "https://www.facebook.com/lambdatest/") { 27 | facebookPage = pages[index]; 28 | } 29 | } 30 | const text = await facebookPage.textContent("//h1") 31 | console.log(text); 32 | 33 | 34 | // await pages[1].fill("", "kous"); 35 | 36 | 37 | // const [newWindow] = await Promise.all([ 38 | // page.waitForEvent("popup"), 39 | // page.click("'Follow On Twitter'") 40 | // ]); 41 | 42 | // console.log(newWindow.url()); 43 | // newWindow.fill("", "") 44 | 45 | 46 | 47 | 48 | 49 | }) -------------------------------------------------------------------------------- /uploadItems/apple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortoniKC/playwright-ts-lambdatest/2f113809ea6019308b2c46e2f3da3ed940eada48/uploadItems/apple.png -------------------------------------------------------------------------------- /uploadItems/mango.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortoniKC/playwright-ts-lambdatest/2f113809ea6019308b2c46e2f3da3ed940eada48/uploadItems/mango.png --------------------------------------------------------------------------------