I met puppeteer

With this tool, we can become a puppeteer. Puppeteer is a NodeJS library that calls Chrome’s API to manipulate the Web. Compared to Selenium or PhantomJs, puppeteer’s biggest feature is that its manipulation Dom can be simulated completely in memory, both in the V8 engine and without opening the browser. And the key is that this is being maintained by the Chrome team, which will have better compatibility and prospects.

Puppeteer function

  • 1. Grab web pages, screenshots, PDFS, or images
  • 2. Front-end automated testing
  • 3. Simulate various browser events
  • 4. We can capture the time line of the web page, and we can do the performance monitoring and optimization of the page
  • 5. Waiting for your excavation

Install the puppeteer

yarn add puppeteer
# or "npm i puppeteer"
Copy the code

You may have problems downloading Chromium

./node/npm i --save puppeteer --ignore-scripts
Copy the code

Next, we need to download Chromium, enter the puppeteer directory in node_modules, open package.json, and find the corresponding puppeteer version number

"puppeteer": {
    "chromium_revision": "536395"
 },
Copy the code

Download address for each version:

  • linus: https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/536395/chrome-linux.zip
  • mac: https://storage.googleapis.com/chromium-browser-snapshots/Mac/536395/chrome-mac.zip
  • win32:https://storage.googleapis.com/chromium-browser-snapshots/Win/536395/chrome-win32.zip
  • win64:https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/536395/chrome-win32.zip

Add the. Local-chromium directory to the puppeteer directory (win64-536395 for Windows 64, linux-536395 for Linux) and unzip the files. Next, we create a file named index.js, the contents of the file

const puppeteer = require('puppeteer');

(async () = > {
  	const browser = await puppeteer.launch();
	const page = await browser.newPage();
	await page.goto('https://y.qq.com');
	await page.screenshot({path: 'yqq.png'}); browser.close(); }) ();Copy the code

This code will open https://y.qq.com and take a screenshot that we run

node  index.js
Copy the code

If you see y.q.ng in the puppeteer directory, congratulations, we can continue to learn puppeteer.

Experience the first demo, UI automation test of digital album automatic purchase

The function tested here is to automatically log in to buy a digital album and jump to the nameplate page after the successful purchase. Let’s take a look at the whole process.

