7

我正在尝试一些非常简单的事情:

  • 导航到 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();
    }
  }
})();

起初我试图用 a 得到第一个结果,page.$()但它没有用。在稍微调查了这个问题之后,我发现page.waitForNavigation()我认为这是解决方案,但事实并非如此。

我正在使用最新的编剧版本:1.0.2。

4

3 回答 3

3

在我看来,唯一的问题是您最初的承诺组合,我刚刚将承诺重构为 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 对导航承诺的支持的问题。

于 2020-08-30T12:37:36.607 回答
1

如果您等待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()}`);

另请注意,您需要awaitfor textContent()

于 2020-05-21T14:54:44.853 回答
0
  1. Target closed在我的情况下,第一次尝试从页面检索文本时出现了剧作家错误。错误不准确,实际原因是在目标站点中启用了基本身份验证。剧作家无法打开页面,只是停留在“目标已关闭”。

    const options = { 
       httpCredentials = { username: 'user', password: 'password'}
    };
    const context = await browser.newContext(options);
    
  2. 另一个问题是本地测试运行没有问题,包括 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

  3. 使用mcr.microsoft.com/playwrightMicrosoft 提供的 docker hub 映像和预安装的节点、npm 和 playwright。或者在剧作家安装期间不要忘记通过运行安装系统包依赖项npx playwright install-deps

  4. VM 应该有足够的资源来处理浏览器测试。CI/CD 工作流中的一个常见问题。

于 2022-02-05T18:40:23.513 回答