Puppeteer 與其他 UI 測試工具

測試工具

跨平台測試

https://saucelabs.com/beta/dashboard/manual

https://developer.mozilla.org/zh-TW/docs/Learn/Tools_and_testing/Cross_browser_testing/Automated_testing

https://developer.mozilla.org/zh-TW/docs/Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment

安裝:

https://github.com/GoogleChrome/puppeteer

文件:https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageclickselector-options

安裝時他會安裝最新版本的Chromium 所以安裝會比較久

記得加上headless: false 才會打開瀏覽器

const browser = await puppeteer.launch({headless: false});

Example:

const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.goto('https://google.com')
  const hg = await page.$eval('.gb_P', el => el.innerHTML);
  console.log(hg)
  await page.type('#lst-ib', 'Hello', {delay: 100});
  await page.click('#gsri_ok0')
  await page.screenshot({ path: 'example.png' });
})();

連線到已經開啟的chrome

因為預設程式結束時chrome也會關閉,所以要用connect的方法。

使用以下方式開啟chrome

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --no-first-run --no-default-browser-check --user-data-dir=$(mktemp -d -t 'chrome-remote_data_dir')

之後將以下擷取下來之後用如下方式

const puppeteer = require('puppeteer');
const browserWSEndpoint = 'ws://127.0.0.1:9222/devtools/browser/15d59f55-f1c9-4c95-89c9-3f164988ba58';
(async () => {
    const browser = await puppeteer.connect({
        browserWSEndpoint,
    });
    const page = (await browser.pages())[0]; //存取第一個 tab
    let page = 'https://sakatu.com/';

    await page.goto(pageUrl, {
        waitUntil: 'networkidle0'
    });
})();

將 dom 傳送到 nodejs 端處理

在 evaluate 後 return 出來即可


const puppeteer = require("puppeteer");
puppeteer.launch({ headless: false }).then(function (browser) {
  browser.newPage().then(function (page) {
    page.goto("http://www.cwl.gov.cn/kjxx/ssq/kjgg/").then(async function () {
      const pageData = await page.evaluate(async () => {
        function delay(time) {
          return new Promise(function (resolve) {
            setTimeout(resolve, time);
          });
        }
        document.querySelector(".zdy").click(); //2013001 // 2020120
        document.querySelectorAll("Strong")[1].click();
        document.querySelector(".inpQa").value = "2013001";
        document.querySelector(".inpQz").value = "2020120";
        document.querySelector(".anKs.aQzQ").click();
        await delay(500);
        return document.querySelector("body").innerHTML
      });
      console.log(pageData)
    });
  });
});

傳遞參數到 evaluate

因為 evaluate 預設執行環境是瀏覽器,變數抓不到 node 的

let name = 'test';

await page.evaluate(({name}) => {

    console.log(name);
    console.log(age);
    console.log(location);

},{name});

https://stackoverflow.com/a/47598159/4622645

傳遞 function

await page.exposeFunction("myFunc", myFunc);

https://stackoverflow.com/a/61336937/4622645

Puppeteer-firefox

https://github.com/GoogleChrome/puppeteer/tree/master/experimental/puppeteer-firefoxgoo

WebDriver.io

http://webdriver.io/

selenium-webdriver

https://github.com/SeleniumHQ/selenium/tree/master/javascript/node/selenium-webdriver

nightmare

(使用electron當作介面)

https://github.com/segmentio/nightmare

異步需要參考如下:

https://github.com/rosshinkley/nightmare-examples/blob/master/docs/common-pitfalls/async-operations-loops.md

var Nightmare = require('nightmare'),
  nightmare = Nightmare({
    show: true
  });

nightmare
  //load a url
  .goto('http://localhost:5081')
  //simulate typing into an element identified by a CSS selector
  //here, Nightmare is typing into the search bar
  .type('#username', 'daniel06')
  .type('#password', 'qwe123')
  .click('#loginBTN')
  .wait(1000)
  .click('#agree_btn')

  function runplay(nightmare, gametype){
    nightmare
    .wait(1000)
    .click(gametype)
    .wait(1500)
    .click('#auto_select')
    .wait(1000)
    .click('#bet_btn')
    .wait(1000)
    .click('#ok_btn')
    .wait(1500)
    .click('#other_btn')
  }

    runplay(nightmare, '#UUFFC');
    runplay(nightmare, '#UUSSC');
    runplay(nightmare, '#UU11X5');
    runplay(nightmare, '#TCP3P5');
    runplay(nightmare, '#JSK3');
  nightmare
  //end the Nightmare instance along with the Electron instance it wraps

  //run the queue of commands specified
  .run(function(error, result) {
    if (error) {
      console.error(error);
    } else {
      console.log(result);
    }
  });

mocha + nightmare範例

import Nightmare from 'nightmare';
import {expect} from 'chai';

describe('test duckduckgo search results', () => {
  it('should find the nightmare github link first', (done) => {
    const nightmare = Nightmare()
    nightmare
      .goto('https://duckduckgo.com')
      .type('#search_form_input_homepage', 'github nightmare')
      .click('#search_button_homepage')
      .wait('#zero_click_wrapper .c-info__title a')
      .evaluate(() =>
        document.querySelector('#zero_click_wrapper .c-info__title a').href
      )
      .end()
      .then((link) => {
        expect(link).to.equal('https://github.com/segmentio/nightmare');
        done();
      })
  });
});

https://segment.com/blog/ui-testing-with-nightmare/

phantomjs

http://phantomjs.org/quick-start.html

casper.js

http://casperjs.org/

Last updated