SlideShare ist ein Scribd-Unternehmen logo
1 von 96
Downloaden Sie, um offline zu lesen
possibly
Puppeteer can
automate that!
with the help of minions
Önder Ceylan
@onderceylan
Sharing knowledge on #javascript, #typescript, #angular, #ionic and #pwa
JS Squad Lead @LINKIT
Speaker, Organiser @ITNEXT
Speaker, Organiser @GDG NL
Chrome
Chrome
canarychromiumchrome
Headless Chrome
Headless Chrome
chrome —-headless —-remote-debugging-port=9222
Puppeteer
Puppeteer
npm i puppeteer
–Puppeteer docs
“Most things that you can do
manually in the browser can be
done using Puppeteer! ”
Examples to get you started
• Generate screenshots and PDFs of pages
• Crawl a SPA and generate pre-rendered
content
• Automate form submission, UI testing,
keyboard input, etc
• Capture a timeline trace of your site to
help diagnose performance issues
puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  await page.goto('https://www.linkit.nl');
  await page.screenshot({path: 'screenshot.png'});
  await browser.close();
});
pptr.dev
try-puppeteer.appspot.com
github.com/transitive-bullshit/awesome-puppeteer
Puppeteer Recorder Extension
DEMOS
Alex ! "
Xander # $
Ellen % &
Yelda ' (
Text to speech!
Alex ! "
Text to speech!
Xander # $
Text to speech!
Ellen % &
Text to speech!
Yelda ' (
speechSynthesis.getVoices()
Whatsapp messages every day!
const browser = await puppeteer.launch(({
userDataDir: ".tmp",
}));
const page = await browser.newPage();
await page.goto('https://web.whatsapp.com/', {waitUntil: 'networkidle2'});

await page.waitForSelector('#side input[type=text]');

await page.type('#side input[type=text]', groupName);

await page.waitForSelector(`#pane-side span[title=“${groupName}"]`,
{visible: true});

await page.click(`span[title="${groupName}"`);

await page.waitForSelector('footer .copyable-text', {visible: true});

await page.type('footer .copyable-text', getTodaysMessage());

await page.keyboard.press('Enter');

await browser.close();
Whatsapp messages every day!
Emulating color scheme NEW

in v2
await page.goto('https://googlechromelabs.github.io/dark-mode-toggle/demo/index.html');

await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'light' }]);

await page.screenshot({ path: 'light.jpg', type: 'jpeg', omitBackground: true });

await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'dark' }]);
await page.screenshot({ path: 'dark.jpg', type: 'jpeg', omitBackground: true });
Emulating color scheme NEW

in v2
Side by side page load
const devices = require('puppeteer/DeviceDescriptors');
const nexus5X = devices['Nexus 5X'];



const browser = await puppeteer.launch({
headless: false,
args: [
`--window-size=${DEFAULT_VIEWPORT.width},${DEFAULT_VIEWPORT.height}`,
CENTER_WINDOWS_ON_SCREEN ? `--window-position=${x},${y}` : `--window-position=${dx},0`,
],
});
const page = await browser.newPage();
await page.emulate(nexus5X);


const session = await page.target().createCDPSession();
// Emulate "Slow 3G" according to WebPageTest
await session.send('Network.emulateNetworkConditions', {
offline: false,
latency: 400,
downloadThroughput: Math.floor(400 * 1024 / 8), // 400 Kbps
uploadThroughput: Math.floor(400 * 1024 / 8) // 400 Kbps
});
await session.send('Emulation.setCPUThrottlingRate', {rate: 4});
Side by side page load
Element to PDF
const overlay = await page.$('.tweet.permalink-tweet');



await page.evaluate(tweet => {
const width = getComputedStyle(tweet).width;
tweet = tweet.cloneNode(true);
tweet.style.width = width;
document.body.innerHTML = `
<div style="display:flex;justify-content:center;align-items:center;height:100vh;">;
${tweet.outerHTML}
</div>
`;
}, overlay);


await page.pdf({path: 'tweet.pdf', printBackground: true});
Element to PDF
Accessibility test
await page.goto('https://frontmania.com');
await page.addScriptTag(
{ url: 'https://cdnjs.cloudflare.com/ajax/libs/axe-core/3.3.2/axe.min.js' }
);
const results = await page.evaluate(() => axe.run(document));


expect(results.violations.length).toBe(0);
Accessibility test
Code coverage test
const pti = require('puppeteer-to-istanbul');


const page = await browser.newPage();
await page.coverage.startJSCoverage();
await page.goto('https://www.linkit.nl/');
const jsCoverage = await page.coverage.stopJSCoverage();


