SlideShare a Scribd company logo
1 of 150
Download to read offline
🎭 Playwright
Who We Are
● 2009-2019
WebKit Web Inspector
Chrome Developer Tools
Who We Are
● 2009-2019
WebKit Web Inspector
Chrome Developer Tools
Who We Are
● 2009-2019
WebKit Web Inspector
Chrome Developer Tools
Who We Are
● 2009-2019
WebKit Web Inspector
Chrome Developer Tools
● 2011-...
Chrome DevTools Protocol
Who We Are
● 2009-2019
WebKit Web Inspector
Chrome Developer Tools
● 2011-...
Chrome DevTools Protocol
● 2015-2016
Node.js Debugger
Who We Are
● 2009-2019
WebKit Web Inspector
Chrome Developer Tools
● 2011-...
Chrome DevTools Protocol
● 2015-2016
Node.js Debugger
● 2017-2019
Puppeteer
Who We Are
● 2009-2019
WebKit Web Inspector
Chrome Developer Tools
● 2011-...
Chrome DevTools Protocol
● 2015-2016
Node.js Debugger
● 2017-2019
Puppeteer
Who We Are
● 2009-2019
WebKit Web Inspector
Chrome Developer Tools
● 2011-...
Chrome DevTools Protocol
● 2015-2016
Node.js Debugger
● 2017-2019
Puppeteer
● 2019-...
Playwright
Who We Are
Playwright
github.com/microsoft/playwright
🍿 Demo Time! 🍿
import {chromium, firefox, webkit} from 'playwright';
for (const browserType of [chromium, firefox, webkit]) {
const browser = await browserType.launch();
const page = await browser.newPage();
await page.goto('https://playwright.dev');
await page.screenshot({path: `image-${browserType.name()}.png`});
await browser.close();
}
import {chromium, firefox, webkit} from 'playwright';
for (const browserType of [chromium, firefox, webkit]) {
const browser = await browserType.launch();
const page = await browser.newPage();
await page.goto('https://playwright.dev');
await page.screenshot({path: `image-${browserType.name()}.png`});
await browser.close();
}
J
a
v
a
S
c
r
i
p
t
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
for browser_type in [p.chromium, p.firefox, p.webkit]:
browser = browser_type.launch()
page = browser.new_page()
page.goto("https://playwright.dev")
page.screenshot(path="image-" + browser_type.name + ".png")
browser.close()
P
y
t
h
o
n
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
List<BrowserType> browserTypes = Arrays.asList(
playwright.chromium(), playwright.webkit(), playwright.firefox()
);
for (BrowserType browserType : browserTypes) {
try (Browser browser = browserType.launch()) {
Page page = browser.newPage();
page.navigate("http://playwright.dev");
page.screenshot(new Page.ScreenshotOptions()
.setPath(Paths.get("image-" + browserType.name() + ".png")));
}
}
}
}
J
a
v
a
Why Playwright?
Playwright:
✅ dependable
✅ efficient
✅ capable
✅ ubiquitous
✅ delightful
✅ lively
Act I
Dependable
Dependable
Efficient
Capable
Ubiquitous
Delightful
Lively
Dependable
👌 We Triage Issues in <48 hours
📚 We Fix Issues (>1600 fixed)
✈ We Take Full Responsibility
github.com/microsoft/playwright
Downloads API
Downloads API
Level 1: Browser Engineering
C++
- Chromium Development
- Improving Chrome DevTools Protocol
- Google Chrome, Microsoft Edge, Opera, etc
Level 1: Browser Engineering
C++
- Chromium Development
- Improving Chrome DevTools Protocol
- Google Chrome, Microsoft Edge, Opera, etc
- WebKit Development
- Improving Web Inspector Protocol
- Safari, Mobile Safari, Epiphany, etc
Level 1: Browser Engineering
C++
- Chromium Development
- Improving Chrome DevTools Protocol
- Google Chrome, Microsoft Edge, Opera, etc
- WebKit Development
- Improving Web Inspector Protocol
- Safari, Mobile Safari, Epiphany, etc
- Firefox Development
- Improving “Juggler” Protocol
- Mozilla Firefox
Level 1: Browser Engineering
C++
- Chromium Development
- Improving Chrome DevTools Protocol
- Google Chrome, Microsoft Edge, Opera, etc
- WebKit Development
- Improving Web Inspector Protocol
- Safari, Mobile Safari, Epiphany, etc
- Firefox Development
- Improving “Juggler” Protocol
- Mozilla Firefox
Level 1: Browser Engineering
C++
Level 2: Playwright Driver
Level 1: Browser Engineering
C++
TypeScript
- Single web automation protocol
- Unify all remote debugging protocols
- Expose “Downloads API” in driver
Level 2: Playwright Driver
🎭 Playwright Driver
Level 1: Browser Engineering
C++
TypeScript
Level 3: Language Bindings
🎭 Playwright Driver
Level 1: Browser Engineering
C++
Level 2: Playwright Driver
TypeScript
Level 3: Language Bindings
🎭 Playwright Driver
Level 1: Browser Engineering
C++
Level 2: Playwright Driver
Playwright
Playwright
for
Java
Playwright
for
Python
Playwright
for
C#
Expose language idiomatic API to
control downloads
TypeScript
Level 3: Language Bindings
🎭 Playwright Driver
Level 1: Browser Engineering
C++
Level 2: Playwright Driver
Playwright
Playwright
for
Java
Playwright
for
Python
Playwright
for
C#
Expose language idiomatic API to
control downloads
TypeScript
Level 3: Language Bindings
🎭 Playwright Driver
Level 1: Browser Engineering
C++
Level 2: Playwright Driver
Playwright
Playwright
for
Java
Playwright
for
Python
Playwright
for
C#
Expose language idiomatic API to
control downloads
TypeScript
Being Dependable
🎭 Playwright Driver
C++
Playwright
Playwright
for
Java
Playwright
for
Python
Playwright
for
C#
Cross-Browser Testing Tool
● 👀 8 teams from multiple companies
● 🐌 Slow feedback loop (months /
years)
Playwright
● 💫 1 team from a single company
● 🐆 Fast feedback loop (days / weeks)
More Like This
● Downloads API
● Screencast API
● Drag & Drop API
● Clipboard API
● Browser-Level cookies
● Browser Contexts
● Per-context HTTP proxy
● ...
Summary: Playwright is Dependable
👌 We Triage Issues in <48 hours
📚 We Fix Issues (>1600 fixed)
✈ We Take Full Responsibility
Act II
Efficient
Dependable
Efficient
Capable
Ubiquitous
Delightful
Lively
What is “Efficient”?
Efficient = Fast
?
Automation Costs
● Throughput = spend less CPU cycles
● Latency = run tests fast
● Flakiness = reliable runs
Playwright Being Efficient
● Trick 1: Browser Contexts
● Trick 2: Auto-waiting
Trick 1: Browser Contexts
❌ Never Restart a Browser
● Slow instantiation (>100ms)
● Huge memory overhead
✅ Always create Browser Contexts
● Full isolation
● Fast instantiation (~1ms)
● Low overhead Browser Context
Trick 1: Browser Contexts
Context 1
Trick 1: Browser Contexts
Context 1 Context 2
Trick 1: Browser Contexts
Context 1 Context 2
import {webkit, chromium, firefox} from 'playwright';
const browser = await chromium.launch();
for (let i = 0; i < 10; ++i) {
// Fast, simple, configurable!
const context = await browser.newContext()
const page = await context.newPage();
await page.goto('https://playwright.dev');
await context.close();
}
import {webkit, chromium, firefox} from 'playwright';
const browser = await chromium.launch();
for (let i = 0; i < 10; ++i) {
// Fast, simple, configurable!
const context = await browser.newContext()
const page = await context.newPage();
await page.goto('https://playwright.dev');
await context.close();
}
import {webkit, chromium, firefox} from 'playwright';
const browser = await chromium.launch();
for (let i = 0; i < 10; ++i) {
// Fast, simple, configurable!
const context = await browser.newContext()
const page = await context.newPage();
await page.goto('https://playwright.dev');
await context.close();
}
Form Filling: No Autowait
Form Filling: No Autowait
e-mail..
Form Filling: No Autowait
e-mail..
Form Filling: No Autowait
e-mail..
Form Filling: No Autowait
passwd...
Form Filling: No Autowait
passwd...
Form Filling: No Autowait
passwd...
Form Filling: No Autowait
submitting...
Form Filling: No Autowait
submitting...
Form Filling: No Autowait
MISSED
Form Filling: No Autowait
MISSED
Disabled button!
await page.goto('https://form.example.com');
// Shall we wait for fields to be enabled?..
await page.fill('#email', 'aslushnikov@gmail.com');
await page.fill('#password', 'mypassword');
// Wait for button to get enabled and click submit
setTimeout(async () => {
await page.click('#submit');
}, 1000);
N
o
n
-
P
l
a
y
w
r
i
g
h
t
P
s
e
u
d
o
-
C
o
d
e
await page.goto('https://form.example.com');
// Shall we wait for fields to be enabled?..
await page.fill('#email', 'aslushnikov@gmail.com');
await page.fill('#password', 'mypassword');
// Wait for button to get enabled and click submit
setTimeout(async () => {
await page.click('#submit');
}, 1000);
N
o
n
-
P
l
a
y
w
r
i
g
h
t
P
s
e
u
d
o
-
C
o
d
e
await page.goto('https://form.example.com');
// Shall we wait for fields to be enabled?..
await page.fill('#email', 'aslushnikov@gmail.com');
await page.fill('#password', 'mypassword');
// Wait for button to get enabled and click submit
setTimeout(async () => {
await page.click('#submit');
}, 1000);
N
o
n
-
P
l
a
y
w
r
i
g
h
t
P
s
e
u
d
o
-
C
o
d
e
Time Does Not Exist in the Cloud!
Trick 2: Auto-waiting ✨
Auto-Waiting..
Trick 2: Auto-waiting ✨
Successful!
Enabled!
Trick 2: Auto-waiting ✨
Trick 2: Auto-waiting ✨
// ✨ Playwright auto-waiting by default!
await page.goto('https://form.example.com');
await page.fill('#email', 'aslushnikov@gmail.com');
await page.fill('#password', 'mypassword');
await page.click('#submit');
P
l
a
y
w
r
i
g
h
t
// ✨ Playwright auto-waiting by default!
await page.goto('https://form.example.com');
await page.fill('#email', 'aslushnikov@gmail.com');
await page.fill('#password', 'mypassword');
await page.click('#submit');
P
l
a
y
w
r
i
g
h
t
// ✨ Playwright auto-waiting by default!
await page.goto('https://form.example.com');
await page.fill('#email', 'aslushnikov@gmail.com');
await page.fill('#password', 'mypassword');
await page.click('#submit');
P
l
a
y
w
r
i
g
h
t
// ✨ Playwright auto-waiting by default!
await page.goto('https://form.example.com');
await page.fill('#email', 'aslushnikov@gmail.com');
await page.fill('#password', 'mypassword');
await page.click('#submit');
P
l
a
y
w
r
i
g
h
t
Trick 2: Auto-waiting ✨
Trick 2: Auto-waiting ✨
Trick 2: Auto-waiting ✨
Trick 2: Auto-waiting ✨
Trick 2: Auto-waiting ✨
Trick 2: Auto-waiting ✨
Trick 2: Auto-waiting ✨
Summary: Playwright is Efficient
● Trick 1: Browser Contexts
● Trick 2: Auto-waiting
Act III
Capable
Dependable
Efficient
Capable
Ubiquitous
Delightful
Lively
import {webkit, devices} from 'playwright';
const browser = await webkit.launch();
const context = await browser.newContext({
...devices['iPhone 12 Pro'],
});
const page = await context.newPage();
await page.goto('https://playwright.dev');
await browser.close();
📱
D
e
v
i
c
e
E
m
u
l
a
t
i
o
n
import {webkit, devices} from 'playwright';
const browser = await webkit.launch();
const context = await browser.newContext({
...devices['iPhone 12 Pro'],
});
const page = await context.newPage();
await page.goto('https://playwright.dev');
await browser.close();
📱
D
e
v
i
c
e
E
m
u
l
a
t
i
o
n
import {webkit, devices} from 'playwright';
const browser = await webkit.launch();
const context = await browser.newContext({
...devices['iPhone 12 Pro'],
});
const page = await context.newPage();
await page.goto('https://playwright.dev');
await browser.close();
📱
D
e
v
i
c
e
E
m
u
l
a
t
i
o
n
import {chromium, firefox, webkit} from 'playwright';
const browser = await firefox.launch();
const context = await browser.newContext({
geolocation: { longitude: 48.858455, latitude: 2.294474 },
permissions: ['geolocation']
});
const page = await context.newPage();
await page.goto('https://playwright.dev');
await context.setGeolocation({
longitude: 29.97, latitude: 31.13
});
G
e
o
l
o
c
a
t
i
o
n
&
P
e
r
m
i
s
s
i
o
n
s
import {chromium, firefox, webkit} from 'playwright';
const browser = await firefox.launch();
const context = await browser.newContext({
geolocation: { longitude: 48.858455, latitude: 2.294474 },
permissions: ['geolocation']
});
const page = await context.newPage();
await page.goto('https://playwright.dev');
await context.setGeolocation({
longitude: 29.97, latitude: 31.13
});
G
e
o
l
o
c
a
t
i
o
n
&
P
e
r
m
i
s
s
i
o
n
s
import {chromium, firefox, webkit} from 'playwright';
const browser = await firefox.launch();
const context = await browser.newContext({
geolocation: { longitude: 48.858455, latitude: 2.294474 },
permissions: ['geolocation']
});
const page = await context.newPage();
await page.goto('https://playwright.dev');
await context.setGeolocation({
longitude: 29.97, latitude: 31.13
});
G
e
o
l
o
c
a
t
i
o
n
&
P
e
r
m
i
s
s
i
o
n
s
import {chromium, firefox, webkit} from 'playwright';
const browser = await firefox.launch();
const context = await browser.newContext({
geolocation: { longitude: 48.858455, latitude: 2.294474 },
permissions: ['geolocation']
});
const page = await context.newPage();
await page.goto('https://playwright.dev');
await context.setGeolocation({
longitude: 29.97, latitude: 31.13
});
G
e
o
l
o
c
a
t
i
o
n
&
P
e
r
m
i
s
s
i
o
n
s
import {webkit, chromium, firefox} from 'playwright';
const browser = await chromium.launch();
const context = await browser.newContext({
recordVideo: {
dir: 'videos/',
size: { width: 800, height: 600 },
},
});
const page = await context.newPage();
await page.goto('https://playwright.dev');
await page.close();
🎥
V
i
d
e
o
s
import {webkit, chromium, firefox} from 'playwright';
const browser = await chromium.launch();
const context = await browser.newContext({
recordVideo: {
dir: 'videos/',
size: { width: 800, height: 600 },
},
});
const page = await context.newPage();
await page.goto('https://playwright.dev');
await page.close();
🎥
V
i
d
e
o
s
import {webkit, chromium, firefox} from 'playwright';
const browser = await chromium.launch();
const context = await browser.newContext({
recordVideo: {
dir: 'videos/',
size: { width: 800, height: 600 },
},
});
const page = await context.newPage();
await page.goto('https://playwright.dev');
await page.close();
🎥
V
i
d
e
o
s
import {webkit, chromium, firefox} from 'playwright';
const browser = await webkit.launch();
const page = await browser.newPage();
page.on('request', r => console.log(r.method(), r.url()));
page.on('websocket', ws => console.log(ws.url()));
await page.goto('https://playwright.dev');
await browser.close();
🌎
N
e
t
w
o
r
k
&
W
e
b
S
o
c
k
e
t
s
import {webkit, chromium, firefox} from 'playwright';
const browser = await webkit.launch();
const page = await browser.newPage();
page.on('request', r => console.log(r.method(), r.url()));
page.on('websocket', ws => console.log(ws.url()));
await page.goto('https://playwright.dev');
await browser.close();
🌎
N
e
t
w
o
r
k
&
W
e
b
S
o
c
k
e
t
s
import {webkit, chromium, firefox} from 'playwright';
const browser = await firefox.launch();
const page = await browser.newPage();
await page.route('**/*.{png,jpg,jpeg}', route => route.abort());
await page.goto('https://playwright.dev');
await browser.close();
P
a
g
e
R
e
q
u
e
s
t
I
n
t
e
r
c
e
p
t
i
o
n
import {webkit, chromium, firefox} from 'playwright';
const browser = await firefox.launch();
const context = await browser.newContext();
await context.route('**/*.{png,jpg,jpeg}', route => route.abort());
const page = await page.newPage();
await page.goto('https://playwright.dev');
await browser.close();
C
o
n
t
e
x
t
R
e
q
u
e
s
t
I
n
t
e
r
c
e
p
t
i
o
n
import {webkit, chromium, firefox} from 'playwright';
const browser = await webkit.launch();
const page = await browser.newPage();
await page.goto('https://playwright.dev');
const [ download ] = await Promise.all([
page.waitForEvent('download'),
page.click('button#delayed-download')
]);
console.log(await download.path());
await browser.close();
D
o
w
n
l
o
a
d
s
import {webkit, chromium, firefox} from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://playwright.dev');
await page.click('button'); // CSS selector
await page.click('xpath=//button'); // XPath selector
await page.click('text=Log in'); // Text selector
await page.click(':nth-match(:text("Buy"), 3)'); // N-th match
await page.click('div:right-of(:text("Name"))'); // Layout 😱
await page.click(`xpath=//form >> text=Submit`); // Composite
S
m
a
r
t
S
e
l
e
c
t
o
r
s
import {webkit, chromium, firefox} from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://playwright.dev');
await page.click('button'); // CSS selector
await page.click('xpath=//button'); // XPath selector
await page.click('text=Log in'); // Text selector
await page.click(':nth-match(:text("Buy"), 3)'); // N-th match
await page.click('div:right-of(:text("Name"))'); // Layout 😱
await page.click(`xpath=//form >> text=Submit`); // Composite
S
m
a
r
t
S
e
l
e
c
t
o
r
s
import {webkit, chromium, firefox} from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://playwright.dev');
await page.click('button'); // CSS selector
await page.click('xpath=//button'); // XPath selector
await page.click('text=Log in'); // Text selector
await page.click(':nth-match(:text("Buy"), 3)'); // N-th match
await page.click('div:right-of(:text("Name"))'); // Layout 😱
await page.click(`xpath=//form >> text=Submit`); // Composite
S
m
a
r
t
S
e
l
e
c
t
o
r
s
import {webkit, chromium, firefox} from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://playwright.dev');
await page.click('button'); // CSS selector
await page.click('xpath=//button'); // XPath selector
await page.click('text=Log in'); // Text selector
await page.click(':nth-match(:text("Buy"), 3)'); // N-th match
await page.click('div:right-of(:text("Name"))'); // Layout 😱
await page.click(`xpath=//form >> text=Submit`); // Composite
S
m
a
r
t
S
e
l
e
c
t
o
r
s
import {webkit, chromium, firefox} from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://playwright.dev');
await page.click('button'); // CSS selector
await page.click('xpath=//button'); // XPath selector
await page.click('text=Log in'); // Text selector
await page.click(':nth-match(:text("Buy"), 3)'); // N-th match
await page.click('div:right-of(:text("Name"))'); // Layout 😱
await page.click(`xpath=//form >> text=Submit`); // Composite
S
m
a
r
t
S
e
l
e
c
t
o
r
s
import {webkit, chromium, firefox} from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://playwright.dev');
await page.click('button'); // CSS selector
await page.click('xpath=//button'); // XPath selector
await page.click('text=Log in'); // Text selector
await page.click(':nth-match(:text("Buy"), 3)'); // N-th match
await page.click('div:right-of(:text("Name"))'); // Layout 😱
await page.click(`xpath=//form >> text=Submit`); // Composite
S
m
a
r
t
S
e
l
e
c
t
o
r
s
import {webkit, chromium, firefox} from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://playwright.dev');
await page.click('button'); // CSS selector
await page.click('xpath=//button'); // XPath selector
await page.click('text=Log in'); // Text selector
await page.click(':nth-match(:text("Buy"), 3)'); // N-th match
await page.click('div:right-of(:text("Name"))'); // Layout 😱
await page.click(`xpath=//form >> text=Submit`); // Composite
S
m
a
r
t
S
e
l
e
c
t
o
r
s
// text content
const content = await page.textContent('nav:first-child');
expect(content).toBe('home');
// Attributes
const alt = await page.getAttribute('input', 'alt');
expect(alt).toBe('Text');
// Checkbox state
const checked = await page.isChecked('input');
expect(checked).toBeTruthy();
// Visibility
const visible = await page.isVisible('input');
expect(visible).toBeTruthy();
A
s
s
e
r
t
i
o
n
s
// text content
const content = await page.textContent('nav:first-child');
expect(content).toBe('home');
// Attributes
const alt = await page.getAttribute('input', 'alt');
expect(alt).toBe('Text');
// Checkbox state
const checked = await page.isChecked('input');
expect(checked).toBeTruthy();
// Visibility
const visible = await page.isVisible('input');
expect(visible).toBeTruthy();
A
s
s
e
r
t
i
o
n
s
// text content
const content = await page.textContent('nav:first-child');
expect(content).toBe('home');
// Attributes
const alt = await page.getAttribute('input', 'alt');
expect(alt).toBe('Text');
// Checkbox state
const checked = await page.isChecked('input');
expect(checked).toBeTruthy();
// Visibility
const visible = await page.isVisible('input');
expect(visible).toBeTruthy();
A
s
s
e
r
t
i
o
n
s
// text content
const content = await page.textContent('nav:first-child');
expect(content).toBe('home');
// Attributes
const alt = await page.getAttribute('input', 'alt');
expect(alt).toBe('Text');
// Checkbox state
const checked = await page.isChecked('input');
expect(checked).toBeTruthy();
// Visibility
const visible = await page.isVisible('input');
expect(visible).toBeTruthy();
A
s
s
e
r
t
i
o
n
s
import {chromium} from 'playwright';
const browser = await chromium.launch({
// Can be 'chrome', 'chrome-beta', 'msedge-beta', 'msedge-dev'
channel: 'msedge',
});
const page = await context.newPage();
await page.goto('https://playwright.dev');
await browser.close();
M
i
c
r
o
s
o
f
t
E
d
g
e
import {chromium} from 'playwright';
const browser = await chromium.launch({
// Can be 'chrome', 'chrome-beta', 'msedge-beta', 'msedge-dev'
channel: 'msedge',
});
const page = await context.newPage();
await page.goto('https://playwright.dev');
await browser.close();
M
i
c
r
o
s
o
f
t
E
d
g
e
More Features
● Built-in Shadow DOM piercing
● Idiomatic frames API
● Custom Selector Engines
● TimeZone / Locale / Color Scheme emulation
● Per-Context HTTP Proxy
● Workers / Service Workers
● Console sniffing
● Dialogs
● File Uploads
● Element Handles
● ...
● ubuntu-18.04 (chromium)
● ubuntu-18.04 (firefox)
● ubuntu-18.04 (webkit)
● ubuntu-20.04 (chromium)
● ubuntu-20.04 (firefox)
● ubuntu-20.04 (webkit)
● macos-10.14 (chromium)
● macos-10.14 (firefox)
● macos-10.14 (webkit)
● macos-10.15 (chromium)
● macos-10.15 (firefox)
● macos-10.15 (webkit)
● macos-11.0 (chromium)
● macos-11.0 (firefox)
● macos-11.0 (webkit)
● macos-11.0 arm64 (chromium)
● macos-11.0 arm64 (firefox)
● macos-11.0 arm64 (webkit)
Rigorous Testing ● Windows (chromium)
● Windows (firefox)
● Windows (webkit)
● test-package-installations (^10.17.0)
● test-package-installations (^12.0.0)
● test-package-installations (^14.1.0)
● Headful Linux (chromium)
● Headful Linux (firefox)
● Headful Linux (webkit)
● Transport (driver)
● Transport (service)
● Video Linux (chromium)
● Video Linux (firefox)
● Video Linux (webkit)
● Android Emulator (shard 1)
● Android Emulator (shard 2)
● Chrome Stable (Linux)
● Chrome Stable (Win)
● Chrome Stable (Mac)
● Edge Stable (Win)
● Electron Linux
Act IV
Ubiquitous
Dependable
Efficient
Capable
Ubiquitous
Delightful
Lively
WebKit Availability
Headed
Headless
❌
❌ ❌ ❌
✅
WebKit Availability
Headed
Headless
❌
❌ ❌ ❌
✅
🎭 Playwright WebKit Availability
Headed
Headless
✅
✅
✅
✅
✅
✅
● All Browsers
○ Chrome, Safari, Firefox
🎭 Playwright is Ubiquitous
● All Browsers
○ Chrome, Safari, Firefox
● All OS
○ Linux, Mac, Windows
🎭 Playwright is Ubiquitous
🎭 Playwright is Ubiquitous
● All Browsers
○ Chrome, Safari, Firefox
● All OS
○ Linux, Mac, Windows
● All Popular Languages
○ JavaScript / TypeScript
○ Java
○ Python
○ C# (alpha)
CI/CD, Services, Clients
● Any CI/CD
○ Github Actions, Travis CI, Azure Pipelines, Jenkins, Circle CI,
AWS, GCP, …
● Any CI/CD
○ Github Actions, Travis CI, Azure Pipelines, Jenkins, Circle CI,
AWS, GCP, …
● Docker Containers
○ docker pull mcr.microsoft.com/playwright
○ docker pull mcr.microsoft.com/playwright-java
CI/CD, Services, Clients
CI/CD, Services, Clients
● Any CI/CD
○ Github Actions, Travis CI, Azure Pipelines, Jenkins, Circle CI,
AWS, GCP, …
● Docker Containers
○ docker pull mcr.microsoft.com/playwright
○ docker pull mcr.microsoft.com/playwright-java
● Third-Party integrations
○ applitools.com
○ saucelabs.com
○ Checklyhq.com
○ www.testim.io
○ github.com/aerokube/moon
○ seleniumbox.com
CI/CD, Services, Clients
● Any CI/CD
○ Github Actions, Travis CI, Azure Pipelines, Jenkins, Circle CI,
AWS, GCP, …
● Docker Containers
○ docker pull mcr.microsoft.com/playwright
○ docker pull mcr.microsoft.com/playwright-java
● Third-Party integrations
○ applitools.com
○ saucelabs.com
○ Checklyhq.com
○ www.testim.io
○ github.com/aerokube/moon
○ seleniumbox.com
Playwright ❤ WebDriver
Chrome
DevTools
Protocol
Historical Context
Chrome
DevTools
Protocol
ChromeDriver
2013
Historical Context
Chrome
DevTools
Protocol
Playwright
2013
Historical Context
ChromeDriver
WebDriver Integration
WebDriver-Grid
WebDriver-Grid
WebDriver-Grid
WebDriver Integration
Chrome
DevTools
Protocol
WebDriver-Grid
WebDriver-Grid
WebDriver-Grid
WebDriver Integration
chromium.connectOverCDP()
Chrome
DevTools
Protocol
🎭 Playwright
WebDriver-Grid
WebDriver-Grid
WebDriver-Grid
Act V
Delightful Authoring & Debugging
Dependable
Efficient
Capable
Ubiquitous
Delightful
Lively
🍿 Demo Time 🍿
Authoring & Debugging
- Code Generation
- npx playwright codegen
- Built-In Inspector
- PWDEBUG=1 node snippet.js
- Devtools Console integration
- playwright.$
- Simple Node.js Debugging
- Logging
- DEBUG=pw:api node snippet.js
- Storage State re-use
Act VI
Lively
Dependable
Efficient
Capable
Ubiquitous
Delightful
Lively
Lively 🐈
● Active Development
○ 2500+ commits in the last year
○ 1600+ closed issues
● Growing Team
○ We’re hiring!
● Expanding Horizons
const { _electron } = require('playwright');
(async () => {
const electronApp = await _electron.launch({ args: ['main.js'] });
const window = await electronApp.firstWindow();
console.log(await window.title());
await window.screenshot({ path: 'intro.png' });
await window.click('text=Click me');
await electronApp.close();
})();
🧪
E
x
p
e
r
i
m
e
n
t
a
l
:
E
l
e
c
t
r
o
n
.
j
s
const { _android } = require('playwright');
(async () => {
const [device] = await _android.devices();
await device.shell('am force-stop com.android.chrome');
const context = await device.launchBrowser();
const page = await context.newPage();
await page.goto('https://playwright.dev/');
await page.screenshot({ path: 'page.png' });
await context.close();
await device.close();
})();
🧪
E
x
p
e
r
i
m
e
n
t
a
l
:
A
n
d
r
o
i
d
Conclusion?
Dependable
Efficient
Capable
Ubiquitous
Delightful
Lively
Web Automation
can be
Fun
🎭 playwright.dev
@aslushnikov
aslushnikov@gmail.com
Andrey Lushnikov
@playwrightweb
https:/
/aka.ms/playwright-slack
microsoft/playwright
Playwright
@aslushnikov
aslushnikov@gmail.com
Andrey Lushnikov
@playwrightweb
https:/
/aka.ms/playwright-slack
microsoft/playwright
Q
u
e
s
t
i
o
n
s
?
Playwright
How-To: Authentication Re-use
Context 1
1. npx playwright codegen --save-storage=auth.json
How-To: Authentication Re-use
Context 1
Storage State
2. Extract & Save Storage State
1. npx playwright codegen --save-storage=auth.json
How-To: Authentication Re-use
Context 1 Context N
Storage State
2. Extract & Save Storage State
3. Re-Use Storage State
1. npx playwright codegen --save-storage=auth.json
🎁
Authentication Re-Use
Authentication is Slow
Authentication is Slow
Authentication is Slow
Authentication is Slow Too Slow!
🍿 Demo Time 🍿
const context = await browser.newContext({
storageState: require('auth.json'),
});
A
u
t
h
e
n
t
i
c
a
t
i
o
n
R
e
-
U
s
e
const context = await browser.newContext({
storageState: require('auth.json'),
});
A
u
t
h
e
n
t
i
c
a
t
i
o
n
R
e
-
U
s
e

