Slide 1

Slide 1 text

@JecelynYeen Developer advocate, Google @ChromeDevTools

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

My road bike

Slide 4

Slide 4 text

Mountain bike My road bike

Slide 5

Slide 5 text

Mountain bike Hiking, hot and humid My road bike

Slide 6

Slide 6 text

Mountain bike Hiking, hot and humid Hiking, Switzerland My road bike

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

Browser automation with Puppeteer

Slide 9

Slide 9 text

PM YANG Professional developer PAUL

Slide 10

Slide 10 text

PM YANG I want a daily email on our server’s internet speed. Professional developer PAUL

Slide 11

Slide 11 text

PM YANG I want a daily email on our server’s internet speed. Professional developer PAUL Why does he need that?

Slide 12

Slide 12 text

PM YANG It’s easy. Go to fast.com on the server and send me the screenshot.

Slide 13

Slide 13 text

PM YANG It’s easy. Go to fast.com on the server and send me the screenshot. Professional developer PAUL I never said it’s hard...

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

Professional developer PAUL There are 2 ways to do this: Manually 1. Login to server 2. Open a browser 3. Go to fast.com 4. Take a screenshot 5. Send email

Slide 17

Slide 17 text

Professional developer PAUL There are 2 ways to do this: Manually 1. Login to server 2. Open a browser 3. Go to fast.com 4. Take a screenshot 5. Send email Automate it 1. Schedule a daily server task 2. Automate screenshot 3. Automate email sending

Slide 18

Slide 18 text

Professional developer PAUL Researching...

Slide 19

Slide 19 text

Professional developer PAUL Researching... Puppeteer

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

Browser automation library for Node.js

Slide 22

Slide 22 text

Control a browser with modern JavaScript API.

Slide 23

Slide 23 text

const puppeteer = require('puppeteer'); (async () => { })();

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); })();

Slide 26

Slide 26 text

const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://fast.com/'); })();

Slide 27

Slide 27 text

const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://fast.com/'); await page.screenshot({ path: 'img/screenshot-yyyyMMdd.png' }); })();

Slide 28

Slide 28 text

const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://fast.com/'); await page.screenshot({ path: 'img/screenshot-yyyyMMdd.png' }); await browser.close(); })();

Slide 29

Slide 29 text

Not working

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://fast.com/'); await page.waitForSelector('.speed-results-container.succeeded'); await page.screenshot({ path: 'img/screenshot-yyyyMMdd.png' }); await browser.close(); })();

Slide 32

Slide 32 text

Run it again

Slide 33

Slide 33 text

Professional developer PAUL

Slide 34

Slide 34 text

PM YANG Cool, it will be great if to have date in the screenshot. Possible?

Slide 35

Slide 35 text

const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://fast.com/'); await page.waitForSelector('.speed-results-container.succeeded'); await page.$eval('#your-speed-message', (el, dt) => { el.innerText = `Internet speed as of ${dt} is`; }, 'yyyy-MM-dd')); await page.screenshot({ path: `img/screenshot-yyyyMMdd.png` }); await browser.close(); })();

Slide 36

Slide 36 text

PM YANG I want...

Slide 37

Slide 37 text

// Save as pdf, only work in headless mode await page.pdf({ path: `doc/speed-yyyyMMdd.pdf` }); // Click to show more details await page.click('#show-more-details-link'); await page.waitForSelector('#upload-label.succeeded', { timeout: 0 }); // Emulate mobile view and save screenshot // src/common/DeviceDescriptors.ts const tablet = puppeteer.devices['iPad Mini']; await page.emulate(tablet); await page.screenshot({ path: `img/screenshot-yyyyMMdd.png` }); // Reload page await page.reload();

Slide 38

Slide 38 text

