如何在点击[target="_blank"]后针对新标签页定位选择器 - 无法激活新创建的标签页

3
点击[target="_blank"]后会打开一个新标签页。如何获取代码以获取新页面对象,以便我可以访问密码输入字段?使用NodeJS、JavaScript、Puppeteer。
导航工作到下面包含的点为止。
编辑:我使用了page.url()方法来检索当前URL,新创建的选项卡的URL不会记录到控制台中,之前的页面会记录。
我尝试调整脚本并收到以下错误 Cannot read properties of undefined (reading 'page') - 我认为添加时间延迟会解决这个问题,但没有用。
我遇到了这个错误,但是由于下面的代码,我没有得到这个错误:No node found for selector: #Password
我查看了相关问题 我遇到了dheerajbhaskar GitHub问题,并阅读了相关问题。
  • #386
  • #3535
  • #978 and more
我尝试实现来自已接受答案的代码,但没有成功。 使用Puppeteer在"_blank"点击后获取新页面的句柄?
try {
      await sleep(2300)
// This block creates a new tab 
// I was previously using a selector and not mouse click API 
      await Promise.all([
        page.mouse.click(xToolsBtn, yToolsBtn, { delay: 2000 }),
      ])
      // NEW TARGET CREATED
      // Below is a snippet from an accepted answer but the the type method 
      // does not work
      // Seems like page is still not activated
      const [newTarget] = await Promise.all([
        // Await new target to be created with the proper opener
        new Promise((x) =>
          browser.on("targetcreated", (target) => {
            if (target.opener() !== page.target()) return
            browser.removeListener("targetcreated", arguments.callee)
            x()
          })
        ),
        // page.click('link')
      ])
      // Trying to input password without success
      const newPage = await newTarget.newPage()
      await newPage.type("#Password", process.env.PASSWORD, {
        delay: randomGenerator,
      })
    } catch (err) {
      console.error(
        "LOGIN BUTTON FAIL",
        err.message
      )
    }

另一种尝试#1:我试图通过鼠标x,y坐标选择输入,以激活输入字段,但是这返回以下错误:“未找到选择器的节点:#Password
另一种尝试#2:
//* WAIT FOR TARGET
    try {
      await sleep(2300)
      await Promise.all([
        page.mouse.click(xToolsBtn, yToolsBtn, { delay: 2000 }),
      ])
      sleep(5000)
      await page.evaluate(() => window.open(`${loginUrl3}`))
      const newWindowTarget = await browser.waitForTarget(
        (target) => target.url() === `${loginUrl3}`
      )
      console.log("GOT TARGET")
      await newWindowTarget.type("#Password", process.env.PASSWORD, {
        delay: randomGenerator,
      })
    } catch (err) {
      console.log("WAIT FOR TARGET FAILED")
    }

注意:URL是随机生成的,所以我很好奇是否有任何解决方法可以使用当前的URL。我认为新创建的选项卡仍然需要被激活...
2个回答

3
我和Linker一起成功解决了这个问题。

过程

首先,我们将正在创建的目标映射到检查焦点。

browser.on('targetcreated', function (target) {
    console.log('New tab:');
    console.log(target);
});

我们发现URL正在尝试打开 - 出于某种原因,目标中的URL为空。我们重新安装了一些东西以排除奇怪的依赖错误,然后发现存在焦点问题。
解决方法
为了解决这个问题,我们需要等待.newPage()打开后再goto到URL,调用bringToFront(),然后等待它加载(短暂的睡眠是简单的方法)。一旦我们做到了这一点,就有一个可行的POC可以开始使用。
解决方案中的相关部分:
let mappedURL = tabs
  .map((e, index) => e.url())
  .filter((e, idx) => idx == 2)
console.log("MAPPED URL ", mappedURL)
sleep(2500)
const page3 = await browser.newPage()
await page3.goto(`${mappedURL}`)
await page3.bringToFront()

参考文献

这是一个很棒的Stack Overflow答案,展示了如何使用once语法测试事件。很高兴我们能够解决它,希望这个过程对其他人有所帮助。


2

仅回答标题���的问题,“如何在单击[target="_blank"]后针对新标签页定位选择器” -

如果您不习惯处理Playwright中新打开的选项卡,则会发现它们远非直观。以下是它们的工作摘要:

如果您在测试中使用target="_blank"点击链接,打开一个新的选项卡,则您正在使用的page对象仍然指向您打开链接的原始页面/选项卡。

要获取新页面,您必须使用context对象,就像使用page一样,在测试参数中解构它,然后使用waitForEvent('page')方法。

test('my component works', async ({context, page}) => { // get the `context` object

// ...

const [newPage] = await Promise.all([
    context.waitForEvent('page'), // get `context` by destructuring with `page` in the test params; 'page' is a built-in event, and **you must wait for this like this,**, or `newPage` will just be the response object, rather than an actual Playwright page object.
    page.locator('text=Click me').click() // note that, like all waiting in Playwright, this is somewhat unintuitive. This is the action which is *causing the navigation*; you have to set up the wait *before* it happens, hence the use of Promise.all().
])

 await newPage.waitForLoadState(); // wait for the new tab to fully load
 // now, use `newPage` to access the newly opened tab, rather than `page`, which will still refer to the original page/tab.
 await expect(newPage).toHaveURL('http://www.someURL.com');
 await newPage.locator('text=someText');

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接