More Related Content

What's hot

Cypress - Best Practices
Cypress - Best PracticesCypress - Best Practices
Cypress - Best PracticesBrian Mann
 
Cypress e2e automation testing - day1 intor by: Hassan Hameed
Cypress e2e automation testing -  day1 intor by: Hassan HameedCypress e2e automation testing -  day1 intor by: Hassan Hameed
Cypress e2e automation testing - day1 intor by: Hassan HameedHassan Muhammad
 
e2e testing with cypress
e2e testing with cypresse2e testing with cypress
e2e testing with cypressTomasz Bak
 
Automated testing with Cypress
Automated testing with CypressAutomated testing with Cypress
Automated testing with CypressYong Shean Chong
 
Introduction to Integration Testing With Cypress
Introduction to Integration Testing With CypressIntroduction to Integration Testing With Cypress
Introduction to Integration Testing With CypressErez Cohen
 
QA Challenge Accepted 4.0 - Cypress vs. Selenium
QA Challenge Accepted 4.0 - Cypress vs. SeleniumQA Challenge Accepted 4.0 - Cypress vs. Selenium
QA Challenge Accepted 4.0 - Cypress vs. SeleniumLyudmil Latinov
 
Build CICD Pipeline for Container Presentation Slides
Build CICD Pipeline for Container Presentation SlidesBuild CICD Pipeline for Container Presentation Slides
Build CICD Pipeline for Container Presentation SlidesAmazon Web Services
 