// Save as pdf, only work in headless mode await page.pdf({ path: `doc/speed-yyyyMMdd.pdf` }); // Click to show more details await page.click('#show-more-details-link'); await page.waitForSelector('#upload-label.succeeded', { timeout: 0 }); // Emulate mobile view and save screenshot // src/common/DeviceDescriptors.ts const tablet = puppeteer.devices['iPad Mini']; await page.emulate(tablet); await page.screenshot({ path: `img/screenshot-yyyyMMdd.png` }); // Reload page await page.reload();

Slide 39

Slide 39 text

// Save as pdf, only work in headless mode await page.pdf({ path: `doc/speed-yyyyMMdd.pdf` }); // Click to show more details await page.click('#show-more-details-link'); await page.waitForSelector('#upload-label.succeeded', { timeout: 0 }); // Emulate mobile view and save screenshot // src/common/DeviceDescriptors.ts const tablet = puppeteer.devices['iPad Mini']; await page.emulate(tablet); await page.screenshot({ path: `img/screenshot-yyyyMMdd.png` }); // Reload page await page.reload();

Slide 40

Slide 40 text

// Save as pdf, only work in headless mode await page.pdf({ path: `doc/speed-yyyyMMdd.pdf` }); // Click to show more details await page.click('#show-more-details-link'); await page.waitForSelector('#upload-label.succeeded', { timeout: 0 }); // Emulate mobile view and save screenshot // src/common/DeviceDescriptors.ts const tablet = puppeteer.devices['iPad Mini']; await page.emulate(tablet); await page.screenshot({ path: `img/screenshot-yyyyMMdd.png` }); // Reload page await page.reload();

Slide 41

Slide 41 text

github.com/puppeteer

Slide 42

Slide 42 text

Slide 43

Slide 43 text

const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://v8.dev/blog/10-years'); // Create screenshots of your web app in Light Mode and Dark Mode. // Tip: check out `npx dark-mode-screenshot` for more options! await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'light' }]); await page.screenshot({ path: 'light.png', fullPage: true }); await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'dark' }]); await page.screenshot({ path: 'dark.png', fullPage: true }); await browser.close();

Slide 44

Slide 44 text

const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://mathiasbynens.be/demo/timezone'); page.evaluate(() => { globalThis.date = new Date(1479579154987); }); await page.emulateTimezone('America/Buenos_Aires'); console.log(await page.evaluate(() => date.toString())); // → 'Sat Nov 19 2016 15:12:34 GMT-0300 (Argentina Standard Time)' await page.emulateTimezone('Asia/Kuala_Lumpur'); console.log(await page.evaluate(() => date.toString())); // → 'Sun Nov 20 2016 02:12:34 GMT+0800 (Malaysia Time)' await browser.close();

Slide 45

Slide 45 text

const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://developer.chrome.com/tags/devtools/'); await page.emulateVisionDeficiency('blurredVision'); await page.screenshot({ path: 'blurred-vision.png', fullPage: true }); await page.emulateVisionDeficiency('achromatopsia'); await page.screenshot({ path: 'achromatopsia.png', fullPage: true }); await page.emulateVisionDeficiency('deuteranopia'); await page.screenshot({ path: 'deuteranopia.png', fullPage: true }); await browser.close();

Slide 46

Slide 46 text

addyosmani.com/blog/ puppeteer-recipes/

Slide 47

Slide 47 text

const browser = await puppeteer.launch();

Slide 48

Slide 48 text

const browser = await puppeteer.launch(); // Launch options const browser = await puppeteer.launch({ product: 'firefox' });

Slide 49

Slide 49 text

const browser = await puppeteer.launch(); // Launch options const browser = await puppeteer.launch({ product: 'firefox' }); const browser = await puppeteer.launch({ headless: false, slowMo: 3000 });

Slide 50

Slide 50 text

const browser = await puppeteer.launch(); // Launch options const browser = await puppeteer.launch({ product: 'firefox' }); const browser = await puppeteer.launch({ headless: false, slowMo: 3000 }); const browser = await puppeteer.launch({ devtools: true });

Slide 51

Slide 51 text

goo.gle/devtools-blog

Slide 52

Slide 52 text

@JecelynYeen Developer advocate, Google @ChromeDevTools