最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Playwright - Find multiple elements or class names - Stack Overflow

programmeradmin3浏览0评论

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:

.png

.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 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");
Share Improve this question edited Mar 19, 2021 at 11:48 hardkoded 21.6k3 gold badges60 silver badges74 bronze badges asked Mar 19, 2021 at 4:32 RussellRussell 1611 gold badge1 silver badge7 bronze badges 2
  • 1 This code worked for me gist.github.com/kblok/19b60e76197c4d8aebaba650b2b1af93 what's different there? – hardkoded Commented Mar 19, 2021 at 11:53
  • Hi @hardkoded - you're response helped me. But see my answer to what the main issue was. – Russell Commented Mar 20, 2021 at 7:14
Add a comment  | 

3 Answers 3

Reset to default 6

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"));
});
  public async validListOfItems(name) {
  await this.page.waitForSelector(name, {timeout: 5000});
  const itemlists = await this.page.$$(name);

  let allitems: string[]=new Array();

    for await (const itemlist of itemlists) {
        allitems.push(await itemlist.innerText());
    }
  return allitems;
  }

Make a common method and call by sending parameters.

发布评论

评论列表(0)

  1. 暂无评论