导航后编剧错误(目标已关闭)
Posted
技术标签:
【中文标题】导航后编剧错误(目标已关闭)【英文标题】:Playwright error (Target closed) after navigation 【发布时间】:2020-09-08 00:33:37 【问题描述】:我正在尝试一些非常简单的事情:
导航到 google.com 用“奶酪”填充搜索框 在搜索框中按回车键 打印第一个结果的标题文本如此简单,但我无法让它工作。这是代码:
const playwright = require('playwright');
(async () =>
for (const browserType of ['chromium', 'firefox', 'webkit'])
const browser = await playwright[browserType].launch();
try
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://google.com');
await page.fill('input[name=q]', 'cheese');
await page.press('input[name=q]', 'Enter');
await page.waitForNavigation();
page.waitForSelector('div#rso h3')
.then(firstResult => console.log(`$browserType: $firstResult.textContent()`))
.catch(error => console.error(`Waiting for result: $error`));
catch(error)
console.error(`Trying to run test on $browserType: $error`);
finally
await browser.close();
)();
起初我尝试使用page.$()
获得第一个结果,但没有成功。在稍微调查了这个问题后,我发现我认为page.waitForNavigation()
会是解决方案,但事实并非如此。
我用的是最新的编剧版本:1.0.2。
【问题讨论】:
这可能不是您的问题,而是其他任何人在谷歌上搜索此错误:如果您的测试在waitForNavigation
调用期间超时,您将获得“目标关闭”。在这种情况下,它还会在控制台输出中显示Timeout of XXXms exceeded.
。
【参考方案1】:
在我看来,唯一的问题是您最初的承诺组合,我刚刚将承诺重构为 async/await 并使用 page.$eval
检索 textContent
它完美地工作,没有 目标已关闭错误了。
try
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://google.com');
await page.fill('input[name=q]', 'cheese');
await page.press('input[name=q]', 'Enter');
await page.waitForNavigation();
// page.waitForSelector('div#rso h3').then(firstResult => console.log(`$browserType: $firstResult.textContent()`)).catch(error => console.error(`Waiting for result: $error`));
await page.waitForSelector('div#rso h3');
const firstResult = await page.$eval('div#rso h3', firstRes => firstRes.textContent);
console.log(`$browserType: $firstResult`)
catch(error)
console.error(`Trying to run test on $browserType: $error`);
finally
await browser.close();
输出:
chrome: Cheese – Wikipedia
firefox: Cheese – Wikipedia
webkit: Cheese – Wikipedia
注意: chrome 和 webkit 可以工作,firefox 在 waitForNavigation
上对我来说失败了。如果我用await page.waitForTimeout(5000);
替换它,firefox 也可以。这可能是剧作家的 Firefox 对导航承诺的支持问题。
【讨论】:
【参考方案2】:如果您等待page.press('input[name=q]', 'Enter');
,那么waitForNavigation
工作可能为时已晚。
您可以在新闻发布会上删除await
。您可能需要等待导航,而不是按下操作。
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://google.com');
await page.fill('input[name=q]', 'cheese');
page.press('input[name=q]', 'Enter');
await page.waitForNavigation();
var firstResult = await page.waitForSelector('div#rso h3');
console.log(`$browserType: $await firstResult.textContent()`);
另请注意,您需要await
才能获得textContent()
。
【讨论】:
等待还是不等待 page.pres() 我认为这无关紧要。我已经尝试过你不等待的建议,但我仍然遇到同样的错误。那不是问题。问题是它在导航后不知何故失去了上下文。 我遇到了同样的问题。它在导航之前使用页面的上下文。你有没有找到解决方案?【参考方案3】:在我的情况下,Playwright 错误Target closed
出现在第一次尝试从页面检索文本时。
错误不准确,实际原因是在目标站点中启用了基本身份验证。
Playwright 无法打开页面,只是停留在“目标已关闭”。
const options =
httpCredentials = username: 'user', password: 'password'
;
const context = await browser.newContext(options);
另一个问题是本地测试运行没有问题,包括 docker 容器,而 Github CI 在 Playwright 上失败,除了上述错误之外没有任何细节。
原因是 Github Secret 中有一个特殊符号。例如,美元符号 $
将从 Github Actions 中的机密中删除。要更正它,请使用env:
部分
env:
XXX: $ secrets.SUPER_SECRET
或将秘密用单引号括起来:
run: |
export XXX='$ secrets.YYY'
在 Kubernetes、Docker 和 Gitlub 中存在类似的转义特性; $$
变为 $
和 z$abc
变为 z
。
使用来自 Microsoft 的 mcr.microsoft.com/playwright
docker hub 映像,并预装了节点、npm 和 playwright。或者在 playwright 安装过程中不要忘记通过运行 npx playwright install-deps
来安装系统包依赖项。
VM 应该有足够的资源来处理浏览器测试。 CI/CD 工作流中的一个常见问题。
【讨论】:
Artur,你能分享一些浏览器启动和 dockerfile 的配置吗?我被困在一个类似的问题上。我在 GKE 中运行自动浏览器并看到同样的错误。在我的主机笔记本电脑上本地运行它们或在我的笔记本电脑上运行 docker 容器都可以正常工作。以上是关于导航后编剧错误(目标已关闭)的主要内容,如果未能解决你的问题,请参考以下文章
Puppeteer - 协议错误(Page.navigate):目标已关闭
Flutter:来自后退导航的回调产生“错误状态:调用关闭后无法添加新事件”
安装VS 2015更新2后,“基础连接已关闭:发送时发生意外错误”