Michael Lynch (@deliberatecoder)
Task | Cypress | Playwright | Difference |
---|---|---|---|
Run tests on CircleCI | 127s | 84s | -34% |
Run tests from development machine | 40s | 7s | -83% |
should
, expect
, and assert
depending on contextThese two snippets are functionally equivalent
cy.get("#error-message").should("be.visible");
cy.get("#error-message").should(($el) => expect($el).to.be.visible);
expect(page.locator("#error-message")).toBeVisible();
// Save the route to the guest link URL so that we can return to it later.
cy.get('.table td[test-data-id="guest-link-label"] a')
.invoke("attr", "href")
.then(($href) => {
// Log out.
cy.get("#navbar-log-out").click();
cy.location("pathname").should("eq", "/");
// Make sure we can still access the guest link after logging out.
cy.visit($href);
// Continue with the test
});
then()
doesn’t return a real Promise
objectthen()
support await
Promise
s// Save the route to the guest link URL so that we can return to it later.
const guestLinkRouteValue = await page
.locator('.table td[test-data-id="guest-link-label"] a')
.getAttribute("href");
expect(guestLinkRouteValue).not.toBeNull();
const guestLinkRoute = String(guestLinkRouteValue);
// Log out.
await page.locator("#navbar-log-out").click();
await expect(page).toHaveURL("/");
// Make sure we can still access the guest link after logging out.
await page.goto(guestLinkRoute);
// Continue with the test.
<p data-test-id="github-instructions">
Visit our
<a href="https://github.com/mtlynch/picoshare">Github repo</a> to create your
own PicoShare server.
</p>
Naive test:
cy.get("[data-test-id='github-instructions']").should(
"have.text",
"Visit our Github repo to create your own PicoShare server."
);
Timed out retrying after 10000ms
+ expected - actual
-'\n Visit our\n Github repo to create\n your own PicoShare server.\n '
+'Visit our Github repo to create your own PicoShare server.'
<p data-test-id="github-instructions">
Visit our
<a href="https://github.com/mtlynch/picoshare">Github repo</a> to create your
own PicoShare server.
</p>
Correct test:
cy.get("[data-test-id='github-instructions']").should(($el) => {
expect($el.get(0).innerText).to.eq(
"Visit our Github repo to create your own PicoShare server."
);
});
<p data-test-id="github-instructions">
Visit our
<a href="https://github.com/mtlynch/picoshare">Github repo</a> to create your
own PicoShare server.
</p>
await expect(page.locator("data-test-id=github-instructions")).toHaveText(
"Visit our Github repo to create your own PicoShare server."
);
webServer: {
command: "PS_SHARED_SECRET=dummypass PORT=6001 ./bin/picoshare",
port: 6001,
},
console.log("hello from Cypress"); // this does nothing
cy.log("hello from Cypress"); // this prints nothing to the terminal
console.log
in Playwright just worksconsole.log("hello from Playwright");
[chromium] › auth.spec.ts:3:1 › logs in and logs out
hello from Playwright
cy.get(".navbar-item [data-test-id='log-in']").should("be.visible");
How Playwright works:
await expect(
page.locator(".navbar-item [data-test-id='log-in']")
).toBeVisible();
What I want:
// INVALID - not how Playwright actually behaves
await page
.locator(".navbar-item [data-test-id='log-in']")
.expect()
.toBeVisible();
Promise
s