Puppeteer - 如何与新窗口交互或强制新窗口进入同一个实例

时间:2018-04-12 15:20:55

标签: puppeteer

我正在使用Puppeteer在Chromium的非无头模式下进行测试。我有一个测试的一部分,它点击网页上的节点,然后打开一个新窗口。我无法与新窗口进行交互。我尝试了browser.pages(),遗憾的是它只会与原始Chromium实例中的预先存在的标签进行交互,而不是新窗口。

示例:

let pages = await browser.pages();
let newWindow = pages[pages.length - 1];
// try to find element on newWindow - fails
// last element in pages is still window that click was made in to open new window

我在Puppeteer API中找到event: 'targetcreated',但一直无法弄清楚如何使用它来访问新窗口。

我也尝试使用browser.targets()来获取新实例但未成功。

我想知道如何与新窗口实例进行交互,或者如何强制所有新窗口在同一实例中打开,以便可以通过browser.pages()进行交互。

我不相信这是关于检测何时打开新标签的类似主题的链接问题的重复,因为我不只是尝试检测何时打开新标签而且还要访问新标签/打开新标签/窗口的测试窗口。

1 个答案:

答案 0 :(得分:1)

我能够通过targetCreated的事件监听器解决这个问题,多个用户可以帮助我进行设置。我不得不弄明白自己的另外一个部分就是如何使用该事件监听器来实际访问创建它的测试中的新页面。我使用带有global.pages变量的lodash,事件监听器添加了任何新页面,请参阅下面的代码:

的package.json

{
"name": "workflow-tests",
  "version": "1.0.0",
  "description": "Workflow tests",
  "main": "index.js",
  "scripts": {
    "test": "mocha test/bootstrap.js --recursive test"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "chai": "^4.1.0",
    "mocha": "^3.4.2"
  },
  "dependencies": {
    "puppeteer": "^1.0.0"
  }
}

测试/ bootstrap.js:

const puppeteer = require('puppeteer');
const { expect } = require('chai');
const _ = require('lodash');
const globalVariables = _.pick(global, ['browser', 'expect', 'pages']);

// puppeteer options
const opts = {
    headless: false,
    slowMo: 100,
    timeout: 10000
};

// expose variables
before (async function () {
    global.expect = expect;
    global.browser = await puppeteer.launch(opts);
    global.pages = await global.browser.pages();
    // console.log('global.pages.length', global.pages.length);

    // Event listener for taargetCreated events (new pages/popups)
    // adds the new page to the global.pages variable so it can be accessed immediately in the test that created it
    global.browser.on('targetcreated', async () => {
        // console.log('New Tab Created');
        global.pages = await global.browser.pages();
        // console.log('global.pages.length', global.pages.length);
    });
});

// close browser and reset global variables
after (function () {
    browser.close();
    global.browser = globalVariables.browser;
    global.expect = globalVariables.expect;
    global.pages = globalVariables.pages;
});

test / workflow1.js - 可以访问创建的弹出窗口的伪代码/示例测试:

describe('Workflow tests', function () {
    let page = null;
    this.timeout(60000);

    it('should access new window after clicking opens it', () => {
        return new Promise(async (resolve, reject) => {
            page = global.pages[0];
            await page.setViewport({ width: 1500, height: 1000 });
            await page.goto('https://system.netsuite.com/pages/customerlogin.jsp');

            // click something that opens a new window or use this test/example new window opener
            window.open('http://www.example.com', '_blank');

            // targetCreated event listener in test.bootstrap.js activated and sets global.pages to all open windows in instance
            // new page/popup is last item in global.pages array
            let popup = global.pages[global.pages.length - 1];

            // do things in the new window - #addr2 is an example selector from my instance
            await popup.waitForSelector('#addr2');
            await popup.click('#addr2');
            await popup.keyboard.type("popup test typing! :D");
            await popup.keyboard.press('Enter');
            resolve();
        })
    })
});

这些测试将使用命令npm test运行。由于这些测试使用async,因此需要某个版本的节点,我相信它是任何节点> = 8.9.1。我试图在早期版本的节点上运行这些测试,但它们不起作用。