Postman: An Introduction for Testers
Postman: An Introduction for TestersPostman: An Introduction for Testers
Postman: An Introduction for TestersPostman
 
Automation Testing using Selenium
Automation Testing using SeleniumAutomation Testing using Selenium
Automation Testing using SeleniumNaresh Chintalcheru
 
Continuous Integration, Build Pipelines and Continuous Deployment
Continuous Integration, Build Pipelines and Continuous DeploymentContinuous Integration, Build Pipelines and Continuous Deployment
Continuous Integration, Build Pipelines and Continuous DeploymentChristopher Read
 
CI CD Pipeline Using Jenkins | Continuous Integration and Deployment | DevOps...
CI CD Pipeline Using Jenkins | Continuous Integration and Deployment | DevOps...CI CD Pipeline Using Jenkins | Continuous Integration and Deployment | DevOps...
CI CD Pipeline Using Jenkins | Continuous Integration and Deployment | DevOps...Edureka!
 
Introduction to CICD
Introduction to CICDIntroduction to CICD
Introduction to CICDKnoldus Inc.
 

What's hot (20)

Cypress - Best Practices
Cypress - Best PracticesCypress - Best Practices
Cypress - Best Practices
 
Cypress e2e automation testing - day1 intor by: Hassan Hameed
Cypress e2e automation testing -  day1 intor by: Hassan HameedCypress e2e automation testing -  day1 intor by: Hassan Hameed
Cypress e2e automation testing - day1 intor by: Hassan Hameed
 
