
⭐️ This post was featured in Software Testing Weekly #110 and Coding JAG #76
My first experience with Playwright was terrible. However the testing community seems to be loving it, thus I gave it another shot. I started by doing a free course, but I don’t recommend it, it’s very outdated by now.
I know you loved my Cypress recipes post, so here’s a new one for Playwright with up-to-date code snippets on how to implement common automation scenarios.
- Setup
- Test skeleton (Test version)
- Test skeleton (Library version)
- Actions
- Visit URL
- Select page element
- Count selected elements
- Type text
- Click element
- Dropdowns
- Checkboxes and Radios
- iFrames
- Alerts / Dialog popups
- Check status of element
- Assertions
- Check the page title
- Check something exists in the page
- Miscellaneous
- Take a screenshot
- Record a video
- Emulate a mobile device
⚙️ Setup
Test skeleton (Test version)
const { expect, test } = require("@playwright/test");
test.describe("Google search", () => {
test("is online", async ({ page }) => {
await page.goto("https://google.com/");
await expect(page).not.toBeNull();
});
});
Test skeleton (Library version)
const { chromium } = require("playwright");
(async () => {
const browser = await chromium.launch({ headless: false, slowMo: 100 }); // options
const page = await browser.newPage();
// do stuff
await browser.close();
})();
⚡️ Actions
Visit URL
await page.goto("https://google.com");
Select page element
// locate based on user visible text
const emailInput = await page.locator("text=Action was successful");
// locate based on CSS selector
const emailInput = await page.locator("#cssSelector > goes here");
Count selected elements
const matches = await page.locator("#cssSelector > goes here");
const total = matches.count();
const firstMatch = matches.first();
const thirdMatch = matches.nth(2); // index is 0-based
const lastMatch = matches.last();
Type text
const emailInput = ...;
await emailInput.fill("Text to type goes here");
// or inline
await page.locator("#cssSelector").fill("Fake user will type this");
// send keys to the page, regardless what is currently focused
await page.keyboard.type("pressing some KEYS!");
// send key combinations (e.g. shortcuts)
await page.keyboard.press('Ctrl+C');
// press and hold a key (e.g. select something)
await page.keyboard.down('Shift');
for (let i = 0; i < 'KEYS!'.length; i++)
await page.keyboard.press('ArrowLeft');
await page.keyboard.up('Shift');
Click element
await page.locator("#cssSelector").click();
Dropdowns
await page.selectOption("#css", "blue" ); // by internal value
await page.selectOption("#css", { label: "Blue ink" }); // by visible label
await page.selectOption("#css", { index: 1 }); // by 0-based index
await page.selectOption("#css", ["red", "blue"]); // multi select
Checkboxes and Radios
await page.check('#css');
await page.uncheck('#css');
await page.check('text=XL'); // check radio
expect(await page.isChecked('#css')).toBeTruthy(); // assert state
iFrames
const iframeCheckoutSanddox = "#checkout-demo";
const sectionPaymentSummary = "#ProductSummary-totalAmount";
const inputEmail = "#email";
await page.goto("https://checkout.stripe.dev/preview");
// select the iframe
const stripeFrame = page.frameLocator(iframeCheckoutSanddox);
await expect(stripeFrame).not.toBeNull();
// assert elements withing the iframe
await expect(stripeFrame.locator(sectionPaymentSummary)).toBeVisible();
// interact with elements withing the iframe
await frame.locator(inputEmail).fill("[email protected]");
Alerts / Dialog popups
/* TODO: Update this code, I think it's outdated by now
// code to listen for a dialog popup
page.once("dialog", async (dialog) => {
console.log(dialog.message()); // confirm msg seen by user
await dialog.accept(); // close dialog
});
// actually trigger the dialog
await page.click("#confirmButton");
// using ".once" instead of ".on" allows multiple listeners in the same test
page.once("dialog", async (dialog) => {
await dialog.accept("Hello input!"); // to input something in a dialog
});
await page.click("#promptButton");
*/
Check status of element
await page.locator("#cssSelector").isVisible();
P.S: list with all the assertions available
✅ Assertions
Check the page title
await expect(page).toHaveTitle("The Geeky Gecko - The most amazing blog");
Check something exists in the page
await expect(page.locator("#cssSelector")).toBeVisible();
Miscellaneous
Take a screenshot
await page.screenshot({path: "path/to/generated_file.png"}); // page above the fold
await page.screenshot({path: "path/to/file.png", fullPage: true}); // entire page
await page.locator("#css").screenshot({path: "path/to/file.png"}); // just an element