Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Why compare
Cypress against Playwright?
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
The Matchup
🥊 10 rounds of code challenges
💻 Show implementations in Cypress and Playwright
🗣 Compare and discuss the code
🗳 You vote!
Round 1:
Element Interaction
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Element Interaction in Cypress
cy.visit('https://demo.applitools.com/')
cy.get('#username').type('filip')
cy.get('#password').type('i<3slovakia!')
cy.get('#log-in').click()
cy.contains('.element-header', 'Financial Overview')
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Element Interaction in Playwright
await page.goto("https://demo.applitools.com/");
await page.locator("id=username").fill("andy");
await page.locator("id=password").fill("panda<3");
await page.locator("id=log-in").click();
await expect(page.locator(".element-header").first())
.toHaveText("Financial Overview");
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Element Interaction Head-to-Head
cy.visit('https://demo.applitools.com/')
cy.get('#username').type('filip')
cy.get('#password').type('i<3slovakia!')
cy.get('#log-in').click()
cy.contains('.element-header', 'Financial Overview')
await page.goto("https://demo.applitools.com/");
await page.locator("id=username").fill("andy");
await page.locator("id=password").fill("panda<3");
await page.locator("id=log-in").click();
await expect(page.locator(".element-header").first())
.toHaveText("Financial Overview");
Cypress Playwright
Round 2:
Inline Frames
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Inline Frames in Playwright
await page.goto("https://kitchen.applitools.com/ingredients/iframe");
const iframe = page.frameLocator("id=the-kitchen-table");
const table = iframe.locator("id=fruits-vegetables");
await expect(table).toBeVisible();
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Inline Frames in Cypress
cy.visit('https://kitchen.applitools.com/ingredients/iframe')
cy.iframe('#the-kitchen-table')
.find('#fruits-vegetables')
.should('be.visible')
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Inline Frames Head-to-Head
cy.visit(
'https://kitchen.applitools.com/ingredients/iframe')
cy.iframe('#the-kitchen-table')
.find('#fruits-vegetables')
.should('be.visible')
await page.goto(
"https://kitchen.applitools.com/ingredients/iframe");
const iframe = page.frameLocator("id=the-kitchen-table");
const table = iframe.locator("id=fruits-vegetables");
await expect(table).toBeVisible();
Cypress Playwright
Round 3:
Waiting
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Waiting in Cypress
cy.visit('https://automationbookstore.dev/')
cy.get('#searchBar').type('testing')
cy.get('li:visible').should('have.length', 1)
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Waiting in Playwright
await page.goto("https://automationbookstore.dev/");
await page.locator("id=searchBar").fill("testing");
await expect(page.locator("li:visible")).toHaveCount(1);
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Waiting Head-to-Head
cy.visit('https://automationbookstore.dev/')
cy.get('#searchBar').type('testing')
cy.get('li:visible').should('have.length', 1)
await page.goto("https://automationbookstore.dev/");
await page.locator("id=searchBar").fill("testing");
await expect(page.locator("li:visible")).toHaveCount(1);
Cypress Playwright
Round 4:
Alerts
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Alerts in Playwright
// Accept alert
page.on('dialog', dialog => {
expect(dialog.message()).toBe("Airfryers can make anything!");
dialog.accept();
});
await page.goto("https://kitchen.applitools.com/ingredients/alert");
await page.locator("id=alert-button").click();
// Dismiss alert
page.on('dialog', dialog => dialog.dismiss());
await page.goto("https://kitchen.applitools.com/ingredients/alert");
await page.locator("id=confirm-button").click();
// Answer prompt
page.on('dialog', dialog => dialog.accept("nachos"));
await page.goto("https://kitchen.applitools.com/ingredients/alert");
await page.locator("id=prompt-button").click();
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Alerts in Cypress
// Accept alert
cy.visit('https://kitchen.applitools.com/ingredients/alert')
cy.get('#alert-button').click()
cy.on('window:alert', (alert) => {
expect(alert).to.eq('Airfryers can make anything!')
})
// Dismiss alert
cy.visit('https://kitchen.applitools.com/ingredients/alert')
const dismiss = () => false
cy.get('#confirm-button').click()
cy.on('window:confirm', dismiss)
// Answer prompt
cy.visit('https://kitchen.applitools.com/ingredients/alert', {
onLoad(win: Window) {
cy.stub(win, 'prompt').returns('Hi mom!');
}
})
cy.get('#prompt-button').click()
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Alerts Head-to-Head
// Accept alert
cy.visit('https://kitchen.applitools.com/ingredients/alert')
cy.get('#alert-button').click()
cy.on('window:alert', (alert) => {
expect(alert).to.eq('Airfryers can make anything!')
})
// Dismiss alert
cy.visit('https://kitchen.applitools.com/ingredients/alert')
const dismiss = () => false
cy.get('#confirm-button').click()
cy.on('window:confirm', dismiss)
// Answer prompt
cy.visit('https://kitchen.applitools.com/ingredients/alert', {
onLoad(win: Window) {
cy.stub(win, 'prompt').returns('nachos');
}
})
cy.get('#prompt-button').click()
// Accept alert
page.on('dialog', dialog => {
expect(dialog.message()).toBe("Airfryers can make anything!");
dialog.accept();
});
await page.goto("https://kitchen.applitools.com/ingredients/alert");
await page.locator("id=alert-button").click();
// Dismiss alert
page.on('dialog', dialog => dialog.dismiss());
await page.goto("https://kitchen.applitools.com/ingredients/alert");
await page.locator("id=confirm-button").click();
// Answer prompt
page.on('dialog', dialog => dialog.accept("nachos"));
await page.goto("https://kitchen.applitools.com/ingredients/alert");
await page.locator("id=prompt-button").click();
Cypress Playwright
Round 5:
Navigation to New Windows
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Navigation to New Windows in Cypress
cy.visit('https://kitchen.applitools.com/ingredients/links')
cy.get('#button-the-kitchen-table')
.invoke('removeAttr', 'target')
.click()
cy.location('pathname')
.should('eq', '/ingredients/table')
cy.get('#fruits-vegetables:visible')
.should('have.length', 1)
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Navigation to New Windows in Playwright
await page.goto("https://kitchen.applitools.com/ingredients/links");
let [newPage] = await Promise.all([
context.waitForEvent('page'),
page.locator("id=button-the-kitchen-table").click()
]);
await newPage.waitForLoadState();
expect(newPage.url()).toContain('/ingredients/table');
await expect(newPage.locator("id=fruits-vegetables")).toBeVisible();
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Navigation to New Windows Head-to-Head
cy.visit(
'https://kitchen.applitools.com/ingredients/links')
cy.get('#button-the-kitchen-table')
.invoke('removeAttr', 'target')
.click()
cy.location('pathname')
.should('eq', '/ingredients/table')
cy.get('#fruits-vegetables:visible')
.should('have.length', 1)
await page.goto(
"https://kitchen.applitools.com/ingredients/links");
let [newPage] = await Promise.all([
context.waitForEvent('page'),
page.locator("id=button-the-kitchen-table").click()
]);
await newPage.waitForLoadState();
expect(newPage.url()).toContain('/ingredients/table');
await expect(newPage.locator("id=fruits-vegetables"))
.toBeVisible();
Cypress Playwright
Round 6:
API Requests
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
https://kitchen.applitools.com/api/recipes
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
API Requests in Playwright
const requestContext = await request.newContext(
{baseURL: 'https://kitchen.applitools.com'});
const response = await requestContext.get('api/recipes');
await expect(response).toBeOK();
const body = await response.json();
expect(body.time).toBeGreaterThan(0);
expect(body.data.length).toBeGreaterThan(0);
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
API Requests in Cypress
cy.request('https://kitchen.applitools.com/api/recipes')
.then(({ status, body, duration }) => {
expect(status).to.eq(200)
expect(body.data).to.have.length.greaterThan(0)
expect(duration).to.be.greaterThan(0)
})
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
API Requests Head-to-Head
cy.request('https://kitchen.applitools.com/api/recipes')
.then(({ status, body, duration }) => {
expect(status).to.eq(200)
expect(body.data).to.have.length.greaterThan(0)
expect(duration).to.be.greaterThan(0)
})
const requestContext = await request.newContext(
{baseURL: 'https://kitchen.applitools.com'});
const response = await requestContext.get('api/recipes');
await expect(response).toBeOK();
const body = await response.json();
expect(body.time).toBeGreaterThan(0);
expect(body.data.length).toBeGreaterThan(0);
Cypress Playwright
Round 7:
Page Objects
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Page Objects in Cypress
export const loginPage = {
username: '#username',
password: '#password',
log_in: '#log-in',
load() {
cy.visit('https://demo.applitools.com/')
return this
},
login(username: string, pass: string) {
cy.get(this.username).type(username)
cy.get(this.password).type(pass)
cy.get(this.log_in).click()
return this
}
}
loginPage
.load()
.login('filip', 'i<3slovakia!')
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Page Objects in Playwright
export class LoginPage {
page: Page;
usernameInput: Locator;
passwordInput: Locator;
loginButton: Locator;
constructor(page: Page) {
this.page = page;
this.usernameInput = page.locator("id=username");
this.passwordInput = page.locator("id=password");
this.loginButton = page.locator("id=log-in")
}
async load() {
await this.page.goto("https://demo.applitools.com/");
}
async login(username: string, password: string) {
await this.usernameInput.fill(username);
await this.passwordInput.fill(password);
await this.loginButton.click();
}
}
const loginPage = new LoginPage(page);
await loginPage.load();
await loginPage.login("andy", "panda<3");
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Page Objects Head-to-Head
export const loginPage = {
username: '#username',
password: '#password',
log_in: '#log-in',
load() {
cy.visit('https://demo.applitools.com/')
return this
},
login(username: string, pass: string) {
cy.get(this.username).type(username)
cy.get(this.password).type(pass)
cy.get(this.log_in).click()
return this
}
}
export class LoginPage {
page: Page;
usernameInput: Locator;
passwordInput: Locator;
loginButton: Locator;
constructor(page: Page) {
this.page = page;
this.usernameInput = page.locator("id=username");
this.passwordInput = page.locator("id=password");
this.loginButton = page.locator("id=log-in")
}
async load() {
await this.page.goto("https://demo.applitools.com/");
}
async login(username: string, password: string) {
await this.usernameInput.fill(username);
await this.passwordInput.fill(password);
await this.loginButton.click();
}
}
Cypress Playwright
Round 8:
Language Support
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Language Support Head-to-Head
● TypeScript/JavaScript ● TypeScript/JavaScript
● Python
● Java
● .NET (C#)
Cypress Playwright
Round 9:
Browsers
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Browsers Head-to-Head
Supported browsers:
● Chrome
● Edge
● Electron
● Firefox
Can only test one browser at a time.
Supported browsers:
● Chromium
● Firefox
● WebKit
● Chrome & Edge (browser channels)
Can test multiple browsers in parallel.
Cypress Playwright
Round 10:
Speed
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Speed Head-to-Head
Command:
npx cypress run --browser chrome
Execution times (s):
23-24-24-24-24
Average time:
23.8s
Command:
npx playwright test –-project chromium
Execution times (s):
5-4-5-5-5-4-4-7-7-6
Average time:
5.2s (4.6x faster than Cypress)
Cypress Playwright
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Which is the Winner?
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
filiphric.com/workshop
● 4 module online workshop
● learn by doing
● core principles and best
practices
starting on 31th May
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
And the Winner is…
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak
Continue the Conversation
#LetTheCodeSpeak
@filip_hric
@AutomationPanda
@applitools
Cypress | @filip_hric Playwright | @AutomationPanda
#LetTheCodeSpeak

Cypress-vs-Playwright: Let the Code Speak

  • 1.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak
  • 2.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak
  • 3.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Why compare Cypress against Playwright?
  • 4.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak The Matchup 🥊 10 rounds of code challenges 💻 Show implementations in Cypress and Playwright 🗣 Compare and discuss the code 🗳 You vote!
  • 5.
  • 6.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak
  • 7.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Element Interaction in Cypress cy.visit('https://demo.applitools.com/') cy.get('#username').type('filip') cy.get('#password').type('i<3slovakia!') cy.get('#log-in').click() cy.contains('.element-header', 'Financial Overview')
  • 8.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Element Interaction in Playwright await page.goto("https://demo.applitools.com/"); await page.locator("id=username").fill("andy"); await page.locator("id=password").fill("panda<3"); await page.locator("id=log-in").click(); await expect(page.locator(".element-header").first()) .toHaveText("Financial Overview");
  • 9.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Element Interaction Head-to-Head cy.visit('https://demo.applitools.com/') cy.get('#username').type('filip') cy.get('#password').type('i<3slovakia!') cy.get('#log-in').click() cy.contains('.element-header', 'Financial Overview') await page.goto("https://demo.applitools.com/"); await page.locator("id=username").fill("andy"); await page.locator("id=password").fill("panda<3"); await page.locator("id=log-in").click(); await expect(page.locator(".element-header").first()) .toHaveText("Financial Overview"); Cypress Playwright
  • 10.
  • 11.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak
  • 12.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Inline Frames in Playwright await page.goto("https://kitchen.applitools.com/ingredients/iframe"); const iframe = page.frameLocator("id=the-kitchen-table"); const table = iframe.locator("id=fruits-vegetables"); await expect(table).toBeVisible();
  • 13.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Inline Frames in Cypress cy.visit('https://kitchen.applitools.com/ingredients/iframe') cy.iframe('#the-kitchen-table') .find('#fruits-vegetables') .should('be.visible')
  • 14.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Inline Frames Head-to-Head cy.visit( 'https://kitchen.applitools.com/ingredients/iframe') cy.iframe('#the-kitchen-table') .find('#fruits-vegetables') .should('be.visible') await page.goto( "https://kitchen.applitools.com/ingredients/iframe"); const iframe = page.frameLocator("id=the-kitchen-table"); const table = iframe.locator("id=fruits-vegetables"); await expect(table).toBeVisible(); Cypress Playwright
  • 15.
  • 16.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak
  • 17.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Waiting in Cypress cy.visit('https://automationbookstore.dev/') cy.get('#searchBar').type('testing') cy.get('li:visible').should('have.length', 1)
  • 18.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Waiting in Playwright await page.goto("https://automationbookstore.dev/"); await page.locator("id=searchBar").fill("testing"); await expect(page.locator("li:visible")).toHaveCount(1);
  • 19.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Waiting Head-to-Head cy.visit('https://automationbookstore.dev/') cy.get('#searchBar').type('testing') cy.get('li:visible').should('have.length', 1) await page.goto("https://automationbookstore.dev/"); await page.locator("id=searchBar").fill("testing"); await expect(page.locator("li:visible")).toHaveCount(1); Cypress Playwright
  • 20.
  • 21.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak
  • 22.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Alerts in Playwright // Accept alert page.on('dialog', dialog => { expect(dialog.message()).toBe("Airfryers can make anything!"); dialog.accept(); }); await page.goto("https://kitchen.applitools.com/ingredients/alert"); await page.locator("id=alert-button").click(); // Dismiss alert page.on('dialog', dialog => dialog.dismiss()); await page.goto("https://kitchen.applitools.com/ingredients/alert"); await page.locator("id=confirm-button").click(); // Answer prompt page.on('dialog', dialog => dialog.accept("nachos")); await page.goto("https://kitchen.applitools.com/ingredients/alert"); await page.locator("id=prompt-button").click();
  • 23.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Alerts in Cypress // Accept alert cy.visit('https://kitchen.applitools.com/ingredients/alert') cy.get('#alert-button').click() cy.on('window:alert', (alert) => { expect(alert).to.eq('Airfryers can make anything!') }) // Dismiss alert cy.visit('https://kitchen.applitools.com/ingredients/alert') const dismiss = () => false cy.get('#confirm-button').click() cy.on('window:confirm', dismiss) // Answer prompt cy.visit('https://kitchen.applitools.com/ingredients/alert', { onLoad(win: Window) { cy.stub(win, 'prompt').returns('Hi mom!'); } }) cy.get('#prompt-button').click()
  • 24.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Alerts Head-to-Head // Accept alert cy.visit('https://kitchen.applitools.com/ingredients/alert') cy.get('#alert-button').click() cy.on('window:alert', (alert) => { expect(alert).to.eq('Airfryers can make anything!') }) // Dismiss alert cy.visit('https://kitchen.applitools.com/ingredients/alert') const dismiss = () => false cy.get('#confirm-button').click() cy.on('window:confirm', dismiss) // Answer prompt cy.visit('https://kitchen.applitools.com/ingredients/alert', { onLoad(win: Window) { cy.stub(win, 'prompt').returns('nachos'); } }) cy.get('#prompt-button').click() // Accept alert page.on('dialog', dialog => { expect(dialog.message()).toBe("Airfryers can make anything!"); dialog.accept(); }); await page.goto("https://kitchen.applitools.com/ingredients/alert"); await page.locator("id=alert-button").click(); // Dismiss alert page.on('dialog', dialog => dialog.dismiss()); await page.goto("https://kitchen.applitools.com/ingredients/alert"); await page.locator("id=confirm-button").click(); // Answer prompt page.on('dialog', dialog => dialog.accept("nachos")); await page.goto("https://kitchen.applitools.com/ingredients/alert"); await page.locator("id=prompt-button").click(); Cypress Playwright
  • 25.
  • 26.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak
  • 27.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Navigation to New Windows in Cypress cy.visit('https://kitchen.applitools.com/ingredients/links') cy.get('#button-the-kitchen-table') .invoke('removeAttr', 'target') .click() cy.location('pathname') .should('eq', '/ingredients/table') cy.get('#fruits-vegetables:visible') .should('have.length', 1)
  • 28.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Navigation to New Windows in Playwright await page.goto("https://kitchen.applitools.com/ingredients/links"); let [newPage] = await Promise.all([ context.waitForEvent('page'), page.locator("id=button-the-kitchen-table").click() ]); await newPage.waitForLoadState(); expect(newPage.url()).toContain('/ingredients/table'); await expect(newPage.locator("id=fruits-vegetables")).toBeVisible();
  • 29.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Navigation to New Windows Head-to-Head cy.visit( 'https://kitchen.applitools.com/ingredients/links') cy.get('#button-the-kitchen-table') .invoke('removeAttr', 'target') .click() cy.location('pathname') .should('eq', '/ingredients/table') cy.get('#fruits-vegetables:visible') .should('have.length', 1) await page.goto( "https://kitchen.applitools.com/ingredients/links"); let [newPage] = await Promise.all([ context.waitForEvent('page'), page.locator("id=button-the-kitchen-table").click() ]); await newPage.waitForLoadState(); expect(newPage.url()).toContain('/ingredients/table'); await expect(newPage.locator("id=fruits-vegetables")) .toBeVisible(); Cypress Playwright
  • 30.
  • 31.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak https://kitchen.applitools.com/api/recipes
  • 32.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak API Requests in Playwright const requestContext = await request.newContext( {baseURL: 'https://kitchen.applitools.com'}); const response = await requestContext.get('api/recipes'); await expect(response).toBeOK(); const body = await response.json(); expect(body.time).toBeGreaterThan(0); expect(body.data.length).toBeGreaterThan(0);
  • 33.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak API Requests in Cypress cy.request('https://kitchen.applitools.com/api/recipes') .then(({ status, body, duration }) => { expect(status).to.eq(200) expect(body.data).to.have.length.greaterThan(0) expect(duration).to.be.greaterThan(0) })
  • 34.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak API Requests Head-to-Head cy.request('https://kitchen.applitools.com/api/recipes') .then(({ status, body, duration }) => { expect(status).to.eq(200) expect(body.data).to.have.length.greaterThan(0) expect(duration).to.be.greaterThan(0) }) const requestContext = await request.newContext( {baseURL: 'https://kitchen.applitools.com'}); const response = await requestContext.get('api/recipes'); await expect(response).toBeOK(); const body = await response.json(); expect(body.time).toBeGreaterThan(0); expect(body.data.length).toBeGreaterThan(0); Cypress Playwright
  • 35.
  • 36.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak
  • 37.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Page Objects in Cypress export const loginPage = { username: '#username', password: '#password', log_in: '#log-in', load() { cy.visit('https://demo.applitools.com/') return this }, login(username: string, pass: string) { cy.get(this.username).type(username) cy.get(this.password).type(pass) cy.get(this.log_in).click() return this } } loginPage .load() .login('filip', 'i<3slovakia!')
  • 38.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Page Objects in Playwright export class LoginPage { page: Page; usernameInput: Locator; passwordInput: Locator; loginButton: Locator; constructor(page: Page) { this.page = page; this.usernameInput = page.locator("id=username"); this.passwordInput = page.locator("id=password"); this.loginButton = page.locator("id=log-in") } async load() { await this.page.goto("https://demo.applitools.com/"); } async login(username: string, password: string) { await this.usernameInput.fill(username); await this.passwordInput.fill(password); await this.loginButton.click(); } } const loginPage = new LoginPage(page); await loginPage.load(); await loginPage.login("andy", "panda<3");
  • 39.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Page Objects Head-to-Head export const loginPage = { username: '#username', password: '#password', log_in: '#log-in', load() { cy.visit('https://demo.applitools.com/') return this }, login(username: string, pass: string) { cy.get(this.username).type(username) cy.get(this.password).type(pass) cy.get(this.log_in).click() return this } } export class LoginPage { page: Page; usernameInput: Locator; passwordInput: Locator; loginButton: Locator; constructor(page: Page) { this.page = page; this.usernameInput = page.locator("id=username"); this.passwordInput = page.locator("id=password"); this.loginButton = page.locator("id=log-in") } async load() { await this.page.goto("https://demo.applitools.com/"); } async login(username: string, password: string) { await this.usernameInput.fill(username); await this.passwordInput.fill(password); await this.loginButton.click(); } } Cypress Playwright
  • 40.
  • 41.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Language Support Head-to-Head ● TypeScript/JavaScript ● TypeScript/JavaScript ● Python ● Java ● .NET (C#) Cypress Playwright
  • 42.
  • 43.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Browsers Head-to-Head Supported browsers: ● Chrome ● Edge ● Electron ● Firefox Can only test one browser at a time. Supported browsers: ● Chromium ● Firefox ● WebKit ● Chrome & Edge (browser channels) Can test multiple browsers in parallel. Cypress Playwright
  • 44.
  • 45.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Speed Head-to-Head Command: npx cypress run --browser chrome Execution times (s): 23-24-24-24-24 Average time: 23.8s Command: npx playwright test –-project chromium Execution times (s): 5-4-5-5-5-4-4-7-7-6 Average time: 5.2s (4.6x faster than Cypress) Cypress Playwright
  • 46.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak Which is the Winner?
  • 47.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak filiphric.com/workshop ● 4 module online workshop ● learn by doing ● core principles and best practices starting on 31th May
  • 48.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak
  • 49.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak And the Winner is…
  • 50.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak
  • 51.
  • 52.
    Cypress | @filip_hricPlaywright | @AutomationPanda #LetTheCodeSpeak