e2e testing with cypress
e2e testing with cypresse2e testing with cypress
e2e testing with cypress
 
Automated testing with Cypress
Automated testing with CypressAutomated testing with Cypress
Automated testing with Cypress
 
Jenkins
JenkinsJenkins
Jenkins
 
Introduction to Integration Testing With Cypress
Introduction to Integration Testing With CypressIntroduction to Integration Testing With Cypress
Introduction to Integration Testing With Cypress
 
QA Challenge Accepted 4.0 - Cypress vs. Selenium
QA Challenge Accepted 4.0 - Cypress vs. SeleniumQA Challenge Accepted 4.0 - Cypress vs. Selenium
QA Challenge Accepted 4.0 - Cypress vs. Selenium
 
Build CICD Pipeline for Container Presentation Slides
Build CICD Pipeline for Container Presentation SlidesBuild CICD Pipeline for Container Presentation Slides
Build CICD Pipeline for Container Presentation Slides
 
Introduction to CI/CD
Introduction to CI/CDIntroduction to CI/CD
Introduction to CI/CD
 
Postman: An Introduction for Testers
Postman: An Introduction for TestersPostman: An Introduction for Testers
Postman: An Introduction for Testers
 
Cypress Automation
Cypress  AutomationCypress  Automation
Cypress Automation
 
CICD with Jenkins
CICD with JenkinsCICD with Jenkins
CICD with Jenkins
 
Automation Testing using Selenium
Automation Testing using SeleniumAutomation Testing using Selenium
Automation Testing using Selenium
 
Jenkins tutorial
Jenkins tutorialJenkins tutorial
Jenkins tutorial
 
Continuous Integration, Build Pipelines and Continuous Deployment
Continuous Integration, Build Pipelines and Continuous DeploymentContinuous Integration, Build Pipelines and Continuous Deployment
Continuous Integration, Build Pipelines and Continuous Deployment
 
CI CD Pipeline Using Jenkins | Continuous Integration and Deployment | DevOps...
CI CD Pipeline Using Jenkins | Continuous Integration and Deployment | DevOps...CI CD Pipeline Using Jenkins | Continuous Integration and Deployment | DevOps...
CI CD Pipeline Using Jenkins | Continuous Integration and Deployment | DevOps...
 
Introduction to Selenium Web Driver
Introduction to Selenium Web DriverIntroduction to Selenium Web Driver
Introduction to Selenium Web Driver
 
Cypress testing
Cypress testingCypress testing
Cypress testing
 
Introduction to CICD
Introduction to CICDIntroduction to CICD
Introduction to CICD
 
Cypress for Testing
Cypress for TestingCypress for Testing
Cypress for Testing
 

Similar to Playwright: A New Test Automation Framework for the Modern Web

Build and Deploy a Python Web App to Amazon in 30 Mins
Build and Deploy a Python Web App to Amazon in 30 MinsBuild and Deploy a Python Web App to Amazon in 30 Mins
Build and Deploy a Python Web App to Amazon in 30 MinsJeff Hull
 
Engage 2022: The Superpower of Integrating External APIs for Notes and Domino...
Engage 2022: The Superpower of Integrating External APIs for Notes and Domino...Engage 2022: The Superpower of Integrating External APIs for Notes and Domino...
Engage 2022: The Superpower of Integrating External APIs for Notes and Domino...Serdar Basegmez
 
You Can Work on the Web Patform! (GOSIM 2023)
You Can Work on the Web Patform! (GOSIM 2023)You Can Work on the Web Patform! (GOSIM 2023)
You Can Work on the Web Patform! (GOSIM 2023)Igalia
 
playwrightmeetup-14jan2021-210114173639.pdf
playwrightmeetup-14jan2021-210114173639.pdfplaywrightmeetup-14jan2021-210114173639.pdf
playwrightmeetup-14jan2021-210114173639.pdfManjuBiradar6
 
AWS Community Day 2022 Angelo Mandato_First Lambda function using VSCode - C...
AWS Community Day 2022  Angelo Mandato_First Lambda function using VSCode - C...AWS Community Day 2022  Angelo Mandato_First Lambda function using VSCode - C...
AWS Community Day 2022 Angelo Mandato_First Lambda function using VSCode - C...AWS Chicago
 
Hacking the browser with puppeteer sharp .NET conf AR 2018
Hacking the browser with puppeteer sharp .NET conf AR 2018Hacking the browser with puppeteer sharp .NET conf AR 2018
Hacking the browser with puppeteer sharp .NET conf AR 2018Darío Kondratiuk
 
Scraping the web with Laravel, Dusk, Docker, and PHP
Scraping the web with Laravel, Dusk, Docker, and PHPScraping the web with Laravel, Dusk, Docker, and PHP
Scraping the web with Laravel, Dusk, Docker, and PHPPaul Redmond
 
Google I/O 2012 - Protecting your user experience while integrating 3rd party...
Google I/O 2012 - Protecting your user experience while integrating 3rd party...Google I/O 2012 - Protecting your user experience while integrating 3rd party...
Google I/O 2012 - Protecting your user experience while integrating 3rd party...Patrick Meenan
 
Behat Workshop at WeLovePHP
Behat Workshop at WeLovePHPBehat Workshop at WeLovePHP
Behat Workshop at WeLovePHPMarcos Quesada
 
Building Kick Ass Video Games for the Cloud
Building Kick Ass Video Games for the CloudBuilding Kick Ass Video Games for the Cloud
Building Kick Ass Video Games for the CloudChris Schalk
 
Debugging Web Apps on Real Mobile Devices
Debugging Web Apps on Real Mobile DevicesDebugging Web Apps on Real Mobile Devices
Debugging Web Apps on Real Mobile DevicesDale Lane
 
Yet Another Continuous Integration Story
Yet Another Continuous Integration StoryYet Another Continuous Integration Story
Yet Another Continuous Integration StoryAnton Serdyuk
 
iPhone Development For Experienced Web Developers
iPhone Development For Experienced Web DevelopersiPhone Development For Experienced Web Developers
iPhone Development For Experienced Web Developerslisab517
 
Creating a Responsive Website From Scratch
Creating a Responsive Website From ScratchCreating a Responsive Website From Scratch
Creating a Responsive Website From ScratchCorky Brown
 
Introducing chrome apps (ogura)
Introducing chrome apps (ogura)Introducing chrome apps (ogura)
Introducing chrome apps (ogura)Kazuhiro Ogura
 
08 - Data Fetch (Monica).pptx
08 - Data Fetch (Monica).pptx08 - Data Fetch (Monica).pptx
08 - Data Fetch (Monica).pptxAliDaanish1
 
JS Fest 2019. Minko Gechev. Building Fast Angular Applications by Default
JS Fest 2019. Minko Gechev. Building Fast Angular Applications by DefaultJS Fest 2019. Minko Gechev. Building Fast Angular Applications by Default
JS Fest 2019. Minko Gechev. Building Fast Angular Applications by DefaultJSFestUA
 
Modern Web 2016: Using Golang to build a smart IM Bot
Modern Web 2016: Using Golang to build a smart IM Bot Modern Web 2016: Using Golang to build a smart IM Bot
Modern Web 2016: Using Golang to build a smart IM Bot Evan Lin
 

Similar to Playwright: A New Test Automation Framework for the Modern Web (20)

Build and Deploy a Python Web App to Amazon in 30 Mins
Build and Deploy a Python Web App to Amazon in 30 MinsBuild and Deploy a Python Web App to Amazon in 30 Mins
Build and Deploy a Python Web App to Amazon in 30 Mins
 
Engage 2022: The Superpower of Integrating External APIs for Notes and Domino...
Engage 2022: The Superpower of Integrating External APIs for Notes and Domino...Engage 2022: The Superpower of Integrating External APIs for Notes and Domino...
Engage 2022: The Superpower of Integrating External APIs for Notes and Domino...
 
You Can Work on the Web Patform! (GOSIM 2023)
You Can Work on the Web Patform! (GOSIM 2023)You Can Work on the Web Patform! (GOSIM 2023)
You Can Work on the Web Patform! (GOSIM 2023)
 
