首页 > 编程语言 >当通过 target="_blank" 链接打开新页面时,Playwright 会截取错误页面的截图

当通过 target="_blank" 链接打开新页面时,Playwright 会截取错误页面的截图

时间:2024-05-29 23:39:18浏览次数:25  
标签:javascript playwright

我在使用 Playwright 时遇到了一个问题,它截取了错误页面的屏幕截图。当通过 target="_blank" 链接打开新页面时,它不会截取最新页面,而是截取旧页面的屏幕截图。

我的应用程序的业务逻辑主要包含在一个 while 循环中,而且我没有使用 Playwright 进行测试。我尝试了两种方法来解决这个问题,但效果都不尽如人意。

方法 1:监听页面事件

我尝试监听上下文中的页面事件,并将新页面替换为当前页面。以下是代码:

let page = await context.newPage();
context.on("page", async (newPage) => {
  await newPage.waitForLoadState();
  page = newPage;
});

然而,这种方法似乎并不奏效,而且我也没有收到任何错误信息。

方法 2:从上下文中获取最新页面

我还尝试使用 context.pages() 从上下文中获取最新页面,然后将最新页面传递给 takeScreenshot 函数。以下是代码:

pages = await context.pages();
currentPage = pages[pages.length - 1];
const screenshot = await takeScreenshot(currentPage);

不幸的是,这种方法也行不通。

预期结果:

I want Playwright to takeScreenshot(currentPage).

我希望 Playwright 始终对最近打开的页面进行截图。有人能帮我解决这个问题吗?

代码片段:

以下是我的代码简化版本:

try {
    const browser = await chromium.launch({ headless: false });
    const context = await browser.newContext();
    let page = await context.newPage();
    
    await page.goto("https://somewebsite.com");
    // let pages = context.pages();
    // let currentPage = page;

    while (/* 一些逻辑 */) {
      try {
        //...
        const screenshot = await takeScreenshot(page);
        //...

       /// 一些逻辑
      // ...


        // context.on("page", async (newPage) => {
        // await newPage.waitForLoadState();
        // page = newPage
        // });

        // context.waitForEvent('page')
      } catch (error) {
        console.log(error);
      }
    }
  catch (error) {
    console.error("err:", error);
  }

遇到的问题是,当点击带有 target="_blank" 的链接时,Playwright 不会自动将焦点切换到新页面。因此,需要手动告诉 Playwright 切换到新页面。

以下是可以尝试的解决方案:

方法 1:使用 page.waitForEvent('popup') 监听弹出窗口

try {
  const browser = await chromium.launch({ headless: false });
  const context = await browser.newContext();
  let page = await context.newPage();

  await page.goto("https://somewebsite.com");

  while (/* 一些逻辑 */) {
    try {
      //...

      // 点击打开新页面的链接之前,监听 'popup' 事件
      const [newPage] = await Promise.all([
        context.waitForEvent('popup'),
        page.click('a[target="_blank"]') // 用的链接选择器替换
      ]);

      // 将 page 变量更新为新页面
      page = newPage;

      // 等待新页面加载完成
      await page.waitForLoadState();

      // 现在可以对新页面进行截图
      const screenshot = await page.screenshot(); 

      //...
    } catch (error) {
      console.log(error);
    }
  }
} catch (error) {
  console.error("err:", error);
}

方法 2:使用 context.pages() 查找新页面

try {
  const browser = await chromium.launch({ headless: false });
  const context = await browser.newContext();
  let page = await context.newPage();

  await page.goto("https://somewebsite.com");

  while (/* 一些逻辑 */) {
    try {
      //...

      // 获取当前页面数量
      const initialPageCount = context.pages().length;

      // 点击打开新页面的链接
      await page.click('a[target="_blank"]'); // 用的链接选择器替换

      // 等待新页面打开
      await context.waitForEvent('page');

      // 获取所有页面并找到新页面
      const pages = context.pages();
      const newPage = pages.find(p => !pages.slice(0, initialPageCount).includes(p));

      // 将 page 变量更新为新页面
      page = newPage;

      // 等待新页面加载完成
      await page.waitForLoadState();

      // 现在可以对新页面进行截图
      const screenshot = await page.screenshot();

      //...
    } catch (error) {
      console.log(error);
    }
  }
} catch (error) {
  console.error("err:", error);
}

这两种方法都可以解决遇到的问题。选择哪种方法取决于的个人偏好和具体情况。

一些额外的建议:

  • 确保在截图之前等待新页面完全加载。
  • 使用浏览器的开发者工具检查页面结构和链接选择器,以确保代码正确地定位到目标链接。
  • 可以使用 console.log(page.url()) 打印当前页面的 URL,以便调试代码并确保 Playwright 正确地切换页面。

标签:javascript,playwright
From: 78550624

相关文章

  • 前端学习笔记——JavaScript基础语言的学习(三)
    作者简介:大家好,本人刚专升本上岸,是个前端小菜鸟。每日都会虚心的学习。有什么写的不好的,大家都可以帮我提出来。我跟着pink老师学的!!!强烈推荐:https://www.bilibili.com/video/BV14J4114768p=1&vd_source=38cea56ff3dcca4556d2d0f0f2c18c0c1,类型转换:把一种数据类型的变量转换成......
  • 前端学习笔记——JavaScript基础语言的学习(二)
    作者简介:大家好,本人刚专升本上岸,是个前端小菜鸟。每日都会虚心的学习。有什么写的不好的,大家都可以帮我提出来。我跟着pink老师学的!!!强烈推荐:https://www.bilibili.com/video/BV14J4114768p=1&vd_source=38cea56ff3dcca4556d2d0f0f2c18c0c1.数组的基本使用2.常量的基本使用......
  • javascript引入了不同版本的多个jquery,如何不同版本之间不互相影响
    1️⃣ 原因  由于是一个比较老的项目,所以在做功能时,用到了老项目的一个控件,这一个控件是以前封装好的,依赖的是jquery-1.6.min.js。但是在做下拉框多选功能时,在网上找了一个下拉框多选的框架,但是这个框架依赖是jquery.js(3.7.1),所以才出现了这个问题。  简单来说就是新老控件......
  • javascript右键菜单
      文章来源:https://segmentfault.com/a/1190000023098787 HTML<h1>Clickonblanktoshowcustomcontextmenus</h1>CSS.custom-context-menu{position:fixed;border:1pxsolid#ccc;list-style:none;padding:4px0;border-radius:......
  • JavaScript基础ECMAScript知识点复习整理
    **本篇文章食用的简单说明**本篇文章为复习JavaScript基础ECMAScript进行了知识点梳理,加粗部分为重点!!!加粗加红为重重点!!!由于JavaScript内容比较多,本篇文章只是基础部分,WebAPIs(DOM和BOM)等知识在后续过程中会继续更新,欢迎小伙伴在评论区补充~推荐大家按记忆梳理部分的内容自......
  • JavaScript中的let关键字详解
    在JavaScript中,let关键字用于声明局部变量,它与传统的var关键字类似,但引入了几个关键的区别和改进,主要体现在作用域规则、重复声明限制以及引入了“暂时性死区”等概念。下面将详细介绍let的特点及其与var的不同之处。块级作用域vs函数作用域var声明的变量:其作用域是函数......
  • 《最新出炉》系列入门篇-Python+Playwright自动化测试-49-Route类拦截修改请求-下篇
    1.简介 在日常工作和学习中,自动化测试的时候:在加载页面时,可能页面出现很多不是很重要或者不是我们所关注的,这个时候我们就可以选择不加载这些内容,以提高页面加载速度,节省资源。例如:可能页面上图片比较多,而我们又不关心图片内容。那么,在加载页面时,可以选择不加载图片,以提高页面加......
  • JavaScript日期与时间处理的艺术
    JavaScript日期与时间处理的艺术基础概念:JavaScript中的日期对象诞生时刻时间戳:纪元的秘密案例一:格式化日期的艺术美化你的日期自定义格式化案例二:跨时区的舞蹈时区转换案例三:时间旅行的挑战闰年与月份天数避免日期计算的陷阱实战技巧与避坑指南性能优化安全性考量问......
  • JavaScript 中的 Range 和 Selection 对象
    JavaScript中的Range和Selection对象前言最近在做鼠标框选的需求,鼠标框选就需要用到Range和Selection对象。Range表示选择的区间范围,Selection表示选择的文档内容。下面就详细说下这两个对象一、RangeRange接口表示一个包含节点与文本节点的一部分的文档片段。......
  • 前端历程(包括html,JavaScript,jQuery,bootstrap)
    前端学习历程jQuery"""jQuery内部封装了原生的js代码(还额外添加了很多功能)能够让你通过书写更少的代码完成js操作类似于python里面的模块在前端模块不叫模块叫"类库"兼容多个浏览器的你在使用jQuery的时候就不需要考虑浏览器兼容问题jQuery的宗旨 writelessdom......