javascript 如何在单击[target="_blank”]后将选择器定位在新选项卡上-无法激活创建的新选项卡

jpfvwuh4  于 2023-04-19  发布在  Java
关注(0)|答案(2)|浏览(99)

点击一个[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更多

我试图从一个接受的答案实现代码,但没有任何成功。使用 puppet 师在“_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坐标来选择输入,这会激活输入字段,但这会返回以下错误“No node found for selector: #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。我会假设创建的新标签仍然需要激活…

2nbm6dog

2nbm6dog1#

我们一起解决了这个问题(Linker:)

流程

首先,我们Map正在创建的目标以检查焦点

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

我们看到URL正在尝试打开-由于某种原因,目标中的URL为空。我们重新安装了一些东西以排除奇怪的依赖性错误,然后发现有一个焦点问题。

解决方案

为了解决这个问题,我们需要等待.newPage()打开,然后goto 'ing到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()

参考

这里有一个很酷的SO Answer,展示了如何使用once语法来测试事件。很高兴我们能够解决这个问题,我希望这个过程能帮助其他人。

h43kikqp

h43kikqp2#

只是解决了标题中的问题,“如何在单击[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');

相关问题