pti.write(jsCoverage);
await page.close();
Code coverage test
Chrome DevTools
throttle network
track memory usage
emulate devices
run audits
github.com/ChromeDevTools/devtools-frontend
Protocol Monitor
chrome://flags/#enable-devtools-experiments
chrome —-remote-debugging-port=9222
Chrome DevTools
Protocol
127.0.0.1:9222/json/version
chromedevtools.github.io/devtools-protocol
github.com/ChromeDevTools/awesome-chrome-devtools
puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  await page.goto('https://www.linkit.nl');
  await page.screenshot({path: 'screenshot.png'});
  await browser.close();
});
Using DevTools
Protocol with PPTR
puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  await page.goto('https://www.linkit.nl');
const session = await page.target().createCDPSession();
  session.on('Animation.animationCreated', () => {
    console.log('Animation created!');
  });
  await session.send('Animation.enable');
  await session.send('Animation.setPlaybackRate', {
    playbackRate: 10,
  });
  await browser.close();
});
Puppeteer Core
npm i puppeteer-core
Puppeteer Core
browser = await puppeteer.connect({
  browserWSEndpoint: 'ws://127.0.0.1:9222/.../...'
});
// or 
browser = await puppeteer.launch({
  executablePath: '/Applications/Google Chrome.app
/Contents/MacOS/Google Chrome'
});
Chrome Launcher
npm i chrome-launcher
const chromeLauncher = require('chrome-launcher');
// Launches a debugging instance of Chrome
function launchChrome(headless=true) {
  return chromeLauncher.launch({
    // port: 9222,
    chromeFlags: [
      '--window-size=412,732',
      '--disable-gpu',
      headless ? '--headless' : ''
    ]
  });
}
launchChrome().then(chrome => {
  console.log(`Chrome debuggable on port: ${chrome.port}`);
  // chrome.kill();
});
const chromeLauncher = require('chrome-launcher');
// Launches a debugging instance of Chrome
function launchChrome(headless=true) {
  return chromeLauncher.launch({
    // port: 9222,
    chromeFlags: [
      '--window-size=412,732',
      '--disable-gpu',
      headless ? '--headless' : ''
    ]
  });
}
launchChrome().then(chrome => {
  console.log(`Chrome debuggable on port: ${chrome.port}`);
  // chrome.kill();
});
chrome instance
Puppeteer Light
npm i puppeteer-core
npm i chrome-launcher
const chromeLauncher = require('chrome-launcher');
const puppeteer = require('puppeteer-core');
const util = require('util');
(async() => {
const URL = 'https://www.linkit.nl';
// Chrome executable launch arguments
const opts = {
  chromeFlags: ['--headless'],
  logLevel: 'info',
  output: 'json'
};
// Launching chrome using chrome-launcher
const chrome = await chromeLauncher.launch(opts);
opts.port = chrome.port;
// Connecting to WS using puppeteer.connect()
const resp = await util.promisify(request)(`http://localhost:${opts.port}/json/version`);
const chromeVersion = JSON.parse(resp.body);
const browser = await puppeteer.connect({
  browserWSEndpoint: chromeVersion.webSocketDebuggerUrl
});
// Cleanup of resources
await browser.disconnect();
await chrome.kill();
})();
const chromeLauncher = require('chrome-launcher');
const puppeteer = require(‘puppeteer-core');
const util = require('util');
(async() => {
const URL = 'https://www.linkit.nl';
// Chrome executable launch arguments
const opts = {
  chromeFlags: ['--headless'],
  logLevel: 'info',
  output: 'json'
};
// Launching chrome using chrome-launcher
const chrome = await chromeLauncher.launch(opts);
opts.port = chrome.port;
// Connecting to WS using puppeteer.connect()
const resp = await util.promisify(request)(`http://localhost:${opts.port}/json/version`);
const chromeVersion = JSON.parse(resp.body);
const browser = await puppeteer.connect({
  browserWSEndpoint: chromeVersion.webSocketDebuggerUrl
});
// Cleanup of resources
await browser.disconnect();
await chrome.kill();
})();
const chromeLauncher = require('chrome-launcher');
const puppeteer = require(‘puppeteer-core');
const util = require('util');
(async() => {
const URL = 'https://www.linkit.nl';
// Chrome executable launch arguments
const opts = {
  chromeFlags: ['--headless'],
  logLevel: 'info',
  output: 'json'
};
// Launching chrome using chrome-launcher
const chrome = await chromeLauncher.launch(opts);
opts.port = chrome.port;
// Connecting to WS using puppeteer.connect()
const resp = await util.promisify(request)(`http://localhost:${opts.port}/json/version`);
const chromeVersion = JSON.parse(resp.body);
const browser = await puppeteer.connect({
  browserWSEndpoint: chromeVersion.webSocketDebuggerUrl
});
// Cleanup of resources
await browser.disconnect();
await chrome.kill();
})();
const chromeLauncher = require('chrome-launcher');
const puppeteer = require(‘puppeteer-core');
const util = require('util');
(async() => {
const URL = 'https://www.linkit.nl';
// Chrome executable launch arguments
const opts = {
  chromeFlags: ['--headless'],
  logLevel: 'info',
  output: 'json'
};
// Launching chrome using chrome-launcher
const chrome = await chromeLauncher.launch(opts);
opts.port = chrome.port;
// Connecting to WS using puppeteer.connect()
const resp = await util.promisify(request)(`http://localhost:${opts.port}/json/version`);
const chromeVersion = JSON.parse(resp.body);
const browser = await puppeteer.connect({
  browserWSEndpoint: chromeVersion.webSocketDebuggerUrl
});
// Cleanup of resources
await browser.disconnect();
await chrome.kill();
})();
const chromeLauncher = require('chrome-launcher');
const puppeteer = require(‘puppeteer-core');
const util = require('util');
(async() => {
const URL = 'https://www.linkit.nl';
// Chrome executable launch arguments
const opts = {
  chromeFlags: ['--headless'],
  logLevel: 'info',
  output: 'json'
};
// Launching chrome using chrome-launcher
const chrome = await chromeLauncher.launch(opts);
opts.port = chrome.port;
// Connecting to WS using puppeteer.connect()
const resp = await util.promisify(request)(`http://localhost:${opts.port}/json/version`);
const chromeVersion = JSON.parse(resp.body);
const browser = await puppeteer.connect({
  browserWSEndpoint: chromeVersion.webSocketDebuggerUrl
});
// Cleanup of resources
await browser.disconnect();
await chrome.kill();
})();
DEMOS
even more
github.com/onderceylan/pwa-asset-generator
PptrGram
await Promise.all(filters.map(async (filter) => {
const page = await browser.newPage();
await page.setContent(`
<style>/* Page styles here */</style>
<figure class="${filter}">
<img src="${getImageBase64Url('./sample.jpg')}">
<span>@onderceylan</span>
</figure>
`, { waitUntil: 'networkidle2' });
await page.addStyleTag({
url: 'https://cdnjs.cloudflare.com/ajax/libs/cssgram/0.1.10/cssgram.min.css'
});
// Get original image dimensions
const { width, height } = await page.evaluate(() => {
return (({naturalWidth: width, naturalHeight: height}) =>
({width, height}))(document.querySelector('img'));
});
await page.setViewport({ width, height });
await page.screenshot({
path: `pptgram/pptrgram-${filter}.jpeg`,
type: 'jpeg',
quality: 70,
fullPage: true,
});
});
PptrGram
PptrFlow
PptrFlow
PptrFlow
await page.goto(`http://localhost:8002/tensorflow.html`);
const result = await page.evaluate(() => {
const img = document.getElementById('img');
// Load the model
return cocoSsd.load().then(model => model.detect(img))
});
console.log(result);
PptrFlow
Monitoring
Visual Regression Testing
const takeScreenshot = async (page, title) => {
if (!fs.existsSync('./.screenshots')) {
fs.mkdirSync('./.screenshots');
}
const filePath = `./.screenshots/${title}.png`;
if (fs.existsSync(filePath)) {
const newFilePath = `./.screenshots/${title}-new.png`;

await page.screenshot({
path: newFilePath,
fullPage: true
});

const result = await new Promise(resolve =>
looksSame(filePath, newFilePath, (err, equal) => resolve(equal)));


fs.unlinkSync(newFilePath);
return result;
} else {
await page.screenshot({
path: filePath,
fullPage: true
});
return true;
}
};


await page.goto('https://www.linkit.nl');
expect(await takeScreenshot(page, 'main-page.1')).toBeTruthy();
Visual Regression Testing
DOM Snapshot Testing
const page = await browser.newPage();
await page.goto('https://www.linkit.nl/');
expect(await page.content()).toMatchSnapshot();
DOM Snapshot Testing
Timeline Trace Monitoring
await page.tracing.start({ path: 'trace.json' });

await page.goto('https://www.google.com');

await page.tracing.stop();
Timeline Trace Monitoring
FPS Monitoring
const protocol = await page.target().createCDPSession();

await protocol.send('Overlay.setShowFPSCounter', { show: true });

await page.goto('https://www.linkit.nl');
// Do graphical regressions here by interacting with the page
await protocol.send('Input.synthesizeScrollGesture', {
x: 100,
y: 100,
yDistance: -400,
repeatCount: 3
});
await page.screenshot({
path: 'fps.jpeg',
type: 'jpeg',
clip: {
x:0,
y:0,
width: 370,
height: 370
}
});
FPS Monitoring
Memory leak by Heap
const protocol = await page.target().createCDPSession();
await protocol.send('HeapProfiler.enable');
await protocol.send('HeapProfiler.collectGarbage');
const startMetrics = await page.metrics();
// Do memory regressions here by interacting with the page
await protocol.send('Input.synthesizeScrollGesture', {
x: 100,
y: 100,
yDistance: -400,
repeatCount: 3
});
await protocol.send('HeapProfiler.collectGarbage');
const endMetrics = await page.metrics();
expect(endMetrics.JSHeapUsedSize < startMetrics.JSHeapUsedSize * 1.1)
.toBeTruthy();
Memory leak by Heap
Memory leak by Prototype
// Get a handle to the Map object prototype
const mapPrototype = await page.evaluateHandle(() => Map.prototype);
// Query all map instances into an array
const mapInstances = await page.queryObjects(mapPrototype);
// Count amount of map objects in heap
const count = await page.evaluate(maps => maps.length, mapInstances);
// Idea here is to test object instances on the page
// where it's expected to be invalidated
expect(count).toBe(0);
Memory leak by Prototype
Monitor change on security state
const protocol = await page.target().createCDPSession();

await protocol.send('Security.enable');
protocol.on('Security.securityStateChanged', console.log);
Monitor change on security state
Monitor SSL certificate expiration
const page = await browser.newPage();
page.on('response', (resp) => {
const url = resp.url();

if (url === siteUrl) {
const secDetails = resp.securityDetails();
const now = Math.floor((new Date()).getTime() / 1000);

console.log((Math.floor((secDetails.validTo() - now) / 86400)),
'days to expire');
}
});
await page.goto(siteUrl, { waitUntil: 'networkidle0' });
Monitor SSL certificate expiration
Puppeteer on Cloud
const launchChrome = require('@serverless-chrome/lambda');
const request = require('superagent');
module.exports.getChrome = async () => {
const chrome = await launchChrome();
const response = await request
.get(`${chrome.url}/json/version`)
.set('Content-Type', 'application/json');
const endpoint = response.body.webSocketDebuggerUrl;
return {
endpoint,
instance: chrome,
};
};
Ppptr on AWS Lambda via Serverless Framework
const puppeteer = require('puppeteer');
const { getChrome } = require('./chrome-script');
module.exports.hello = async (event) => {
const { url } = event.queryStringParameters;
const chrome = await getChrome();
const browser = await puppeteer.connect({
browserWSEndpoint: chrome.endpoint,
});
const page = await browser.newPage();

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

const content = await page.evaluate(() => document.body.innerHTML);

return {
statusCode: 200,
body: JSON.stringify({
content,
}),
};
};
Ppptr on AWS Lambda via Serverless Framework
PaaS
Puppeteer as a Service
browserless.io
checklyhq.com
Main Takeaways
• Chrome can be instrumented with a WS connection over
Chrome DevTools Protocol — CDP
• You might not need to download chromium revision every time
—puppeteer-core + chrome-launcher
• Headless chrome can be executed on servers— cloud, and CI
pipelines
• You can automate anything you do on DevTools, by using raw
protocol of CDP on puppeteer—CDPSession
Thank you!
@onderceylan
https://github.com/onderceylan/puppeteer-demos

Weitere ähnliche Inhalte

Was ist angesagt?

Angular Routing Guard
Angular Routing GuardAngular Routing Guard
Angular Routing GuardKnoldus Inc.
 
BugBounty Roadmap with Mohammed Adam
BugBounty Roadmap with Mohammed AdamBugBounty Roadmap with Mohammed Adam
BugBounty Roadmap with Mohammed AdamMohammed Adam
 
Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.Visual Engineering
 
The Image that called me - Active Content Injection with SVG Files
The Image that called me - Active Content Injection with SVG FilesThe Image that called me - Active Content Injection with SVG Files
The Image that called me - Active Content Injection with SVG FilesMario Heiderich
 
gRPC: The Story of Microservices at Square
gRPC: The Story of Microservices at SquaregRPC: The Story of Microservices at Square
gRPC: The Story of Microservices at SquareApigee | Google Cloud
 
Nodejs Explained with Examples
Nodejs Explained with ExamplesNodejs Explained with Examples
Nodejs Explained with ExamplesGabriele Lana
 
Introducing Playwright's New Test Runner
Introducing Playwright's New Test RunnerIntroducing Playwright's New Test Runner
Introducing Playwright's New Test RunnerApplitools
 
Shodan- That Device Search Engine
Shodan- That Device Search EngineShodan- That Device Search Engine
Shodan- That Device Search EngineInMobi Technology
 
What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.
What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.
What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.Mikhail Egorov
 
Mikhail Egorov - Hunting for bugs in Adobe Experience Manager webapps
Mikhail Egorov - Hunting for bugs in Adobe Experience Manager webappsMikhail Egorov - Hunting for bugs in Adobe Experience Manager webapps
Mikhail Egorov - Hunting for bugs in Adobe Experience Manager webappshacktivity
 
Pentesting react native application for fun and profit - Abdullah
Pentesting react native application for fun and profit - AbdullahPentesting react native application for fun and profit - Abdullah
Pentesting react native application for fun and profit - Abdullahidsecconf
 
Racing The Web - Hackfest 2016
Racing The Web - Hackfest 2016Racing The Web - Hackfest 2016
Racing The Web - Hackfest 2016Aaron Hnatiw
 
A New Era of SSRF - Exploiting URL Parser in Trending Programming Languages! ...
A New Era of SSRF - Exploiting URL Parser in Trending Programming Languages! ...A New Era of SSRF - Exploiting URL Parser in Trending Programming Languages! ...
A New Era of SSRF - Exploiting URL Parser in Trending Programming Languages! ...CODE BLUE
 

Was ist angesagt? (20)

Burp suite
Burp suiteBurp suite
Burp suite
 
Angular Routing Guard
Angular Routing GuardAngular Routing Guard
Angular Routing Guard
 
BugBounty Roadmap with Mohammed Adam
BugBounty Roadmap with Mohammed AdamBugBounty Roadmap with Mohammed Adam
BugBounty Roadmap with Mohammed Adam
 
Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.
 
Vue.js
Vue.jsVue.js
Vue.js
 
The Image that called me - Active Content Injection with SVG Files
The Image that called me - Active Content Injection with SVG FilesThe Image that called me - Active Content Injection with SVG Files
The Image that called me - Active Content Injection with SVG Files
 
Node js introduction
Node js introductionNode js introduction
Node js introduction
 
gRPC: The Story of Microservices at Square
gRPC: The Story of Microservices at SquaregRPC: The Story of Microservices at Square
gRPC: The Story of Microservices at Square
 
Nodejs Explained with Examples
Nodejs Explained with ExamplesNodejs Explained with Examples
Nodejs Explained with Examples
 
Introducing Playwright's New Test Runner
Introducing Playwright's New Test RunnerIntroducing Playwright's New Test Runner
Introducing Playwright's New Test Runner
 
Shodan- That Device Search Engine
Shodan- That Device Search EngineShodan- That Device Search Engine
Shodan- That Device Search Engine
 
What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.
What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.
What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.
 
Mikhail Egorov - Hunting for bugs in Adobe Experience Manager webapps
Mikhail Egorov - Hunting for bugs in Adobe Experience Manager webappsMikhail Egorov - Hunting for bugs in Adobe Experience Manager webapps
Mikhail Egorov - Hunting for bugs in Adobe Experience Manager webapps
 
Pentesting react native application for fun and profit - Abdullah
Pentesting react native application for fun and profit - AbdullahPentesting react native application for fun and profit - Abdullah
Pentesting react native application for fun and profit - Abdullah
 
Racing The Web - Hackfest 2016
Racing The Web - Hackfest 2016Racing The Web - Hackfest 2016
Racing The Web - Hackfest 2016
 
Intro to WebSockets
Intro to WebSocketsIntro to WebSockets
Intro to WebSockets
 
BugBounty Tips.pdf
BugBounty Tips.pdfBugBounty Tips.pdf
BugBounty Tips.pdf
 
A New Era of SSRF - Exploiting URL Parser in Trending Programming Languages! ...
A New Era of SSRF - Exploiting URL Parser in Trending Programming Languages! ...A New Era of SSRF - Exploiting URL Parser in Trending Programming Languages! ...
A New Era of SSRF - Exploiting URL Parser in Trending Programming Languages! ...
 
GRPC.pptx
GRPC.pptxGRPC.pptx
GRPC.pptx
 
Socket.IO
Socket.IOSocket.IO
Socket.IO
 

Ähnlich wie Automate web tasks like screenshots, form fills and more with Puppeteer

Puppeteer can automate that! - HolyJS Piter 2020
Puppeteer can automate that! - HolyJS Piter 2020Puppeteer can automate that! - HolyJS Piter 2020
Puppeteer can automate that! - HolyJS Piter 2020Önder Ceylan
 
Introducing perf budgets on CI with puppeteer - perf.now()
Introducing perf budgets on CI with puppeteer - perf.now()Introducing perf budgets on CI with puppeteer - perf.now()
Introducing perf budgets on CI with puppeteer - perf.now()Önder Ceylan
 
Bruce Lawson, Web Development 2.0, SparkUp! Poznan Poland
Bruce Lawson, Web Development 2.0, SparkUp! Poznan PolandBruce Lawson, Web Development 2.0, SparkUp! Poznan Poland
Bruce Lawson, Web Development 2.0, SparkUp! Poznan Polandbrucelawson
 
[convergese] Adaptive Images in Responsive Web Design
[convergese] Adaptive Images in Responsive Web Design[convergese] Adaptive Images in Responsive Web Design
[convergese] Adaptive Images in Responsive Web DesignChristopher Schmitt
 
[refreshaustin] Adaptive Images in Responsive Web Design
[refreshaustin] Adaptive Images in Responsive Web Design[refreshaustin] Adaptive Images in Responsive Web Design
[refreshaustin] Adaptive Images in Responsive Web DesignChristopher Schmitt
 
Pinkoi Mobile Web
Pinkoi Mobile WebPinkoi Mobile Web
Pinkoi Mobile Webmikeleeme
 
Backend, app e internet das coisas com NodeJS no Google Cloud Platform
Backend, app e internet das coisas com NodeJS no Google Cloud PlatformBackend, app e internet das coisas com NodeJS no Google Cloud Platform
Backend, app e internet das coisas com NodeJS no Google Cloud PlatformDevMT
 
Backend, app e internet das coisas com NodeJS no Google Cloud Platform
Backend, app e internet das coisas com NodeJS no Google Cloud PlatformBackend, app e internet das coisas com NodeJS no Google Cloud Platform
Backend, app e internet das coisas com NodeJS no Google Cloud PlatformAlvaro Viebrantz
 
Google Compute Engine Starter Guide
Google Compute Engine Starter GuideGoogle Compute Engine Starter Guide
Google Compute Engine Starter GuideSimon Su
 
vodQA Pune (2019) - Browser automation using dev tools
vodQA Pune (2019) - Browser automation using dev toolsvodQA Pune (2019) - Browser automation using dev tools
vodQA Pune (2019) - Browser automation using dev toolsvodQA
 
Drive chrome(headless) with puppeteer
Drive chrome(headless) with puppeteerDrive chrome(headless) with puppeteer
Drive chrome(headless) with puppeteerVodqaBLR
 
soft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.jssoft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.jssoft-shake.ch
 
FINHTML5 - Breaking the mobile web
FINHTML5 - Breaking the mobile webFINHTML5 - Breaking the mobile web
FINHTML5 - Breaking the mobile webMaximiliano Firtman
 
Electron - cross platform desktop applications made easy
Electron - cross platform desktop applications made easyElectron - cross platform desktop applications made easy
Electron - cross platform desktop applications made easyUlrich Krause
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applicationsTom Croucher
 
Василевский Илья (Fun-box): "автоматизация браузера при помощи PhantomJS"
Василевский Илья (Fun-box): "автоматизация браузера при помощи PhantomJS"Василевский Илья (Fun-box): "автоматизация браузера при помощи PhantomJS"
Василевский Илья (Fun-box): "автоматизация браузера при помощи PhantomJS"Provectus
 
AFUP Lorraine - Symfony Webpack Encore
AFUP Lorraine - Symfony Webpack EncoreAFUP Lorraine - Symfony Webpack Encore
AFUP Lorraine - Symfony Webpack EncoreEngineor
 

Ähnlich wie Automate web tasks like screenshots, form fills and more with Puppeteer (20)

Puppeteer can automate that! - HolyJS Piter 2020
Puppeteer can automate that! - HolyJS Piter 2020Puppeteer can automate that! - HolyJS Piter 2020
Puppeteer can automate that! - HolyJS Piter 2020
 
Introducing perf budgets on CI with puppeteer - perf.now()
Introducing perf budgets on CI with puppeteer - perf.now()Introducing perf budgets on CI with puppeteer - perf.now()
Introducing perf budgets on CI with puppeteer - perf.now()
 
JavaScript on the Desktop
JavaScript on the DesktopJavaScript on the Desktop
JavaScript on the Desktop
 
Node azure
Node azureNode azure
Node azure
 
Bruce Lawson, Web Development 2.0, SparkUp! Poznan Poland
Bruce Lawson, Web Development 2.0, SparkUp! Poznan PolandBruce Lawson, Web Development 2.0, SparkUp! Poznan Poland
Bruce Lawson, Web Development 2.0, SparkUp! Poznan Poland
 
[convergese] Adaptive Images in Responsive Web Design
[convergese] Adaptive Images in Responsive Web Design[convergese] Adaptive Images in Responsive Web Design
[convergese] Adaptive Images in Responsive Web Design
 
[refreshaustin] Adaptive Images in Responsive Web Design
[refreshaustin] Adaptive Images in Responsive Web Design[refreshaustin] Adaptive Images in Responsive Web Design
[refreshaustin] Adaptive Images in Responsive Web Design
 
Always on! Or not?
Always on! Or not?Always on! Or not?
Always on! Or not?
 
Pinkoi Mobile Web
Pinkoi Mobile WebPinkoi Mobile Web
Pinkoi Mobile Web
 
Backend, app e internet das coisas com NodeJS no Google Cloud Platform
Backend, app e internet das coisas com NodeJS no Google Cloud PlatformBackend, app e internet das coisas com NodeJS no Google Cloud Platform
Backend, app e internet das coisas com NodeJS no Google Cloud Platform
 
Backend, app e internet das coisas com NodeJS no Google Cloud Platform
Backend, app e internet das coisas com NodeJS no Google Cloud PlatformBackend, app e internet das coisas com NodeJS no Google Cloud Platform
Backend, app e internet das coisas com NodeJS no Google Cloud Platform
 
Google Compute Engine Starter Guide
Google Compute Engine Starter GuideGoogle Compute Engine Starter Guide
Google Compute Engine Starter Guide
 
vodQA Pune (2019) - Browser automation using dev tools
vodQA Pune (2019) - Browser automation using dev toolsvodQA Pune (2019) - Browser automation using dev tools
vodQA Pune (2019) - Browser automation using dev tools
 
Drive chrome(headless) with puppeteer
Drive chrome(headless) with puppeteerDrive chrome(headless) with puppeteer
Drive chrome(headless) with puppeteer
 
soft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.jssoft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.js
 
FINHTML5 - Breaking the mobile web
FINHTML5 - Breaking the mobile webFINHTML5 - Breaking the mobile web
FINHTML5 - Breaking the mobile web
 
Electron - cross platform desktop applications made easy
Electron - cross platform desktop applications made easyElectron - cross platform desktop applications made easy
Electron - cross platform desktop applications made easy
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
Василевский Илья (Fun-box): "автоматизация браузера при помощи PhantomJS"
Василевский Илья (Fun-box): "автоматизация браузера при помощи PhantomJS"Василевский Илья (Fun-box): "автоматизация браузера при помощи PhantomJS"
Василевский Илья (Fun-box): "автоматизация браузера при помощи PhantomJS"
 
AFUP Lorraine - Symfony Webpack Encore
AFUP Lorraine - Symfony Webpack EncoreAFUP Lorraine - Symfony Webpack Encore
AFUP Lorraine - Symfony Webpack Encore
 

Mehr von Önder Ceylan

Make your PWA feel more like an app
Make your PWA feel more like an appMake your PWA feel more like an app
Make your PWA feel more like an appÖnder Ceylan
 
Build a production ready PWA - LINKIT & KLM Digital Studio Meetup
Build a production ready PWA - LINKIT & KLM Digital Studio MeetupBuild a production ready PWA - LINKIT & KLM Digital Studio Meetup
Build a production ready PWA - LINKIT & KLM Digital Studio MeetupÖnder Ceylan
 
Build a production ready PWA with Angular and Firebase
Build a production ready PWA with Angular and FirebaseBuild a production ready PWA with Angular and Firebase
Build a production ready PWA with Angular and FirebaseÖnder Ceylan
 
Level up your NgRx game
Level up your NgRx gameLevel up your NgRx game
Level up your NgRx gameÖnder Ceylan
 
Building angular apps at scale
Building angular apps at scaleBuilding angular apps at scale
Building angular apps at scaleÖnder Ceylan
 
Progressive Web Apps: Is it a replacement for your mobile app?
Progressive Web Apps: Is it a replacement for your mobile app?Progressive Web Apps: Is it a replacement for your mobile app?
Progressive Web Apps: Is it a replacement for your mobile app?Önder Ceylan
 

Mehr von Önder Ceylan (6)

Make your PWA feel more like an app
Make your PWA feel more like an appMake your PWA feel more like an app
Make your PWA feel more like an app
 
Build a production ready PWA - LINKIT & KLM Digital Studio Meetup
Build a production ready PWA - LINKIT & KLM Digital Studio MeetupBuild a production ready PWA - LINKIT & KLM Digital Studio Meetup
Build a production ready PWA - LINKIT & KLM Digital Studio Meetup
 
Build a production ready PWA with Angular and Firebase
Build a production ready PWA with Angular and FirebaseBuild a production ready PWA with Angular and Firebase
Build a production ready PWA with Angular and Firebase
 
Level up your NgRx game
Level up your NgRx gameLevel up your NgRx game
Level up your NgRx game
 
Building angular apps at scale
Building angular apps at scaleBuilding angular apps at scale
Building angular apps at scale
 
Progressive Web Apps: Is it a replacement for your mobile app?
Progressive Web Apps: Is it a replacement for your mobile app?Progressive Web Apps: Is it a replacement for your mobile app?
Progressive Web Apps: Is it a replacement for your mobile app?
 

Kürzlich hochgeladen

Unidad 4 – Redes de ordenadores (en inglés).pptx
Unidad 4 – Redes de ordenadores (en inglés).pptxUnidad 4 – Redes de ordenadores (en inglés).pptx
Unidad 4 – Redes de ordenadores (en inglés).pptxmibuzondetrabajo
 
ETHICAL HACKING dddddddddddddddfnandni.pptx
ETHICAL HACKING dddddddddddddddfnandni.pptxETHICAL HACKING dddddddddddddddfnandni.pptx
ETHICAL HACKING dddddddddddddddfnandni.pptxNIMMANAGANTI RAMAKRISHNA
 
TRENDS Enabling and inhibiting dimensions.pptx
TRENDS Enabling and inhibiting dimensions.pptxTRENDS Enabling and inhibiting dimensions.pptx
TRENDS Enabling and inhibiting dimensions.pptxAndrieCagasanAkio
 
Company Snapshot Theme for Business by Slidesgo.pptx
Company Snapshot Theme for Business by Slidesgo.pptxCompany Snapshot Theme for Business by Slidesgo.pptx
Company Snapshot Theme for Business by Slidesgo.pptxMario
 
Film cover research (1).pptxsdasdasdasdasdasa
Film cover research (1).pptxsdasdasdasdasdasaFilm cover research (1).pptxsdasdasdasdasdasa
Film cover research (1).pptxsdasdasdasdasdasa494f574xmv
 
Top 10 Interactive Website Design Trends in 2024.pptx
Top 10 Interactive Website Design Trends in 2024.pptxTop 10 Interactive Website Design Trends in 2024.pptx
Top 10 Interactive Website Design Trends in 2024.pptxDyna Gilbert
 
SCM Symposium PPT Format Customer loyalty is predi
SCM Symposium PPT Format Customer loyalty is prediSCM Symposium PPT Format Customer loyalty is predi
SCM Symposium PPT Format Customer loyalty is predieusebiomeyer
 
办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书
办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书
办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书zdzoqco
 
IP addressing and IPv6, presented by Paul Wilson at IETF 119
IP addressing and IPv6, presented by Paul Wilson at IETF 119IP addressing and IPv6, presented by Paul Wilson at IETF 119
IP addressing and IPv6, presented by Paul Wilson at IETF 119APNIC
 
『澳洲文凭』买拉筹伯大学毕业证书成绩单办理澳洲LTU文凭学位证书
『澳洲文凭』买拉筹伯大学毕业证书成绩单办理澳洲LTU文凭学位证书『澳洲文凭』买拉筹伯大学毕业证书成绩单办理澳洲LTU文凭学位证书
『澳洲文凭』买拉筹伯大学毕业证书成绩单办理澳洲LTU文凭学位证书rnrncn29
 
『澳洲文凭』买詹姆士库克大学毕业证书成绩单办理澳洲JCU文凭学位证书
『澳洲文凭』买詹姆士库克大学毕业证书成绩单办理澳洲JCU文凭学位证书『澳洲文凭』买詹姆士库克大学毕业证书成绩单办理澳洲JCU文凭学位证书
『澳洲文凭』买詹姆士库克大学毕业证书成绩单办理澳洲JCU文凭学位证书rnrncn29
 

Kürzlich hochgeladen (11)

Unidad 4 – Redes de ordenadores (en inglés).pptx
Unidad 4 – Redes de ordenadores (en inglés).pptxUnidad 4 – Redes de ordenadores (en inglés).pptx
Unidad 4 – Redes de ordenadores (en inglés).pptx
 
ETHICAL HACKING dddddddddddddddfnandni.pptx
ETHICAL HACKING dddddddddddddddfnandni.pptxETHICAL HACKING dddddddddddddddfnandni.pptx
ETHICAL HACKING dddddddddddddddfnandni.pptx
 
TRENDS Enabling and inhibiting dimensions.pptx
TRENDS Enabling and inhibiting dimensions.pptxTRENDS Enabling and inhibiting dimensions.pptx
TRENDS Enabling and inhibiting dimensions.pptx
 
Company Snapshot Theme for Business by Slidesgo.pptx
Company Snapshot Theme for Business by Slidesgo.pptxCompany Snapshot Theme for Business by Slidesgo.pptx
Company Snapshot Theme for Business by Slidesgo.pptx
 
Film cover research (1).pptxsdasdasdasdasdasa
Film cover research (1).pptxsdasdasdasdasdasaFilm cover research (1).pptxsdasdasdasdasdasa
Film cover research (1).pptxsdasdasdasdasdasa
 
Top 10 Interactive Website Design Trends in 2024.pptx
Top 10 Interactive Website Design Trends in 2024.pptxTop 10 Interactive Website Design Trends in 2024.pptx
Top 10 Interactive Website Design Trends in 2024.pptx
 
SCM Symposium PPT Format Customer loyalty is predi
SCM Symposium PPT Format Customer loyalty is prediSCM Symposium PPT Format Customer loyalty is predi
SCM Symposium PPT Format Customer loyalty is predi
 
办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书
办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书
办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书
 
IP addressing and IPv6, presented by Paul Wilson at IETF 119
IP addressing and IPv6, presented by Paul Wilson at IETF 119IP addressing and IPv6, presented by Paul Wilson at IETF 119
IP addressing and IPv6, presented by Paul Wilson at IETF 119
 
『澳洲文凭』买拉筹伯大学毕业证书成绩单办理澳洲LTU文凭学位证书
『澳洲文凭』买拉筹伯大学毕业证书成绩单办理澳洲LTU文凭学位证书『澳洲文凭』买拉筹伯大学毕业证书成绩单办理澳洲LTU文凭学位证书
『澳洲文凭』买拉筹伯大学毕业证书成绩单办理澳洲LTU文凭学位证书
 
『澳洲文凭』买詹姆士库克大学毕业证书成绩单办理澳洲JCU文凭学位证书
『澳洲文凭』买詹姆士库克大学毕业证书成绩单办理澳洲JCU文凭学位证书『澳洲文凭』买詹姆士库克大学毕业证书成绩单办理澳洲JCU文凭学位证书
『澳洲文凭』买詹姆士库克大学毕业证书成绩单办理澳洲JCU文凭学位证书
 

Automate web tasks like screenshots, form fills and more with Puppeteer