├── .env ├── .gitignore ├── ExpectedResults └── globalexpected.json ├── README.md ├── hars ├── 25cc30e4a440111abd545551113b7bf2e2cad209.bin └── fruit.har ├── package-lock.json ├── package.json ├── pages ├── homepage.js ├── playlistpage.js └── resultpage.js ├── playwright.config.js ├── quize.txt ├── screenshots ├── element.png ├── fullpage.png └── page.png ├── selectors └── globalselector.json ├── test-data ├── qa │ ├── google.json │ └── testdata.csv └── stage │ └── google.json ├── tests-examples └── demo-todo-app.spec.js └── tests ├── annotations.spec.js ├── apimocking.spec.js ├── assertions.spec.js ├── datadriventestingcsv.spec.js ├── datadriventestingjson.spec.js ├── datepicker.spec.js ├── demo.spec.js ├── dropdownlist.spec.js ├── example.spec.js ├── failedtest.spec.js ├── firsttest.spec.js ├── google.spec.js ├── group.spec.js ├── hooks.spec.js ├── iframedraganddrop.spec.js ├── keyboardactions.spec.js ├── locators.spec.js ├── mfatest.spec.js ├── mouseactions.spec.js ├── multi_tabs.spec.js ├── objectrepositorytest.spec.js ├── pageobjecttest.spec.js ├── parameterizetest.spec.js ├── phone_call_test.spec.js ├── readdatabasedonenv.spec.js ├── readenvfile.spec.js ├── recordatcursortest.spec.js ├── recordtest.spec.js ├── screenshots.spec.js ├── softassertion.spec.js ├── tagtest.spec.js ├── testerstalk.spec.js ├── visualtesting.spec.js └── visualtesting.spec.js-snapshots └── githubpage-Google-Chrome-win32.png /.env: -------------------------------------------------------------------------------- 1 | ENV=stage 2 | URL=https://www.google.com/ 3 | USER_NAME=1234DF 4 | PASSWORD=DFGHJK67 5 | 6 | #MFA token 7 | AUTHENTICATOR_SECRET= 8 | MFA_APP_USER= 9 | MFA_APP_PASSWORK= 10 | 11 | #Twilio 12 | TWILIO_ACCOUNT_SID= 13 | TWILIO_AUTH_TOKEN= 14 | TWIML_URL=https://demo.twilio.com/welcome/voice/ 15 | TWILIO_PHONE_NUMBER=+16 16 | TO_PHONE_NUMBER=+91 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | /test-results/ 3 | /playwright-report/ 4 | /blob-report/ 5 | /playwright/.cache/ 6 | -------------------------------------------------------------------------------- /ExpectedResults/globalexpected.json: -------------------------------------------------------------------------------- 1 | { 2 | "Tab":{ 3 | "Title":"Playwright Tutorial Full Course 2024 | Playwright Testing Tutorial - YouTube" 4 | } 5 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Playwright Full Courses 2 | 1. Playwright Tutorial Full Course - https://bit.ly/playwright-tutorial-automation-testing 3 | 2. Playwright API Testing Tutorial - https://bit.ly/playwright-api-testing-tutorial 4 | 3. Playwright with Dynamics 365 CRM - https://youtu.be/WwovRRp0f4o?si=oqPE2ux7UcDeJMm6 5 | 4. Playwright with Azure DevOps Pipeline - https://bit.ly/playwright-azure-devops-tutorial 6 | 7 | #### Install Playwright & Select Configurations 8 | - npm init playwright@latest 9 | 10 | Playwright will download the browsers needed as well as create the following files. 11 | 12 | - node_modules 13 | - playwright.config.js 14 | - package.json 15 | - package-lock.json 16 | - tests/ 17 | example.spec.js 18 | - tests-examples/ 19 | demo-todo-app.spec.js 20 | 21 | 22 | #### dotenv Package Installation Command 23 | - npm install dotenv --save 24 | 25 | #### csv-parse Package Installation Command 26 | - npm install csv-parse 27 | 28 | #### faker-js plugin for test data generation 29 | - npm install @faker-js/faker --save-dev 30 | 31 | #### luxon plugin for custom dates 32 | - npm install --save luxon 33 | 34 | ## How to update to playwright to the latest version 35 | - npm install -D @playwright/test@latest 36 | - npx playwright install --with-deps #Also download new browser binaries and their dependencies: 37 | 38 | ## Playwright Important Commands 39 | 40 | npx playwright install 41 | - Install Browsers manually. 42 | 43 | npx playwright test 44 | - Runs the end-to-end tests. 45 | 46 | npx playwright test --ui 47 | - Starts the interactive UI mode. 48 | 49 | npx playwright test --project=chromium 50 | - Runs the tests only on Desktop Chrome. 51 | 52 | npx playwright test example 53 | - Runs the tests in a specific file. 54 | 55 | npx playwright test --debug 56 | - Runs the tests in debug mode. 57 | 58 | npx playwright codegen 59 | - Auto generate tests with Codegen. 60 | 61 | We suggest that you begin by typing: 62 | 63 | npx playwright test 64 | 65 | ### And check out the following files: 66 | - .\tests\example.spec.js - Example end-to-end test 67 | - .\tests-examples\demo-todo-app.spec.js - Demo Todo App end-to-end tests 68 | - .\playwright.config.js - Playwright Test configuration 69 | 70 | ## Allure Report with Playwright [Screenshots, Videos & Traces] 71 | - Step1: Install Allure Report command-line tool 72 | ### npm install -g --save-dev allure-commandline 73 | 74 | - Step2: Install the Allure Playwright adapter. 75 | ### npm install --save-dev allure-playwright 76 | 77 | - Step3: Add below config in playwright.config.js file. 78 | ### reporter:[ 79 | ### ['html'], 80 | ### ['allure-playwright'] 81 | ### ], 82 | 83 | - Step4: Run Playwright tests. 84 | ### npx playwright test 85 | 86 | - Step5: Generate Allure Report 87 | ### npx allure serve allure-results 88 | 89 | or 90 | 91 | ### allure generate allure-results --clean 92 | ### allure open 93 | 94 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/0dc08076-a4ba-4f9f-9b89-ecd8fc81f5ba) 95 | 96 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/5fc751fa-81ca-4dc6-9c49-54834258d0aa) 97 | 98 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/36161f37-2cf2-4373-a30d-f888adb405de) 99 | 100 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/b7ef2588-adbd-40fc-9801-ed1554fd38ef) 101 | 102 | 103 | 104 | ## Playwright Test Report 105 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/dd9e360b-bd9e-425a-9191-848a13791d29) 106 | 107 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/9ea0128b-5906-476f-9fc7-615b240d7623) 108 | 109 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/379bb630-b84d-4a47-a70e-8afca0d33240) 110 | 111 | 112 | ## Integrate Playwright with Azure Devops Pipeline 113 | There are 2 options, option1 is using yaml file & option2 is without using yaml file. let's see one by one 114 | 115 | 1. Option1 - Using YAML File 116 | - Step1: Create a new project in ADO then Click on Project 117 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/0ec3b6b7-748f-4d0a-80bf-762e24728afb) 118 | 119 | - Step2: Click on Repos & Let's create new repository, Click on New reposiotry 120 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/fe0485c8-2708-456b-9030-a046b1170c70) 121 | 122 | - Step3: Enter Repository name & Click on Create 123 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/ea15010a-4308-41c2-883e-f0ddee48908f) 124 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/0ee53f40-2d9e-4dbb-8301-5cc2c615d647) 125 | 126 | - Step4: Click on Clone button and get the URL. Go to your system then clone repository. 127 | - Step5: Add all the playwright framework folders inside cloned repository 128 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/b8039254-cba5-46ff-9696-0aad20dd9876) 129 | 130 | - Step6: Push all the folders into Azure devops 131 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/add3e34a-5ba8-4792-9d2c-dbae06bc6a64) 132 | 133 | - Step7: Repository is ready now, let's create pipeline. Click on Pipelines->Create Pipeline 134 | - ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/7bb2f8dc-8253-46ab-879a-743446211bdf) 135 | 136 | - Step8: Click on Azure Repos Git 137 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/885628e1-8e4c-43fc-ba6a-6125ec34e6fb) 138 | 139 | - Step9: Select previously created repository 140 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/09b1489d-f699-4885-84a4-c06554adc3e6) 141 | 142 | - Step10: Select Starter Pipeline 143 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/3db45ed6-c0c9-4033-b786-b8ca7e263ce4) 144 | 145 | - Step11: Copy below yaml content and paste it inside azure-pipelines.yml file. 146 | ``` 147 | trigger: 148 | - main 149 | 150 | pool: 151 | vmImage: ubuntu-latest 152 | 153 | steps: 154 | - task: NodeTool@0 155 | inputs: 156 | versionSpec: '18' 157 | displayName: 'Install Node.js' 158 | - script: npm ci 159 | displayName: 'npm ci' 160 | - script: npx playwright install --with-deps 161 | displayName: 'Install Playwright browsers' 162 | - script: npx playwright test 163 | displayName: 'Run Playwright tests' 164 | env: 165 | CI: 'true' 166 | ``` 167 | If you are running in self hosted agent replace pool commands 168 | ``` 169 | pool: 170 | name: AgentPoolName 171 | demands: 172 | - agent.name -equals AgentName 173 | ``` 174 | - Step12: Click on Save and run 175 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/208f9b43-735a-45e1-b5c3-699df9e6d8f2) 176 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/41262f5d-6e80-4274-a4fc-75d0536e73a7) 177 | 178 | - Step13: You will see job queued like this. 179 | - ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/1fff0860-2ac5-45b0-aa45-757afb76777e) 180 | 181 | - Step14: Click on Job & Verify build status. 182 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/66326c8f-d789-4856-b90c-8909bef95930) 183 | 184 | - Step15: Now let's Upload playwright-report folder with Azure Pipelines & Report generation 185 | Firstly update azure-pipelines.yml file 186 | ``` 187 | trigger: 188 | - main 189 | 190 | pool: 191 | vmImage: ubuntu-latest 192 | 193 | steps: 194 | - task: NodeTool@0 195 | inputs: 196 | versionSpec: '18' 197 | displayName: 'Install Node.js' 198 | - script: npm ci 199 | displayName: 'npm ci' 200 | - script: npx playwright install --with-deps 201 | displayName: 'Install Playwright browsers' 202 | - script: npx playwright test 203 | displayName: 'Run Playwright tests' 204 | env: 205 | CI: 'true' 206 | 207 | - task: PublishTestResults@2 208 | displayName: 'Publish test results' 209 | inputs: 210 | searchFolder: 'test-results' 211 | testResultsFormat: 'JUnit' 212 | testResultsFiles: 'e2e-junit-results.xml' 213 | mergeTestResults: true 214 | failTaskOnFailedTests: true 215 | testRunTitle: 'My End-To-End Tests' 216 | condition: succeededOrFailed() 217 | - task: PublishPipelineArtifact@1 218 | inputs: 219 | targetPath: playwright-report 220 | artifact: playwright-report 221 | publishLocation: 'pipeline' 222 | condition: succeededOrFailed() 223 | ``` 224 | 225 | - Step16: Verify playwright-report folder attachment & report. 226 | From job we can navigate into artifacts folder. Download playwright report and verify results. 227 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/54aaf4b4-7715-435d-b96a-7a19c23fa384) 228 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/5ed6c543-4162-43a9-9f21-9643d7f52438) 229 | 230 | 231 | 2. Option2 - Without using YAML File 232 | - Step1: Repeat step 1 to 6 above from Option1 233 | - Step2: Click on Pipelines then click on New Pipeline 234 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/1f753af4-881e-495d-a7dd-8c9163de97ff) 235 | 236 | - Step3: Click on Use the classic editor & Click on Continue 237 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/499f6cf4-0458-4aba-813a-ad131cea4b02) 238 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/332011f7-0ae4-46ce-a9c2-3c2a9d66f599) 239 | 240 | - Step4: Click on Emtpy job 241 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/d84dda85-cbc0-4c9f-9147-bc1de36823c4) 242 | 243 | - Step5: Click on + icon, Search for Node and add Node.js tool installer 244 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/73d32c4d-2cd1-4f78-beb7-ec1bf5f5138a) 245 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/64fcf35f-1200-4ccf-b34c-d53072728ced) 246 | 247 | 248 | - Step6: Select just now added task and add Node v16 becuase playwright supports for Node v14 and above 249 | - ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/aa804427-464c-434f-b4e4-27547b245bd9) 250 | 251 | - Step7: Click on + icon, Similary add Command line task, 252 | Display name: Install Playwright & Dependencies 253 | Script: npm install && npx playwright install 254 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/df63a628-ccb4-4709-8c2a-166358dc5264) 255 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/70991c9e-ad21-4ab8-978e-ba02d0f5971f) 256 | 257 | Click on Advanced-> Click on little icon(i) & select the Link. This will enable working directory for the task. 258 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/1d6dc42d-e720-4446-b1f7-4589f105ff04) 259 | 260 | - Step8: Add another task by clicking on + icon, search for npm & Add npm 261 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/49eadf73-d640-4c7d-8ea6-730f2291d503) 262 | 263 | Enter Display name, Select Command as custom & Enter Command and Arguments as run tests 264 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/f055ace0-8cdb-46e7-9f24-33c808eef4ee) 265 | 266 | In this task we are referring to the package.json file. 267 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/6074a566-6efb-46a7-ad37-2108eed90bf8) 268 | 269 | - Step9: Once everthing is completed now it is a time run script. Click on Save & queue. 270 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/112334f9-6adb-43a5-b2d4-41f364c7527d) 271 | 272 | Add commit message then click save & run. 273 | 274 | - Step10: It looks like this 275 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/ae48637e-d0bf-4a32-8d93-2ea251301068) 276 | 277 | Click on Job and you will see a screen like this 278 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/b135a6c0-039c-4b90-934c-849b35e47cbc) 279 | 280 | - Step11: We can also upload playwright-report using Publish Pipeline Artifacts task 281 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/138a4af7-addd-4498-8296-64468c957610) 282 | 283 | - Step12: Let's Publish Test Results using Publish Test Results task 284 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/f0ea2efe-3509-4e48-baa5-01a2ec9f283d) 285 | 286 | 287 | - Let's run the pipeline 288 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/575518de-feed-4267-b7f1-290e4ad76903) 289 | 290 | - Artifacts are published & also we have published test results 291 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/d575766a-2f20-42f2-a1e3-aa5f71259823) 292 | 293 | ![image](https://github.com/BakkappaN/PlaywrightTutorialFullCourse/assets/22426896/45821475-feb2-4b16-a9ae-126c55cf20a1) 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | -------------------------------------------------------------------------------- /hars/25cc30e4a440111abd545551113b7bf2e2cad209.bin: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Strawberry", 4 | "id": 3 5 | }, 6 | { 7 | "name": "Banana", 8 | "id": 1 9 | }, 10 | { 11 | "name": "Tomato", 12 | "id": 5 13 | }, 14 | { 15 | "name": "Pear", 16 | "id": 4 17 | }, 18 | { 19 | "name": "Blackberry", 20 | "id": 64 21 | }, 22 | { 23 | "name": "Kiwi", 24 | "id": 66 25 | }, 26 | { 27 | "name": "Pineapple", 28 | "id": 10 29 | }, 30 | { 31 | "name": "Passionfruit", 32 | "id": 70 33 | }, 34 | { 35 | "name": "Orange", 36 | "id": 2 37 | }, 38 | { 39 | "name": "Raspberry", 40 | "id": 23 41 | }, 42 | { 43 | "name": "Watermelon", 44 | "id": 25 45 | }, 46 | { 47 | "name": "Lemon", 48 | "id": 26 49 | }, 50 | { 51 | "name": "Mango", 52 | "id": 27 53 | }, 54 | { 55 | "name": "Blueberry", 56 | "id": 33 57 | }, 58 | { 59 | "name": "Apple", 60 | "id": 6 61 | }, 62 | { 63 | "name": "Melon", 64 | "id": 41 65 | }, 66 | { 67 | "name": "Lime", 68 | "id": 44 69 | }, 70 | { 71 | "name": "rest assured by testers talk", 72 | "id": 101 73 | }, 74 | { 75 | "name": "postman by testers talk", 76 | "id": 102 77 | }, 78 | { 79 | "name": "api testing by testers talk", 80 | "id": 103 81 | }, 82 | { 83 | "name": "cypress by testers talk", 84 | "id": 104 85 | }, 86 | { 87 | "name": "playwright by testers talk", 88 | "id": 105 89 | } 90 | ] 91 | -------------------------------------------------------------------------------- /hars/fruit.har: -------------------------------------------------------------------------------- 1 | { 2 | "log": { 3 | "version": "1.2", 4 | "creator": { 5 | "name": "Playwright", 6 | "version": "1.46.1" 7 | }, 8 | "browser": { 9 | "name": "chromium", 10 | "version": "128.0.6613.85" 11 | }, 12 | "entries": [ 13 | { 14 | "startedDateTime": "2024-08-28T16:18:00.885Z", 15 | "time": 7.408, 16 | "request": { 17 | "method": "GET", 18 | "url": "https://demo.playwright.dev/api-mocking/api/v1/fruits", 19 | "httpVersion": "HTTP/2.0", 20 | "cookies": [], 21 | "headers": [ 22 | { "name": ":authority", "value": "demo.playwright.dev" }, 23 | { "name": ":method", "value": "GET" }, 24 | { "name": ":path", "value": "/api-mocking/api/v1/fruits" }, 25 | { "name": ":scheme", "value": "https" }, 26 | { "name": "accept", "value": "*/*" }, 27 | { "name": "accept-encoding", "value": "gzip, deflate, br, zstd" }, 28 | { "name": "accept-language", "value": "en-US" }, 29 | { "name": "cache-control", "value": "max-age=0" }, 30 | { "name": "priority", "value": "u=1, i" }, 31 | { "name": "referer", "value": "https://demo.playwright.dev/api-mocking/" }, 32 | { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"128\", \"Not;A=Brand\";v=\"24\", \"Google Chrome\";v=\"128\"" }, 33 | { "name": "sec-ch-ua-mobile", "value": "?0" }, 34 | { "name": "sec-ch-ua-platform", "value": "\"Windows\"" }, 35 | { "name": "sec-fetch-dest", "value": "empty" }, 36 | { "name": "sec-fetch-mode", "value": "cors" }, 37 | { "name": "sec-fetch-site", "value": "same-origin" }, 38 | { "name": "user-agent", "value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.18 Safari/537.36" } 39 | ], 40 | "queryString": [], 41 | "headersSize": -1, 42 | "bodySize": -1 43 | }, 44 | "response": { 45 | "status": 200, 46 | "statusText": "", 47 | "httpVersion": "HTTP/2.0", 48 | "cookies": [], 49 | "headers": [ 50 | { "name": "accept-ranges", "value": "bytes" }, 51 | { "name": "access-control-allow-origin", "value": "*" }, 52 | { "name": "age", "value": "0" }, 53 | { "name": "cache-control", "value": "max-age=600" }, 54 | { "name": "content-length", "value": "762" }, 55 | { "name": "content-type", "value": "application/octet-stream" }, 56 | { "name": "date", "value": "Wed, 28 Aug 2024 16:18:01 GMT" }, 57 | { "name": "etag", "value": "\"667ed88a-2fa\"" }, 58 | { "name": "expires", "value": "Wed, 28 Aug 2024 16:01:01 GMT" }, 59 | { "name": "last-modified", "value": "Fri, 28 Jun 2024 15:36:42 GMT" }, 60 | { "name": "server", "value": "GitHub.com" }, 61 | { "name": "vary", "value": "Accept-Encoding" }, 62 | { "name": "via", "value": "1.1 varnish" }, 63 | { "name": "x-cache", "value": "HIT" }, 64 | { "name": "x-cache-hits", "value": "0" }, 65 | { "name": "x-fastly-request-id", "value": "2d65abd7012a843f6406ec792a1e31791f2898ed" }, 66 | { "name": "x-github-request-id", "value": "A99A:266DC7:1CA1ED:2152E9:66CF4763" }, 67 | { "name": "x-proxy-cache", "value": "MISS" }, 68 | { "name": "x-served-by", "value": "cache-maa10226-MAA" }, 69 | { "name": "x-timer", "value": "S1724861881.902142,VS0,VE221" } 70 | ], 71 | "content": { 72 | "size": -1, 73 | "mimeType": "application/octet-stream", 74 | "_file": "25cc30e4a440111abd545551113b7bf2e2cad209.bin" 75 | }, 76 | "headersSize": -1, 77 | "bodySize": -1, 78 | "redirectURL": "" 79 | }, 80 | "cache": {}, 81 | "timings": { "send": -1, "wait": -1, "receive": 7.408 } 82 | } 83 | ] 84 | } 85 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "playwrighttutorialfullcourse", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "playwrighttutorialfullcourse", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "csv-parse": "^5.5.3", 13 | "dotenv": "^16.3.1", 14 | "otplib": "^12.0.1", 15 | "twilio": "^5.3.0" 16 | }, 17 | "devDependencies": { 18 | "@playwright/test": "^1.46.1", 19 | "@types/node": "^20.10.4", 20 | "allure-commandline": "^2.25.0", 21 | "allure-playwright": "^2.10.0" 22 | } 23 | }, 24 | "node_modules/@otplib/core": { 25 | "version": "12.0.1", 26 | "resolved": "https://registry.npmjs.org/@otplib/core/-/core-12.0.1.tgz", 27 | "integrity": "sha512-4sGntwbA/AC+SbPhbsziRiD+jNDdIzsZ3JUyfZwjtKyc/wufl1pnSIaG4Uqx8ymPagujub0o92kgBnB89cuAMA==" 28 | }, 29 | "node_modules/@otplib/plugin-crypto": { 30 | "version": "12.0.1", 31 | "resolved": "https://registry.npmjs.org/@otplib/plugin-crypto/-/plugin-crypto-12.0.1.tgz", 32 | "integrity": "sha512-qPuhN3QrT7ZZLcLCyKOSNhuijUi9G5guMRVrxq63r9YNOxxQjPm59gVxLM+7xGnHnM6cimY57tuKsjK7y9LM1g==", 33 | "dependencies": { 34 | "@otplib/core": "^12.0.1" 35 | } 36 | }, 37 | "node_modules/@otplib/plugin-thirty-two": { 38 | "version": "12.0.1", 39 | "resolved": "https://registry.npmjs.org/@otplib/plugin-thirty-two/-/plugin-thirty-two-12.0.1.tgz", 40 | "integrity": "sha512-MtT+uqRso909UkbrrYpJ6XFjj9D+x2Py7KjTO9JDPhL0bJUYVu5kFP4TFZW4NFAywrAtFRxOVY261u0qwb93gA==", 41 | "dependencies": { 42 | "@otplib/core": "^12.0.1", 43 | "thirty-two": "^1.0.2" 44 | } 45 | }, 46 | "node_modules/@otplib/preset-default": { 47 | "version": "12.0.1", 48 | "resolved": "https://registry.npmjs.org/@otplib/preset-default/-/preset-default-12.0.1.tgz", 49 | "integrity": "sha512-xf1v9oOJRyXfluBhMdpOkr+bsE+Irt+0D5uHtvg6x1eosfmHCsCC6ej/m7FXiWqdo0+ZUI6xSKDhJwc8yfiOPQ==", 50 | "dependencies": { 51 | "@otplib/core": "^12.0.1", 52 | "@otplib/plugin-crypto": "^12.0.1", 53 | "@otplib/plugin-thirty-two": "^12.0.1" 54 | } 55 | }, 56 | "node_modules/@otplib/preset-v11": { 57 | "version": "12.0.1", 58 | "resolved": "https://registry.npmjs.org/@otplib/preset-v11/-/preset-v11-12.0.1.tgz", 59 | "integrity": "sha512-9hSetMI7ECqbFiKICrNa4w70deTUfArtwXykPUvSHWOdzOlfa9ajglu7mNCntlvxycTiOAXkQGwjQCzzDEMRMg==", 60 | "dependencies": { 61 | "@otplib/core": "^12.0.1", 62 | "@otplib/plugin-crypto": "^12.0.1", 63 | "@otplib/plugin-thirty-two": "^12.0.1" 64 | } 65 | }, 66 | "node_modules/@playwright/test": { 67 | "version": "1.46.1", 68 | "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.46.1.tgz", 69 | "integrity": "sha512-Fq6SwLujA/DOIvNC2EL/SojJnkKf/rAwJ//APpJJHRyMi1PdKrY3Az+4XNQ51N4RTbItbIByQ0jgd1tayq1aeA==", 70 | "dev": true, 71 | "dependencies": { 72 | "playwright": "1.46.1" 73 | }, 74 | "bin": { 75 | "playwright": "cli.js" 76 | }, 77 | "engines": { 78 | "node": ">=18" 79 | } 80 | }, 81 | "node_modules/@types/node": { 82 | "version": "20.10.4", 83 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", 84 | "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", 85 | "dev": true, 86 | "dependencies": { 87 | "undici-types": "~5.26.4" 88 | } 89 | }, 90 | "node_modules/agent-base": { 91 | "version": "6.0.2", 92 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", 93 | "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", 94 | "dependencies": { 95 | "debug": "4" 96 | }, 97 | "engines": { 98 | "node": ">= 6.0.0" 99 | } 100 | }, 101 | "node_modules/allure-commandline": { 102 | "version": "2.25.0", 103 | "resolved": "https://registry.npmjs.org/allure-commandline/-/allure-commandline-2.25.0.tgz", 104 | "integrity": "sha512-HYMQwuX/8ySTrXqgr6ZY830c6xgRbSusxVwZIBbDyNTCDb3mqK2b1ENjsD8yhl/7/8S02NZCDAwJFxt3f8qL9Q==", 105 | "dev": true, 106 | "bin": { 107 | "allure": "bin/allure" 108 | } 109 | }, 110 | "node_modules/allure-js-commons": { 111 | "version": "2.10.0", 112 | "resolved": "https://registry.npmjs.org/allure-js-commons/-/allure-js-commons-2.10.0.tgz", 113 | "integrity": "sha512-DgACWBU2dchQD8tQOo5Y0MXx08SSzdgCnKBdwrOu29vITYBXih+0r8SbmrFYQhjAbn8eKMM+mXq+rKtjZRa2oA==", 114 | "dev": true, 115 | "dependencies": { 116 | "properties": "^1.2.1" 117 | } 118 | }, 119 | "node_modules/allure-playwright": { 120 | "version": "2.10.0", 121 | "resolved": "https://registry.npmjs.org/allure-playwright/-/allure-playwright-2.10.0.tgz", 122 | "integrity": "sha512-zDljPJ/Fnyd2fn7msChtZebwkSVmAGLe/oWK7okGi0Ed+iHZ0E5Vwe5Z5MtUdfLjnT/OkOduwmS7R/DHeTXFSA==", 123 | "dev": true, 124 | "dependencies": { 125 | "allure-js-commons": "2.10.0" 126 | } 127 | }, 128 | "node_modules/asynckit": { 129 | "version": "0.4.0", 130 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 131 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" 132 | }, 133 | "node_modules/axios": { 134 | "version": "1.7.7", 135 | "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", 136 | "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", 137 | "dependencies": { 138 | "follow-redirects": "^1.15.6", 139 | "form-data": "^4.0.0", 140 | "proxy-from-env": "^1.1.0" 141 | } 142 | }, 143 | "node_modules/buffer-equal-constant-time": { 144 | "version": "1.0.1", 145 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", 146 | "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" 147 | }, 148 | "node_modules/call-bind": { 149 | "version": "1.0.7", 150 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", 151 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", 152 | "dependencies": { 153 | "es-define-property": "^1.0.0", 154 | "es-errors": "^1.3.0", 155 | "function-bind": "^1.1.2", 156 | "get-intrinsic": "^1.2.4", 157 | "set-function-length": "^1.2.1" 158 | }, 159 | "engines": { 160 | "node": ">= 0.4" 161 | }, 162 | "funding": { 163 | "url": "https://github.com/sponsors/ljharb" 164 | } 165 | }, 166 | "node_modules/combined-stream": { 167 | "version": "1.0.8", 168 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 169 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 170 | "dependencies": { 171 | "delayed-stream": "~1.0.0" 172 | }, 173 | "engines": { 174 | "node": ">= 0.8" 175 | } 176 | }, 177 | "node_modules/csv-parse": { 178 | "version": "5.5.3", 179 | "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-5.5.3.tgz", 180 | "integrity": "sha512-v0KW6C0qlZzoGjk6u5tLmVfyZxNgPGXZsWTXshpAgKVGmGXzaVWGdlCFxNx5iuzcXT/oJN1HHM9DZKwtAtYa+A==" 181 | }, 182 | "node_modules/dayjs": { 183 | "version": "1.11.13", 184 | "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", 185 | "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==" 186 | }, 187 | "node_modules/debug": { 188 | "version": "4.3.7", 189 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", 190 | "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", 191 | "dependencies": { 192 | "ms": "^2.1.3" 193 | }, 194 | "engines": { 195 | "node": ">=6.0" 196 | }, 197 | "peerDependenciesMeta": { 198 | "supports-color": { 199 | "optional": true 200 | } 201 | } 202 | }, 203 | "node_modules/define-data-property": { 204 | "version": "1.1.4", 205 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", 206 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", 207 | "dependencies": { 208 | "es-define-property": "^1.0.0", 209 | "es-errors": "^1.3.0", 210 | "gopd": "^1.0.1" 211 | }, 212 | "engines": { 213 | "node": ">= 0.4" 214 | }, 215 | "funding": { 216 | "url": "https://github.com/sponsors/ljharb" 217 | } 218 | }, 219 | "node_modules/delayed-stream": { 220 | "version": "1.0.0", 221 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 222 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", 223 | "engines": { 224 | "node": ">=0.4.0" 225 | } 226 | }, 227 | "node_modules/dotenv": { 228 | "version": "16.3.1", 229 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", 230 | "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", 231 | "engines": { 232 | "node": ">=12" 233 | }, 234 | "funding": { 235 | "url": "https://github.com/motdotla/dotenv?sponsor=1" 236 | } 237 | }, 238 | "node_modules/ecdsa-sig-formatter": { 239 | "version": "1.0.11", 240 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", 241 | "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", 242 | "dependencies": { 243 | "safe-buffer": "^5.0.1" 244 | } 245 | }, 246 | "node_modules/es-define-property": { 247 | "version": "1.0.0", 248 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", 249 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", 250 | "dependencies": { 251 | "get-intrinsic": "^1.2.4" 252 | }, 253 | "engines": { 254 | "node": ">= 0.4" 255 | } 256 | }, 257 | "node_modules/es-errors": { 258 | "version": "1.3.0", 259 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 260 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 261 | "engines": { 262 | "node": ">= 0.4" 263 | } 264 | }, 265 | "node_modules/follow-redirects": { 266 | "version": "1.15.9", 267 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", 268 | "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", 269 | "funding": [ 270 | { 271 | "type": "individual", 272 | "url": "https://github.com/sponsors/RubenVerborgh" 273 | } 274 | ], 275 | "engines": { 276 | "node": ">=4.0" 277 | }, 278 | "peerDependenciesMeta": { 279 | "debug": { 280 | "optional": true 281 | } 282 | } 283 | }, 284 | "node_modules/form-data": { 285 | "version": "4.0.0", 286 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", 287 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", 288 | "dependencies": { 289 | "asynckit": "^0.4.0", 290 | "combined-stream": "^1.0.8", 291 | "mime-types": "^2.1.12" 292 | }, 293 | "engines": { 294 | "node": ">= 6" 295 | } 296 | }, 297 | "node_modules/fsevents": { 298 | "version": "2.3.2", 299 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 300 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 301 | "dev": true, 302 | "hasInstallScript": true, 303 | "optional": true, 304 | "os": [ 305 | "darwin" 306 | ], 307 | "engines": { 308 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 309 | } 310 | }, 311 | "node_modules/function-bind": { 312 | "version": "1.1.2", 313 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 314 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 315 | "funding": { 316 | "url": "https://github.com/sponsors/ljharb" 317 | } 318 | }, 319 | "node_modules/get-intrinsic": { 320 | "version": "1.2.4", 321 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", 322 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", 323 | "dependencies": { 324 | "es-errors": "^1.3.0", 325 | "function-bind": "^1.1.2", 326 | "has-proto": "^1.0.1", 327 | "has-symbols": "^1.0.3", 328 | "hasown": "^2.0.0" 329 | }, 330 | "engines": { 331 | "node": ">= 0.4" 332 | }, 333 | "funding": { 334 | "url": "https://github.com/sponsors/ljharb" 335 | } 336 | }, 337 | "node_modules/gopd": { 338 | "version": "1.0.1", 339 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", 340 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", 341 | "dependencies": { 342 | "get-intrinsic": "^1.1.3" 343 | }, 344 | "funding": { 345 | "url": "https://github.com/sponsors/ljharb" 346 | } 347 | }, 348 | "node_modules/has-property-descriptors": { 349 | "version": "1.0.2", 350 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", 351 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", 352 | "dependencies": { 353 | "es-define-property": "^1.0.0" 354 | }, 355 | "funding": { 356 | "url": "https://github.com/sponsors/ljharb" 357 | } 358 | }, 359 | "node_modules/has-proto": { 360 | "version": "1.0.3", 361 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", 362 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", 363 | "engines": { 364 | "node": ">= 0.4" 365 | }, 366 | "funding": { 367 | "url": "https://github.com/sponsors/ljharb" 368 | } 369 | }, 370 | "node_modules/has-symbols": { 371 | "version": "1.0.3", 372 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 373 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 374 | "engines": { 375 | "node": ">= 0.4" 376 | }, 377 | "funding": { 378 | "url": "https://github.com/sponsors/ljharb" 379 | } 380 | }, 381 | "node_modules/hasown": { 382 | "version": "2.0.2", 383 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 384 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 385 | "dependencies": { 386 | "function-bind": "^1.1.2" 387 | }, 388 | "engines": { 389 | "node": ">= 0.4" 390 | } 391 | }, 392 | "node_modules/https-proxy-agent": { 393 | "version": "5.0.1", 394 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", 395 | "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", 396 | "dependencies": { 397 | "agent-base": "6", 398 | "debug": "4" 399 | }, 400 | "engines": { 401 | "node": ">= 6" 402 | } 403 | }, 404 | "node_modules/jsonwebtoken": { 405 | "version": "9.0.2", 406 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", 407 | "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", 408 | "dependencies": { 409 | "jws": "^3.2.2", 410 | "lodash.includes": "^4.3.0", 411 | "lodash.isboolean": "^3.0.3", 412 | "lodash.isinteger": "^4.0.4", 413 | "lodash.isnumber": "^3.0.3", 414 | "lodash.isplainobject": "^4.0.6", 415 | "lodash.isstring": "^4.0.1", 416 | "lodash.once": "^4.0.0", 417 | "ms": "^2.1.1", 418 | "semver": "^7.5.4" 419 | }, 420 | "engines": { 421 | "node": ">=12", 422 | "npm": ">=6" 423 | } 424 | }, 425 | "node_modules/jwa": { 426 | "version": "1.4.1", 427 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", 428 | "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", 429 | "dependencies": { 430 | "buffer-equal-constant-time": "1.0.1", 431 | "ecdsa-sig-formatter": "1.0.11", 432 | "safe-buffer": "^5.0.1" 433 | } 434 | }, 435 | "node_modules/jws": { 436 | "version": "3.2.2", 437 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", 438 | "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", 439 | "dependencies": { 440 | "jwa": "^1.4.1", 441 | "safe-buffer": "^5.0.1" 442 | } 443 | }, 444 | "node_modules/lodash.includes": { 445 | "version": "4.3.0", 446 | "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", 447 | "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" 448 | }, 449 | "node_modules/lodash.isboolean": { 450 | "version": "3.0.3", 451 | "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", 452 | "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" 453 | }, 454 | "node_modules/lodash.isinteger": { 455 | "version": "4.0.4", 456 | "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", 457 | "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" 458 | }, 459 | "node_modules/lodash.isnumber": { 460 | "version": "3.0.3", 461 | "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", 462 | "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" 463 | }, 464 | "node_modules/lodash.isplainobject": { 465 | "version": "4.0.6", 466 | "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", 467 | "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" 468 | }, 469 | "node_modules/lodash.isstring": { 470 | "version": "4.0.1", 471 | "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", 472 | "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" 473 | }, 474 | "node_modules/lodash.once": { 475 | "version": "4.1.1", 476 | "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", 477 | "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" 478 | }, 479 | "node_modules/mime-db": { 480 | "version": "1.52.0", 481 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 482 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 483 | "engines": { 484 | "node": ">= 0.6" 485 | } 486 | }, 487 | "node_modules/mime-types": { 488 | "version": "2.1.35", 489 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 490 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 491 | "dependencies": { 492 | "mime-db": "1.52.0" 493 | }, 494 | "engines": { 495 | "node": ">= 0.6" 496 | } 497 | }, 498 | "node_modules/ms": { 499 | "version": "2.1.3", 500 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 501 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 502 | }, 503 | "node_modules/object-inspect": { 504 | "version": "1.13.2", 505 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", 506 | "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", 507 | "engines": { 508 | "node": ">= 0.4" 509 | }, 510 | "funding": { 511 | "url": "https://github.com/sponsors/ljharb" 512 | } 513 | }, 514 | "node_modules/otplib": { 515 | "version": "12.0.1", 516 | "resolved": "https://registry.npmjs.org/otplib/-/otplib-12.0.1.tgz", 517 | "integrity": "sha512-xDGvUOQjop7RDgxTQ+o4pOol0/3xSZzawTiPKRrHnQWAy0WjhNs/5HdIDJCrqC4MBynmjXgULc6YfioaxZeFgg==", 518 | "dependencies": { 519 | "@otplib/core": "^12.0.1", 520 | "@otplib/preset-default": "^12.0.1", 521 | "@otplib/preset-v11": "^12.0.1" 522 | } 523 | }, 524 | "node_modules/playwright": { 525 | "version": "1.46.1", 526 | "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.1.tgz", 527 | "integrity": "sha512-oPcr1yqoXLCkgKtD5eNUPLiN40rYEM39odNpIb6VE6S7/15gJmA1NzVv6zJYusV0e7tzvkU/utBFNa/Kpxmwng==", 528 | "dev": true, 529 | "dependencies": { 530 | "playwright-core": "1.46.1" 531 | }, 532 | "bin": { 533 | "playwright": "cli.js" 534 | }, 535 | "engines": { 536 | "node": ">=18" 537 | }, 538 | "optionalDependencies": { 539 | "fsevents": "2.3.2" 540 | } 541 | }, 542 | "node_modules/playwright-core": { 543 | "version": "1.46.1", 544 | "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.1.tgz", 545 | "integrity": "sha512-h9LqIQaAv+CYvWzsZ+h3RsrqCStkBHlgo6/TJlFst3cOTlLghBQlJwPOZKQJTKNaD3QIB7aAVQ+gfWbN3NXB7A==", 546 | "dev": true, 547 | "bin": { 548 | "playwright-core": "cli.js" 549 | }, 550 | "engines": { 551 | "node": ">=18" 552 | } 553 | }, 554 | "node_modules/properties": { 555 | "version": "1.2.1", 556 | "resolved": "https://registry.npmjs.org/properties/-/properties-1.2.1.tgz", 557 | "integrity": "sha512-qYNxyMj1JeW54i/EWEFsM1cVwxJbtgPp8+0Wg9XjNaK6VE/c4oRi6PNu5p7w1mNXEIQIjV5Wwn8v8Gz82/QzdQ==", 558 | "dev": true, 559 | "engines": { 560 | "node": ">=0.10" 561 | } 562 | }, 563 | "node_modules/proxy-from-env": { 564 | "version": "1.1.0", 565 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", 566 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" 567 | }, 568 | "node_modules/qs": { 569 | "version": "6.13.0", 570 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", 571 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", 572 | "dependencies": { 573 | "side-channel": "^1.0.6" 574 | }, 575 | "engines": { 576 | "node": ">=0.6" 577 | }, 578 | "funding": { 579 | "url": "https://github.com/sponsors/ljharb" 580 | } 581 | }, 582 | "node_modules/safe-buffer": { 583 | "version": "5.2.1", 584 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 585 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 586 | "funding": [ 587 | { 588 | "type": "github", 589 | "url": "https://github.com/sponsors/feross" 590 | }, 591 | { 592 | "type": "patreon", 593 | "url": "https://www.patreon.com/feross" 594 | }, 595 | { 596 | "type": "consulting", 597 | "url": "https://feross.org/support" 598 | } 599 | ] 600 | }, 601 | "node_modules/scmp": { 602 | "version": "2.1.0", 603 | "resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz", 604 | "integrity": "sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q==" 605 | }, 606 | "node_modules/semver": { 607 | "version": "7.6.3", 608 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", 609 | "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", 610 | "bin": { 611 | "semver": "bin/semver.js" 612 | }, 613 | "engines": { 614 | "node": ">=10" 615 | } 616 | }, 617 | "node_modules/set-function-length": { 618 | "version": "1.2.2", 619 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", 620 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", 621 | "dependencies": { 622 | "define-data-property": "^1.1.4", 623 | "es-errors": "^1.3.0", 624 | "function-bind": "^1.1.2", 625 | "get-intrinsic": "^1.2.4", 626 | "gopd": "^1.0.1", 627 | "has-property-descriptors": "^1.0.2" 628 | }, 629 | "engines": { 630 | "node": ">= 0.4" 631 | } 632 | }, 633 | "node_modules/side-channel": { 634 | "version": "1.0.6", 635 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", 636 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", 637 | "dependencies": { 638 | "call-bind": "^1.0.7", 639 | "es-errors": "^1.3.0", 640 | "get-intrinsic": "^1.2.4", 641 | "object-inspect": "^1.13.1" 642 | }, 643 | "engines": { 644 | "node": ">= 0.4" 645 | }, 646 | "funding": { 647 | "url": "https://github.com/sponsors/ljharb" 648 | } 649 | }, 650 | "node_modules/thirty-two": { 651 | "version": "1.0.2", 652 | "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz", 653 | "integrity": "sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA==", 654 | "engines": { 655 | "node": ">=0.2.6" 656 | } 657 | }, 658 | "node_modules/twilio": { 659 | "version": "5.3.0", 660 | "resolved": "https://registry.npmjs.org/twilio/-/twilio-5.3.0.tgz", 661 | "integrity": "sha512-bwveAxChPPFR2umttraRjUJdq/WY0OJCCgetzuKqLoGYqYSyYGsiFYYFAB5EOL/XnzCQNwAvq5622u+jqMTLOA==", 662 | "dependencies": { 663 | "axios": "^1.7.4", 664 | "dayjs": "^1.11.9", 665 | "https-proxy-agent": "^5.0.0", 666 | "jsonwebtoken": "^9.0.2", 667 | "qs": "^6.9.4", 668 | "scmp": "^2.1.0", 669 | "xmlbuilder": "^13.0.2" 670 | }, 671 | "engines": { 672 | "node": ">=14.0" 673 | } 674 | }, 675 | "node_modules/undici-types": { 676 | "version": "5.26.5", 677 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", 678 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", 679 | "dev": true 680 | }, 681 | "node_modules/xmlbuilder": { 682 | "version": "13.0.2", 683 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", 684 | "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==", 685 | "engines": { 686 | "node": ">=6.0" 687 | } 688 | } 689 | } 690 | } 691 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "playwrighttutorialfullcourse", 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.46.1", 12 | "@types/node": "^20.10.4", 13 | "allure-commandline": "^2.25.0", 14 | "allure-playwright": "^2.10.0" 15 | }, 16 | "dependencies": { 17 | "csv-parse": "^5.5.3", 18 | "dotenv": "^16.3.1", 19 | "otplib": "^12.0.1", 20 | "twilio": "^5.3.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /pages/homepage.js: -------------------------------------------------------------------------------- 1 | // Inlcude playwright module 2 | const { expect } = require('@playwright/test') 3 | 4 | // create class 5 | exports.HomePage = class HomePage { 6 | 7 | /** 8 | * 9 | * @param {import ('@playwright/test').Page} page 10 | */ 11 | constructor(page){ 12 | // Init page object 13 | this.page = page; 14 | 15 | // Elements 16 | this.searchTextbox = page.locator('#APjFqb'); 17 | } 18 | 19 | async goto(){ 20 | await this.page.setViewportSize({width:1366, height:728}) 21 | await this.page.goto(process.env.URL); 22 | } 23 | 24 | async searchKeywords(param1){ 25 | await expect(this.searchTextbox).toBeEnabled(); 26 | await this.searchTextbox.click(); 27 | await this.searchTextbox.fill(param1); 28 | await this.searchTextbox.press('Enter'); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /pages/playlistpage.js: -------------------------------------------------------------------------------- 1 | // Inlcude playwright module 2 | const { expect } = require('@playwright/test') 3 | 4 | // create class 5 | exports.PlaylistPage = class PlaylistPage { 6 | 7 | /** 8 | * 9 | * @param {import ('@playwright/test').Page} page 10 | */ 11 | constructor(page){ 12 | // Init page object 13 | this.page = page; 14 | 15 | // Elements 16 | this.videoLink = page.locator('#container > #thumbnail'); 17 | } 18 | 19 | async clickOnVideo(){ 20 | await this.page.waitForTimeout(4000); 21 | await expect(this.videoLink.first()).toBeEnabled(); 22 | await this.videoLink.first().click(); 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /pages/resultpage.js: -------------------------------------------------------------------------------- 1 | // Inlcude playwright module 2 | const { expect } = require('@playwright/test') 3 | 4 | // create class 5 | exports.ResultPage = class ResultPage { 6 | 7 | /** 8 | * 9 | * @param {import ('@playwright/test').Page} page 10 | */ 11 | constructor(page){ 12 | // Init page object 13 | this.page = page; 14 | 15 | // Elements 16 | this.playlistlink = page.getByRole('link',{name:'Playwright by Testers Talk'}); 17 | } 18 | 19 | async clickOnPlaylist(){ 20 | await expect(this.playlistlink.first()).toBeEnabled(); 21 | await this.playlistlink.first().click(); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /playwright.config.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | const { defineConfig, devices } = require('@playwright/test'); 3 | 4 | // Read environment variables from file. 5 | require('dotenv').config(); 6 | 7 | /** 8 | * @see more at https://bit.ly/playwright-tutorial-automation-testing 9 | */ 10 | module.exports = defineConfig({ 11 | // test timeout 12 | timeout: 7 * 60 * 1000, 13 | expect: { 14 | timeout: 3 * 60 * 1000 15 | }, 16 | 17 | testDir: './tests', 18 | /* Run tests in files in parallel */ 19 | fullyParallel: false, 20 | /* Fail the build on CI if you accidentally left test.only in the source code. */ 21 | forbidOnly: !!process.env.CI, 22 | /* Retry on CI only */ 23 | retries: process.env.CI ? 2 : 0, 24 | /* Opt out of parallel tests on CI. */ 25 | workers: process.env.CI ? 1 : 1, 26 | // Reporter 27 | reporter:[ 28 | ['html', { open: 'never' }], 29 | // ['html'], 30 | // ['allure-playwright'], 31 | // ['junit', { outputFile: 'test-results/e2e-junit-results.xml' }], 32 | ], 33 | 34 | use: { 35 | /* Base URL to use in actions like `await page.goto('/')`. */ 36 | // baseURL: 'http://127.0.0.1:3000', 37 | 38 | // launchOptions: { 39 | // args: ["--start-fullscreen"] 40 | // }, 41 | 42 | // video, screenshot, headless mode 43 | video:'on', 44 | screenshot: 'on', 45 | headless : false, 46 | 47 | // custom attribute 48 | testIdAttribute: 'autocomplete', 49 | 50 | // Collect trace when retrying the failed test 51 | trace: 'on', 52 | }, 53 | 54 | /* Configure projects for major browsers */ 55 | projects: [ 56 | // { 57 | // name: 'chromium', 58 | // use: { ...devices['Desktop Chrome'] }, 59 | // }, 60 | 61 | // { 62 | // name: 'firefox', 63 | // use: { ...devices['Desktop Firefox'] }, 64 | // }, 65 | 66 | // { 67 | // name: 'webkit', 68 | // use: { ...devices['Desktop Safari'] }, 69 | // }, 70 | 71 | /* Test against mobile viewports. */ 72 | // { 73 | // name: 'Mobile Chrome', 74 | // use: { ...devices['Pixel 5'] }, 75 | // }, 76 | // { 77 | // name: 'Mobile Safari', 78 | // use: { ...devices['iPhone 12'] }, 79 | // }, 80 | 81 | /* Test against branded browsers. */ 82 | // { 83 | // name: 'Microsoft Edge', 84 | // use: { ...devices['Desktop Edge'], channel: 'msedge' }, 85 | // }, 86 | { 87 | name: 'Google Chrome', 88 | use: { ...devices['Desktop Chrome'], channel: 'chrome', 89 | }, 90 | }, 91 | ], 92 | 93 | /* Run your local dev server before starting the tests */ 94 | // webServer: { 95 | // command: 'npm run start', 96 | // url: 'http://127.0.0.1:3000', 97 | // reuseExistingServer: !process.env.CI, 98 | // }, 99 | }); 100 | 101 | -------------------------------------------------------------------------------- /quize.txt: -------------------------------------------------------------------------------- 1 | Chapter01 2 | 1) Playwright is ______ tool 3 | a) Paid 4 | b) Open source 5 | c) Paid + Open source 6 | d) None of the above 7 | 8 | 2) Playwright uses which protocol to communicate with chromium or chrome browser? 9 | a) HTTP 10 | b) HTTPS 11 | c) UDP 12 | d) CDP 13 | 14 | 3) In which format client sends automation test to the server? 15 | a) HTML format 16 | b) JSON format 17 | c) Text file 18 | d) JavaScript format 19 | 20 | 4) Cypress supports for which programming language? 21 | a) JavaScript 22 | b) Python 23 | c) C# .NET 24 | d) None of the above 25 | 26 | 5) Playwright doesn’t support which programming language? 27 | a) Python 28 | b) Java 29 | c) PHP 30 | d) None of the above 31 | 32 | 6) Which extension helps to install playwright in VS Code? 33 | a) Cucumber bdd 34 | b) Playwright Test for VSCode 35 | c) Playwright for VSCode 36 | d) None of the above 37 | 38 | 7) Does Playwright tool generates test execution report? 39 | a) False 40 | b) True 41 | 42 | 8) Playwright supports for cross browser testing? 43 | a) True 44 | b) False 45 | 46 | 9) What is Record at Cursor in playwright? 47 | a) Used to record test 48 | b) Used to insert steps in between test 49 | c) Generates reports 50 | d) None of the above 51 | 52 | 10) What is use of expect keyword in playwright? 53 | a) It is library to write assertions 54 | b) It is a test method 55 | c) Variable 56 | d) None of the above 57 | 58 | 11) Why we use page object in playwright? 59 | a) To interact with test methods 60 | b) To interact with browsers 61 | c) To read test data 62 | d) None of the above 63 | 64 | 12) Which one of the following opens browser and enters URL in playwright? 65 | a) page.goto(‘URL’) 66 | b) page.go(‘URL’) 67 | c) page.enter(‘URL’) 68 | d) None of the above 69 | 70 | 13) Which one of the following syntax is correct to identify the element in playwright? 71 | a) page.goto(‘Locator’) 72 | b) page.element(‘Locator’) 73 | c) page.getByRole(‘Locator’) 74 | d) None of the above 75 | 76 | 14) What is the use of pick locator in playwright? 77 | a) Identifies locator value 78 | b) Identifies error 79 | c) Validates actual & expected value 80 | d) None of the above 81 | 82 | 15) What is the command used to install playwright latest version? 83 | a) npm init playwright@test 84 | b) playwright install 85 | c) npm init playwright 86 | d) None of the above 87 | 88 | 16) Which command used to run playwright tests? 89 | a) npx playwright 90 | b) npx playwright test 91 | c) Run playwright test 92 | d) None of the above 93 | 94 | 17) Codegen used for_____? 95 | a) Write a test 96 | b) To identify locator? 97 | c) Used to run test? 98 | d) Used to record test? 99 | 100 | 18) What is the syntax cmd to run specific spec file in playwright? 101 | a) npx playwright test specfilename 102 | b) playwright test specfilename 103 | c) run specfilename 104 | d) None of the above 105 | 106 | Chapter02 107 | 108 | 19) Select Invalid locator type in playwright 109 | a) Page.getByRole(‘test’) 110 | b) Page.getByTitle(‘test’) 111 | c) Page.getByXpath(‘test’) 112 | d) Page.getByLabel(‘test’) 113 | 114 | 20) How to click on web page element in playwright? 115 | a) await page.getByTitle(‘test’).click(); 116 | b) page.getByTitle(‘test’).click(); 117 | a) await page.getByXpath(‘test’).click(); 118 | b) None of the above 119 | 120 | 21) Is it possible to capture web page element screenshot in playwright? 121 | a) Yes 122 | b) No 123 | 124 | 22) Select correct Hooks Methods in playwright. 125 | a) before, beforeeach, after,aftereach 126 | b) beforeEach, beforeAll, afterEach,afterAll 127 | c) beforeeach, aftereach 128 | d) None of the above 129 | 130 | 23) Select a correct statement to select dropdown value. 131 | a) dropDownList.select ('5'); 132 | b) dropDownList.selectValue('5'); 133 | c) dropDownList.selectString('5'); 134 | d) dropDownList.selectOption('5'); 135 | 136 | 24) Select a correct statement to perform mouse actions in playwright 137 | a) await page.getByLabel(test').click({button:'right'}) 138 | b) await page.getByLabel(test').click() 139 | c) await page.getByLabel(test').click({'right'}) 140 | d) await page.getByLabel(test').click({button}) 141 | 142 | 25) How to press ENTER key from keyboard in playwright? 143 | a) await page.locator("test").click() .press('Enter') 144 | b) await page.locator("test").press('Enter') 145 | c) await page.locator("test").press(ENTER) 146 | d) None of the above 147 | 148 | 26) How to check web page element is displayed or not in playwright? 149 | a) toBeEnabled() 150 | b) toBeVisible() 151 | c) toBeEmpty() 152 | d) None of the above 153 | 154 | 27) Which method used to validate text message in playwright? 155 | a) toHaveURL() 156 | b) toHaveTitle() 157 | c) toHaveText() 158 | d) None of the above 159 | 160 | 28) What is watch mode in playwright? 161 | a) It is used to record test 162 | b) Locator identifier 163 | c) Debugging tool 164 | d) Runs test automatically when updated test 165 | 166 | Chapter03 167 | 168 | 29) Is it possible to auto rerun failed test? 169 | a) Yes 170 | b) No 171 | 172 | 30) Which one of the following statement used to tag a test? 173 | a) #tag1 174 | b) @@tag1 175 | c) @tag1 176 | d) $tag1 177 | 178 | 31) Is it possible to run playwright test parallelly? 179 | a) No 180 | b) Yes 181 | 182 | 32) Which one of the following statement used to group playwright tests? 183 | a) test.describe() 184 | b) test.group() 185 | c) test.skip() 186 | d) test.only() 187 | 188 | 33) What is visual comparison testing in playwright? 189 | a) Comparing 2 objects? 190 | b) Comparing 2 videos? 191 | c) Comparing 2 images? 192 | d) None of the above? 193 | 194 | 34) How to parameterize tests in playwright? 195 | a) Using for loop? 196 | b) Using functions? 197 | c) Using operators? 198 | d) None of the above 199 | 200 | 35) How to run only 1 test in a particular spec file? 201 | a) skip 202 | b) only 203 | c) and 204 | d) spec 205 | 206 | Chapter04 207 | 208 | 36) What exactly .env file contains? 209 | a) Automation test 210 | b) Test steps 211 | c) Test Reports 212 | d) Configurations 213 | 214 | 37) Is it possible to perform data driven testing in playwright? 215 | a) Yes 216 | b) No 217 | 218 | 38) What is Page object model? 219 | a) Framework 220 | b) Automation tool 221 | c) Programming language 222 | d) Design pattern 223 | 224 | 39) In page object model playwright where we are declaring locator values? 225 | a) Constructor 226 | b) Json file 227 | c) Env file 228 | d) None of the above 229 | 230 | 40) Is it possible record test execution video & attach into report? 231 | a) Yes 232 | b) No 233 | 234 | -------------------------------------------------------------------------------- /screenshots/element.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BakkappaN/PlaywrightTutorialFullCourse/b651140a845bd2c0bfb8bd23f875c9a99fa15de0/screenshots/element.png -------------------------------------------------------------------------------- /screenshots/fullpage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BakkappaN/PlaywrightTutorialFullCourse/b651140a845bd2c0bfb8bd23f875c9a99fa15de0/screenshots/fullpage.png -------------------------------------------------------------------------------- /screenshots/page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BakkappaN/PlaywrightTutorialFullCourse/b651140a845bd2c0bfb8bd23f875c9a99fa15de0/screenshots/page.png -------------------------------------------------------------------------------- /selectors/globalselector.json: -------------------------------------------------------------------------------- 1 | { 2 | "Placeholder":{ 3 | "Search":"Search" 4 | }, 5 | "Link":{ 6 | "Playwright":"Playwright by Testers Talk" 7 | } 8 | } -------------------------------------------------------------------------------- /test-data/qa/google.json: -------------------------------------------------------------------------------- 1 | { 2 | "Module1TestData":{ 3 | "skill1":"playwright by testers talk", 4 | "skill2":"cypress by testers talk", 5 | "skill3":"javascript by testers talk", 6 | "skill4":"postman by testers talk", 7 | "skill5":"rest assured by testers talk", 8 | "skill6":"specflow by testers talk", 9 | "skill7":"easyrepro by testers talk", 10 | "skill8":"api testing by testers talk" 11 | }, 12 | "qaTestData":{ 13 | "skill1":"playwright by testers talk", 14 | "skill2":"cypress by testers talk", 15 | "skill3":"javascript by testers talk", 16 | "skill4":"postman by testers talk", 17 | "skill5":"rest assured by testers talk", 18 | "skill6":"specflow by testers talk", 19 | "skill7":"easyrepro by testers talk", 20 | "skill8":"api testing by testers talk" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test-data/qa/testdata.csv: -------------------------------------------------------------------------------- 1 | "TestCaseId","Skill1","Skill2" 2 | "TC_01","playwright by testers talk","playwright by testers talk" 3 | "TC_02","cypress by testers talk","playwright by testers talk" 4 | "TC_03","javascript by testers talk","playwright by testers talk" 5 | "TC_04","postman by testers talk","playwright by testers talk" 6 | "TC_05","rest assured by testers talk","playwright by testers talk" 7 | "TC_06","specflow by testers talk","playwright by testers talk" 8 | "TC_07","easyrepro by testers talk","playwright by testers talk" 9 | "TC_08","api testing by testers talk","playwright by testers talk" 10 | -------------------------------------------------------------------------------- /test-data/stage/google.json: -------------------------------------------------------------------------------- 1 | { 2 | "Module1TestData":{ 3 | "skill1":"playwright by testers talk", 4 | "skill2":"cypress by testers talk", 5 | "skill3":"javascript by testers talk", 6 | "skill4":"postman by testers talk", 7 | "skill5":"rest assured by testers talk", 8 | "skill6":"specflow by testers talk", 9 | "skill7":"easyrepro by testers talk", 10 | "skill8":"api testing by testers talk" 11 | }, 12 | "stageTestData":{ 13 | "skill1":"cypress by testers talk", 14 | "skill2":"playwright by testers talk", 15 | "skill3":"javascript by testers talk", 16 | "skill4":"postman by testers talk", 17 | "skill5":"rest assured by testers talk", 18 | "skill6":"specflow by testers talk", 19 | "skill7":"easyrepro by testers talk", 20 | "skill8":"api testing by testers talk" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests-examples/demo-todo-app.spec.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | const { test, expect } = require('@playwright/test'); 3 | 4 | test.beforeEach(async ({ page }) => { 5 | await page.goto('https://demo.playwright.dev/todomvc'); 6 | }); 7 | 8 | const TODO_ITEMS = [ 9 | 'buy some cheese', 10 | 'feed the cat', 11 | 'book a doctors appointment' 12 | ]; 13 | 14 | test.describe('New Todo', () => { 15 | test('should allow me to add todo items', async ({ page }) => { 16 | // create a new todo locator 17 | const newTodo = page.getByPlaceholder('What needs to be done?'); 18 | 19 | // Create 1st todo. 20 | await newTodo.fill(TODO_ITEMS[0]); 21 | await newTodo.press('Enter'); 22 | 23 | // Make sure the list only has one todo item. 24 | await expect(page.getByTestId('todo-title')).toHaveText([ 25 | TODO_ITEMS[0] 26 | ]); 27 | 28 | // Create 2nd todo. 29 | await newTodo.fill(TODO_ITEMS[1]); 30 | await newTodo.press('Enter'); 31 | 32 | // Make sure the list now has two todo items. 33 | await expect(page.getByTestId('todo-title')).toHaveText([ 34 | TODO_ITEMS[0], 35 | TODO_ITEMS[1] 36 | ]); 37 | 38 | await checkNumberOfTodosInLocalStorage(page, 2); 39 | }); 40 | 41 | test('should clear text input field when an item is added', async ({ page }) => { 42 | // create a new todo locator 43 | const newTodo = page.getByPlaceholder('What needs to be done?'); 44 | 45 | // Create one todo item. 46 | await newTodo.fill(TODO_ITEMS[0]); 47 | await newTodo.press('Enter'); 48 | 49 | // Check that input is empty. 50 | await expect(newTodo).toBeEmpty(); 51 | await checkNumberOfTodosInLocalStorage(page, 1); 52 | }); 53 | 54 | test('should append new items to the bottom of the list', async ({ page }) => { 55 | // Create 3 items. 56 | await createDefaultTodos(page); 57 | 58 | // create a todo count locator 59 | const todoCount = page.getByTestId('todo-count') 60 | 61 | // Check test using different methods. 62 | await expect(page.getByText('3 items left')).toBeVisible(); 63 | await expect(todoCount).toHaveText('3 items left'); 64 | await expect(todoCount).toContainText('3'); 65 | await expect(todoCount).toHaveText(/3/); 66 | 67 | // Check all items in one call. 68 | await expect(page.getByTestId('todo-title')).toHaveText(TODO_ITEMS); 69 | await checkNumberOfTodosInLocalStorage(page, 3); 70 | }); 71 | }); 72 | 73 | test.describe('Mark all as completed', () => { 74 | test.beforeEach(async ({ page }) => { 75 | await createDefaultTodos(page); 76 | await checkNumberOfTodosInLocalStorage(page, 3); 77 | }); 78 | 79 | test.afterEach(async ({ page }) => { 80 | await checkNumberOfTodosInLocalStorage(page, 3); 81 | }); 82 | 83 | test('should allow me to mark all items as completed', async ({ page }) => { 84 | // Complete all todos. 85 | await page.getByLabel('Mark all as complete').check(); 86 | 87 | // Ensure all todos have 'completed' class. 88 | await expect(page.getByTestId('todo-item')).toHaveClass(['completed', 'completed', 'completed']); 89 | await checkNumberOfCompletedTodosInLocalStorage(page, 3); 90 | }); 91 | 92 | test('should allow me to clear the complete state of all items', async ({ page }) => { 93 | const toggleAll = page.getByLabel('Mark all as complete'); 94 | // Check and then immediately uncheck. 95 | await toggleAll.check(); 96 | await toggleAll.uncheck(); 97 | 98 | // Should be no completed classes. 99 | await expect(page.getByTestId('todo-item')).toHaveClass(['', '', '']); 100 | }); 101 | 102 | test('complete all checkbox should update state when items are completed / cleared', async ({ page }) => { 103 | const toggleAll = page.getByLabel('Mark all as complete'); 104 | await toggleAll.check(); 105 | await expect(toggleAll).toBeChecked(); 106 | await checkNumberOfCompletedTodosInLocalStorage(page, 3); 107 | 108 | // Uncheck first todo. 109 | const firstTodo = page.getByTestId('todo-item').nth(0); 110 | await firstTodo.getByRole('checkbox').uncheck(); 111 | 112 | // Reuse toggleAll locator and make sure its not checked. 113 | await expect(toggleAll).not.toBeChecked(); 114 | 115 | await firstTodo.getByRole('checkbox').check(); 116 | await checkNumberOfCompletedTodosInLocalStorage(page, 3); 117 | 118 | // Assert the toggle all is checked again. 119 | await expect(toggleAll).toBeChecked(); 120 | }); 121 | }); 122 | 123 | test.describe('Item', () => { 124 | 125 | test('should allow me to mark items as complete', async ({ page }) => { 126 | // create a new todo locator 127 | const newTodo = page.getByPlaceholder('What needs to be done?'); 128 | 129 | // Create two items. 130 | for (const item of TODO_ITEMS.slice(0, 2)) { 131 | await newTodo.fill(item); 132 | await newTodo.press('Enter'); 133 | } 134 | 135 | // Check first item. 136 | const firstTodo = page.getByTestId('todo-item').nth(0); 137 | await firstTodo.getByRole('checkbox').check(); 138 | await expect(firstTodo).toHaveClass('completed'); 139 | 140 | // Check second item. 141 | const secondTodo = page.getByTestId('todo-item').nth(1); 142 | await expect(secondTodo).not.toHaveClass('completed'); 143 | await secondTodo.getByRole('checkbox').check(); 144 | 145 | // Assert completed class. 146 | await expect(firstTodo).toHaveClass('completed'); 147 | await expect(secondTodo).toHaveClass('completed'); 148 | }); 149 | 150 | test('should allow me to un-mark items as complete', async ({ page }) => { 151 | // create a new todo locator 152 | const newTodo = page.getByPlaceholder('What needs to be done?'); 153 | 154 | // Create two items. 155 | for (const item of TODO_ITEMS.slice(0, 2)) { 156 | await newTodo.fill(item); 157 | await newTodo.press('Enter'); 158 | } 159 | 160 | const firstTodo = page.getByTestId('todo-item').nth(0); 161 | const secondTodo = page.getByTestId('todo-item').nth(1); 162 | const firstTodoCheckbox = firstTodo.getByRole('checkbox'); 163 | 164 | await firstTodoCheckbox.check(); 165 | await expect(firstTodo).toHaveClass('completed'); 166 | await expect(secondTodo).not.toHaveClass('completed'); 167 | await checkNumberOfCompletedTodosInLocalStorage(page, 1); 168 | 169 | await firstTodoCheckbox.uncheck(); 170 | await expect(firstTodo).not.toHaveClass('completed'); 171 | await expect(secondTodo).not.toHaveClass('completed'); 172 | await checkNumberOfCompletedTodosInLocalStorage(page, 0); 173 | }); 174 | 175 | test('should allow me to edit an item', async ({ page }) => { 176 | await createDefaultTodos(page); 177 | 178 | const todoItems = page.getByTestId('todo-item'); 179 | const secondTodo = todoItems.nth(1); 180 | await secondTodo.dblclick(); 181 | await expect(secondTodo.getByRole('textbox', { name: 'Edit' })).toHaveValue(TODO_ITEMS[1]); 182 | await secondTodo.getByRole('textbox', { name: 'Edit' }).fill('buy some sausages'); 183 | await secondTodo.getByRole('textbox', { name: 'Edit' }).press('Enter'); 184 | 185 | // Explicitly assert the new text value. 186 | await expect(todoItems).toHaveText([ 187 | TODO_ITEMS[0], 188 | 'buy some sausages', 189 | TODO_ITEMS[2] 190 | ]); 191 | await checkTodosInLocalStorage(page, 'buy some sausages'); 192 | }); 193 | }); 194 | 195 | test.describe('Editing', () => { 196 | test.beforeEach(async ({ page }) => { 197 | await createDefaultTodos(page); 198 | await checkNumberOfTodosInLocalStorage(page, 3); 199 | }); 200 | 201 | test('should hide other controls when editing', async ({ page }) => { 202 | const todoItem = page.getByTestId('todo-item').nth(1); 203 | await todoItem.dblclick(); 204 | await expect(todoItem.getByRole('checkbox')).not.toBeVisible(); 205 | await expect(todoItem.locator('label', { 206 | hasText: TODO_ITEMS[1], 207 | })).not.toBeVisible(); 208 | await checkNumberOfTodosInLocalStorage(page, 3); 209 | }); 210 | 211 | test('should save edits on blur', async ({ page }) => { 212 | const todoItems = page.getByTestId('todo-item'); 213 | await todoItems.nth(1).dblclick(); 214 | await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill('buy some sausages'); 215 | await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).dispatchEvent('blur'); 216 | 217 | await expect(todoItems).toHaveText([ 218 | TODO_ITEMS[0], 219 | 'buy some sausages', 220 | TODO_ITEMS[2], 221 | ]); 222 | await checkTodosInLocalStorage(page, 'buy some sausages'); 223 | }); 224 | 225 | test('should trim entered text', async ({ page }) => { 226 | const todoItems = page.getByTestId('todo-item'); 227 | await todoItems.nth(1).dblclick(); 228 | await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill(' buy some sausages '); 229 | await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Enter'); 230 | 231 | await expect(todoItems).toHaveText([ 232 | TODO_ITEMS[0], 233 | 'buy some sausages', 234 | TODO_ITEMS[2], 235 | ]); 236 | await checkTodosInLocalStorage(page, 'buy some sausages'); 237 | }); 238 | 239 | test('should remove the item if an empty text string was entered', async ({ page }) => { 240 | const todoItems = page.getByTestId('todo-item'); 241 | await todoItems.nth(1).dblclick(); 242 | await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill(''); 243 | await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Enter'); 244 | 245 | await expect(todoItems).toHaveText([ 246 | TODO_ITEMS[0], 247 | TODO_ITEMS[2], 248 | ]); 249 | }); 250 | 251 | test('should cancel edits on escape', async ({ page }) => { 252 | const todoItems = page.getByTestId('todo-item'); 253 | await todoItems.nth(1).dblclick(); 254 | await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill('buy some sausages'); 255 | await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Escape'); 256 | await expect(todoItems).toHaveText(TODO_ITEMS); 257 | }); 258 | }); 259 | 260 | test.describe('Counter', () => { 261 | test('should display the current number of todo items', async ({ page }) => { 262 | // create a new todo locator 263 | const newTodo = page.getByPlaceholder('What needs to be done?'); 264 | 265 | // create a todo count locator 266 | const todoCount = page.getByTestId('todo-count') 267 | 268 | await newTodo.fill(TODO_ITEMS[0]); 269 | await newTodo.press('Enter'); 270 | await expect(todoCount).toContainText('1'); 271 | 272 | await newTodo.fill(TODO_ITEMS[1]); 273 | await newTodo.press('Enter'); 274 | await expect(todoCount).toContainText('2'); 275 | 276 | await checkNumberOfTodosInLocalStorage(page, 2); 277 | }); 278 | }); 279 | 280 | test.describe('Clear completed button', () => { 281 | test.beforeEach(async ({ page }) => { 282 | await createDefaultTodos(page); 283 | }); 284 | 285 | test('should display the correct text', async ({ page }) => { 286 | await page.locator('.todo-list li .toggle').first().check(); 287 | await expect(page.getByRole('button', { name: 'Clear completed' })).toBeVisible(); 288 | }); 289 | 290 | test('should remove completed items when clicked', async ({ page }) => { 291 | const todoItems = page.getByTestId('todo-item'); 292 | await todoItems.nth(1).getByRole('checkbox').check(); 293 | await page.getByRole('button', { name: 'Clear completed' }).click(); 294 | await expect(todoItems).toHaveCount(2); 295 | await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); 296 | }); 297 | 298 | test('should be hidden when there are no items that are completed', async ({ page }) => { 299 | await page.locator('.todo-list li .toggle').first().check(); 300 | await page.getByRole('button', { name: 'Clear completed' }).click(); 301 | await expect(page.getByRole('button', { name: 'Clear completed' })).toBeHidden(); 302 | }); 303 | }); 304 | 305 | test.describe('Persistence', () => { 306 | test('should persist its data', async ({ page }) => { 307 | // create a new todo locator 308 | const newTodo = page.getByPlaceholder('What needs to be done?'); 309 | 310 | for (const item of TODO_ITEMS.slice(0, 2)) { 311 | await newTodo.fill(item); 312 | await newTodo.press('Enter'); 313 | } 314 | 315 | const todoItems = page.getByTestId('todo-item'); 316 | const firstTodoCheck = todoItems.nth(0).getByRole('checkbox'); 317 | await firstTodoCheck.check(); 318 | await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); 319 | await expect(firstTodoCheck).toBeChecked(); 320 | await expect(todoItems).toHaveClass(['completed', '']); 321 | 322 | // Ensure there is 1 completed item. 323 | await checkNumberOfCompletedTodosInLocalStorage(page, 1); 324 | 325 | // Now reload. 326 | await page.reload(); 327 | await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); 328 | await expect(firstTodoCheck).toBeChecked(); 329 | await expect(todoItems).toHaveClass(['completed', '']); 330 | }); 331 | }); 332 | 333 | test.describe('Routing', () => { 334 | test.beforeEach(async ({ page }) => { 335 | await createDefaultTodos(page); 336 | // make sure the app had a chance to save updated todos in storage 337 | // before navigating to a new view, otherwise the items can get lost :( 338 | // in some frameworks like Durandal 339 | await checkTodosInLocalStorage(page, TODO_ITEMS[0]); 340 | }); 341 | 342 | test('should allow me to display active items', async ({ page }) => { 343 | const todoItem = page.getByTestId('todo-item'); 344 | await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); 345 | 346 | await checkNumberOfCompletedTodosInLocalStorage(page, 1); 347 | await page.getByRole('link', { name: 'Active' }).click(); 348 | await expect(todoItem).toHaveCount(2); 349 | await expect(todoItem).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); 350 | }); 351 | 352 | test('should respect the back button', async ({ page }) => { 353 | const todoItem = page.getByTestId('todo-item'); 354 | await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); 355 | 356 | await checkNumberOfCompletedTodosInLocalStorage(page, 1); 357 | 358 | await test.step('Showing all items', async () => { 359 | await page.getByRole('link', { name: 'All' }).click(); 360 | await expect(todoItem).toHaveCount(3); 361 | }); 362 | 363 | await test.step('Showing active items', async () => { 364 | await page.getByRole('link', { name: 'Active' }).click(); 365 | }); 366 | 367 | await test.step('Showing completed items', async () => { 368 | await page.getByRole('link', { name: 'Completed' }).click(); 369 | }); 370 | 371 | await expect(todoItem).toHaveCount(1); 372 | await page.goBack(); 373 | await expect(todoItem).toHaveCount(2); 374 | await page.goBack(); 375 | await expect(todoItem).toHaveCount(3); 376 | }); 377 | 378 | test('should allow me to display completed items', async ({ page }) => { 379 | await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); 380 | await checkNumberOfCompletedTodosInLocalStorage(page, 1); 381 | await page.getByRole('link', { name: 'Completed' }).click(); 382 | await expect(page.getByTestId('todo-item')).toHaveCount(1); 383 | }); 384 | 385 | test('should allow me to display all items', async ({ page }) => { 386 | await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); 387 | await checkNumberOfCompletedTodosInLocalStorage(page, 1); 388 | await page.getByRole('link', { name: 'Active' }).click(); 389 | await page.getByRole('link', { name: 'Completed' }).click(); 390 | await page.getByRole('link', { name: 'All' }).click(); 391 | await expect(page.getByTestId('todo-item')).toHaveCount(3); 392 | }); 393 | 394 | test('should highlight the currently applied filter', async ({ page }) => { 395 | await expect(page.getByRole('link', { name: 'All' })).toHaveClass('selected'); 396 | 397 | //create locators for active and completed links 398 | const activeLink = page.getByRole('link', { name: 'Active' }); 399 | const completedLink = page.getByRole('link', { name: 'Completed' }); 400 | await activeLink.click(); 401 | 402 | // Page change - active items. 403 | await expect(activeLink).toHaveClass('selected'); 404 | await completedLink.click(); 405 | 406 | // Page change - completed items. 407 | await expect(completedLink).toHaveClass('selected'); 408 | }); 409 | }); 410 | 411 | async function createDefaultTodos(page) { 412 | // create a new todo locator 413 | const newTodo = page.getByPlaceholder('What needs to be done?'); 414 | 415 | for (const item of TODO_ITEMS) { 416 | await newTodo.fill(item); 417 | await newTodo.press('Enter'); 418 | } 419 | } 420 | 421 | /** 422 | * @param {import('@playwright/test').Page} page 423 | * @param {number} expected 424 | */ 425 | async function checkNumberOfTodosInLocalStorage(page, expected) { 426 | return await page.waitForFunction(e => { 427 | return JSON.parse(localStorage['react-todos']).length === e; 428 | }, expected); 429 | } 430 | 431 | /** 432 | * @param {import('@playwright/test').Page} page 433 | * @param {number} expected 434 | */ 435 | async function checkNumberOfCompletedTodosInLocalStorage(page, expected) { 436 | return await page.waitForFunction(e => { 437 | return JSON.parse(localStorage['react-todos']).filter(i => i.completed).length === e; 438 | }, expected); 439 | } 440 | 441 | /** 442 | * @param {import('@playwright/test').Page} page 443 | * @param {string} title 444 | */ 445 | async function checkTodosInLocalStorage(page, title) { 446 | return await page.waitForFunction(t => { 447 | return JSON.parse(localStorage['react-todos']).map(i => i.title).includes(t); 448 | }, title); 449 | } 450 | -------------------------------------------------------------------------------- /tests/annotations.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const {test, expect} = require('@playwright/test'); 3 | 4 | // Write a test 5 | test.only('Assertions in playwright1', async({page}) =>{ 6 | 7 | console.log('Assertions in playwright test is running...!') 8 | 9 | // Go to URL 10 | await page.goto('https://www.google.com/search?q=playwright+by+testers+talk') 11 | 12 | // assert url 13 | await expect(page).toHaveURL('https://www.google.com/search?q=playwright+by+testers+talk') 14 | 15 | // assert title 16 | await expect(page).toHaveTitle('playwright by testers talk - Google Search') 17 | 18 | // assert text 19 | await expect(page.locator("[aria-label='Search']").first()).toHaveText('playwright by testers talk') 20 | 21 | //assert editable enabled visible 22 | await expect(page.locator("[aria-label='Search']").first()).toBeEditable(); 23 | await expect(page.locator("[aria-label='Search']").first()).toBeVisible(); 24 | await expect(page.locator("[aria-label='Search']").first()).toBeEnabled(); 25 | 26 | //assert disabled empty count 27 | //await expect(page.locator("[aria-label='Search']").first()).toBeDisabled(); 28 | 29 | await expect(page.locator("[aria-label='Search']").first()).not.toBeEmpty(); 30 | 31 | await expect(page.locator("[aria-label='Search']")).toHaveCount(2) 32 | 33 | await page.waitForTimeout(5000); 34 | }) 35 | 36 | // Write a test 37 | test.skip('Assertions in playwright2', async({page}) =>{ 38 | 39 | console.log('Assertions in playwright test is running...!') 40 | 41 | // Go to URL 42 | await page.goto('https://www.google.com/search?q=playwright+by+testers+talk') 43 | 44 | // assert url 45 | await expect(page).toHaveURL('https://www.google.com/search?q=playwright+by+testers+talk') 46 | 47 | // assert title 48 | await expect(page).toHaveTitle('playwright by testers talk - Google Search') 49 | 50 | // assert text 51 | await expect(page.locator("[aria-label='Search']").first()).toHaveText('playwright by testers talk') 52 | 53 | //assert editable enabled visible 54 | await expect(page.locator("[aria-label='Search']").first()).toBeEditable(); 55 | await expect(page.locator("[aria-label='Search']").first()).toBeVisible(); 56 | await expect(page.locator("[aria-label='Search']").first()).toBeEnabled(); 57 | 58 | //assert disabled empty count 59 | //await expect(page.locator("[aria-label='Search']").first()).toBeDisabled(); 60 | 61 | await expect(page.locator("[aria-label='Search']").first()).not.toBeEmpty(); 62 | 63 | await expect(page.locator("[aria-label='Search']")).toHaveCount(2) 64 | 65 | await page.waitForTimeout(5000); 66 | }) 67 | 68 | // Write a test 69 | test('Assertions in playwright3', async({page}) =>{ 70 | 71 | console.log('Assertions in playwright test is running...!') 72 | 73 | // Go to URL 74 | await page.goto('https://www.google.com/search?q=playwright+by+testers+talk') 75 | 76 | // assert url 77 | await expect(page).toHaveURL('https://www.google.com/search?q=playwright+by+testers+talk') 78 | 79 | // assert title 80 | await expect(page).toHaveTitle('playwright by testers talk - Google Search') 81 | 82 | // assert text 83 | await expect(page.locator("[aria-label='Search']").first()).toHaveText('playwright by testers talk') 84 | 85 | //assert editable enabled visible 86 | await expect(page.locator("[aria-label='Search']").first()).toBeEditable(); 87 | await expect(page.locator("[aria-label='Search']").first()).toBeVisible(); 88 | await expect(page.locator("[aria-label='Search']").first()).toBeEnabled(); 89 | 90 | //assert disabled empty count 91 | //await expect(page.locator("[aria-label='Search']").first()).toBeDisabled(); 92 | 93 | await expect(page.locator("[aria-label='Search']").first()).not.toBeEmpty(); 94 | 95 | await expect(page.locator("[aria-label='Search']")).toHaveCount(2) 96 | 97 | await page.waitForTimeout(5000); 98 | }) 99 | 100 | -------------------------------------------------------------------------------- /tests/apimocking.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const { test, expect } = require('@playwright/test'); 3 | 4 | /** 5 | * Bakkappa N 6 | */ 7 | test("API Requests Mocking Using Playwright", async ({ page }) => { 8 | 9 | // Mock the api call before navigating 10 | await page.route('*/**/api/v1/fruits', async route => { 11 | const json = [ 12 | { name: 'playwright by testers talk', id: 21 }, 13 | { name: 'cypress by testers talk', id: 71 }, 14 | { name: 'api testing by testers talk', id: 72 }, 15 | { name: 'postman by testers talk', id: 73 }, 16 | { name: 'rest assured by testers talk', id: 74 }, 17 | ]; 18 | await route.fulfill({ json }); 19 | }); 20 | 21 | // Go to the page 22 | await page.goto('https://demo.playwright.dev/api-mocking'); 23 | 24 | // Assert that the mocked values 25 | await expect(page.getByText('playwright by testers talk')).toBeVisible(); 26 | await expect(page.getByText('cypress by testers talk')).toBeVisible(); 27 | await expect(page.getByText('api testing by testers talk')).toBeVisible(); 28 | await expect(page.getByText('postman by testers talk')).toBeVisible(); 29 | await expect(page.getByText('rest assured by testers talk')).toBeVisible(); 30 | }); 31 | 32 | /** 33 | * Bakkappa N 34 | */ 35 | test('Gets the json from api and adds a new string value', async ({ page }) => { 36 | 37 | // Get the response and add to it 38 | await page.route('*/**/api/v1/fruits', async route => { 39 | const response = await route.fetch(); 40 | const json = await response.json(); 41 | json.push({ name: 'playwright by testers talk', id: 100 }); 42 | json.push({ name: 'cypress by testers talk', id: 101 }); 43 | json.push({ name: 'api testing by testers talk', id: 102 }); 44 | json.push({ name: 'postman by testers talk', id: 103 }); 45 | json.push({ name: 'rest assured by testers talk', id: 104 }); 46 | 47 | // Fulfill using the original response, while patching the response body 48 | // with the given JSON object. 49 | await route.fulfill({ response, json }); 50 | }); 51 | 52 | // Go to the page 53 | await page.goto('https://demo.playwright.dev/api-mocking'); 54 | 55 | // Assert that the new fruit is visible 56 | await expect(page.getByText('playwright by testers talk')).toBeVisible(); 57 | await expect(page.getByText('cypress by testers talk')).toBeVisible(); 58 | await expect(page.getByText('api testing by testers talk')).toBeVisible(); 59 | await expect(page.getByText('postman by testers talk')).toBeVisible(); 60 | await expect(page.getByText('rest assured by testers talk')).toBeVisible(); 61 | }); 62 | 63 | /** 64 | * Bakkappa N 65 | */ 66 | test('Record or Modify the HAR file', async ({ page }) => { 67 | 68 | // Get the response from the HAR file 69 | await page.routeFromHAR('./hars/fruit.har', { 70 | url: '*/**/api/v1/fruits', 71 | update: false, 72 | }); 73 | 74 | // Go to the page 75 | await page.goto('https://demo.playwright.dev/api-mocking'); 76 | 77 | // Assert that the fruit is visible 78 | await expect(page.getByText('playwright by testers talk')).toBeVisible(); 79 | await expect(page.getByText('cypress by testers talk')).toBeVisible(); 80 | await expect(page.getByText('api testing by testers talk')).toBeVisible(); 81 | await expect(page.getByText('postman by testers talk')).toBeVisible(); 82 | await expect(page.getByText('rest assured by testers talk')).toBeVisible(); 83 | }); -------------------------------------------------------------------------------- /tests/assertions.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const {test, expect} = require('@playwright/test'); 3 | 4 | // Write a test 5 | test('Assertions in playwright', async({page}) =>{ 6 | 7 | console.log('Assertions in playwright test is running...!') 8 | 9 | // Go to URL 10 | await page.goto('https://www.google.com/search?q=playwright+by+testers+talk') 11 | 12 | // assert url 13 | await expect(page).toHaveURL('https://www.google.com/search?q=playwright+by+testers+talk') 14 | 15 | // assert title 16 | await expect(page).toHaveTitle('playwright by testers talk - Google Search') 17 | 18 | // assert text 19 | await expect(page.locator("[aria-label='Search']").first()).toHaveText('playwright by testers talk') 20 | 21 | //assert editable enabled visible 22 | await expect(page.locator("[aria-label='Search']").first()).toBeEditable(); 23 | await expect(page.locator("[aria-label='Search']").first()).toBeVisible(); 24 | await expect(page.locator("[aria-label='Search']").first()).toBeEnabled(); 25 | 26 | //assert disabled empty count 27 | //await expect(page.locator("[aria-label='Search']").first()).toBeDisabled(); 28 | 29 | await expect(page.locator("[aria-label='Search']").first()).not.toBeEmpty(); 30 | 31 | await expect(page.locator("[aria-label='Search']")).toHaveCount(2) 32 | 33 | await page.waitForTimeout(5000); 34 | }) 35 | 36 | -------------------------------------------------------------------------------- /tests/datadriventestingcsv.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const {test, expect} = require('@playwright/test'); 3 | 4 | import fs from 'fs'; 5 | import path from 'path'; 6 | import { parse } from 'csv-parse/sync'; 7 | 8 | const records = parse ( 9 | fs.readFileSync(path.join(__dirname,"../test-data/qa/testdata.csv")), 10 | { 11 | columns:true, 12 | skip_empty_lines:true, 13 | }); 14 | 15 | 16 | for (const record of records) { 17 | 18 | // Write a test 19 | test(`Data Driven Testing Using CSV file in playwright ${record.TestCaseId}`, async({page}) =>{ 20 | // Go to URL 21 | await page.goto(process.env.URL); 22 | 23 | // search with keywords 24 | await page.locator('#APjFqb').click(); 25 | await page.locator('#APjFqb').fill(record.Skill2); 26 | await page.locator('#APjFqb').press('Enter'); 27 | 28 | await page.waitForTimeout(5000); 29 | }) 30 | } 31 | 32 | 33 | -------------------------------------------------------------------------------- /tests/datadriventestingjson.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const {test, expect} = require('@playwright/test'); 3 | import { Module1TestData } from '../test-data/qa/google.json' 4 | 5 | for (const [key,value] of Object.entries(Module1TestData)) { 6 | 7 | // Write a test 8 | test(`Data Driven Testing Using JSON file in playwright ${value}`, async({page}) =>{ 9 | // Go to URL 10 | await page.goto(process.env.URL); 11 | 12 | // search with keywords 13 | await page.locator('#APjFqb').click(); 14 | await page.locator('#APjFqb').fill(value); 15 | await page.locator('#APjFqb').press('Enter'); 16 | 17 | await page.waitForTimeout(5000); 18 | }) 19 | } 20 | 21 | 22 | -------------------------------------------------------------------------------- /tests/datepicker.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const {test, expect} = require('@playwright/test'); 3 | 4 | // Write a test 5 | test('Date Picker in playwright', async({page}) =>{ 6 | // Go to URL 7 | await page.goto('https://jqueryui.com/datepicker/') 8 | 9 | const frameElement = page.frameLocator('.demo-frame'); 10 | 11 | //frameElement.locator('.hasDatepicker').fill('12/20/2023'); 12 | 13 | frameElement.locator('.hasDatepicker').click(); 14 | 15 | // today's date 16 | //await frameElement.locator('.ui-datepicker-today').click(); 17 | 18 | // custom date value 19 | const defaultDate = frameElement.locator('.ui-datepicker-today > a') 20 | const currentDateValue = await defaultDate.getAttribute('data-date'); // 22 as a value 21 | 22 | let customDate = (parseInt(currentDateValue)+3); // 19 as value 23 | 24 | const element = "[data-date="+"'"+customDate.toString()+"'"+"]"; 25 | 26 | await frameElement.locator(element).click(); 27 | 28 | await page.waitForTimeout(5000); 29 | 30 | }) 31 | 32 | -------------------------------------------------------------------------------- /tests/demo.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | import { test, chromium } from '@playwright/test'; 3 | 4 | 5 | test('Open multiple browser sessions', async () => { 6 | const browser = await chromium.launch(); 7 | 8 | const context1 = await browser.newContext(); 9 | const context2 = await browser.newContext(); 10 | 11 | const page1 = await context1.newPage(); 12 | const page2 = await context2.newPage(); 13 | 14 | await page1.goto('https://youtube.com/playlist?list=PLUeDIlio4THEgPRVJRqZRS8uw8hhVNQCM&si=-US8rBdfw1kxRBnt'); 15 | await page1.locator('#contents > ytd-playlist-video-renderer:nth-child(1)').click() 16 | await page1.waitForTimeout(5000); 17 | 18 | await page2.goto('https://youtube.com/playlist?list=PLUeDIlio4THEgPRVJRqZRS8uw8hhVNQCM&si=-US8rBdfw1kxRBnt'); 19 | 20 | await browser.close(); 21 | }); 22 | 23 | test('run test in already opened browser', async () => { 24 | const browser = await chromium.connectOverCDP('http://localhost:9222'); 25 | const defaultContext = browser.contexts()[0]; 26 | const page = defaultContext.pages()[0]; 27 | 28 | await page.goto('https://www.google.com/search?q=playwright+by+testers+talk'); 29 | await page.getByRole('link', { name: 'Playwright by Testers Talk' }).first().click(); 30 | }); 31 | 32 | test('Rerun all failed test', async ({ page }) => { 33 | }); 34 | 35 | test('latest tags', async ({ page }) => { 36 | }); 37 | 38 | test('popups alerts', async ({ page }) => { 39 | }); 40 | 41 | test('multiple test reports', async ({ page }) => { 42 | }); 43 | 44 | test('upload file', async ({ page }) => { 45 | }); 46 | 47 | test('download file', async ({ page }) => { 48 | }); -------------------------------------------------------------------------------- /tests/dropdownlist.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const { test, expect } = require('@playwright/test'); 3 | 4 | // Write a testa 5 | test('Handle dropdown list in playwright', async ({ page }) => { 6 | // Go to URL 7 | await page.goto('https://www.facebook.com/') 8 | await page.getByText('Create new account').click(); 9 | 10 | // Identify select tag 11 | const dropDownList = page.locator('#month'); 12 | 13 | // Validating default selected value 14 | await expect(dropDownList).toHaveValue('8'); 15 | 16 | // Drop down list all the options 17 | const dropDownListOptions = page.locator('#month > option'); 18 | await expect(dropDownListOptions).toHaveText(['Jan', 'Feb', 'Mar', 19 | 'Apr', 'May', 'Jun', 'Jul', 20 | 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' 21 | ]) 22 | 23 | // Select by value 24 | dropDownList.selectOption('5'); 25 | dropDownList.selectOption('6'); 26 | 27 | // Select by visible text 28 | dropDownList.selectOption('Aug'); 29 | await page.waitForTimeout(5000); 30 | }) 31 | 32 | -------------------------------------------------------------------------------- /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 page to have a heading with the name of Installation. 18 | await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible(); 19 | }); 20 | -------------------------------------------------------------------------------- /tests/failedtest.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const {test, expect} = require('@playwright/test'); 3 | 4 | // Write a test 5 | test('Validate Youtube title', async({page}) =>{ 6 | // Go to URL 7 | await page.goto('https://www.youtube.com/') 8 | 9 | // Search with keywords 10 | await page.getByPlaceholder('Search').click(); 11 | await page.getByPlaceholder('Search').fill('cypress by testers talk'); 12 | 13 | await expect(page.getByRole('button', { name: 'Search', exact: true })).toBeEnabled(); 14 | await page.getByRole('button', { name: 'Search', exact: true }).click(); 15 | 16 | await page.waitForTimeout(2000); 17 | 18 | // Click on playlist 19 | await page.getByRole('link', { name: 'Cypress by Testers Talk Testers Talk · Playlist' }).click(); 20 | 21 | // Validate title 22 | await expect(page).toHaveTitle('Cypress Tutorial Full Course | Learn Cypress in 5 Hrs - YouTube'); 23 | 24 | }) 25 | 26 | -------------------------------------------------------------------------------- /tests/firsttest.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const { test, expect } = require('@playwright/test'); 3 | 4 | // Write a test 5 | test('Validate Youtube title', async ({ page }) => { 6 | // Go to URL 7 | await page.goto('https://www.youtube.com/') 8 | 9 | // Search with keywords 10 | await page.getByPlaceholder('Search').click(); 11 | await page.getByPlaceholder('Search').fill('cypress by testers talk'); 12 | 13 | await expect(page.getByRole('button', { name: 'Search', exact: true })).toBeEnabled(); 14 | await page.getByRole('button', { name: 'Search', exact: true }).click(); 15 | 16 | await page.waitForTimeout(2000); 17 | 18 | // Click on playlist 19 | await page.getByRole('link', { name: 'Cypress by Testers Talk' }).click(); 20 | 21 | // Validate title 22 | await expect(page).toHaveTitle('Cypress Tutorial Full Course 2023 | Learn Cypress in 5 Hrs - YouTube'); 23 | }) 24 | 25 | -------------------------------------------------------------------------------- /tests/google.spec.js: -------------------------------------------------------------------------------- 1 | const { test, expect, chromium } = require('@playwright/test'); 2 | 3 | test('Google test using playwright', async () => { 4 | test.setTimeout(20 * 60 * 60 * 1000); 5 | for (let index = 0; index < 3; index++) { 6 | const browser = await chromium.connectOverCDP('http://localhost:9222/') 7 | const context = browser.contexts()[0]; 8 | const page = context.pages()[0]; 9 | const keywords = ['Postman', 'Playwright', 'Cypress', 'Rest Assured', 'Specflow']; 10 | for (const keyword of keywords) { 11 | let lowercasedWord = keyword.charAt(0).toLowerCase() + keyword.slice(1); 12 | await page.goto('https://www.google.com/search?q='+lowercasedWord+'+by+testers+talk'); 13 | await page.waitForTimeout(2000); 14 | await expect(page.getByRole('link', { name: keyword+' by Testers Talk' }).first()).toBeEnabled(); 15 | await page.getByRole('link', { name: keyword+' by Testers Talk' }).first().click(); 16 | await expect(page.locator('#container > #thumbnail').first()).toBeVisible(); 17 | await page.locator('#container > #thumbnail').first().click(); 18 | await page.waitForTimeout(20000); 19 | } 20 | console.log(`Number of times test executed : ${index}`); 21 | } 22 | }) 23 | 24 | test.skip('Google test for playwright', async () => { 25 | const browser = await chromium.connectOverCDP('http://localhost:9222/') 26 | const context = browser.contexts()[0]; 27 | const page = context.pages()[0]; 28 | await page.goto('https://www.google.com/search?q=playwright+tutorial'); 29 | await page.waitForTimeout(2000); 30 | await page.getByRole('link', { name: 'View all' }).click(); 31 | await page.getByRole('link', { name: 'Playwright Tutorial Full Course 2024' }).click(); 32 | await page.waitForTimeout(20000); 33 | }) 34 | -------------------------------------------------------------------------------- /tests/group.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const {test, expect} = require('@playwright/test'); 3 | 4 | test.describe('Smoke Testing', () => { 5 | 6 | // Write a test 7 | test('Test1', async({page}) =>{ 8 | 9 | console.log('Assertions in playwright test is running...!') 10 | 11 | // Go to URL 12 | await page.goto('https://www.google.com/search?q=playwright+by+testers+talk') 13 | 14 | // assert url 15 | await expect(page).toHaveURL('https://www.google.com/search?q=playwright+by+testers+talk') 16 | 17 | // assert title 18 | await expect(page).toHaveTitle('playwright by testers talk - Google Search') 19 | 20 | // assert text 21 | await expect(page.locator("[aria-label='Search']").first()).toHaveText('playwright by testers talk') 22 | 23 | //assert editable enabled visible 24 | await expect(page.locator("[aria-label='Search']").first()).toBeEditable(); 25 | await expect(page.locator("[aria-label='Search']").first()).toBeVisible(); 26 | await expect(page.locator("[aria-label='Search']").first()).toBeEnabled(); 27 | 28 | //assert disabled empty count 29 | //await expect(page.locator("[aria-label='Search']").first()).toBeDisabled(); 30 | 31 | await expect(page.locator("[aria-label='Search']").first()).not.toBeEmpty(); 32 | 33 | await expect(page.locator("[aria-label='Search']")).toHaveCount(2) 34 | 35 | await page.waitForTimeout(5000); 36 | }) 37 | 38 | // Write a test 39 | test('Test2', async({page}) =>{ 40 | 41 | console.log('Assertions in playwright test is running...!') 42 | 43 | // Go to URL 44 | await page.goto('https://www.google.com/search?q=playwright+by+testers+talk') 45 | 46 | // assert url 47 | await expect(page).toHaveURL('https://www.google.com/search?q=playwright+by+testers+talk') 48 | 49 | // assert title 50 | await expect(page).toHaveTitle('playwright by testers talk - Google Search') 51 | 52 | // assert text 53 | await expect(page.locator("[aria-label='Search']").first()).toHaveText('playwright by testers talk') 54 | 55 | //assert editable enabled visible 56 | await expect(page.locator("[aria-label='Search']").first()).toBeEditable(); 57 | await expect(page.locator("[aria-label='Search']").first()).toBeVisible(); 58 | await expect(page.locator("[aria-label='Search']").first()).toBeEnabled(); 59 | 60 | //assert disabled empty count 61 | //await expect(page.locator("[aria-label='Search']").first()).toBeDisabled(); 62 | 63 | await expect(page.locator("[aria-label='Search']").first()).not.toBeEmpty(); 64 | 65 | await expect(page.locator("[aria-label='Search']")).toHaveCount(2) 66 | 67 | await page.waitForTimeout(5000); 68 | }) 69 | }) 70 | 71 | test.describe('Sanity Testing', () => { 72 | // Write a test 73 | test('Test3', async({page}) =>{ 74 | 75 | console.log('Assertions in playwright test is running...!') 76 | 77 | // Go to URL 78 | await page.goto('https://www.google.com/search?q=playwright+by+testers+talk') 79 | 80 | // assert url 81 | await expect(page).toHaveURL('https://www.google.com/search?q=playwright+by+testers+talk') 82 | 83 | // assert title 84 | await expect(page).toHaveTitle('playwright by testers talk - Google Search') 85 | 86 | // assert text 87 | await expect(page.locator("[aria-label='Search']").first()).toHaveText('playwright by testers talk') 88 | 89 | //assert editable enabled visible 90 | await expect(page.locator("[aria-label='Search']").first()).toBeEditable(); 91 | await expect(page.locator("[aria-label='Search']").first()).toBeVisible(); 92 | await expect(page.locator("[aria-label='Search']").first()).toBeEnabled(); 93 | 94 | //assert disabled empty count 95 | //await expect(page.locator("[aria-label='Search']").first()).toBeDisabled(); 96 | 97 | await expect(page.locator("[aria-label='Search']").first()).not.toBeEmpty(); 98 | 99 | await expect(page.locator("[aria-label='Search']")).toHaveCount(2) 100 | 101 | await page.waitForTimeout(5000); 102 | }) 103 | 104 | // Write a test 105 | test('Test4', async({page}) =>{ 106 | 107 | console.log('Assertions in playwright test is running...!') 108 | 109 | // Go to URL 110 | await page.goto('https://www.google.com/search?q=playwright+by+testers+talk') 111 | 112 | // assert url 113 | await expect(page).toHaveURL('https://www.google.com/search?q=playwright+by+testers+talk') 114 | 115 | // assert title 116 | await expect(page).toHaveTitle('playwright by testers talk - Google Search') 117 | 118 | // assert text 119 | await expect(page.locator("[aria-label='Search']").first()).toHaveText('playwright by testers talk') 120 | 121 | //assert editable enabled visible 122 | await expect(page.locator("[aria-label='Search']").first()).toBeEditable(); 123 | await expect(page.locator("[aria-label='Search']").first()).toBeVisible(); 124 | await expect(page.locator("[aria-label='Search']").first()).toBeEnabled(); 125 | 126 | //assert disabled empty count 127 | //await expect(page.locator("[aria-label='Search']").first()).toBeDisabled(); 128 | 129 | await expect(page.locator("[aria-label='Search']").first()).not.toBeEmpty(); 130 | 131 | await expect(page.locator("[aria-label='Search']")).toHaveCount(2) 132 | 133 | await page.waitForTimeout(5000); 134 | }) 135 | 136 | // Write a test 137 | test('Test5', async({page}) =>{ 138 | 139 | console.log('Assertions in playwright test is running...!') 140 | 141 | // Go to URL 142 | await page.goto('https://www.google.com/search?q=playwright+by+testers+talk') 143 | 144 | // assert url 145 | await expect(page).toHaveURL('https://www.google.com/search?q=playwright+by+testers+talk') 146 | 147 | // assert title 148 | await expect(page).toHaveTitle('playwright by testers talk - Google Search') 149 | 150 | // assert text 151 | await expect(page.locator("[aria-label='Search']").first()).toHaveText('playwright by testers talk') 152 | 153 | //assert editable enabled visible 154 | await expect(page.locator("[aria-label='Search']").first()).toBeEditable(); 155 | await expect(page.locator("[aria-label='Search']").first()).toBeVisible(); 156 | await expect(page.locator("[aria-label='Search']").first()).toBeEnabled(); 157 | 158 | //assert disabled empty count 159 | //await expect(page.locator("[aria-label='Search']").first()).toBeDisabled(); 160 | 161 | await expect(page.locator("[aria-label='Search']").first()).not.toBeEmpty(); 162 | 163 | await expect(page.locator("[aria-label='Search']")).toHaveCount(5) 164 | 165 | await page.waitForTimeout(5000); 166 | }) 167 | }) 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /tests/hooks.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const {test, expect} = require('@playwright/test'); 3 | 4 | test.beforeEach('Run before each test', async({page}) =>{ 5 | console.log('Running before each test...!') 6 | 7 | // Go to URL 8 | await page.goto('https://www.youtube.com/') 9 | }) 10 | 11 | test.beforeAll('Run before all test', async() =>{ 12 | console.log('Running before all test...!') 13 | }) 14 | 15 | test.afterEach('Run after each test', async({page}) =>{ 16 | console.log('Running after each test...!') 17 | }) 18 | 19 | test.afterAll('Run after all test', async() =>{ 20 | console.log('Running after all test...!') 21 | }) 22 | 23 | // Write a testa 24 | test('Hooks in playwright', async({page}) =>{ 25 | 26 | // Search with keywords 27 | await page.getByPlaceholder('Search').click(); 28 | await page.getByPlaceholder('Search').fill('cypress by testers talk'); 29 | 30 | await expect(page.getByRole('button', { name: 'Search', exact: true })).toBeEnabled(); 31 | await page.getByRole('button', { name: 'Search', exact: true }).click(); 32 | 33 | await page.waitForTimeout(5000); 34 | 35 | // Click on playlist 36 | await page.getByRole('link', { name: 'Cypress by Testers Talk Testers Talk · Playlist' }).click(); 37 | 38 | // Validate title 39 | await expect(page).toHaveTitle('Cypress Tutorial Full Course 2023 | Learn Cypress in 5 Hrs - YouTube'); 40 | 41 | }) 42 | 43 | // Write a testa 44 | test('Hooks in playwright2', async({page}) =>{ 45 | 46 | // Search with keywords 47 | await page.getByPlaceholder('Search').click(); 48 | await page.getByPlaceholder('Search').fill('api testing by testers talk'); 49 | 50 | await expect(page.getByRole('button', { name: 'Search', exact: true })).toBeEnabled(); 51 | await page.getByRole('button', { name: 'Search', exact: true }).click(); 52 | 53 | await page.waitForTimeout(5000); 54 | }) 55 | 56 | -------------------------------------------------------------------------------- /tests/iframedraganddrop.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const {test, expect} = require('@playwright/test'); 3 | 4 | // Write a test 5 | test('Handle iframes in playwright & Drag nd Drop', async({page}) =>{ 6 | // Go to URL 7 | await page.goto('https://jqueryui.com/droppable/') 8 | 9 | // iframe 10 | const iframeElement = page.frameLocator('.demo-frame') 11 | 12 | // src and dest element 13 | const dragElement = iframeElement.locator("[id='draggable']"); 14 | const dropElement = iframeElement.locator("[id='droppable']"); 15 | 16 | // drag and drop element 17 | await dragElement.dragTo(dropElement); 18 | 19 | await page.waitForTimeout(5000); 20 | 21 | }) 22 | 23 | -------------------------------------------------------------------------------- /tests/keyboardactions.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const {test, expect} = require('@playwright/test'); 3 | 4 | // Write a test 5 | test('Keyboard actions in playwright', async({page}) =>{ 6 | // Go to URL 7 | await page.goto('https://www.google.com/') 8 | 9 | await page.locator("[aria-label='Search']").first().click() 10 | await page.locator("[aria-label='Search']").first().fill('playwright by testers talk') 11 | 12 | // press enter 13 | await page.locator("[aria-label='Search']").first().press('Enter') 14 | 15 | // press control+a & delete 16 | await page.locator("[aria-label='Search']").first().click() 17 | await page.locator("[aria-label='Search']").first().press('Control+a'); 18 | await page.locator("[aria-label='Search']").first().press('Delete'); 19 | 20 | // press tab 21 | // await page.keyboard.press('Tab'); 22 | // await page.keyboard.press('Enter'); 23 | 24 | await page.waitForTimeout(8000); 25 | 26 | }) 27 | 28 | -------------------------------------------------------------------------------- /tests/locators.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const {test, expect} = require('@playwright/test'); 3 | 4 | // Write a test 5 | test('Locators Test', async({page}) =>{ 6 | 7 | // by role 8 | // Go to URL 9 | await page.goto('https://www.google.com/search?q=cypress+by+testers+talk'); 10 | await page.getByRole('link',{name:'Images'}).click(); 11 | 12 | // by label 13 | await page.goto('https://www.google.com/'); 14 | await page.getByLabel('Search',{exact:true}).fill('api testing by testers talk'); 15 | await page.getByLabel('Search',{exact:true}).press('Enter'); 16 | 17 | // by alt text 18 | await page.goto('https://github.com/BakkappaN'); 19 | await page.getByAltText("View BakkappaN's full-sized avatar").click(); 20 | 21 | // by test id 22 | await page.goto('https://github.com/login'); 23 | await page.getByTestId('username').fill('testers talk'); 24 | 25 | // by text 26 | await page.goto('https://www.youtube.com/@testerstalk'); 27 | await page.getByText('Cypress by Testers Talk').click(); 28 | 29 | // by title 30 | await page.goto('https://www.youtube.com/@testerstalk'); 31 | await page.getByTitle('Cypress by Testers Talk').click(); 32 | 33 | // // by xpath 34 | await page.goto('https://www.youtube.com/'); 35 | await page.locator("//*[@name='search_query']").click(); 36 | await page.locator("//*[@name='search_query']").fill('javascript by testers talk'); 37 | await page.locator("//*[@name='search_query']").press('Enter'); 38 | 39 | // // by css selector 40 | await page.goto('https://www.youtube.com/'); 41 | await page.locator("css=[name='search_query']").click(); 42 | await page.locator("css=[name='search_query']").fill('javascript by testers talk'); 43 | await page.locator("css=[name='search_query']").press('Enter'); 44 | 45 | await page.waitForTimeout(3000); 46 | 47 | 48 | }) 49 | 50 | -------------------------------------------------------------------------------- /tests/mfatest.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const { test } = require('@playwright/test'); 3 | 4 | const TOTP = require('otplib'); 5 | 6 | /** 7 | * Bakkappa N 8 | */ 9 | test('MFA Multi Factor Authentication Test', async ({ page }) => { 10 | 11 | // Generate MFA token 12 | const token = getAuthenticatorToken(); 13 | 14 | // Go to URL 15 | await page.goto('https://mysignins.microsoft.com/'); 16 | 17 | // Enter username 18 | await page.getByPlaceholder('Email or phone').click(); 19 | await page.getByPlaceholder('Email or phone').fill(process.env.MFA_APP_USER); 20 | 21 | await page.getByRole('button', { name: 'Next' }).click(); 22 | 23 | // Enter password 24 | await page.getByPlaceholder('Password').click(); 25 | await page.getByPlaceholder('Password').fill(process.env.MFA_APP_PASSWORK); 26 | await page.getByRole('button', { name: 'Sign in' }).click(); 27 | 28 | await page.getByRole('link', { name: "I can't use my Microsoft Authenticator app right now" }).click(); 29 | await page.getByRole('button', { name: 'Use a verification code' }).click(); 30 | 31 | // Enter authenticator app code 32 | await page.getByPlaceholder('Code').click(); 33 | await page.getByPlaceholder('Code').fill(token); 34 | await page.getByRole('button', { name: 'Verify' }).click(); 35 | await page.getByRole('button', { name: 'Yes' }).click(); 36 | 37 | // Logout 38 | await page.getByLabel('Account manager for testers').click(); 39 | await page.getByLabel('Sign out of this account').click(); 40 | }); 41 | 42 | function getAuthenticatorToken() { 43 | const secret = process.env.AUTHENTICATOR_SECRET; 44 | TOTP.authenticator.options = { 45 | step: 30, //default is 30 seconds 46 | window: 1 // acceptable time window 47 | } 48 | const otp = TOTP.authenticator.generate(secret); 49 | return otp; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /tests/mouseactions.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const {test, expect} = require('@playwright/test'); 3 | 4 | // Write a test 5 | test('Mouse actions in playwright', async({page}) =>{ 6 | // Go to URL 7 | await page.goto('https://www.google.com/search?q=testers+talk'); 8 | 9 | // click 10 | //await page.getByRole('link',{name:'Testers Talk'}).first().click(); 11 | 12 | // double click 13 | //await page.getByRole('link',{name:'Testers Talk'}).first().dblclick(); 14 | 15 | // mouse right click 16 | // await page.getByRole('link',{name:'Testers Talk'}).first().click({button:'right'}) 17 | 18 | // mouse middle click 19 | //await page.getByRole('link',{name:'Testers Talk'}).first().click({button:'middle'}) 20 | 21 | // mouse left click 22 | //await page.getByRole('link',{name:'Testers Talk'}).first().click({button:'left'}) 23 | 24 | // mouse hover 25 | await page.locator("[aria-label='Search by voice']").hover(); 26 | 27 | await page.waitForTimeout(5000); 28 | 29 | }) 30 | 31 | -------------------------------------------------------------------------------- /tests/multi_tabs.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const { test, expect } = require('@playwright/test'); 3 | const exp = require('constants'); 4 | const { TIMEOUT } = require('dns'); 5 | 6 | /** 7 | * Bakkappa N 8 | */ 9 | test('Handling multiple browser tabs in Playwright', async ({ browser }) => { 10 | 11 | // Create a new browser context 12 | const context = await browser.newContext(); 13 | 14 | // Open new first tab and enter URL 15 | const tab1 = await context.newPage(); 16 | await tab1.goto('https://www.youtube.com/results?search_query=playwright+by+testers+talk') 17 | 18 | // Open new second tab and enter URL 19 | const tab2 = await context.newPage(); 20 | await tab2.goto('https://www.youtube.com/results?search_query=api+testing+by+testers+talk') 21 | 22 | // Perform actions in the first tab 23 | await tab1.getByRole('link', { name: 'Playwright by Testers Talk' }).first().click(); 24 | 25 | // Perform actions in the second tab 26 | await tab2.getByRole('link', { name: 'API Testing by Testers Talk' }).first().click(); 27 | 28 | // Validate first tab title 29 | expect(tab1).toHaveTitle('Playwright Tutorial Full Course 2024 | Playwright Testing Tutorial - YouTube', { timeout: 60000 }); 30 | 31 | // Validate second tab title 32 | expect(tab2).toHaveTitle('API Testing Postman Tutorial Full Course 2023 - YouTube', { timeout: 60000 }); 33 | 34 | // Close the browser 35 | await context.close(); 36 | 37 | // Also you can create multiple sessions & multiple tabs 38 | }) 39 | 40 | -------------------------------------------------------------------------------- /tests/objectrepositorytest.spec.js: -------------------------------------------------------------------------------- 1 | // Import playwright module 2 | const { test, expect } = require('@playwright/test'); 3 | import { Placeholder, Link } from '../selectors/globalselector.json'; 4 | import { Tab } from '../expectedresults/globalexpected.json'; 5 | 6 | // Write a test 7 | test('Object Repository in Playwright', async ({ page }) => { 8 | // Go to URL 9 | await page.goto('https://www.youtube.com/') 10 | 11 | // Search with keywords 12 | await page.getByPlaceholder(Placeholder.Search).click(); 13 | await page.getByPlaceholder(Placeholder.Search).fill('playwright by testers talk'); 14 | 15 | await expect(page.getByRole('button', { name: Placeholder.Search, exact: true })).toBeEnabled(); 16 | await page.getByRole('button', { name: Placeholder.Search, exact: true }).click(); 17 | 18 | await page.waitForTimeout(2000); 19 | 20 | // Click on playlist 21 | await page.getByRole('link', { name: Link.Playwright }).first().click(); 22 | 23 | // Validate title 24 | await expect(page).toHaveTitle(Tab.Title); 25 | }) -------------------------------------------------------------------------------- /tests/pageobjecttest.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const {test, expect} = require('@playwright/test'); 3 | const { HomePage } = require('../pages/homepage'); 4 | const { ResultPage } = require('../pages/resultpage'); 5 | const { PlaylistPage } = require('../pages/playlistpage'); 6 | 7 | // Write a test 8 | test('Page Object Model in playwright', async({page}) =>{ 9 | // Go to URL 10 | const homepage = new HomePage(page); 11 | await homepage.goto(); 12 | 13 | // Search with keywords 14 | homepage.searchKeywords('playwright by testers talk'); 15 | 16 | // Click on playlist 17 | const resultpage = new ResultPage(page); 18 | resultpage.clickOnPlaylist(); 19 | 20 | await page.waitForTimeout(4000) 21 | 22 | // Click on video 23 | const playlistpage = new PlaylistPage(page); 24 | playlistpage.clickOnVideo(); 25 | 26 | await page.waitForTimeout(8000) 27 | }) 28 | 29 | -------------------------------------------------------------------------------- /tests/parameterizetest.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const {test, expect} = require('@playwright/test'); 3 | 4 | const testParameters = ['playwright by testers talk','cypress by testers talk','javascript by testers talk']; 5 | 6 | for (const searchKeyword of testParameters) { 7 | 8 | // Write a test 9 | test(`Parameterize tests in playwright ${searchKeyword}`, async({page}) =>{ 10 | // Go to URL 11 | await page.goto('https://www.youtube.com/') 12 | 13 | // search with keywords 14 | await page.getByPlaceholder('Search').click(); 15 | await page.getByPlaceholder('Search').fill(searchKeyword) 16 | await page.getByPlaceholder('Search').press('Enter'); 17 | 18 | await page.waitForTimeout(5000); 19 | 20 | }) 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /tests/phone_call_test.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const { test, expect } = require('@playwright/test'); 3 | 4 | const client = require('twilio')(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN); 5 | 6 | /** 7 | * Bakkappa N 8 | */ 9 | test('How to automate phone call in Plawright', async ({ page }) => { 10 | 11 | // Playwright actions 12 | 13 | // Make a phone call using Twilio 14 | await client.calls.create({ 15 | twiml: process.env.TWIML_URL, 16 | to: process.env.TO_PHONE_NUMBER, 17 | from: process.env.TWILIO_PHONE_NUMBER 18 | }) 19 | .then(call => console.log(`Call SID: ${call.sid}`)) 20 | .catch(error => console.error('Error making the call:', error)); 21 | 22 | // Playwright actions 23 | }) 24 | 25 | -------------------------------------------------------------------------------- /tests/readdatabasedonenv.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const { test, expect } = require('@playwright/test'); 3 | import { qaTestData } from '../test-data/qa/google.json'; 4 | import { stageTestData } from '../test-data/stage/google.json'; 5 | 6 | let testData = null; 7 | 8 | test.beforeAll('Running before all tests', () => { 9 | if (process.env.ENV == 'qa') { 10 | testData = qaTestData; 11 | } else { 12 | testData = stageTestData; 13 | } 14 | }) 15 | 16 | // Write a test 17 | test('Read Test data based on different env in playwright ', async ({ page }) => { 18 | // Go to URL 19 | await page.goto(process.env.URL); 20 | 21 | // search with keywords 22 | await page.locator('#APjFqb').click(); 23 | await page.locator('#APjFqb').fill(testData.skill1); 24 | await page.locator('#APjFqb').press('Enter'); 25 | await page.waitForTimeout(5000); 26 | }) 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /tests/readenvfile.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const {test, expect} = require('@playwright/test'); 3 | 4 | // Write a test 5 | test('Read Env File in playwright', async({page}) =>{ 6 | // Go to URL 7 | await page.goto(process.env.URL); 8 | 9 | // search with keywords 10 | await page.locator('#APjFqb').click(); 11 | await page.locator('#APjFqb').fill('playwright by testers talk'); 12 | await page.locator('#APjFqb').press('Enter'); 13 | 14 | console.log("Username is : "+process.env.USER_NAME); 15 | console.log("Password is : "+process.env.PASSWORD); 16 | 17 | await page.waitForTimeout(5000); 18 | 19 | }) 20 | 21 | -------------------------------------------------------------------------------- /tests/recordatcursortest.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | 3 | test('test', async ({ page }) => { 4 | await page.goto('https://github.com/BakkappaN'); 5 | await page.getByRole('link', { name: 'Sign in' }).click(); 6 | await page.getByLabel('Username or email address').click(); 7 | await page.getByLabel('Username or email address').fill('456789dfgh'); 8 | await page.getByLabel('Password').click(); 9 | await page.getByLabel('Password').fill('ertyu34567'); 10 | await expect(page.getByRole('button', { name: '56789', exact: true })).toBeVisible(); 11 | await page.getByRole('button', { name: 'Sign in', exact: true }).click(); 12 | await expect(page.getByRole('alert')).toContainText('Incorrect username or password.'); 13 | }); -------------------------------------------------------------------------------- /tests/recordtest.spec.js: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | 3 | test('test', async ({ page }) => { 4 | await page.goto('https://github.com/BakkappaN'); 5 | await page.getByRole('link', { name: 'Sign in' }).click(); 6 | await page.getByLabel('Username or email address').click(); 7 | await page.getByLabel('Username or email address').fill('456789dfgh'); 8 | await page.getByLabel('Password').click(); 9 | await page.getByLabel('Password').fill('ertyu34567'); 10 | await page.getByRole('button', { name: 'Sign in', exact: true }).click(); 11 | await expect(page.getByRole('alert')).toContainText('Incorrect username or password.'); 12 | }); -------------------------------------------------------------------------------- /tests/screenshots.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const { test, expect } = require('@playwright/test'); 3 | 4 | // Write a testa 5 | test('Take screenshot in playwright', async ({ page }) => { 6 | 7 | await test.step('Go to URL', async () => { 8 | await page.goto('https://www.youtube.com/@testerstalk') 9 | }); 10 | 11 | await test.step('Take a element screenshot', async () => { 12 | await page.locator('#page-header-banner').screenshot({ path: './screenshots/element.png' }) 13 | }); 14 | 15 | await test.step('Capture a page screenshot', async () => { 16 | await page.screenshot({ path: './screenshots/page.png' }); 17 | }); 18 | 19 | await test.step('Take a full page screenshot', async () => { 20 | await page.screenshot({ path: './screenshots/fullpage.png', fullPage: true }); 21 | await page.waitForTimeout(5000); 22 | }); 23 | }) -------------------------------------------------------------------------------- /tests/softassertion.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const {test, expect} = require('@playwright/test'); 3 | 4 | // Write a test 5 | test('Soft Assertions in playwright', async({page}) =>{ 6 | // Go to URL 7 | await page.goto('https://www.google.com/search?q=playwright+by+testers+talk') 8 | 9 | // assert url 10 | await expect.soft(page).toHaveURL('https://www.google.com/playwright+by+testers+talk') 11 | 12 | // assert title 13 | await expect(page).toHaveTitle('playwright by testers talk - Google Search') 14 | 15 | // assert text 16 | await expect.soft(page.locator("[aria-label='Search']").first()).toHaveText('playwright testers talk') 17 | 18 | //assert editable enabled visible 19 | await expect(page.locator("[aria-label='Search']").first()).toBeEditable(); 20 | await expect(page.locator("[aria-label='Search']").first()).toBeVisible(); 21 | await expect(page.locator("[aria-label='Search']").first()).toBeEnabled(); 22 | 23 | //assert disabled empty count 24 | //await expect(page.locator("[aria-label='Search']").first()).toBeDisabled(); 25 | 26 | await expect(page.locator("[aria-label='Search']").first()).not.toBeEmpty(); 27 | 28 | await expect(page.locator("[aria-label='Search']")).toHaveCount(2) 29 | 30 | await page.waitForTimeout(5000); 31 | }) 32 | 33 | -------------------------------------------------------------------------------- /tests/tagtest.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const {test, expect} = require('@playwright/test'); 3 | 4 | // Write a test 5 | test('Test1 @Tag1', async({page}) =>{ 6 | // Go to URL 7 | await page.goto('https://www.youtube.com/') 8 | 9 | // Search with keywords 10 | await page.getByPlaceholder('Search').click(); 11 | await page.getByPlaceholder('Search').fill('cypress by testers talk'); 12 | 13 | await expect(page.getByRole('button', { name: 'Search', exact: true })).toBeEnabled(); 14 | await page.getByRole('button', { name: 'Search', exact: true }).click(); 15 | 16 | await page.waitForTimeout(2000); 17 | 18 | // Click on playlist 19 | await page.getByRole('link', { name: 'Cypress by Testers Talk Testers Talk · Playlist' }).click(); 20 | 21 | // Validate title 22 | await expect(page).toHaveTitle('Cypress Tutorial Full Course 2023 | Learn Cypress in 5 Hrs - YouTube'); 23 | 24 | }) 25 | 26 | 27 | // Write a test 28 | test('Test2 @Tag2', async({page}) =>{ 29 | // Go to URL 30 | await page.goto('https://www.youtube.com/') 31 | 32 | // Search with keywords 33 | await page.getByPlaceholder('Search').click(); 34 | await page.getByPlaceholder('Search').fill('cypress by testers talk'); 35 | 36 | await expect(page.getByRole('button', { name: 'Search', exact: true })).toBeEnabled(); 37 | await page.getByRole('button', { name: 'Search', exact: true }).click(); 38 | 39 | await page.waitForTimeout(2000); 40 | 41 | // Click on playlist 42 | await page.getByRole('link', { name: 'Cypress by Testers Talk Testers Talk · Playlist' }).click(); 43 | 44 | // Validate title 45 | await expect(page).toHaveTitle('Cypress Tutorial Full Course 2023 | Learn Cypress in 5 Hrs - YouTube'); 46 | 47 | }) 48 | 49 | 50 | // Write a test 51 | test('Test3 @Tag1', async({page}) =>{ 52 | // Go to URL 53 | await page.goto('https://www.youtube.com/') 54 | 55 | // Search with keywords 56 | await page.getByPlaceholder('Search').click(); 57 | await page.getByPlaceholder('Search').fill('cypress by testers talk'); 58 | 59 | await expect(page.getByRole('button', { name: 'Search', exact: true })).toBeEnabled(); 60 | await page.getByRole('button', { name: 'Search', exact: true }).click(); 61 | 62 | await page.waitForTimeout(2000); 63 | 64 | // Click on playlist 65 | await page.getByRole('link', { name: 'Cypress by Testers Talk Testers Talk · Playlist' }).click(); 66 | 67 | // Validate title 68 | await expect(page).toHaveTitle('Cypress Tutorial Full Course 2023 | Learn Cypress in 5 Hrs - YouTube'); 69 | 70 | }) 71 | -------------------------------------------------------------------------------- /tests/testerstalk.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | import fs from 'fs'; 3 | import path from "path"; 4 | const {test, expect} = require('@playwright/test'); 5 | import { parse } from "csv-parse/sync"; 6 | 7 | import { qaTestData } from '../test-data/qa/google.json' 8 | import { stageTestData } from '../test-data/stage/google.json' 9 | 10 | const testParameters = ['playwright by testers talk','cypress by testers talk', 11 | 'javascript by testers talk','api testing by testers talk', 12 | 'postman by testers talk','rest assured by testers talk']; 13 | 14 | test.describe('Module1 Tests', () => { 15 | 16 | let testData = null; 17 | 18 | test.beforeAll('Running before All tests...!!',()=>{ 19 | if(process.env.ENV == 'qa'){ 20 | testData = qaTestData; 21 | }else{ 22 | testData = stageTestData; 23 | } 24 | }) 25 | 26 | // Write a test 27 | test('Env Test', async({page}) =>{ 28 | // Go to URL 29 | await page.goto(process.env.URL); 30 | 31 | // search with keywords 32 | await page.locator('#APjFqb').click(); 33 | await page.locator('#APjFqb').fill(testData.skill1); 34 | await page.locator('#APjFqb').press('Enter') 35 | await page.waitForTimeout(6000); 36 | }) 37 | }) 38 | 39 | const records = parse ( 40 | fs.readFileSync(path.join(__dirname,"../test-data/qa/testdata.csv")), 41 | { 42 | columns: true, 43 | skip_empty_lines:true, 44 | }); 45 | 46 | for (const record of records) { 47 | 48 | test(`data driven testing csv test: ${record.TestCaseId}`, async({ page }) =>{ 49 | // Go to URL 50 | await page.goto(process.env.URL); 51 | 52 | // search with keywords 53 | await page.locator('#APjFqb').click(); 54 | await page.locator('#APjFqb').fill(record.Skill1); 55 | await page.locator('#APjFqb').press('Enter') 56 | await page.waitForTimeout(6000); 57 | }); 58 | } 59 | 60 | 61 | 62 | for (const searchKeyword of testParameters) { 63 | 64 | // Write a test 65 | test(`Parameterization Test ${searchKeyword}`, async({page}) =>{ 66 | // Go to URL 67 | await page.goto('https://www.youtube.com/'); 68 | 69 | // search with keywords 70 | await page.getByPlaceholder('Search').click(); 71 | await page.getByPlaceholder('Search').fill(searchKeyword); 72 | await page.getByPlaceholder('Search').press('Enter'); 73 | await page.waitForTimeout(2000); 74 | 75 | await expect(page.getByText(searchKeyword)).toBeEnabled(); 76 | await page.getByText(searchKeyword).click(); 77 | await page.waitForTimeout(6000); 78 | }) 79 | } 80 | 81 | for (const searchKeyword of testParameters) { 82 | 83 | // Write a test 84 | test(`Google Search with ${searchKeyword}`, async({page}) =>{ 85 | // Go to URL 86 | await page.goto('https://www.google.com/'); 87 | 88 | // search with keywords 89 | await page.locator("[aria-label='Search']").first().click(); 90 | await page.locator("[aria-label='Search']").first().fill(searchKeyword); 91 | await page.locator("[aria-label='Search']").first().press('Enter'); 92 | await page.waitForTimeout(2000); 93 | 94 | await expect(page.getByRole('link',{name:searchKeyword}).first()).toBeEnabled(); 95 | await page.getByRole('link',{name:searchKeyword}).first().click(); 96 | await page.waitForTimeout(6000); 97 | }) 98 | } 99 | 100 | -------------------------------------------------------------------------------- /tests/visualtesting.spec.js: -------------------------------------------------------------------------------- 1 | // Include playwright module 2 | const {test, expect} = require('@playwright/test'); 3 | 4 | // Write a test 5 | test('Visual comparison testing in playwright', async({page}) =>{ 6 | // Go to URL 7 | await page.goto('https://github.com/login') 8 | 9 | // before actions 2 images comparison 10 | await expect(page).toHaveScreenshot('githubpage.png'); 11 | 12 | await page.locator('#login_field').click(); 13 | await page.locator('#login_field').fill('testers talk') 14 | 15 | // after actions 2 images comparisons 16 | await expect(page).toHaveScreenshot('githubpage.png'); 17 | 18 | await page.waitForTimeout(3000); 19 | 20 | }) 21 | 22 | 23 | // Write a test 24 | test('Element Comparison in playwright', async({page}) =>{ 25 | // Go to URL 26 | await page.goto('https://github.com/login') 27 | 28 | const element = page.locator('#login_field'); 29 | await expect(element).toHaveScreenshot('element.png'); 30 | 31 | await page.waitForTimeout(3000); 32 | 33 | }) 34 | 35 | -------------------------------------------------------------------------------- /tests/visualtesting.spec.js-snapshots/githubpage-Google-Chrome-win32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BakkappaN/PlaywrightTutorialFullCourse/b651140a845bd2c0bfb8bd23f875c9a99fa15de0/tests/visualtesting.spec.js-snapshots/githubpage-Google-Chrome-win32.png --------------------------------------------------------------------------------