为什么我不能在 page.waitForFunction 中使用 page.locator?

问题描述 投票:0回答:1

我正在用 Playwright 进行一些实验,凭借我的 Cypress 背景,我对 cypress-wait-until 函数感到满意。

我尝试等待,直到存在预期数量的 DOM 元素。 同时我找到了多种解决方案,但我想知道为什么我的第一种方法不起作用。

也许你们当中有人也陷入了同样的陷阱?

这是我的测试用例。

  1. 打开网页

  2. 接受cookies

  3. 搜索伦勃朗·范·莱恩图片

  4. 等到 WORKS OF ART 图像轮播有 10 件作品

test('search for rembrandt', async ({page, browser, context}) => {
    await page.goto('https://www.rijksmuseum.nl/en/content-search');
    // accept cookies
    await page.click('text=Accept');
    const inputSearch = page.locator("input.search-bar-input")
    await inputSearch.fill('Rembrandt van Rijn')
    const buttonSearch = page.locator("button[class$='search-bar-button']")
    await buttonSearch.click()
    // here comes the wait until code

})
  1. 尝试:❌

     await page.waitForFunction(
         (page)=>
             page.locator('div[aria-label="Carousel with links to works of art"] div.carousel-item')
                 .count()
                 .then(nrOfElements => nrOfElements === 10), page)
    
  2. 尝试:❌

     await page.waitForFunction(
         async (page)=>
            await page.locator('div[aria-label="Carousel with links to works of art"] div.carousel-item')
                 .count()
                 .then(nrOfElements => nrOfElements === 10), page)
    
    

    注意:您需要将页面变量作为参数传递,否则您会得到:

    ReferenceError: page is not defined

    我总是得到:

    Error: Unexpected value
    enter image description here

    虽然

    page.waitForFunction
    能够正确处理这样的 Promise:

    await page.waitForFunction(async() => await new Promise((resolve) => setTimeout(() => resolve(true), 10_000)))

    await page.waitForFunction(() => new Promise((resolve) => setTimeout(() => resolve(true), 10_000)))

  3. 又快又脏,但很有效:

    while(!await page.locator('div[aria-label="Carousel with links to works of art"] div.carousel-item').count().then(nrOfElements => nrOfElements ===10))

    注意:这里您将需要额外的超时,因此如果元素数量不匹配,测试就会停止!

  4. 人工智能的推荐也有效,但在我看来不太好:

    const extendArtQuerySelector = 'div[aria-label="Carousel with links to works of art"] div.carousel-item';
    
    // transferring only selector to browser context
    await page.waitForFunction(ellSelector => {
        const elements = document.querySelectorAll(ellSelector);
        return elements.length >= 10;
    }, extendArtQuerySelector);
    
  5. 最后是最干净的解决方案:

    await expect(page.locator('div[aria-label="Carousel with links to works of art"] div.carousel-item')).toHaveCount(10)

你们有一个想法吗,为什么 page.locator 在 waitForFunction 中不起作用?

typescript promise playwright playwright-typescript
1个回答
0
投票

是的,

waitForFunction
的回调在浏览器中运行,浏览器无法访问剧作家定位器。

由于您正在编写测试,因此可以使用

expect(loc).toHaveLength(10)
:


test("search for rembrandt", async ({page}) => {
  await page.goto(
    "https://www.rijksmuseum.nl/en/content-search"
  );
  await page.getByText("Accept").click();
  await page
    .getByPlaceholder("For info, artist, guided tour or more")
    .fill("Rembrandt van Rijn");
  const searchButton = page.getByRole("button", {
    name: "Search",
    exact: true,
  });
  await searchButton.click();
  const carouselItems = page
    .getByLabel("Carousel with links to works of art")
    .locator(".carousel-item");
  await expect(carouselItems).toHaveCount(10);
});

注意,我已尝试尽可能使用最佳实践用户可见定位器而不是 CSS。

© www.soinside.com 2019 - 2024. All rights reserved.