I have read a few different QAs related to this but none seem to be working.
I am trying to target an element (Angular) called mat-radio-button with a class called mat-radio-checked. And then select the inner text.
In Chrome this is easy:
https://i.sstatic.net/Ev0iQ.png
https://i.sstatic.net/lVoG3.png
To find the first element that matches in Playwright I can do something like:
let test: any = await page.textContent(
"mat-radio-button.mat-radio-checked"
);
console.log(test);
But if I try this:
let test: any = await page.$$(
"mat-radio-button.mat-radio-checked"
);
console.log(test);
console.log(test[0]);
console.log(test[1]);
});
It does not return an array of elements I can select the inner text of.
I need to be able to find all elements with that class so I can use expect to ensure the returned inner text is correct, eg:
expect(test).toBe("Australian Citizen");
I found out the issue was due to the page generating beforehand and the elements were not available. So I added a waitForSelector:
await page.waitForSelector("mat-radio-button");
const elements = await page.$$("mat-radio-button.mat-radio-checked");
console.log(elements.length);
console.log(await elements[0].innerText());
console.log(await elements[1].innerText());
console.log(await elements[2].innerText());
Approaches in existing answers are no longer considered idiomatic Playwright. The current preferred approach is to use locators, which auto-wait for the element(s) to be available. Locators usually mitigate the need for page.$ and waitForSelector, wich are legacy Puppeteer-style methods.
To extract text from a locator matching more than one element, you can use allTextContents:
const playwright = require("playwright"); // 1.30.0
let browser;
(async () => {
browser = await playwright.chromium.launch();
const page = await browser.newPage();
await page.setContent(`<p>a</p><p>b</p>`);
console.log(await page.locator("p").allTextContents()); // => [ 'a', 'b' ]
})()
.catch(err => console.error(err))
.finally(() => browser?.close());
Now, you mention:
I need to be able to find all elements with that class so I can use expect to ensure the returned inner text is correct, eg:
expect(test).toBe("Australian Citizen");
In this case, use toHaveText, a web-first assertion:
import {expect, test} from "@playwright/test"; // ^1.30.0
test("has the right text", async ({page}) => {
await page.setContent("<p>a</p><p>a</p>");
await expect(page.locator("p")).toHaveText(["a", "a"]);
});
If you have a ton of elements, all with the same text, even if you're not sure how many are there in advance:
test("has the right text", async ({page}) => {
await page.setContent("<p>a</p>".repeat(30));
const loc = page.locator("p");
const quantity = await loc.count();
await expect(loc).toHaveText(Array(quantity).fill("a"));
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With