使用Playwright在任意iframe中定位元素



我正在使用Playwright对由多个嵌套iframe组成的web应用程序进行端到端自动化。目前,我使用frameLocator分解多个iframe,然后尝试在所需的iframe:中定位一个元素

const firstFrame = await page.frameLocator("#firstIframe");
const secondFrame = await firstFrame.frameLocator("#secondIframe");
const element = await secondFrame.locator("input").fill("Some text")

有没有一种方法可以在任何iframe中定位元素,这样我就不需要分解所有嵌套的iframe了?

我在C#中编写了这个方法,您可以在Javascript中传输它:

public async Task<IElementHandle> FindElement(string selector)
{
IElementHandle element = null;
var Pages = _context.Pages.ToArray();
foreach (var w in Pages)
{
//============================================================
element = await w.QuerySelectorAsync(selector);
if (element != null)
{
return element;
}
//============================================================
var iframes = w.Frames.ToList();
var index = 0;
for (; index < iframes.Count; index++)
{
var frame = iframes[index];

element = await frame.QuerySelectorAsync(selector);
if (element is not null)
{
return element;
}
var children = frame.ChildFrames;
if (children.Count > 0 && iframes.Any(x => children.Any(y => y.Equals(x))) == false)
{
iframes.InsertRange(index + 1, children);
index--;
}
}
}
return element;
}

首先,它试图在当前页面中找到元素,这在大多数情况下都是愚蠢的尝试,但如果它找到了,那么它节省了时间,然后如果它没有找到,它将搜索页面中的所有iframe,然后在每个帧中搜索元素,同时在每一帧中搜索帧的子帧,将它们添加到列表中,并从子帧开始迭代,通过这种方式,它将在任何嵌套框架中搜索所需的元素。

当我从Selenium过渡到Playwright时,我半心半意地希望Playwright已经实现了这个功能,哦,好吧。

在JS中,快速而肮脏:

async function querySelectorAllFrames( page, selector )
{
let frames = [ page, ... page.frames() ];
while ( frames.length > 0 )
{
let f = frames.shift();
let found = await f.$( selector );
if ( found != null )
return found;
}
return null;
}

最新更新