Given the following markup:
<label for="name">Name</label>
<input type="text" id="name" />
I want to fill the input value in a Playwright test. However, I prefer to follow a paradigm similar to Testing Library, which is using selectors like a real user would (usually visible text content). Therefore, I would like my Playwright selector to use the label text.
When I attempt the following I get an error element is not an <input>
because it selects the actual label element:
await page.fill('"Name"')
Is there another way to achieve this?
Note: I'm not keen on using the Playwright Testing Library package because it simply isn't mature enough. Also, my understanding is that Puppeteer and Playwright are virtually the same, hence why this question applies to both frameworks.
You could .click()
the label to set focus on the input, then use page.keyboard.type
to type into the input.
Here's a minimal example in Puppeteer:
const puppeteer = require("puppeteer");
let browser;
(async () => {
browser = await puppeteer.launch({headless: true});
const [page] = await browser.pages();
await page.setContent(`
<label for="name">Name</label>
<input type="text" id="name" />
`);
await page.click("label[for='name']");
await page.keyboard.type("hello world");
console.log(await page.$eval("#name", e => e.value)); // => hello world
console.log(await page.evaluate(() => document.activeElement.value)); // same
})()
.catch(err => console.error(err))
.finally(() => browser?.close());
Note that although they seem superficially similar, Playwright and Puppeteer have diverged a fair bit as of the time of writing. Playwright has deprecated most of its Puppeteer-style API in favor of locators, so selection and manipulation are now quite different between the two libraries.
The above Puppeteer code pretty much works in Playwright at the time of writing, but an idiomatic, locator-based Playwright approach would be:
const playwright = require("playwright"); // ^1.30.1
let browser;
(async () => {
browser = await playwright.chromium.launch();
const page = await browser.newPage();
await page.setContent(`
<label for="name">Name</label>
<input type="text" id="name" />
`);
const input = page.getByLabel("name");
await input.click();
await page.keyboard.type("hello world");
console.log(await input.inputValue()); // => hello world
console.log(await page.evaluate(() => document.activeElement.value)); // same
})()
.catch(err => console.error(err))
.finally(() => browser?.close());
Addendum, August 2023: Puppeteer has now added support for their own experimental locators.