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

typescript - toBeVisible count of onscreen items - Stack Overflow

programmeradmin2浏览0评论

I'm unsure if I've missed something, but I need to:

  1. Check an item is visible on screen (code below which is working)
  2. Do a count on the number of visible items on screen

Originally I was doing:

 test('Desktop check - (Optimal on desktop / tablet) only shown on smaller screens (i.e mobile breakpoint)', async ({ page, isMobile }) => {
    test.skip(isMobile)
    await page.goto(url);
    const buttonsCount = await page.getByText('(Optimal on desktop / tablet)').count();
    expect(buttonsCount).toBe(0);
  });

But this was also finding all of the hidden versions of this test, so whilst I was expecting 0, it was returning 1.

Easy fix for part one was to switch to .toBeVisible(), but then there is no count property on .toBeVisible() I can access.

How can I do a count on toBeVisible? Or should I do a loop count and pass that into a .toBe()?

I'm unsure if I've missed something, but I need to:

  1. Check an item is visible on screen (code below which is working)
  2. Do a count on the number of visible items on screen

Originally I was doing:

 test('Desktop check - (Optimal on desktop / tablet) only shown on smaller screens (i.e mobile breakpoint)', async ({ page, isMobile }) => {
    test.skip(isMobile)
    await page.goto(url);
    const buttonsCount = await page.getByText('(Optimal on desktop / tablet)').count();
    expect(buttonsCount).toBe(0);
  });

But this was also finding all of the hidden versions of this test, so whilst I was expecting 0, it was returning 1.

Easy fix for part one was to switch to .toBeVisible(), but then there is no count property on .toBeVisible() I can access.

How can I do a count on toBeVisible? Or should I do a loop count and pass that into a .toBe()?

Share Improve this question edited Mar 18 at 5:47 Karen.Schlossberg 2142 silver badges10 bronze badges asked Mar 17 at 14:10 Carl BruinersCarl Bruiners 5902 gold badges8 silver badges23 bronze badges 1
  • Could you share a simple page under test? – ggorlen Commented Mar 17 at 15:17
Add a comment  | 

3 Answers 3

Reset to default 4

Maybe easiest of the options is applying filter method to your getByText().

const buttonCount = await page.getByText('(Optimal on desktop / tablet)')
  .filter({ visible: true })
  .count()

See Matching only visible elements

If you look at the section below that Count items in a list there is a specific assertion toHaveCount() you may use.

expect(page.getByText('(Optimal on desktop / tablet)').filter({ visible: true }))
  .toHaveCount(0)

This is my minimal proof test:

test('filtering by visible', async ({ page }) => {

  const html = `
    <html><body>
      <button style="display:none">(Optimal on desktop / tablet)</button>
    </body></html>
  `
  await page.setContent(html);

  const visibleButtons = page.getByText('(Optimal on desktop / tablet)')
    .filter({ visible: true })
  await expect(visibleButtons).toHaveCount(0)
})

If I remove the display:none style, I can see the test failing which means the test meets expectations.

For interactive elements such as <input> and <button> the getByRole() locator is recommended.

This locator has an implict visible:true criteria.

For reference, see the options section for getByRole

  • includeHidden boolean (optional)

    Option that controls whether hidden elements are matched. By default, only non-hidden elements, as defined by ARIA, are matched by role selector.

So for a button with display:none style, this counts 0 elements:

const count = await page.getByRole('button', { name: /Optimal on desktop/i })
  .count();
expect(count).toBe(0);

but changing the button style to display:block the count becomes 1, and the test no longer passes.

If you're using Playwright 1.51 or above and can use Locator.filter({ visible: true }) (as Karen.Schlossberg describes here, that is an easier solution.

If you're using a version of Playwright below 1.51, continue reading:

You can use JavaScript's Array.filter() alongside Playwright's Locator.isVisible() to filter out any hidden elements. It gets a little trickier when remembering you'll have to use an async function inside of Array.filter().

// Get all elements
const elements = await page.getByText('(Optimal on desktop / tablet)').all();
// Make our promise array
const isVisiblePromises = elements.map(async element => await element.isVisible());
// Resolve our promises
const isVisible = await Promise.all(isVisiblePromises);
// Use our resolved promise array to filter original Locator array
const filteredElements = elements.filter((_, index) => isVisible[index])
// Validate our filtered elements length
expect(filteredElements.length).toBe(0);
发布评论

评论列表(0)

  1. 暂无评论