我正在用 Playwright 进行一些实验,凭借我的 Cypress 背景,我对 cypress-wait-until 函数感到满意。
我尝试等待,直到存在预期数量的 DOM 元素。 同时我找到了多种解决方案,但我想知道为什么我的第一种方法不起作用。
也许你们当中有人也陷入了同样的陷阱?
这是我的测试用例。
打开网页
接受cookies
搜索伦勃朗·范·莱恩图片
等到 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
})
尝试:❌
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)
尝试:❌
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
虽然
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)))
又快又脏,但很有效:
while(!await page.locator('div[aria-label="Carousel with links to works of art"] div.carousel-item').count().then(nrOfElements => nrOfElements ===10))
注意:这里您将需要额外的超时,因此如果元素数量不匹配,测试就会停止!
人工智能的推荐也有效,但在我看来不太好:
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);
最后是最干净的解决方案:
await expect(page.locator('div[aria-label="Carousel with links to works of art"] div.carousel-item')).toHaveCount(10)
你们有一个想法吗,为什么 page.locator 在 waitForFunction 中不起作用?
是的,
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。