playwrightmeetup-14jan2021-210114173639.pdf
playwrightmeetup-14jan2021-210114173639.pdfplaywrightmeetup-14jan2021-210114173639.pdf
playwrightmeetup-14jan2021-210114173639.pdf
 
AWS Community Day 2022 Angelo Mandato_First Lambda function using VSCode - C...
AWS Community Day 2022  Angelo Mandato_First Lambda function using VSCode - C...AWS Community Day 2022  Angelo Mandato_First Lambda function using VSCode - C...
AWS Community Day 2022 Angelo Mandato_First Lambda function using VSCode - C...
 
Building a Slack Bot Workshop @ Nearsoft OctoberTalks 2017
Building a Slack Bot Workshop @ Nearsoft OctoberTalks 2017Building a Slack Bot Workshop @ Nearsoft OctoberTalks 2017
Building a Slack Bot Workshop @ Nearsoft OctoberTalks 2017
 
Hacking the browser with puppeteer sharp .NET conf AR 2018
Hacking the browser with puppeteer sharp .NET conf AR 2018Hacking the browser with puppeteer sharp .NET conf AR 2018
Hacking the browser with puppeteer sharp .NET conf AR 2018
 
Scraping the web with Laravel, Dusk, Docker, and PHP
Scraping the web with Laravel, Dusk, Docker, and PHPScraping the web with Laravel, Dusk, Docker, and PHP
Scraping the web with Laravel, Dusk, Docker, and PHP
 
Google I/O 2012 - Protecting your user experience while integrating 3rd party...
Google I/O 2012 - Protecting your user experience while integrating 3rd party...Google I/O 2012 - Protecting your user experience while integrating 3rd party...
Google I/O 2012 - Protecting your user experience while integrating 3rd party...
 
Behat Workshop at WeLovePHP
Behat Workshop at WeLovePHPBehat Workshop at WeLovePHP
Behat Workshop at WeLovePHP
 
Building Kick Ass Video Games for the Cloud
Building Kick Ass Video Games for the CloudBuilding Kick Ass Video Games for the Cloud
Building Kick Ass Video Games for the Cloud
 
Debugging Web Apps on Real Mobile Devices
Debugging Web Apps on Real Mobile DevicesDebugging Web Apps on Real Mobile Devices
Debugging Web Apps on Real Mobile Devices
 
Yet Another Continuous Integration Story
Yet Another Continuous Integration StoryYet Another Continuous Integration Story
Yet Another Continuous Integration Story
 
iPhone Development For Experienced Web Developers
iPhone Development For Experienced Web DevelopersiPhone Development For Experienced Web Developers
iPhone Development For Experienced Web Developers
 
Creating a Responsive Website From Scratch
Creating a Responsive Website From ScratchCreating a Responsive Website From Scratch
Creating a Responsive Website From Scratch
 
Introducing chrome apps (ogura)
Introducing chrome apps (ogura)Introducing chrome apps (ogura)
Introducing chrome apps (ogura)
 
08 - Data Fetch (Monica).pptx
08 - Data Fetch (Monica).pptx08 - Data Fetch (Monica).pptx
08 - Data Fetch (Monica).pptx
 
JS Fest 2019. Minko Gechev. Building Fast Angular Applications by Default
JS Fest 2019. Minko Gechev. Building Fast Angular Applications by DefaultJS Fest 2019. Minko Gechev. Building Fast Angular Applications by Default
JS Fest 2019. Minko Gechev. Building Fast Angular Applications by Default
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
Modern Web 2016: Using Golang to build a smart IM Bot
Modern Web 2016: Using Golang to build a smart IM Bot Modern Web 2016: Using Golang to build a smart IM Bot
Modern Web 2016: Using Golang to build a smart IM Bot
 

More from Applitools

Leveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + KobitonLeveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + KobitonApplitools
 
Streamlining Your Tech Stack: A Blueprint for Enhanced Efficiency and Coverag...
Streamlining Your Tech Stack: A Blueprint for Enhanced Efficiency and Coverag...Streamlining Your Tech Stack: A Blueprint for Enhanced Efficiency and Coverag...
Streamlining Your Tech Stack: A Blueprint for Enhanced Efficiency and Coverag...Applitools
 
Visual AI for eCommerce: Improving Conversions with a Flawless UI
Visual AI for eCommerce: Improving Conversions with a Flawless UIVisual AI for eCommerce: Improving Conversions with a Flawless UI
Visual AI for eCommerce: Improving Conversions with a Flawless UIApplitools
 
A Test Automation Platform Designed for the Future
A Test Automation Platform Designed for the FutureA Test Automation Platform Designed for the Future
A Test Automation Platform Designed for the FutureApplitools
 
Add AI to Your SDLC, presented by Applitools and Curiosity
Add AI to Your SDLC, presented by Applitools and CuriosityAdd AI to Your SDLC, presented by Applitools and Curiosity
Add AI to Your SDLC, presented by Applitools and CuriosityApplitools
 
The Future of AI-Based Test Automation
The Future of AI-Based Test AutomationThe Future of AI-Based Test Automation
The Future of AI-Based Test AutomationApplitools
 
Test Automation at Scale: Lessons from Top-Performing Distributed Teams
Test Automation at Scale: Lessons from Top-Performing Distributed TeamsTest Automation at Scale: Lessons from Top-Performing Distributed Teams
Test Automation at Scale: Lessons from Top-Performing Distributed TeamsApplitools
 
Can AI Autogenerate and Run Automated Tests?
Can AI Autogenerate and Run Automated Tests?Can AI Autogenerate and Run Automated Tests?
Can AI Autogenerate and Run Automated Tests?Applitools
 
Triple Assurance: AI-Powered Test Automation in UI Design and Functionality
Triple Assurance: AI-Powered Test Automation in UI Design and FunctionalityTriple Assurance: AI-Powered Test Automation in UI Design and Functionality
Triple Assurance: AI-Powered Test Automation in UI Design and FunctionalityApplitools
 
Navigating the Challenges of Testing at Scale: Lessons from Top-Performing Teams
Navigating the Challenges of Testing at Scale: Lessons from Top-Performing TeamsNavigating the Challenges of Testing at Scale: Lessons from Top-Performing Teams
Navigating the Challenges of Testing at Scale: Lessons from Top-Performing TeamsApplitools
 
Introducing the Applitools Self Healing Execution Cloud.pdf
Introducing the Applitools Self Healing Execution Cloud.pdfIntroducing the Applitools Self Healing Execution Cloud.pdf
Introducing the Applitools Self Healing Execution Cloud.pdfApplitools
 
Unlocking the Power of ChatGPT and AI in Testing - NextSteps, presented by Ap...
Unlocking the Power of ChatGPT and AI in Testing - NextSteps, presented by Ap...Unlocking the Power of ChatGPT and AI in Testing - NextSteps, presented by Ap...
Unlocking the Power of ChatGPT and AI in Testing - NextSteps, presented by Ap...Applitools
 
Collaborating From Design To Experience: Introducing Centra
Collaborating From Design To Experience: Introducing CentraCollaborating From Design To Experience: Introducing Centra
Collaborating From Design To Experience: Introducing CentraApplitools
 
What the QA Position Will Look Like in the Future
What the QA Position Will Look Like in the FutureWhat the QA Position Will Look Like in the Future
What the QA Position Will Look Like in the FutureApplitools
 
Getting Started with Visual Testing
Getting Started with Visual TestingGetting Started with Visual Testing
Getting Started with Visual TestingApplitools
 
Workshop: Head-to-Head Web Testing: Part 1 with Cypress
Workshop: Head-to-Head Web Testing: Part 1 with CypressWorkshop: Head-to-Head Web Testing: Part 1 with Cypress
Workshop: Head-to-Head Web Testing: Part 1 with CypressApplitools
 
From Washing Cars To Automating Test Applications
From Washing Cars To Automating Test ApplicationsFrom Washing Cars To Automating Test Applications
From Washing Cars To Automating Test ApplicationsApplitools
 
A Holistic Approach to Testing in Continuous Delivery
A Holistic Approach to Testing in Continuous DeliveryA Holistic Approach to Testing in Continuous Delivery
A Holistic Approach to Testing in Continuous DeliveryApplitools
 
AI-Powered-Cross-Browser Testing
AI-Powered-Cross-Browser TestingAI-Powered-Cross-Browser Testing
AI-Powered-Cross-Browser TestingApplitools
 
Workshop: An Introduction to API Automation with Javascript
Workshop: An Introduction to API Automation with JavascriptWorkshop: An Introduction to API Automation with Javascript
Workshop: An Introduction to API Automation with JavascriptApplitools
 

More from Applitools (20)

Leveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + KobitonLeveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
 
Streamlining Your Tech Stack: A Blueprint for Enhanced Efficiency and Coverag...
Streamlining Your Tech Stack: A Blueprint for Enhanced Efficiency and Coverag...Streamlining Your Tech Stack: A Blueprint for Enhanced Efficiency and Coverag...
Streamlining Your Tech Stack: A Blueprint for Enhanced Efficiency and Coverag...
 
Visual AI for eCommerce: Improving Conversions with a Flawless UI
Visual AI for eCommerce: Improving Conversions with a Flawless UIVisual AI for eCommerce: Improving Conversions with a Flawless UI
Visual AI for eCommerce: Improving Conversions with a Flawless UI
 
A Test Automation Platform Designed for the Future
A Test Automation Platform Designed for the FutureA Test Automation Platform Designed for the Future
A Test Automation Platform Designed for the Future
 
Add AI to Your SDLC, presented by Applitools and Curiosity
Add AI to Your SDLC, presented by Applitools and CuriosityAdd AI to Your SDLC, presented by Applitools and Curiosity
Add AI to Your SDLC, presented by Applitools and Curiosity
 
The Future of AI-Based Test Automation
The Future of AI-Based Test AutomationThe Future of AI-Based Test Automation
The Future of AI-Based Test Automation
 
Test Automation at Scale: Lessons from Top-Performing Distributed Teams
Test Automation at Scale: Lessons from Top-Performing Distributed TeamsTest Automation at Scale: Lessons from Top-Performing Distributed Teams
Test Automation at Scale: Lessons from Top-Performing Distributed Teams
 
Can AI Autogenerate and Run Automated Tests?
Can AI Autogenerate and Run Automated Tests?Can AI Autogenerate and Run Automated Tests?
Can AI Autogenerate and Run Automated Tests?
 