First of all, we first create a device, document (https://github.com/GoogleChrome/puppeteer/blob/master/DeviceDescriptors.js), we can see, the default number of equipment support or a lot of, In addition to these default devices, you can also customize your own, which will be mentioned later when you invoke the Emulate method:

For the time being, we will first create the iphone6 device provided by the system, and then define a time-out function

const puppeteer = require('puppeteer');
const devices = require('puppeteer/DeviceDescriptors');
const iPhone = devices['iPhone 6'];
let timeout = function (delay) {
     return new Promise((resolve, reject) = > {   
           setTimeout((a)= > {   
                  try {
                      resolve(1)}catch (e) {
                      reject(0) } }, delay); })}Copy the code

Next, we create a browser instance and open up a page, careful you must be find in us for to preach the headless parameters when creating the browser, if set to true to can not open the external browser completely under the condition of using v8 engine to test of the page, simply be pages and Dom completely in memory, Even browser events are emulated in memory.

 const browser = await puppeteer.launch({
      headless:false // I set it to false just so you can see the effect. True will not open the browser
 });

 const page = await browser.newPage();
Copy the code

Now that we’ve created this browser instance we need to emulate the iphone6. You can also customize the emulate parameters

awaitpage.emulate(iPhone); Parameters: {'name': 'Galaxy S5'./ / device name
    'userAgent': 'the Mozilla / 5.0 (Linux; The Android 5.0. Sm-g900p Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Mobile Safari/537.36'.//UA
    'viewport': {
      'width': 360.// Screen width
      'height': 640.// Screen height
      'deviceScaleFactor': 3.// Scale
      'isMobile': true.// Is it a mobile device
      'hasTouch': true.// Whether touch events are supported
      'isLandscape': false// Whether to landscape}}Copy the code

Ok next we can write our test step 1: we open the page, considering that there is data to load asynchronously, we call the screenshot method after a delay of 1000ms and leave it as a log.

console.log("Enter page");
await page.goto('https://y.qq.com/m/digitalbum/gold/index.html?_video=true&id=2210323&g_f=tuijiannewupload#index/fans');
await timeout(1000);
await page.screenshot({
     path: '1.png'
 });
Copy the code

Step 2: Simulate trigger click buy now button, this time will open QQ login because there is no login state.

console.log("Click the Buy now button");
await page.tap('.js_sale_buyalbum');
await page.screenshot({
    path: '2.png'
 });
Copy the code

Step 3: Enter the account password in the input box. To simulate the input, we need to call tap method first to simulate clicking the input box, tap parameter is the element selector, and then use type method to input. After the input, we can simulate the login button. Hopefully, we will be able to return to the front page of the previous sales page, and the usRbar at the bottom is also displayed because of the login status.

console.log("Login");
await page.tap("#u"); // Use the dom selector directly
await page.type("521017853");

await page.tap("#p");
await page.type("* * * * * * * * *");// The password is not displayed

await page.tap("#go");

await timeout(3000);

await page.screenshot({
     path: '3.png'
});

console.log("Login successful");
Copy the code

Step 4: Just like the first step, click the “Buy now” button, there will be a purchase option floating layer, and then we need to load the rice master after clicking “Pay Now”, so here we delay 5000ms.

// Click to buy
console.log("Click the Buy now button");
await page.tap('.js_sale_buyalbum');

await page.screenshot({
    path: '4.png'
});

console.log("Click to pay now on the float");
await page.tap(".js_buyalbum_pay");

await timeout(5000);
Copy the code

Step 5: After pulling up the mi master payment float, we need to click the OK button in the prompt. Since mi Master is opened in iframe, Therefore, we need to get the frame of our current page by calling the mainFrame() method of our newly created page instance, or childFrames if we need to get a subframe. After getting the corresponding frame of the master, you can call the method of midas_frame.$(selector) class jquery to get the element, and then simulate clicking.

console.log("Enter m Master pay float layer")
await page.screenshot({
     path: '5.png'
});

let $frame = page.mainFrame();
let midas_frame = $frame.childFrames()[0];// Get the frame corresponding to Midas

console.log("Click the confirm button on the confirm meter Master pay float test environment prompt");
let $dom = await midas_frame.$(".fusion-pm-fl-wrapper .fpm-default");
await $dom.tap();

await page.screenshot({
    path: '6.png'
});
Copy the code

Step 6: Click Q coin to pay

console.log("Click the Mi Master Pay float button to confirm payment");
$dom = await midas_frame.$("#wrap .fpm-default");
await $dom.tap();

await timeout(5000);

await page.screenshot({
    path: '7.png'
});
Copy the code

Step 7: Click Finish to enter the nameplate page. After testing, close the browser instance

console.log("Click on Mi Master pay float layer pay complete");
$dom = await midas_frame.$("#wrap .btn-primary");
await $dom.tap();

await timeout(2000);

console.log("Purchased nameplate page");
await page.screenshot({
     path: '8.png'
});
browser.close();
Copy the code

Finally, in the project directory, we see that screenshots of each step have been generated.

Experience the second demo where page performance checks the Puppeteer Trace API

The Trace API uses Chrome Performance to generate a page Performance tracking file trace.json. Upload this file in Chrome Developer tools, and you can analyze the flame map inside. Example code:

const puppeteer = require('puppeteer');
const devices = require('puppeteer/DeviceDescriptors');
const iPhone = devices['iPhone 6'];

(async () = > {
        const browser = await puppeteer.launch();

        const page = await browser.newPage();

        await page.emulate(iPhone);

        await page.tracing.start({path: './trace.json'});
        await page.goto('https://y.qq.com/m/digitalbum/gold/index.html?_video=true&id=2210323&g_f=tuijiannewupload#index/fans');
        await page.tracing.stop();

        browser.close();
    } catch (e) {
        console.log(e.message);
    }
})();
Copy the code

First of all, this code is to simulate the iphone6 to open Lin junjie’s “denning obsession” sales page, and perform performance analysis. Tracing. Json file trace.json is generated using tracing. Start and stop

Next, open Chrome’s Developer tools, go to the Performance TAB, and drag the trace.json onto it to see the data

conclusion

In the above two examples, we have seen that puppeteer is capable of automated UI testing and page performance testing. In fact, puppeteer is much more than that. For example, it can also be used as a crawler to crawl github articles and nuggets blogs. I hope we can communicate more.