I'm trying to create a basic register script using playwright typescript. If I use debug mode and step through the code it runs perfect but if I use headless, it fails. It fails when trying to do a fill in the email field. The locator that I'm using is able to find the element but it tries to wait for it to be visible even though it's present on the page. There are no iframes on the html.
import { test, expect, Locator, Page } from '@playwright/test';
class RegisterStr{
userName: Locator;
pw: Locator;
button: Locator;
constructor(page: Page){
this.userName = page.locator('#username')
this.pw = page.getByLabel('#password')
this.button = page.locator("#submit")
}
}
test.describe("Resgietring", ()=>{
let regis : RegisterStr;
test('has title', async ({ page }) => {
regis = new RegisterStr(page)
await page.goto('https://practicetestautomation.com/practice-test-login/');
regis.userName.fill("student")
regis.pw.fill("Password123")
regis.button.click();
// await page.waitForURL("https://practicetestautomation.com/logged-in-successfully/")
// Expect signed in
await expect(page.getByRole('heading', { name: 'Logged In Successfully' })).toBeVisible();
});
})
I see two problems:
await
all Playwright API calls that return promises. Failing to do so causes race conditions and nondeterminism, meaning the script can fail at random and give confusing errors or unpredictable behavior..locator()
rather than .getByLabel()
.Applying these fixes passes the test for me headfully or headlessly (I used JS, not TS but it's irrelevant):
import {expect, test} from "@playwright/test"; // ^1.39.0
class Register {
constructor(page) {
this.userName = page.locator("#username");
this.pw = page.locator("#password");
this.button = page.locator("#submit");
}
}
test.describe("Registering", () => {
test("has title", async ({page}) => {
const regis = new Register(page);
await page.goto(
"https://practicetestautomation.com/practice-test-login/"
);
await regis.userName.fill("student");
await regis.pw.fill("Password123");
await regis.button.click();
await page.waitForURL(
"https://practicetestautomation.com/logged-in-successfully/"
);
await expect(
page.getByRole("heading", {name: "Logged In Successfully"})
).toBeVisible();
});
});
Beyond correctness, the POM here should probably be doing more work than it currently is. It's inconsistent to have some locators in the POM and some not, and generally it's useful to add methods that abstract away some of the "raw" Playwright actions.