Triple Assurance: AI-Powered Test Automation in UI Design and Functionality
Triple Assurance: AI-Powered Test Automation in UI Design and FunctionalityTriple Assurance: AI-Powered Test Automation in UI Design and Functionality
Triple Assurance: AI-Powered Test Automation in UI Design and Functionality
 
Navigating the Challenges of Testing at Scale: Lessons from Top-Performing Teams
Navigating the Challenges of Testing at Scale: Lessons from Top-Performing TeamsNavigating the Challenges of Testing at Scale: Lessons from Top-Performing Teams
Navigating the Challenges of Testing at Scale: Lessons from Top-Performing Teams
 
Introducing the Applitools Self Healing Execution Cloud.pdf
Introducing the Applitools Self Healing Execution Cloud.pdfIntroducing the Applitools Self Healing Execution Cloud.pdf
Introducing the Applitools Self Healing Execution Cloud.pdf
 
Unlocking the Power of ChatGPT and AI in Testing - NextSteps, presented by Ap...
Unlocking the Power of ChatGPT and AI in Testing - NextSteps, presented by Ap...Unlocking the Power of ChatGPT and AI in Testing - NextSteps, presented by Ap...
Unlocking the Power of ChatGPT and AI in Testing - NextSteps, presented by Ap...
 
Collaborating From Design To Experience: Introducing Centra
Collaborating From Design To Experience: Introducing CentraCollaborating From Design To Experience: Introducing Centra
Collaborating From Design To Experience: Introducing Centra
 
What the QA Position Will Look Like in the Future
What the QA Position Will Look Like in the FutureWhat the QA Position Will Look Like in the Future
What the QA Position Will Look Like in the Future
 
Getting Started with Visual Testing
Getting Started with Visual TestingGetting Started with Visual Testing
Getting Started with Visual Testing
 
Workshop: Head-to-Head Web Testing: Part 1 with Cypress
Workshop: Head-to-Head Web Testing: Part 1 with CypressWorkshop: Head-to-Head Web Testing: Part 1 with Cypress
Workshop: Head-to-Head Web Testing: Part 1 with Cypress
 
From Washing Cars To Automating Test Applications
From Washing Cars To Automating Test ApplicationsFrom Washing Cars To Automating Test Applications
From Washing Cars To Automating Test Applications
 
A Holistic Approach to Testing in Continuous Delivery
A Holistic Approach to Testing in Continuous DeliveryA Holistic Approach to Testing in Continuous Delivery
A Holistic Approach to Testing in Continuous Delivery
 
AI-Powered-Cross-Browser Testing
AI-Powered-Cross-Browser TestingAI-Powered-Cross-Browser Testing
AI-Powered-Cross-Browser Testing
 
Workshop: An Introduction to API Automation with Javascript
Workshop: An Introduction to API Automation with JavascriptWorkshop: An Introduction to API Automation with Javascript
Workshop: An Introduction to API Automation with Javascript
 

Recently uploaded

%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrandmasabamasaba
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrainmasabamasaba
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfproinshot.com
 
SHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationSHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationShrmpro
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Hararemasabamasaba
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...masabamasaba
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdfPearlKirahMaeRagusta1
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfayushiqss
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionOnePlan Solutions
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...masabamasaba
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durbanmasabamasaba
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesVictorSzoltysek
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 

Recently uploaded (20)

%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
SHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationSHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions Presentation
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 

