Angie Jones PRO
Developer Advocate. International Keynote Speaker. Master Inventor.
@techgirl1908
❝Existing Selenium projects will continue for a long time, but after learning Playwright, I will never start a new E2E test project in Selenium.❞ ~ Andrejs
@AutomationPanda
@techgirl1908
❝I have used both for some time now and can’t wait to see what points both speakers put.❞ ~ Rahul
@AutomationPanda
@techgirl1908
❝I have used both selenium and playwright(js binding). For me playwright is the clear winner. Let the code speak❞ ~ Dushyant
@AutomationPanda
@techgirl1908
@AutomationPanda
❝About time Selenium got a worthy competitor. I've been a WebDriver fan for good 7+ years and can’t wait to see how long will Playwright survive against it 😉❞ ~ Akash
@techgirl1908
@AutomationPanda
❝Sorry Angie. On this one I’m team Andy, my bet is on Playwright❞ ~ Ixchel
@techgirl1908
@AutomationPanda
❝Playwright is absolutely changing the game! Automatic waits, built in device and multiple browser support, available in Python, JS, and more! ❞ ~ Sean
@techgirl1908
@AutomationPanda
@techgirl1908
@AutomationPanda
@techgirl1908
@AutomationPanda
🥊 10 Rounds
💻 Show implementations in Selenium and Playwright
🗳 You vote
💬 Discuss after each round
@techgirl1908
@AutomationPanda
@techgirl1908
@AutomationPanda
@techgirl1908
@AutomationPanda
@Test
public void testLogin()
{
page.navigate("https://demo.applitools.com/");
page.fill("id=username", "andy");
page.fill("id=password", "panda<3");
page.click("id=log-in");
assertThat(page.locator(".element-header >> nth=0"))
.hasText("Financial Overview");
}
@techgirl1908
@AutomationPanda
@Test
public void testLogin()
{
driver.get("https://demo.applitools.com/");
driver.findElement(By.id("username")).sendKeys("angie");
driver.findElement(By.id("password")).sendKeys("12345");
driver.findElement(By.id("log-in")).click();
assertEquals(
"Financial Overview",
driver.findElement(By.className("element-header")).getText());
}
@Test
public void testLogin()
{
page.navigate("https://demo.applitools.com/");
page.fill("id=username", "andy");
page.fill("id=password", "panda<3");
page.click("id=log-in");
assertThat(page.locator(".element-header >> nth=0"))
.hasText("Financial Overview");
}
@Test
public void testLogin()
{
driver.get("https://demo.applitools.com/");
driver.findElement(By.id("username")).sendKeys("angie");
driver.findElement(By.id("password")).sendKeys("12345");
driver.findElement(By.id("log-in")).click();
assertEquals(
"Financial Overview",
driver.findElement(By.className("element-header")).getText());
}
@techgirl1908
@AutomationPanda
@techgirl1908
@AutomationPanda
@techgirl1908
@AutomationPanda
@Test
public void testDropdown()
{
driver.get("https://kitchen.applitools.com/ingredients/select");
Select dropdown =
new Select(driver.findElement(By.id("spices-select-single")));
dropdown.selectByValue("ginger");
assertEquals("ginger",
dropdown.getAllSelectedOptions().get(0).getAttribute("value"));
}
@techgirl1908
@AutomationPanda
@Test
public void testDropdown()
{
page.navigate("https://kitchen.applitools.com/ingredients/select");
page.selectOption("id=spices-select-single", "ginger");
assertThat(page.locator("id=spices-select-single"))
.hasValue("ginger");
}
@Test
public void testDropdown()
{
driver.get("https://kitchen.applitools.com/ingredients/select");
Select dropdown =
new Select(driver.findElement(By.id("spices-select-single")));
dropdown.selectByValue("ginger");
assertEquals("ginger",
dropdown.getAllSelectedOptions().get(0).getAttribute("value"));
}
@Test
public void testDropdown()
{
page.navigate("https://kitchen.applitools.com/ingredients/select");
page.selectOption("id=spices-select-single", "ginger");
assertThat(page.locator("id=spices-select-single"))
.hasValue("ginger");
}
@techgirl1908
@AutomationPanda
@techgirl1908
@AutomationPanda
@Test
public void testFileUpload()
{
page.navigate("https://kitchen.applitools.com/ingredients/file-picker");
page.setInputFiles("id=photo-upload", Paths.get("pic.jpg"));
}
@techgirl1908
@AutomationPanda
@techgirl1908
@AutomationPanda
@Test
public void testFileUpload()
{
driver.get("https://kitchen.applitools.com/ingredients/file-picker");
driver.findElement(By.id("photo-upload")).sendKeys("/Users/angie/tmp/pic.jpg");
}
@Test
public void testFileUpload()
{
driver.get("https://kitchen.applitools.com/ingredients/file-picker");
driver.findElement(By.id("photo-upload")).sendKeys("/Users/angie/tmp/pic.jpg");
}
@Test
public void testFileUpload()
{
page.navigate("https://kitchen.applitools.com/ingredients/file-picker");
page.setInputFiles("id=photo-upload", Paths.get("pic.jpg"));
}
@techgirl1908
@AutomationPanda
@techgirl1908
@AutomationPanda
@techgirl1908
@AutomationPanda
@techgirl1908
@AutomationPanda
@Test
public void testIframe()
{
driver.get("https://kitchen.applitools.com/ingredients/iframe");
assertTrue(
driver.switchTo().frame("the-kitchen-table")
.findElement(By.id("fruits-vegetables"))
.isDisplayed());
}
@techgirl1908
@Test
public void testIframe()
{
page.navigate("https://kitchen.applitools.com/ingredients/iframe");
assertThat(page
.frameLocator("id=the-kitchen-table")
.locator("id=fruits-vegetables")
).isVisible();
}
@AutomationPanda
@Test
public void testIframe()
{
driver.get("https://kitchen.applitools.com/ingredients/iframe");
assertTrue(
driver.switchTo().frame("the-kitchen-table")
.findElement(By.id("fruits-vegetables"))
.isDisplayed());
}
@Test
public void testIframe()
{
page.navigate("https://kitchen.applitools.com/ingredients/iframe");
assertThat(
page.frameLocator("id=the-kitchen-table")
.locator("id=fruits-vegetables")
).isVisible();
}
@techgirl1908
@AutomationPanda
@techgirl1908
@AutomationPanda
@techgirl1908
@Test
public void testWaitForFilter()
{
page.navigate("https://automationbookstore.dev/");
page.fill("id=searchBar", "testing");
page.locator("li.ui-screen-hidden >> nth=0").waitFor(
new Locator.WaitForOptions()
.setState(WaitForSelectorState.HIDDEN)
.setTimeout(5000));
assertThat(page.locator("li:not(.ui-screen-hidden)"))
.hasCount(1, new LocatorAssertions.HasCountOptions().setTimeout(5000));
}
@AutomationPanda
@techgirl1908
@Test
public void testWaitForFilter()
{
page.navigate("https://automationbookstore.dev/");
page.fill("id=searchBar", "testing");
// page.locator("li.ui-screen-hidden >> nth=0").waitFor(
// new Locator.WaitForOptions()
// .setState(WaitForSelectorState.HIDDEN)
// .setTimeout(5000));
assertThat(page.locator("li:not(.ui-screen-hidden)"))
.hasCount(1, new LocatorAssertions.HasCountOptions().setTimeout(5000));
}
@AutomationPanda
Explicitly waiting for hidden elements to attach to the DOM is not required.
Waiting for the non-hidden element count to reach 1 inherently covers it.
@techgirl1908
@Test
public void testWaitForFilter()
{
driver.get("https://automationbookstore.dev/");
driver.findElement(By.id("searchBar")).sendKeys("testing");
new WebDriverWait(driver, Duration.ofSeconds(5))
.until(presenceOfElementLocated(
By.cssSelector("li.ui-screen-hidden"))
);
assertEquals(1,
driver.findElements(By.cssSelector("li:not(.ui-screen-hidden)"))
.size());
}
@AutomationPanda
@techgirl1908
@Test
public void testWaitForFilter()
{
...
new WebDriverWait(driver, Duration.ofSeconds(5))
.until(presenceOfElementLocated(
By.cssSelector("li.ui-screen-hidden"))
);
...
}
@Test
public void testWaitForFilter()
{
...
page.locator("li.ui-screen-hidden >> nth=0").waitFor(
new Locator.WaitForOptions()
.setState(WaitForSelectorState.HIDDEN)
.setTimeout(5000));
...
}
@AutomationPanda
@techgirl1908
@AutomationPanda
@techgirl1908
@AutomationPanda
@BeforeAll
public static void openAlertsPage(){
driver.get("https://kitchen.applitools.com/ingredients/alert");
}
@Test
public void testAcceptAlert(){
driver.findElement(By.id("alert-button")).click();
driver.switchTo().alert().accept();
}
@Test
public void testDismissAlert(){
driver.findElement(By.id("confirm-button")).click();
driver.switchTo().alert().dismiss();
}
@Test
public void testAnswerPrompt(){
driver.findElement(By.id("prompt-button")).click();
Alert alert = driver.switchTo().alert();
alert.sendKeys("nachos");
alert.accept();
}
@techgirl1908
@AutomationPanda
@BeforeAll
public static void openAlertsPage(){
page.navigate("https://kitchen.applitools.com/ingredients/alert");
}
@Test
public void testAcceptAlert(){
page.onDialog(Dialog::accept);
page.click("id=alert-button");
}
@Test
public void testDismissAlert(){
page.onDialog(Dialog::dismiss);
page.click("id=confirm-button");
}
@Test
public void testAnswerPrompt(){
page.onDialog(dialog -> dialog.accept("nachos"));
page.click("id=prompt-button");
}
@BeforeAll
public static void openAlertsPage(){
driver.get("https://kitchen.applitools.com/ingredients/alert");
}
@Test
public void testAcceptAlert(){
driver.findElement(By.id("alert-button")).click();
driver.switchTo().alert().accept();
}
@Test
public void testDismissAlert(){
driver.findElement(By.id("confirm-button")).click();
driver.switchTo().alert().dismiss();
}
@Test
public void testAnswerPrompt(){
driver.findElement(By.id("prompt-button")).click();
Alert alert = driver.switchTo().alert();
alert.sendKeys("nachos");
alert.accept();
}
@BeforeAll
public static void openAlertsPage(){
page.navigate("https://kitchen.applitools.com/ingredients/alert");
}
@Test
public void testAcceptAlert(){
page.onDialog(Dialog::accept);
page.click("id=alert-button");
}
@Test
public void testDismissAlert(){
page.onDialog(Dialog::dismiss);
page.click("id=confirm-button");
}
@Test
public void testAnswerPrompt(){
page.onDialog(dialog -> dialog.accept("nachos"));
page.click("id=prompt-button");
}
@techgirl1908
@AutomationPanda
@techgirl1908
@AutomationPanda
@techgirl1908
@Test
public void testNewTab()
{
page.navigate("https://kitchen.applitools.com/ingredients/links");
Page newTab = context.waitForPage(
() -> page.click("id=button-the-kitchen-table"));
assertThat(newTab.locator("id=fruits-vegetables")).isVisible();
}
@AutomationPanda
@techgirl1908
@Test
public void testNewTab()
{
driver.get("https://kitchen.applitools.com/ingredients/links");
driver.findElement(By.id("button-the-kitchen-table")).click();
driver.getWindowHandles().forEach(tab->driver.switchTo().window(tab));
assertTrue(driver.findElement(By.id("fruits-vegetables")).isDisplayed());
}
@AutomationPanda
@techgirl1908
@Test
public void testNewTab()
{
driver.get("https://kitchen.applitools.com/ingredients/links");
driver.findElement(By.id("button-the-kitchen-table")).click();
driver.getWindowHandles().forEach(tab->driver.switchTo().window(tab));
assertTrue(driver.findElement(By.id("fruits-vegetables")).isDisplayed());
}
@AutomationPanda
@Test
public void testNewTab()
{
page.navigate("https://kitchen.applitools.com/ingredients/links");
Page newTab = context.waitForPage(
() -> page.click("id=button-the-kitchen-table"));
assertThat(newTab.locator("id=fruits-vegetables")).isVisible();
}
@techgirl1908
@AutomationPanda
@techgirl1908
@AutomationPanda
https://kitchen.applitools.com/api/recipes
@techgirl1908
😫
@AutomationPanda
@techgirl1908
@AutomationPanda
Currently, Playwright provides API testing
only for JavaScript and Python.
API testing support will come to Java in 1.18.
It will come to .NET thereafter.
😲
@techgirl1908
def test_kitchen_api_recipes(context):
response = context.request.get(
'https://kitchen.applitools.com/api/recipes')
body = response.json()
assert response.ok
assert body['time'] > 0
assert len(body['data']) > 0
# Include other assertions about body data as appropriate
@AutomationPanda
@techgirl1908
def test_kitchen_api_recipes(context):
response = context.request.get(
'https://kitchen.applitools.com/api/recipes')
body = response.json()
assert response.ok
assert body['time'] > 0
assert len(body['data']) > 0
# Include other assertions about body data as appropriate
@AutomationPanda
@techgirl1908
@AutomationPanda
@techgirl1908
@AutomationPanda
@techgirl1908
@Test
public void testScreenshot()
{
page.navigate("https://kitchen.applitools.com/ingredients/table");
page.click("id=column-button-name");
page.screenshot(
new Page.ScreenshotOptions()
.setPath(Paths.get("fullPage.png"))
.setFullPage(true));
}
@AutomationPanda
@techgirl1908
@Test
public void testScreenshot()
{
driver.get("https://kitchen.applitools.com/ingredients/table");
driver.findElement(By.id("column-button-name")).click();
var screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
try{
Files.move(screenshot, new File("resources/screenshots/test.png"));
}catch(IOException e){
e.printStackTrace();
}
}
@AutomationPanda
@techgirl1908
@Test
public void testScreenshot(){
driver.get("https://kitchen.applitools.com/ingredients/table");
driver.findElement(By.id("column-button-name")).click();
var screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
try{
Files.move(screenshot, new File("resources/screenshots/test.png"));
}catch(IOException e){
e.printStackTrace();
}
}
@Test
public void testScreenshot()
{
page.navigate("https://kitchen.applitools.com/ingredients/table");
page.click("id=column-button-name");
page.screenshot(
new Page.ScreenshotOptions()
.setPath(Paths.get("fullPage.png"))
.setFullPage(true));
}
@AutomationPanda
@techgirl1908
@AutomationPanda
@techgirl1908
@AutomationPanda
@techgirl1908
@AutomationPanda
Selenium WebDriver does not support
video recording out of the box!
😫
@techgirl1908
@BeforeEach
public void startPage() {
context = browser.newContext(
new Browser.NewContextOptions()
.setRecordVideoDir(Paths.get("videos/")));
page = context.newPage();
}
@AfterEach
public void closePage() {
context.close();
}
@Test
public void testLogin() {
// This is the same code from Round 1
...
}
@AutomationPanda
@techgirl1908
@BeforeEach
public void startPage() {
context = browser.newContext(
new Browser.NewContextOptions()
.setRecordVideoDir(Paths.get("videos/")));
page = context.newPage();
}
@AfterEach
public void closePage() {
context.close();
}
...
@AutomationPanda
Selenium WebDriver does not support
video recording out of the box!
@techgirl1908
@AutomationPanda
By Angie Jones
It's a battle of the code! Angie Jones represents Selenium WebDriver while Colby Fayock represents Cypress. Round for round, Angie and Colby take coding tasks and implement them in Selenium as well as Cypress, then analyze how each of the frameworks perform to solve real world testing challenges.
Developer Advocate. International Keynote Speaker. Master Inventor.