'Select input by label text in Puppeteer/Playwright

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.



Solution 1:[1]

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:

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())
;

Solution 2:[2]

To expand on @ggorlen answer, and to make it even more similar to Testing Library, you can use the :has-text() pseudo-class to select the accessible name:

await page.click('label:has-text("Name")');
await page.keyboard.type('hello world');

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ggorlen
Solution 2 cmolina