Playwright: A New Test Automation Framework for the Modern Web

  • 3. ● 2009-2019 WebKit Web Inspector Chrome Developer Tools Who We Are
  • 4. ● 2009-2019 WebKit Web Inspector Chrome Developer Tools Who We Are
  • 5. ● 2009-2019 WebKit Web Inspector Chrome Developer Tools Who We Are
  • 6. ● 2009-2019 WebKit Web Inspector Chrome Developer Tools ● 2011-... Chrome DevTools Protocol Who We Are
  • 7. ● 2009-2019 WebKit Web Inspector Chrome Developer Tools ● 2011-... Chrome DevTools Protocol ● 2015-2016 Node.js Debugger Who We Are
  • 8. ● 2009-2019 WebKit Web Inspector Chrome Developer Tools ● 2011-... Chrome DevTools Protocol ● 2015-2016 Node.js Debugger ● 2017-2019 Puppeteer Who We Are
  • 9. ● 2009-2019 WebKit Web Inspector Chrome Developer Tools ● 2011-... Chrome DevTools Protocol ● 2015-2016 Node.js Debugger ● 2017-2019 Puppeteer Who We Are
  • 10. ● 2009-2019 WebKit Web Inspector Chrome Developer Tools ● 2011-... Chrome DevTools Protocol ● 2015-2016 Node.js Debugger ● 2017-2019 Puppeteer ● 2019-... Playwright Who We Are
  • 13. import {chromium, firefox, webkit} from 'playwright'; for (const browserType of [chromium, firefox, webkit]) { const browser = await browserType.launch(); const page = await browser.newPage(); await page.goto('https://playwright.dev'); await page.screenshot({path: `image-${browserType.name()}.png`}); await browser.close(); }
  • 14. import {chromium, firefox, webkit} from 'playwright'; for (const browserType of [chromium, firefox, webkit]) { const browser = await browserType.launch(); const page = await browser.newPage(); await page.goto('https://playwright.dev'); await page.screenshot({path: `image-${browserType.name()}.png`}); await browser.close(); } J a v a S c r i p t
  • 15. from playwright.sync_api import sync_playwright with sync_playwright() as p: for browser_type in [p.chromium, p.firefox, p.webkit]: browser = browser_type.launch() page = browser.new_page() page.goto("https://playwright.dev") page.screenshot(path="image-" + browser_type.name + ".png") browser.close() P y t h o n
  • 16. public static void main(String[] args) { try (Playwright playwright = Playwright.create()) { List<BrowserType> browserTypes = Arrays.asList( playwright.chromium(), playwright.webkit(), playwright.firefox() ); for (BrowserType browserType : browserTypes) { try (Browser browser = browserType.launch()) { Page page = browser.newPage(); page.navigate("http://playwright.dev"); page.screenshot(new Page.ScreenshotOptions() .setPath(Paths.get("image-" + browserType.name() + ".png"))); } } } } J a v a
  • 18. Playwright: ✅ dependable ✅ efficient ✅ capable ✅ ubiquitous ✅ delightful ✅ lively
  • 20. Dependable 👌 We Triage Issues in <48 hours 📚 We Fix Issues (>1600 fixed) ✈ We Take Full Responsibility github.com/microsoft/playwright
  • 23. Level 1: Browser Engineering C++
  • 24. - Chromium Development - Improving Chrome DevTools Protocol - Google Chrome, Microsoft Edge, Opera, etc Level 1: Browser Engineering C++
  • 25. - Chromium Development - Improving Chrome DevTools Protocol - Google Chrome, Microsoft Edge, Opera, etc - WebKit Development - Improving Web Inspector Protocol - Safari, Mobile Safari, Epiphany, etc Level 1: Browser Engineering C++
  • 26. - Chromium Development - Improving Chrome DevTools Protocol - Google Chrome, Microsoft Edge, Opera, etc - WebKit Development - Improving Web Inspector Protocol - Safari, Mobile Safari, Epiphany, etc - Firefox Development - Improving “Juggler” Protocol - Mozilla Firefox Level 1: Browser Engineering C++
  • 27. - Chromium Development - Improving Chrome DevTools Protocol - Google Chrome, Microsoft Edge, Opera, etc - WebKit Development - Improving Web Inspector Protocol - Safari, Mobile Safari, Epiphany, etc - Firefox Development - Improving “Juggler” Protocol - Mozilla Firefox Level 1: Browser Engineering C++
  • 28. Level 2: Playwright Driver Level 1: Browser Engineering C++
  • 29. TypeScript - Single web automation protocol - Unify all remote debugging protocols - Expose “Downloads API” in driver Level 2: Playwright Driver 🎭 Playwright Driver Level 1: Browser Engineering C++
  • 30. TypeScript Level 3: Language Bindings 🎭 Playwright Driver Level 1: Browser Engineering C++ Level 2: Playwright Driver
  • 31. TypeScript Level 3: Language Bindings 🎭 Playwright Driver Level 1: Browser Engineering C++ Level 2: Playwright Driver Playwright Playwright for Java Playwright for Python Playwright for C# Expose language idiomatic API to control downloads
  • 32. TypeScript Level 3: Language Bindings 🎭 Playwright Driver Level 1: Browser Engineering C++ Level 2: Playwright Driver Playwright Playwright for Java Playwright for Python Playwright for C# Expose language idiomatic API to control downloads
  • 33. TypeScript Level 3: Language Bindings 🎭 Playwright Driver Level 1: Browser Engineering C++ Level 2: Playwright Driver Playwright Playwright for Java Playwright for Python Playwright for C# Expose language idiomatic API to control downloads
  • 34. TypeScript Being Dependable 🎭 Playwright Driver C++ Playwright Playwright for Java Playwright for Python Playwright for C# Cross-Browser Testing Tool ● 👀 8 teams from multiple companies ● 🐌 Slow feedback loop (months / years) Playwright ● 💫 1 team from a single company ● 🐆 Fast feedback loop (days / weeks)
  • 35. More Like This ● Downloads API ● Screencast API ● Drag & Drop API ● Clipboard API ● Browser-Level cookies ● Browser Contexts ● Per-context HTTP proxy ● ...
  • 36. Summary: Playwright is Dependable 👌 We Triage Issues in <48 hours 📚 We Fix Issues (>1600 fixed) ✈ We Take Full Responsibility
  • 39. Automation Costs ● Throughput = spend less CPU cycles ● Latency = run tests fast ● Flakiness = reliable runs
  • 40. Playwright Being Efficient ● Trick 1: Browser Contexts ● Trick 2: Auto-waiting
  • 41. Trick 1: Browser Contexts ❌ Never Restart a Browser ● Slow instantiation (>100ms) ● Huge memory overhead ✅ Always create Browser Contexts ● Full isolation ● Fast instantiation (~1ms) ● Low overhead Browser Context
  • 42. Trick 1: Browser Contexts Context 1
  • 43. Trick 1: Browser Contexts Context 1 Context 2
  • 44. Trick 1: Browser Contexts Context 1 Context 2
  • 45. import {webkit, chromium, firefox} from 'playwright'; const browser = await chromium.launch(); for (let i = 0; i < 10; ++i) { // Fast, simple, configurable! const context = await browser.newContext() const page = await context.newPage(); await page.goto('https://playwright.dev'); await context.close(); }
  • 46. import {webkit, chromium, firefox} from 'playwright'; const browser = await chromium.launch(); for (let i = 0; i < 10; ++i) { // Fast, simple, configurable! const context = await browser.newContext() const page = await context.newPage(); await page.goto('https://playwright.dev'); await context.close(); }
  • 47. import {webkit, chromium, firefox} from 'playwright'; const browser = await chromium.launch(); for (let i = 0; i < 10; ++i) { // Fast, simple, configurable! const context = await browser.newContext() const page = await context.newPage(); await page.goto('https://playwright.dev'); await context.close(); }
  • 48. Form Filling: No Autowait
  • 49. Form Filling: No Autowait e-mail..
  • 50. Form Filling: No Autowait e-mail..
  • 51. Form Filling: No Autowait e-mail..
  • 52. Form Filling: No Autowait passwd...
  • 53. Form Filling: No Autowait passwd...
  • 54. Form Filling: No Autowait passwd...
  • 55. Form Filling: No Autowait submitting...
  • 56. Form Filling: No Autowait submitting...
  • 57. Form Filling: No Autowait MISSED
  • 58. Form Filling: No Autowait MISSED Disabled button!
  • 59. await page.goto('https://form.example.com'); // Shall we wait for fields to be enabled?.. await page.fill('#email', 'aslushnikov@gmail.com'); await page.fill('#password', 'mypassword'); // Wait for button to get enabled and click submit setTimeout(async () => { await page.click('#submit'); }, 1000); N o n - P l a y w r i g h t P s e u d o - C o d e
  • 60. await page.goto('https://form.example.com'); // Shall we wait for fields to be enabled?.. await page.fill('#email', 'aslushnikov@gmail.com'); await page.fill('#password', 'mypassword'); // Wait for button to get enabled and click submit setTimeout(async () => { await page.click('#submit'); }, 1000); N o n - P l a y w r i g h t P s e u d o - C o d e
  • 61. await page.goto('https://form.example.com'); // Shall we wait for fields to be enabled?.. await page.fill('#email', 'aslushnikov@gmail.com'); await page.fill('#password', 'mypassword'); // Wait for button to get enabled and click submit setTimeout(async () => { await page.click('#submit'); }, 1000); N o n - P l a y w r i g h t P s e u d o - C o d e Time Does Not Exist in the Cloud!
  • 62. Trick 2: Auto-waiting ✨ Auto-Waiting..
  • 63. Trick 2: Auto-waiting ✨ Successful! Enabled!
  • 66. // ✨ Playwright auto-waiting by default! await page.goto('https://form.example.com'); await page.fill('#email', 'aslushnikov@gmail.com'); await page.fill('#password', 'mypassword'); await page.click('#submit'); P l a y w r i g h t
  • 67. // ✨ Playwright auto-waiting by default! await page.goto('https://form.example.com'); await page.fill('#email', 'aslushnikov@gmail.com'); await page.fill('#password', 'mypassword'); await page.click('#submit'); P l a y w r i g h t
  • 68. // ✨ Playwright auto-waiting by default! await page.goto('https://form.example.com'); await page.fill('#email', 'aslushnikov@gmail.com'); await page.fill('#password', 'mypassword'); await page.click('#submit'); P l a y w r i g h t
  • 69. // ✨ Playwright auto-waiting by default! await page.goto('https://form.example.com'); await page.fill('#email', 'aslushnikov@gmail.com'); await page.fill('#password', 'mypassword'); await page.click('#submit'); P l a y w r i g h t
  • 77. Summary: Playwright is Efficient ● Trick 1: Browser Contexts ● Trick 2: Auto-waiting
  • 79. import {webkit, devices} from 'playwright'; const browser = await webkit.launch(); const context = await browser.newContext({ ...devices['iPhone 12 Pro'], }); const page = await context.newPage(); await page.goto('https://playwright.dev'); await browser.close(); 📱 D e v i c e E m u l a t i o n
  • 80. import {webkit, devices} from 'playwright'; const browser = await webkit.launch(); const context = await browser.newContext({ ...devices['iPhone 12 Pro'], }); const page = await context.newPage(); await page.goto('https://playwright.dev'); await browser.close(); 📱 D e v i c e E m u l a t i o n
  • 81. import {webkit, devices} from 'playwright'; const browser = await webkit.launch(); const context = await browser.newContext({ ...devices['iPhone 12 Pro'], }); const page = await context.newPage(); await page.goto('https://playwright.dev'); await browser.close(); 📱 D e v i c e E m u l a t i o n
  • 82. import {chromium, firefox, webkit} from 'playwright'; const browser = await firefox.launch(); const context = await browser.newContext({ geolocation: { longitude: 48.858455, latitude: 2.294474 }, permissions: ['geolocation'] }); const page = await context.newPage(); await page.goto('https://playwright.dev'); await context.setGeolocation({ longitude: 29.97, latitude: 31.13 }); G e o l o c a t i o n & P e r m i s s i o n s
  • 83. import {chromium, firefox, webkit} from 'playwright'; const browser = await firefox.launch(); const context = await browser.newContext({ geolocation: { longitude: 48.858455, latitude: 2.294474 }, permissions: ['geolocation'] }); const page = await context.newPage(); await page.goto('https://playwright.dev'); await context.setGeolocation({ longitude: 29.97, latitude: 31.13 }); G e o l o c a t i o n & P e r m i s s i o n s
  • 84. import {chromium, firefox, webkit} from 'playwright'; const browser = await firefox.launch(); const context = await browser.newContext({ geolocation: { longitude: 48.858455, latitude: 2.294474 }, permissions: ['geolocation'] }); const page = await context.newPage(); await page.goto('https://playwright.dev'); await context.setGeolocation({ longitude: 29.97, latitude: 31.13 }); G e o l o c a t i o n & P e r m i s s i o n s
  • 85. import {chromium, firefox, webkit} from 'playwright'; const browser = await firefox.launch(); const context = await browser.newContext({ geolocation: { longitude: 48.858455, latitude: 2.294474 }, permissions: ['geolocation'] }); const page = await context.newPage(); await page.goto('https://playwright.dev'); await context.setGeolocation({ longitude: 29.97, latitude: 31.13 }); G e o l o c a t i o n & P e r m i s s i o n s
  • 86. import {webkit, chromium, firefox} from 'playwright'; const browser = await chromium.launch(); const context = await browser.newContext({ recordVideo: { dir: 'videos/', size: { width: 800, height: 600 }, }, }); const page = await context.newPage(); await page.goto('https://playwright.dev'); await page.close(); 🎥 V i d e o s
  • 87. import {webkit, chromium, firefox} from 'playwright'; const browser = await chromium.launch(); const context = await browser.newContext({ recordVideo: { dir: 'videos/', size: { width: 800, height: 600 }, }, }); const page = await context.newPage(); await page.goto('https://playwright.dev'); await page.close(); 🎥 V i d e o s
  • 88. import {webkit, chromium, firefox} from 'playwright'; const browser = await chromium.launch(); const context = await browser.newContext({ recordVideo: { dir: 'videos/', size: { width: 800, height: 600 }, }, }); const page = await context.newPage(); await page.goto('https://playwright.dev'); await page.close(); 🎥 V i d e o s
  • 89. import {webkit, chromium, firefox} from 'playwright'; const browser = await webkit.launch(); const page = await browser.newPage(); page.on('request', r => console.log(r.method(), r.url())); page.on('websocket', ws => console.log(ws.url())); await page.goto('https://playwright.dev'); await browser.close(); 🌎 N e t w o r k & W e b S o c k e t s
  • 90. import {webkit, chromium, firefox} from 'playwright'; const browser = await webkit.launch(); const page = await browser.newPage(); page.on('request', r => console.log(r.method(), r.url())); page.on('websocket', ws => console.log(ws.url())); await page.goto('https://playwright.dev'); await browser.close(); 🌎 N e t w o r k & W e b S o c k e t s
  • 91. import {webkit, chromium, firefox} from 'playwright'; const browser = await firefox.launch(); const page = await browser.newPage(); await page.route('**/*.{png,jpg,jpeg}', route => route.abort()); await page.goto('https://playwright.dev'); await browser.close(); P a g e R e q u e s t I n t e r c e p t i o n
  • 92. import {webkit, chromium, firefox} from 'playwright'; const browser = await firefox.launch(); const context = await browser.newContext(); await context.route('**/*.{png,jpg,jpeg}', route => route.abort()); const page = await page.newPage(); await page.goto('https://playwright.dev'); await browser.close(); C o n t e x t R e q u e s t I n t e r c e p t i o n
  • 93. import {webkit, chromium, firefox} from 'playwright'; const browser = await webkit.launch(); const page = await browser.newPage(); await page.goto('https://playwright.dev'); const [ download ] = await Promise.all([ page.waitForEvent('download'), page.click('button#delayed-download') ]); console.log(await download.path()); await browser.close(); D o w n l o a d s
  • 94. import {webkit, chromium, firefox} from 'playwright'; const browser = await chromium.launch(); const page = await browser.newPage(); await page.goto('https://playwright.dev'); await page.click('button'); // CSS selector await page.click('xpath=//button'); // XPath selector await page.click('text=Log in'); // Text selector await page.click(':nth-match(:text("Buy"), 3)'); // N-th match await page.click('div:right-of(:text("Name"))'); // Layout 😱 await page.click(`xpath=//form >> text=Submit`); // Composite S m a r t S e l e c t o r s
  • 95. import {webkit, chromium, firefox} from 'playwright'; const browser = await chromium.launch(); const page = await browser.newPage(); await page.goto('https://playwright.dev'); await page.click('button'); // CSS selector await page.click('xpath=//button'); // XPath selector await page.click('text=Log in'); // Text selector await page.click(':nth-match(:text("Buy"), 3)'); // N-th match await page.click('div:right-of(:text("Name"))'); // Layout 😱 await page.click(`xpath=//form >> text=Submit`); // Composite S m a r t S e l e c t o r s
  • 96. import {webkit, chromium, firefox} from 'playwright'; const browser = await chromium.launch(); const page = await browser.newPage(); await page.goto('https://playwright.dev'); await page.click('button'); // CSS selector await page.click('xpath=//button'); // XPath selector await page.click('text=Log in'); // Text selector await page.click(':nth-match(:text("Buy"), 3)'); // N-th match await page.click('div:right-of(:text("Name"))'); // Layout 😱 await page.click(`xpath=//form >> text=Submit`); // Composite S m a r t S e l e c t o r s
  • 97. import {webkit, chromium, firefox} from 'playwright'; const browser = await chromium.launch(); const page = await browser.newPage(); await page.goto('https://playwright.dev'); await page.click('button'); // CSS selector await page.click('xpath=//button'); // XPath selector await page.click('text=Log in'); // Text selector await page.click(':nth-match(:text("Buy"), 3)'); // N-th match await page.click('div:right-of(:text("Name"))'); // Layout 😱 await page.click(`xpath=//form >> text=Submit`); // Composite S m a r t S e l e c t o r s
  • 98. import {webkit, chromium, firefox} from 'playwright'; const browser = await chromium.launch(); const page = await browser.newPage(); await page.goto('https://playwright.dev'); await page.click('button'); // CSS selector await page.click('xpath=//button'); // XPath selector await page.click('text=Log in'); // Text selector await page.click(':nth-match(:text("Buy"), 3)'); // N-th match await page.click('div:right-of(:text("Name"))'); // Layout 😱 await page.click(`xpath=//form >> text=Submit`); // Composite S m a r t S e l e c t o r s
  • 99. import {webkit, chromium, firefox} from 'playwright'; const browser = await chromium.launch(); const page = await browser.newPage(); await page.goto('https://playwright.dev'); await page.click('button'); // CSS selector await page.click('xpath=//button'); // XPath selector await page.click('text=Log in'); // Text selector await page.click(':nth-match(:text("Buy"), 3)'); // N-th match await page.click('div:right-of(:text("Name"))'); // Layout 😱 await page.click(`xpath=//form >> text=Submit`); // Composite S m a r t S e l e c t o r s
  • 100. import {webkit, chromium, firefox} from 'playwright'; const browser = await chromium.launch(); const page = await browser.newPage(); await page.goto('https://playwright.dev'); await page.click('button'); // CSS selector await page.click('xpath=//button'); // XPath selector await page.click('text=Log in'); // Text selector await page.click(':nth-match(:text("Buy"), 3)'); // N-th match await page.click('div:right-of(:text("Name"))'); // Layout 😱 await page.click(`xpath=//form >> text=Submit`); // Composite S m a r t S e l e c t o r s
  • 101. // text content const content = await page.textContent('nav:first-child'); expect(content).toBe('home'); // Attributes const alt = await page.getAttribute('input', 'alt'); expect(alt).toBe('Text'); // Checkbox state const checked = await page.isChecked('input'); expect(checked).toBeTruthy(); // Visibility const visible = await page.isVisible('input'); expect(visible).toBeTruthy(); A s s e r t i o n s
  • 102. // text content const content = await page.textContent('nav:first-child'); expect(content).toBe('home'); // Attributes const alt = await page.getAttribute('input', 'alt'); expect(alt).toBe('Text'); // Checkbox state const checked = await page.isChecked('input'); expect(checked).toBeTruthy(); // Visibility const visible = await page.isVisible('input'); expect(visible).toBeTruthy(); A s s e r t i o n s
  • 103. // text content const content = await page.textContent('nav:first-child'); expect(content).toBe('home'); // Attributes const alt = await page.getAttribute('input', 'alt'); expect(alt).toBe('Text'); // Checkbox state const checked = await page.isChecked('input'); expect(checked).toBeTruthy(); // Visibility const visible = await page.isVisible('input'); expect(visible).toBeTruthy(); A s s e r t i o n s
  • 104. // text content const content = await page.textContent('nav:first-child'); expect(content).toBe('home'); // Attributes const alt = await page.getAttribute('input', 'alt'); expect(alt).toBe('Text'); // Checkbox state const checked = await page.isChecked('input'); expect(checked).toBeTruthy(); // Visibility const visible = await page.isVisible('input'); expect(visible).toBeTruthy(); A s s e r t i o n s
  • 105. import {chromium} from 'playwright'; const browser = await chromium.launch({ // Can be 'chrome', 'chrome-beta', 'msedge-beta', 'msedge-dev' channel: 'msedge', }); const page = await context.newPage(); await page.goto('https://playwright.dev'); await browser.close(); M i c r o s o f t E d g e
  • 106. import {chromium} from 'playwright'; const browser = await chromium.launch({ // Can be 'chrome', 'chrome-beta', 'msedge-beta', 'msedge-dev' channel: 'msedge', }); const page = await context.newPage(); await page.goto('https://playwright.dev'); await browser.close(); M i c r o s o f t E d g e
  • 107. More Features ● Built-in Shadow DOM piercing ● Idiomatic frames API ● Custom Selector Engines ● TimeZone / Locale / Color Scheme emulation ● Per-Context HTTP Proxy ● Workers / Service Workers ● Console sniffing ● Dialogs ● File Uploads ● Element Handles ● ...
  • 108. ● ubuntu-18.04 (chromium) ● ubuntu-18.04 (firefox) ● ubuntu-18.04 (webkit) ● ubuntu-20.04 (chromium) ● ubuntu-20.04 (firefox) ● ubuntu-20.04 (webkit) ● macos-10.14 (chromium) ● macos-10.14 (firefox) ● macos-10.14 (webkit) ● macos-10.15 (chromium) ● macos-10.15 (firefox) ● macos-10.15 (webkit) ● macos-11.0 (chromium) ● macos-11.0 (firefox) ● macos-11.0 (webkit) ● macos-11.0 arm64 (chromium) ● macos-11.0 arm64 (firefox) ● macos-11.0 arm64 (webkit) Rigorous Testing ● Windows (chromium) ● Windows (firefox) ● Windows (webkit) ● test-package-installations (^10.17.0) ● test-package-installations (^12.0.0) ● test-package-installations (^14.1.0) ● Headful Linux (chromium) ● Headful Linux (firefox) ● Headful Linux (webkit) ● Transport (driver) ● Transport (service) ● Video Linux (chromium) ● Video Linux (firefox) ● Video Linux (webkit) ● Android Emulator (shard 1) ● Android Emulator (shard 2) ● Chrome Stable (Linux) ● Chrome Stable (Win) ● Chrome Stable (Mac) ● Edge Stable (Win) ● Electron Linux
  • 112. 🎭 Playwright WebKit Availability Headed Headless ✅ ✅ ✅ ✅ ✅ ✅
  • 113. ● All Browsers ○ Chrome, Safari, Firefox 🎭 Playwright is Ubiquitous
  • 114. ● All Browsers ○ Chrome, Safari, Firefox ● All OS ○ Linux, Mac, Windows 🎭 Playwright is Ubiquitous
  • 115. 🎭 Playwright is Ubiquitous ● All Browsers ○ Chrome, Safari, Firefox ● All OS ○ Linux, Mac, Windows ● All Popular Languages ○ JavaScript / TypeScript ○ Java ○ Python ○ C# (alpha)
  • 116. CI/CD, Services, Clients ● Any CI/CD ○ Github Actions, Travis CI, Azure Pipelines, Jenkins, Circle CI, AWS, GCP, …
  • 117. ● Any CI/CD ○ Github Actions, Travis CI, Azure Pipelines, Jenkins, Circle CI, AWS, GCP, … ● Docker Containers ○ docker pull mcr.microsoft.com/playwright ○ docker pull mcr.microsoft.com/playwright-java CI/CD, Services, Clients
  • 118. CI/CD, Services, Clients ● Any CI/CD ○ Github Actions, Travis CI, Azure Pipelines, Jenkins, Circle CI, AWS, GCP, … ● Docker Containers ○ docker pull mcr.microsoft.com/playwright ○ docker pull mcr.microsoft.com/playwright-java ● Third-Party integrations ○ applitools.com ○ saucelabs.com ○ Checklyhq.com ○ www.testim.io ○ github.com/aerokube/moon ○ seleniumbox.com
  • 119. CI/CD, Services, Clients ● Any CI/CD ○ Github Actions, Travis CI, Azure Pipelines, Jenkins, Circle CI, AWS, GCP, … ● Docker Containers ○ docker pull mcr.microsoft.com/playwright ○ docker pull mcr.microsoft.com/playwright-java ● Third-Party integrations ○ applitools.com ○ saucelabs.com ○ Checklyhq.com ○ www.testim.io ○ github.com/aerokube/moon ○ seleniumbox.com
  • 127. Act V Delightful Authoring & Debugging Dependable Efficient Capable Ubiquitous Delightful Lively
  • 128. 🍿 Demo Time 🍿
  • 129. Authoring & Debugging - Code Generation - npx playwright codegen - Built-In Inspector - PWDEBUG=1 node snippet.js - Devtools Console integration - playwright.$ - Simple Node.js Debugging - Logging - DEBUG=pw:api node snippet.js - Storage State re-use
  • 131. Lively 🐈 ● Active Development ○ 2500+ commits in the last year ○ 1600+ closed issues ● Growing Team ○ We’re hiring! ● Expanding Horizons
  • 132. const { _electron } = require('playwright'); (async () => { const electronApp = await _electron.launch({ args: ['main.js'] }); const window = await electronApp.firstWindow(); console.log(await window.title()); await window.screenshot({ path: 'intro.png' }); await window.click('text=Click me'); await electronApp.close(); })(); 🧪 E x p e r i m e n t a l : E l e c t r o n . j s
  • 133. const { _android } = require('playwright'); (async () => { const [device] = await _android.devices(); await device.shell('am force-stop com.android.chrome'); const context = await device.launchBrowser(); const page = await context.newPage(); await page.goto('https://playwright.dev/'); await page.screenshot({ path: 'page.png' }); await context.close(); await device.close(); })(); 🧪 E x p e r i m e n t a l : A n d r o i d
  • 139.
  • 140. How-To: Authentication Re-use Context 1 1. npx playwright codegen --save-storage=auth.json
  • 141. How-To: Authentication Re-use Context 1 Storage State 2. Extract & Save Storage State 1. npx playwright codegen --save-storage=auth.json
  • 142. How-To: Authentication Re-use Context 1 Context N Storage State 2. Extract & Save Storage State 3. Re-Use Storage State 1. npx playwright codegen --save-storage=auth.json
  • 148. 🍿 Demo Time 🍿
  • 149. const context = await browser.newContext({ storageState: require('auth.json'), }); A u t h e n t i c a t i o n R e - U s e
  • 150. const context = await browser.newContext({ storageState: require('auth.json'), }); A u t h e n t i c a t i o n R e - U s e