diff --git a/detect/synthetic-monitoring/playwright-checks/configuration.mdx b/detect/synthetic-monitoring/playwright-checks/configuration.mdx index ba61703d..c5f360ed 100644 --- a/detect/synthetic-monitoring/playwright-checks/configuration.mdx +++ b/detect/synthetic-monitoring/playwright-checks/configuration.mdx @@ -7,7 +7,7 @@ sidebarTitle: 'Configuration' Use the `checkly.config.ts/js` file to define your Playwright Check Suite. Each Playwright Check Suite can be connected to references in your `playwright.config.ts/js` file. -**A Playwright Check Suite can run up to 15 minutes**. [Please contact us in the Checkly Web App](https://app.checklyhq.com/?support=true) or get in touch with your account executive if you're interested in longer runs. +**A Playwright Check Suite can run up to 30 minutes**. [Please contact us in the Checkly Web App](https://app.checklyhq.com/?support=true) or get in touch with your account executive if you're interested in longer runs. ## Playwright Check Suite definition @@ -216,9 +216,9 @@ Verify that `playwrightConfigPath` points to the correct relative path from your ### Test execution issues -**Tests exceed 20-minute limit** +**Tests exceed 30-minute limit** -If your Playwright Check Suite times out after 20 minutes: +If your Playwright Check Suite times out after 30 minutes: - Split large test suites into multiple Playwright Check Suites using `pwTags` or `pwProjects` - Use `.only` or `.skip` in your tests during development, then create separate check suites for different test priorities @@ -238,4 +238,4 @@ If dependencies fail to install: If tests fail due to authentication issues: - Verify environment variables are set correctly in Checkly. You can verify your environment variables using `npx checkly env ls`, or looking at your Global or Check's environment variables in the Checkly Webapp to ensure any `process.env.VARIABLE_NAME` call from your test is defined. -- For persistent authentication, use Playwright's [`storageState`](https://playwright.dev/docs/auth#reuse-authentication-state) feature. \ No newline at end of file +- For persistent authentication, use Playwright's [`storageState`](https://playwright.dev/docs/auth#reuse-authentication-state) feature. diff --git a/detect/synthetic-monitoring/playwright-checks/overview.mdx b/detect/synthetic-monitoring/playwright-checks/overview.mdx index 3620aef3..7589bec5 100644 --- a/detect/synthetic-monitoring/playwright-checks/overview.mdx +++ b/detect/synthetic-monitoring/playwright-checks/overview.mdx @@ -7,7 +7,7 @@ tags: ['synthetic-monitoring', 'playwright-checks'] ## What are Playwright Check Suites? -Playwright Check Suites turn your Playwright end-to-end tests into production monitors. Run entire test suites, specific projects, or tagged tests globally without modifying your existing code or configuration. +**Playwright Check Suites turn your Playwright end-to-end tests into production monitors.** Run entire test suites, specific projects, or tagged tests globally without modifying your existing code or configuration. **Known limitations**: Playwright Check Suites do not currently support monorepo workspaces for dependency installation. diff --git a/images/icons/playwright.svg b/images/icons/playwright.svg new file mode 100644 index 00000000..bf7f696a --- /dev/null +++ b/images/icons/playwright.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/images/playwright.png b/images/playwright.png deleted file mode 100644 index 8a6e83e3..00000000 Binary files a/images/playwright.png and /dev/null differ diff --git a/images/samples/images/pdf-generation-hd.png b/images/samples/images/pdf-generation-hd.png index 44cb56bb..68735772 100644 Binary files a/images/samples/images/pdf-generation-hd.png and b/images/samples/images/pdf-generation-hd.png differ diff --git a/learn/playwright/assertions.mdx b/learn/playwright/assertions.mdx index 0c1112dc..244c0896 100644 --- a/learn/playwright/assertions.mdx +++ b/learn/playwright/assertions.mdx @@ -12,12 +12,13 @@ sidebarTitle: Assertions --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" ### What are Playwright Assertions? -Playwright is more than a testing framework. With its generalized tool at simulating user behavior in a browser (or via an API), playwright is better defined as a web automation framework. You can use Playwright to scrape websites, automate form submissions, or any other time it would be helpful to replace a human web user with a robot. For most users, Playwright is intimately associated with end-to-end tests, and for these we must stop our automated actions and check to see if everything is working right. +Playwright is more than a testing framework. With its generalized tool at simulating user behavior in a browser (or via an API), Playwright is better defined as a web automation framework. You can use Playwright to scrape websites, automate form submissions, or any other time it would be helpful to replace a human web user with a robot. For most users, Playwright is intimately associated with end-to-end tests, and for these we must stop our automated actions and check to see if everything is working right. To make an automation into a test, we have assertions. When a hard assertion fails, the execution of a Playwright test stops, and following steps are not run. @@ -27,7 +28,7 @@ Playwright offers a variety of assertion types to accommodate different testing ### Auto-retrying, Web-first Assertions -Auto-retrying assertions automatically recheck conditions until they pass or a timeout is reached. They both make a test more stable, and can make tests execute more quickly, and in the language of game theory should be ‘strictly better’ than non-retrying assertions. +Auto-retrying assertions automatically recheck conditions until they pass or a timeout is reached. They both make a test more stable, and can make tests execute more quickly, and in the language of game theory should be 'strictly better' than non-retrying assertions. | **Assertion** | **Description** | | --- | --- | @@ -88,21 +89,27 @@ Non-retrying assertions evaluate conditions only once. They are used when you ex | `expect(value).toBeDefined()` | value is defined (not `undefined`). | | `expect(value).toBeNaN()` | value is `NaN`. | -This makes the most sense when using Playwright to run single end-to-end tests in a controlled environment. If you’re using Playwright to run on a cadence and monitor a production system, for example, with [Checkly](https://www.checklyhq.com/docs/browser-checks/playwright-test/), you generally want to stick with the auto-retrying assertions. +This makes the most sense when using Playwright to run single end-to-end tests in a controlled environment. If you're using Playwright to run on a cadence and monitor a production system, for example, with [Checkly](https://www.checklyhq.com/docs/browser-checks/playwright-test/), you generally want to stick with the auto-retrying assertions to avoid unnecessary alerts. ### Negating Assertions -Negating matchers allow you to assert that a condition does not hold. For example, you can use `toBeFalsy` or `not.toContain` to make negative assertions (as will be explained later, if you’re checking an element directly, probably the latter of these two options will work better as it implements Playwright’s auto-retries). +Negating matchers allow you to assert that a condition does not hold. For example, you can use `toBeFalsy` or `not.toContain` to make negative assertions (as will be explained later, if you're checking an element directly, probably the latter of these two options will work better as it implements Playwright's auto-retries). ### Soft Assertions -Soft assertions collect all failures within a block before failing the test, rather than stopping at the first failure. This approach is useful for gathering more complete information during test runs. Soft assertions are a critical component of production monitoring, as when measuring things like load times, a failing response time may not mean that we want to stop the check entirely. Any Playwright test with failing soft assertions will be listed as failed, but the test will still run to completion (or the next hard assertion that fails). +Soft assertions won't fail your test immediately, but rather allow the test to continue running after a failure. Using soft assertions is useful for gathering more complete information during test runs. Soft assertions are a critical component of production monitoring, as when measuring things like load times, a failing response time may not mean that we want to stop the check entirely. Any Playwright test with failing soft assertions will still be listed as failed, but the test will still run to completion (or the next hard assertion that fails). + +```typescript login.spec.ts +// if this assertion fails the following actions and +// assertions will still run but the test will be marked as failed +await expect.soft(page.getByTestId('cookieBanner')).toBeVisible(); +``` ### Checkly, soft assertions, and degraded check states -Checkly can use soft assertions as part of a ‘degraded’ state for checks. If a check fails soft assertions and there is a call to `markCheckAsDegraded`, the check will be placed in a ‘yellow light’ category of degraded rather than failing. Instead of categorizing the check as a total failure the 'degraded' state signals that the check encountered issues but still completed execution. Degraded checks have different notification policies. For example: you might have degraded checks report to Slack rather than sending a notification that wakes people up. +Checkly can use soft assertions as part of [a `degraded` state for Multistep checks](/detect/synthetic-monitoring/multistep-checks/degraded-states). If a check fails soft assertions and there is a call to `markCheckAsDegraded`, the check will be placed in a 'yellow light' category of degraded rather than failing. Instead of categorizing the check as a total failure the 'degraded' state signals that the check encountered issues but still completed execution. Degraded checks have different notification policies. For example: you might have degraded checks report to Slack rather than sending a notification that wakes people up. -This is useful for distinguishing between partial service disruptions and complete outages, offering teams a more precise understanding of performance and reliability. If your Playwright test is running on Checkly, the check will enter a ‘degraded’ state when some soft assertions fail, or if you call `markCheckAsDegraded` in its execution. +This is useful for distinguishing between partial service disruptions and complete outages, offering teams a more precise understanding of performance and reliability. If your Playwright test is running on Checkly, the check will enter a 'degraded' state when some soft assertions fail, or if you call `markCheckAsDegraded` in its execution. ```ts soft-assertions.spec.ts import { test, expect } from '@playwright/test' @@ -132,7 +139,9 @@ test("SpaceX-API Dragon Capsules & Next Launch", async ({ request }) => { }) ``` -In this case if the response has a 200 status code but the API response time is more than 200 seconds, the status of this check will be degraded and the slow api response time will be included as a failed step. If the response came back as a non-200 status (indicating an error) then the check would be ‘failed,’ whether or not `markCheckAsDegraded` was called. You can [configure alert channels](https://www.checklyhq.com/docs/communicate/alerts/channels#managing-alert-channels) to notify you when a check has degraded. +`degraded` using `@checkly/playwright-helpers` states are currently only available for [Multistep Checks](/detect/synthetic-monitoring/multistep-checks/overview) and [Browser Checks](/detect/synthetic-monitoring/browser-checks/overview). + +In this case if the response has a `200` status code but the API response time is more than 200 milliseconds, the status of this check will be degraded and the slow API response time will be included as a failed step. If the response came back as a non-200 status (indicating an error) then the check would be 'failed,' whether or not `markCheckAsDegraded` was called. You can [configure alert channels](https://www.checklyhq.com/docs/communicate/alerts/channels#managing-alert-channels) to notify you when a check has degraded. ### Custom Assertions @@ -155,9 +164,9 @@ Soft assertions are helpful for tests where understanding multiple failures is b | **Asserting non-deterministic or flaky conditions (for example images loading in X seconds)** | Yes. Can handle variations more gracefully, allowing the test to proceed for better overall coverage. | No. Would stop execution unnecessarily and increase the risk of flaky tests. | | **Pre-check for test prerequisites** | No. If a condition must be true for the rest of the test to proceed, use a hard assertion. | Yes. If a pre-requisite check kicks off further steps, all further steps should stop if the rerequisite fails. | | **Validating UI elements during navigation** | Yes. When testing multiple UI states, soft assertions can log failures without interrupting the flow. | Only if the missing UI element would block further navigation. | -| **Critical database operation validations** | No. If a data inconsistency occurs, it’s usually vital to stop further operations. | Yes. Data integrity should be enforced strictly with hard assertions. | +| **Critical database operation validations** | No. If a data inconsistency occurs, it's usually vital to stop further operations. | Yes. Data integrity should be enforced strictly with hard assertions. | | **Form field validations** | Yes. Allows collecting errors on multiple fields at once, providing more detailed feedback. | No. Stopping at the first validation failure can hinder broader test coverage. | -| **Verifying the presence of essential elements before action** | No. If the element must exist for the test to continue, a hard assertion ensures reliability. | Yes, if the element’s presence is not critical and you want the test to proceed. | +| **Verifying the presence of essential elements before action** | No. If the element must exist for the test to continue, a hard assertion ensures reliability. | Yes, if the element's presence is not critical and you want the test to proceed. | ### How to Get Started with Playwright Assertions in Simple Steps @@ -196,7 +205,7 @@ expect.extend({ expect(100).toBeWithinRange(90, 110) ``` -This can be especially useful if we’re doing complex assertions, or specialized parsing of responses. +This can be especially useful if we're doing complex assertions, or specialized parsing of responses. ## Common Assertion Errors and How to Debug Them @@ -204,19 +213,19 @@ Understanding how to diagnose assertion failures can save significant debugging ### Hard waits -*Hard waits should be avoided.* A ‘hard wait’ refers to giving an exact period of time before going on to the next step of a test. Generally using code like: +*Hard waits should be avoided.* A 'hard wait' refers to giving an exact period of time before going on to the next step of a test. Generally using code like: ```ts bad-practice.spec.ts await page.waitForTimeout(3000); ``` -When you have page components you want to ensure are loading quickly, or you have page components that you know take some time to load, it’s tempting to reach for a hard wait, however, there are better ways to accomplish this functionality, like the soft assertions and auto-retry assertions listed above. +When you have page components you want to ensure are loading quickly, or you have page components that you know take some time to load, it's tempting to reach for a hard wait, however, there are better ways to accomplish this functionality, like the soft assertions and auto-retry assertions listed above. -After that fixed period, if the next step doesn’t work, the test will fail. Hard waits are the most common cause of unreliable or ‘flaky’ tests with Playwright. They’re also inefficient, if the element we’re checking for becomes available *before* the hard wait time has elapsed, the test runner still has to wait to the end of the wait time. Read more about this in our page on [waiting in Playwright](https://www.checklyhq.com/learn/playwright/waits-and-timeouts/). +After that fixed period, if the next step doesn't work, the test will fail. Hard waits are the most common cause of unreliable or 'flaky' tests with Playwright. They're also inefficient, if the element we're checking for becomes available *before* the hard wait time has elapsed, the test runner still has to wait to the end of the wait time. Read more about this in our page on [waiting in Playwright](https://www.checklyhq.com/learn/playwright/waits-and-timeouts/). ### Manual Assertions -While a hard wait is problematic since it doesn’t benefit from Playwright’s auto-waiting, an improperly structured assertion doesn’t include waiting at all. By wrapping the `await` inside the `expect()` instead of vice versa, and by using a non-web-first assertion, we get no waiting. In this case we’re checking that there is some text inside an element. +While a hard wait is problematic since it doesn't benefit from Playwright's auto-waiting, an improperly structured assertion doesn't include waiting at all. By wrapping the `await` inside the `expect()` instead of vice versa, and by using a non-web-first assertion, we get no waiting. In this case we're checking that there is some text inside an element. ```ts manual-assertion-bad.spec.ts // expects the text to be visible instantly @@ -242,26 +251,28 @@ Flaky tests are those that fail intermittently, often due to timing issues or un Implementing best practices can make your tests more reliable and easier to maintain. -- **Test Granularity**: Structure tests to cover distinct, isolated behaviors, making debugging easier. The choice between one ‘super test’ and 5 or 10 smaller tests should always go with the more granular option. Since [tests can be run in parallel](https://www.checklyhq.com/learn/playwright/testing-in-parallel/), it’s likely that better test granularity will also improve test execution time. -- **Create Concise Statements**: Keep assertions simple and focused. Asserting that five different page components is an indicator that you’re testing multiple ideas with one test, and want to consider either breaking up your test or should at least have multiple steps. -- **Use Descriptive Messages**: Adding clear messages to assertions helps identify failures quickly. It’s also good to use [test steps](https://www.checklyhq.com/blog/improve-your-playwright-documentation-with-steps/) to add more description to the exact phase where the test failed. Read further to see how to [add test steps programmatically with Typescript decorators](https://www.checklyhq.com/blog/playwright-test-steps-with-typescript-decorators/). +- **Test Granularity**: Structure tests to cover distinct, isolated behaviors, making debugging easier. The choice between one 'super test' and 5 or 10 smaller tests should always go with the more granular option. Since [tests can be run in parallel](https://www.checklyhq.com/learn/playwright/testing-in-parallel/), it's likely that better test granularity will also improve test execution time. +- **Create Concise Statements**: Keep assertions simple and focused. Asserting that five different page components is an indicator that you're testing multiple ideas with one test, and want to consider either breaking up your test or should at least have multiple steps. +- **Use Descriptive Messages**: Adding clear messages to assertions helps identify failures quickly. It's also good to use [test steps](https://www.checklyhq.com/blog/improve-your-playwright-documentation-with-steps/) to add more description to the exact phase where the test failed. Read further to see how to [add test steps programmatically with Typescript decorators](https://www.checklyhq.com/blog/playwright-test-steps-with-typescript-decorators/). - **Parameterize Assertions**: Use variables for assertion parameters to improve test readability and maintainability. -- **Leverage Libraries**: Utilize existing libraries for common assertions where possible. Note that if you’re running tests on a cadence, a full set of libraries may not be available in your execution environment. +- **Leverage Libraries**: Utilize existing libraries for common assertions where possible. Note that if you're running tests on a cadence, a full set of libraries may not be available in your execution environment. - **Be Specific**: Make sure your assertions are as targeted as possible to avoid false positives. Bet on auto-waiting and web-first assertions. Even a change from checking if a text label has the needed text with [`.toContain()`](https://playwright.dev/docs/api/class-genericassertions#generic-assertions-to-contain-1) rather than `toBe()` can improve the reliability of a page monitor. -- **Leverage Built-in Timeout**: Use Playwright’s built-in timeout features to handle flaky conditions gracefully. Avoid hard waits whenever possible. +- **Leverage Built-in Timeout**: Use Playwright's built-in timeout features to handle flaky conditions gracefully. Avoid hard waits whenever possible. + +### How Checkly can help with Playwright -### How can Checkly Help with Playwright Assertions +Checkly enables you to take your existing Playwright code base to run it as global synthetic monitoring. Use the power of Playwright to effectively simulate a real user's behavior with your site or service, and get alerts of problems before your users have noticed. -Checkly offers tools for continuous monitoring using Playwright scripts. With Checkly, you use the power of Playwright to effectively simulate a real user’s behavior with your site or service, and a can get alerts of problems before your users have noticed. + ### Conclusion -By using the right types of assertions, debugging tools, and best practices, you can ensure your tests are robust and efficient. In general, my direct experience has served to emphasize the wisdom of the Playwright project’s recommendations: web first assertions, dependent on web-first selectors. +By using the right types of assertions, debugging tools, and best practices, you can ensure your tests are robust and efficient. In general, my direct experience has served to emphasize the wisdom of the Playwright project's recommendations: web first assertions, dependent on web-first selectors. -For assertions, web-first, auto-retrying assertions are the preferred choice for most scenarios, as they leverage Playwright’s built-in waiting mechanisms, making tests more resilient and less prone to flakiness. These assertions continuously check conditions until they pass or reach a timeout, which can help streamline test execution. Examples like `toBeVisible` or `toContainText` illustrate how these assertions can improve test stability. On the other hand, non-retrying assertions evaluate conditions just once and should be reserved for scenarios where retries are unnecessary or could introduce ambiguity. Anything other than web-first assertions will lead to brittle tests with more false positives. +For assertions, web-first, auto-retrying assertions are the preferred choice for most scenarios, as they leverage Playwright's built-in waiting mechanisms, making tests more resilient and less prone to flakiness. These assertions continuously check conditions until they pass or reach a timeout, which can help streamline test execution. Examples like `toBeVisible` or `toContainText` illustrate how these assertions can improve test stability. On the other hand, non-retrying assertions evaluate conditions just once and should be reserved for scenarios where retries are unnecessary or could introduce ambiguity. Anything other than web-first assertions will lead to brittle tests with more false positives. Soft assertions also add value by collecting all failures within a block before stopping the test, offering a complete picture of what went wrong. They are especially useful in production monitoring scenarios where partial failures should not disrupt the entire check, as seen in the Checkly example using `markCheckAsDegraded`. The ability to use soft assertions alongside the concept of a degraded state provides a nuanced way to monitor service health without causing false alarms. -I’ll again recommend avoiding some common pitfalls, such as relying on hard waits, which can introduce flakiness and inefficiency into your tests. Using auto-waiting mechanisms and structuring assertions properly can make a significant difference. Debugging tools like `page.pause()` and verbose logging, combined with visual debugging options, can be valuable in diagnosing test failures. +I'll again recommend avoiding some common pitfalls, such as relying on hard waits, which can introduce flakiness and inefficiency into your tests. Using auto-waiting mechanisms and structuring assertions properly can make a significant difference. Debugging tools like `page.pause()` and verbose logging, combined with visual debugging options, can be valuable in diagnosing test failures. Follow best practices now for a better testing and monitoring experience later. These include using concise, focused assertions, adding descriptive messages for better debugging, and leveraging built-in timeouts and parameterization for clarity and maintainability. Granular test design also matters as a way to improve both parallel execution efficiency and debugging ease. Avoiding complex, monolithic tests in favor of smaller, well-defined ones can make your testing framework more manageable and robust. diff --git a/learn/playwright/authentication.mdx b/learn/playwright/authentication.mdx index e4fbfe42..4285769f 100644 --- a/learn/playwright/authentication.mdx +++ b/learn/playwright/authentication.mdx @@ -20,6 +20,7 @@ aliases: - managing-cookies --- +import SignUpCta from "/snippets/sign-up-cta.mdx" import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" @@ -197,14 +198,14 @@ test('API token auth', async ({ request }) => { 'Authorization': `Bearer ${process.env.API_TOKEN}` } }) - expect(response).toBeOK() + expect(response).toBeOK() }) ``` Just like with username and password authentication, make sure to store your API tokens securely using environment variables. -# Reusing authentication state with storageState +# Reusing authentication state with `storageState` All of the above examples work fine if you are running just one test that requires authentication. However, the moment you will run more tests — either in parallel or in sequence — you will exercise your authentication @@ -215,7 +216,7 @@ Ideally, you can authenticate once and reuse the authenticated state across mult [Playwright has this feature baked in](https://playwright.dev/docs/auth) and leverages something called `storageState`. It requires a little setup 👇 -## Setting up the playwright.config.ts file +## Setting up the `playwright.config.ts` file The recommended way to reuse auth state is by setting up **projects** in your `playwright.config.ts` file and defining a `setup` step that references file — `auth.setup.ts` for example — that takes care of the necessary authentication flow. @@ -303,3 +304,5 @@ When writing automation scripts that deal with authentication, there are some ge - [How to automate Google login with Playwright.](https://www.checklyhq.com/learn/playwright/google-login-automation/) - [How to bypass Time-Based 2FA login flows with Playwright.](https://www.checklyhq.com/learn/playwright/bypass-totp/) + + diff --git a/learn/playwright/bypass-totp.mdx b/learn/playwright/bypass-totp.mdx index b28ff6b5..252c03ff 100644 --- a/learn/playwright/bypass-totp.mdx +++ b/learn/playwright/bypass-totp.mdx @@ -14,6 +14,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -188,3 +189,5 @@ I’m still amazed at how far we’ve come with the recent tooling. Playwright c But keep in mind end-to-end testing is only a tiny fraction of guaranteeing that your product is working. Third-party providers can go rogue, or your database can struggle days after you tested your deployment. That’s why I’m excited to announce that [the recently released Checkly runtime (2022.10)](https://www.checklyhq.com/docs/runtimes/specs/#2022.10) includes the “otpauth” package and allows you to test your products at all times — even the ones that are behind a 2FA secured login! Do you want to be the first one to know when something’s off with your application? Give Checkly a try 😉. + + diff --git a/learn/playwright/challenging-flows.mdx b/learn/playwright/challenging-flows.mdx index 23c85f3a..8759d43a 100644 --- a/learn/playwright/challenging-flows.mdx +++ b/learn/playwright/challenging-flows.mdx @@ -13,6 +13,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -67,3 +68,5 @@ In these cases, UI automation is specifically made more difficult by utilising c ## Further reading 1. [OWASP's Automated Threat list](https://wiki.owasp.org/index.php/Category:Automated_Threat) + + diff --git a/learn/playwright/checkout-testing-guide.mdx b/learn/playwright/checkout-testing-guide.mdx index f73badd5..98626dfa 100644 --- a/learn/playwright/checkout-testing-guide.mdx +++ b/learn/playwright/checkout-testing-guide.mdx @@ -13,6 +13,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -82,3 +83,5 @@ Checkout is a peculiar flow: unlike Login and others, it almost always involves 1. Checkout flows will vary depending on what is being purchased. 2. Remember to check different flows (e.g. with and without login) if needed. 3. Additional care is needed on production systems as real transactions will take place. + + diff --git a/learn/playwright/clicking-typing-hovering.mdx b/learn/playwright/clicking-typing-hovering.mdx index e399448f..1da2a952 100644 --- a/learn/playwright/clicking-typing-hovering.mdx +++ b/learn/playwright/clicking-typing-hovering.mdx @@ -17,6 +17,7 @@ learn_playwright: parent: "Interaction" --- +import SignUpCta from "/snippets/sign-up-cta.mdx" import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" @@ -38,12 +39,6 @@ test('can click log in', async ({ page }) => { }) ``` - -For the times when even the humble click fails, you can try the following alternatives: -1. `await page.click('#login', { force: true })` to force the click even if the selected element appears not to be accessible -2. `await page.$eval('#login', elem => elem.click())` to run the click inside the webpage -3. `await page.dispatchEvent('#login', 'click')` to directly dispatch the click event on the element - ## Hovering A popular pattern among web pages is exposing additional information or functionality when the user hovers the mouse cursor over a specific item. Examples include, menus, previews and dialogs containing extra information on the item. @@ -108,6 +103,8 @@ You can run (from the terminal) the above examples as follows: npx playwright test basic-click-type.ts ``` + + ## Further reading 1. The related official documentation of [Playwright](https://playwright.dev/docs/input#mouse-click) 2. [Finding effective selectors](/learn/playwright/selectors/) diff --git a/learn/playwright/codegen.mdx b/learn/playwright/codegen.mdx index 17d04f41..16c2be0c 100644 --- a/learn/playwright/codegen.mdx +++ b/learn/playwright/codegen.mdx @@ -14,6 +14,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" import { YoutubeEmbed } from "/snippets/youtube-embed.jsx" @@ -60,7 +61,7 @@ test('test', async ({ page }) => { Note that codegen will make a ‘best effort’ at emulating your actions and writing ‘best practice’ code, so you should always review it before deploying. -### Step 5: Add Assertions to your tests +### Step 3: Add Assertions to your tests Every action in the script above has implicit assertions about the elements we interact with. Playwright will expect these elements are stable, visible, and enabled; and if one isn’t then the test will fail we could call this done, but we generally want our tests to contain assertions beyond just navigating. There are a few reasons why you should have assertions in your test: It makes it clearer to future coders what your test was checking for, and the error message is more useful from a failed assertion rather than just failing to find an element. Right now all we’ll get if the test above fails is a timeout and a line which failed. @@ -89,11 +90,13 @@ For this example, let's pick JavaScript. You can copy the generated script from ### Step 5: Save and Run Your Script -With your script copied, you can drop the test into your Playwright spec file, and run it to see the results. Note that the script as generated contains no comments, and isn’t in steps. If you want to be considerate of your next coder, who let’s be honest is probably you in 6 months having forgotten everything about this test, add some comments, give the test a more helpful name than `'test'` and [divide the test into steps for readability](https://www.checklyhq.com/blog/improve-your-playwright-documentation-with-steps/). +With your script copied, you can drop the test into a Playwright `spec` file, and run it with `npx playwright test` to see the results. Note that the script as generated contains no comments or further explanations. If you want to be considerate of your next coder, who let’s be honest is probably you in 6 months having forgotten everything about this test, add some comments, give the test a more helpful name than `'test'` and [divide the test into steps for readability](https://www.checklyhq.com/blog/improve-your-playwright-documentation-with-steps/). -### Step 5: Run Your Script in the Cloud +### Step 6: Run Your Script in the Cloud -The script you generated works perfectly in your local environment. But if you want to take it a step further, you can copy and [paste the script into a Checkly browser check](https://www.checklyhq.com/docs/browser-checks/) to run it in the cloud on their infrastructure. This is especially useful for continuous monitoring and testing in different environments and from different geographies. If you’re not partial to a web interface, deploy your locally saved Playwright tests directly to Checkly with the [Checkly CLI](https://www.checklyhq.com/cli/overview). With our CLI, you can work on tests locally and then run them through the Checkly system right from your command line. +If you want to take it a step further, use [Playwright Check Suites](/detect/synthetic-monitoring/playwright-checks/overview) to run your Playwright tests in the Checkly infrastructure as synthetic monitoring. + + ### Bonus Step 1: Add Playwright to Visual Studio Code @@ -131,3 +134,5 @@ To see the highly visual codegen tool in action, check out Stefan’s video belo You’ve just taken your first steps with creating Playwright tests. Playwright's `codegen` is a powerful tool that simplifies the process of creating automation scripts. As it produces assertions and locators that are industry standard, you should use anytime you need to make a clean, readable test or automation for your site. If you’d like to dive deeper into Playwright and Checkly’s monitoring tools, join our [upcoming Kick-Start webinar](https://us02web.zoom.us/webinar/register/WN_gKYeJcMqQ_Kh31ziKM7uYw) to see how your end-to-end testing can grow into bullet-proof site monitoring to defend your SLA. + + diff --git a/learn/playwright/debugging-errors.mdx b/learn/playwright/debugging-errors.mdx index 89ba953c..d3f8f280 100644 --- a/learn/playwright/debugging-errors.mdx +++ b/learn/playwright/debugging-errors.mdx @@ -15,6 +15,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -40,3 +41,5 @@ To help avoid stressful and unsuccessful debugging sessions, it might help to co 2. [Error: element not visible](/learn/playwright/error-element-not-visible/) 3. [Error: target closed](/learn/playwright/error-target-closed/) 4. [Error: wait not respected](/learn/playwright/error-wait-not-respected/) + + diff --git a/learn/playwright/debugging.mdx b/learn/playwright/debugging.mdx index d7b51dfa..df69625f 100644 --- a/learn/playwright/debugging.mdx +++ b/learn/playwright/debugging.mdx @@ -15,6 +15,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -117,3 +118,5 @@ The Inspector allows us to easily step through each instruction of our script, w 1. [Debugging challenges](/learn/playwright/debugging-errors/) 2. [Working with selectors](/learn/playwright/selectors/) + + diff --git a/learn/playwright/emulating-mobile-devices.mdx b/learn/playwright/emulating-mobile-devices.mdx index fd200abc..3e21785c 100644 --- a/learn/playwright/emulating-mobile-devices.mdx +++ b/learn/playwright/emulating-mobile-devices.mdx @@ -17,6 +17,7 @@ learn_playwright: parent: "Basics" --- +import SignUpCta from "/snippets/sign-up-cta.mdx" import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" @@ -95,3 +96,5 @@ test('emulate iPhone SE', async ({ page }) => { 1. [Measuring page performance](/learn/playwright/performance/) 2. [Playwright's emulation documentation](https://playwright.dev/docs/emulation) + + diff --git a/learn/playwright/error-click-not-executed.mdx b/learn/playwright/error-click-not-executed.mdx index 40ceb41a..4af9d7c2 100644 --- a/learn/playwright/error-click-not-executed.mdx +++ b/learn/playwright/error-click-not-executed.mdx @@ -12,6 +12,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -34,3 +35,5 @@ Unless you know for certain, do not assume that the page you are automating foll If you are running Playwright 1.14 or newer, you can also enable [strict mode](https://playwright.dev/docs/release-notes#version-114) to have it throw an error in case your selector matches more than one element on the page: `await page.click('mySelector', { strict: true });` > Note that this list neither is nor aims to be complete: additional possible causes most likely exist for this error. + + diff --git a/learn/playwright/error-element-not-found.mdx b/learn/playwright/error-element-not-found.mdx index 4ba19a5c..41f4a1d0 100644 --- a/learn/playwright/error-element-not-found.mdx +++ b/learn/playwright/error-element-not-found.mdx @@ -12,6 +12,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -33,3 +34,5 @@ UnhandledPromiseRejectionWarning: Error: No node found for selector: ... Either walk through the execution in headful mode or take screenshots before and after the instruction that has raised the error - this will help you verify whether the application state actually is the one you expect. > Note that this list neither is nor aims to be complete: additional possible causes most likely exist for this error. + + diff --git a/learn/playwright/error-element-not-visible.mdx b/learn/playwright/error-element-not-visible.mdx index 88d43a18..d11b80c3 100644 --- a/learn/playwright/error-element-not-visible.mdx +++ b/learn/playwright/error-element-not-visible.mdx @@ -12,6 +12,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -35,3 +36,5 @@ waiting for selector ".contact-form > .form-control" to be visible Either walk through the execution in headful mode or take screenshots before and after the instruction that has raised the error - this will help you verify whether the application state actually is the one you expect. > Note that this list neither is nor aims to be complete: additional possible causes most likely exist for this error. + + diff --git a/learn/playwright/error-target-closed.mdx b/learn/playwright/error-target-closed.mdx index d51b8cac..7d3406d0 100644 --- a/learn/playwright/error-target-closed.mdx +++ b/learn/playwright/error-target-closed.mdx @@ -12,6 +12,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -30,3 +31,5 @@ UnhandledPromiseRejectionWarning: Error: Protocol error: Target closed 2. [Wrong foreach usage](https://github.com/babel/babel/issues/909): [forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) expects a synchronous function, so use a [for-of loop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) if you are using `await`. > Note that this list neither is nor aims to be complete: additional possible causes most likely exist for this error. + + diff --git a/learn/playwright/error-wait-not-respected.mdx b/learn/playwright/error-wait-not-respected.mdx index 27114e0c..2eda7739 100644 --- a/learn/playwright/error-wait-not-respected.mdx +++ b/learn/playwright/error-wait-not-respected.mdx @@ -12,6 +12,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -28,3 +29,5 @@ For example: we are waiting for an element, e.g. with `page.waitForSelector`, bu Try querying for the element in the browser console during inspection. If the element is found, inspect its attributes (e.g. `visibility`) and ensure they match your expectations. > Note that this list neither is nor aims to be complete: additional possible causes most likely exist for this error. + + diff --git a/learn/playwright/file-download.mdx b/learn/playwright/file-download.mdx index d9e047dd..ebdadedc 100644 --- a/learn/playwright/file-download.mdx +++ b/learn/playwright/file-download.mdx @@ -14,6 +14,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -126,3 +127,5 @@ npx playwright test file-download.spec.ts ## Further reading 1. [Playwright's](https://playwright.dev/#version=v1.3.0&path=docs%2Fapi.md&q=class-download) documentation on downloading files. + + diff --git a/learn/playwright/generating-pdfs.mdx b/learn/playwright/generating-pdfs.mdx index 002e69ee..e3896200 100644 --- a/learn/playwright/generating-pdfs.mdx +++ b/learn/playwright/generating-pdfs.mdx @@ -12,6 +12,7 @@ learn_playwright: parent: "Basics" --- +import SignUpCta from "/snippets/sign-up-cta.mdx" import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" @@ -61,7 +62,7 @@ We can also have custom headers and footers added to our pages, displaying value import { test, expect } from '@playwright/test'; test('generate PDF with header and footer', async ({ page }) => { - await page.goto('https://www.checklyhq.com/'); + await page.goto('https://www.checklyhq.com/docs/'); await page.pdf({ path: 'checkly-with-header-footer.pdf', format: 'A4', @@ -78,7 +79,7 @@ test('generate PDF with header and footer', async ({ page }) => { }); ``` -We are including the following template files for our header and footer. +Change `headerTemplate` and `footerTemplate` to include more complex templates like these ones below. **template-header.html** ```html @@ -147,7 +148,7 @@ We are including the following template files for our header and footer. ``` -The first page of the generated PDF looks as follows: +Then, the first page of the generated PDF looks as follows: ![generated pdf example](/images/samples/images/pdf-generation-hd.png) @@ -161,3 +162,4 @@ npx playwright test generate-pdf.ts We can easily transform existing web pages into PDF format, just as we have shown in our example. An even more interesting use case is about generating a brand new document: now we can use our existing HTML and CSS skills to produce high-quality PDFs, often eliminating the need for LaTeX or similar tools. + diff --git a/learn/playwright/google-login-automation.mdx b/learn/playwright/google-login-automation.mdx index c46502dc..c021b3ce 100644 --- a/learn/playwright/google-login-automation.mdx +++ b/learn/playwright/google-login-automation.mdx @@ -14,6 +14,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -70,7 +71,4 @@ npx playwright test google-login.spec.ts 2. Waiting for the navigation as you are redirected to Google is done automatically. 3. Waiting for the navigation as you are redirected back to the start site is done automatically. - - - - + diff --git a/learn/playwright/handling-test-data.mdx b/learn/playwright/handling-test-data.mdx index 27828c60..21850e48 100644 --- a/learn/playwright/handling-test-data.mdx +++ b/learn/playwright/handling-test-data.mdx @@ -14,6 +14,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -101,3 +102,5 @@ Faker covers a wide range of data that includes names, addresses, products, imag 1. Keep test data separate from your scripts. 2. REST APIs can be useful for retrieving test data. 3. Libraries such as Faker can help generate test data. + + diff --git a/learn/playwright/how-to-detect-broken-links.mdx b/learn/playwright/how-to-detect-broken-links.mdx index 4a8ed005..fc79a88f 100644 --- a/learn/playwright/how-to-detect-broken-links.mdx +++ b/learn/playwright/how-to-detect-broken-links.mdx @@ -13,6 +13,7 @@ learn_playwright: parent: "Basics" --- +import SignUpCta from "/snippets/sign-up-cta.mdx" import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" import { YoutubeEmbed } from "/snippets/youtube-embed.jsx" @@ -213,3 +214,5 @@ The loop includes soft assertions to keep running on failure, and we added custo You can now run Playwright in your CICD pipeline and check for broken links whenever you deploy your sites. Success! Again, you can find the final snippet on [GitHub](https://github.com/checkly/playwright-examples/tree/main/404-detection). + + diff --git a/learn/playwright/how-to-parameterize-playwright-projects.mdx b/learn/playwright/how-to-parameterize-playwright-projects.mdx index fe24f213..92e2ae67 100644 --- a/learn/playwright/how-to-parameterize-playwright-projects.mdx +++ b/learn/playwright/how-to-parameterize-playwright-projects.mdx @@ -14,6 +14,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" import { YoutubeEmbed } from "/snippets/youtube-embed.jsx" @@ -233,3 +234,4 @@ If you have any questions or comments, say "Hi" in the Checkly community Slack! But what's Checkly? Checkly enables you to take your existing Playwright tests running in CI/CD and transform them into synthetic [end-to-end monitoring](https://www.checklyhq.com/guides/end-to-end-monitoring/). Your Playwright tests will run around the clock and from anywhere on this planet so that you know that your production sites are up and running. And if they're not, you'll be the first to know because Checkly will alert you. It's pretty cool, trust me. 😉 + diff --git a/learn/playwright/how-to-search.mdx b/learn/playwright/how-to-search.mdx index 15deb822..058b0690 100644 --- a/learn/playwright/how-to-search.mdx +++ b/learn/playwright/how-to-search.mdx @@ -15,6 +15,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -86,3 +87,5 @@ Listing search terms and their corresponding expected results in a file could be 1. Moving test data to a separate file can help when running more thorough comparisons. 2. Assertion libraries help us cleanly verify multiple constraints in our test. + + diff --git a/learn/playwright/iframe-interaction.mdx b/learn/playwright/iframe-interaction.mdx index 596ca623..f275a654 100644 --- a/learn/playwright/iframe-interaction.mdx +++ b/learn/playwright/iframe-interaction.mdx @@ -12,6 +12,7 @@ learn_playwright: parent: "Interaction" --- +import SignUpCta from "/snippets/sign-up-cta.mdx" import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" @@ -33,6 +34,8 @@ test('access iframe content', async ({ page }) => { ``` + + ## Further reading 1. [Playwright's "Frames documentation"](https://playwright.dev/docs/frames) diff --git a/learn/playwright/intercept-requests.mdx b/learn/playwright/intercept-requests.mdx index d274abbd..272326ea 100644 --- a/learn/playwright/intercept-requests.mdx +++ b/learn/playwright/intercept-requests.mdx @@ -16,6 +16,7 @@ learn_playwright: parent: "Basics" --- +import SignUpCta from "/snippets/sign-up-cta.mdx" import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" @@ -127,7 +128,21 @@ npx playwright test request-interception.ts 1. Playwright gives us control over outgoing HTTP requests. 2. Playwright can easily stub HTTP responses. +## Avoid Network Interception in Synthetic Monitoring + +Network interception is valuable if your primary goal is to test a frontend application in isolation. However, if you want to test your application end-to-end or [use Playwright for synthetic production monitoring with Checkly](/detect/synthetic-monitoring/playwright-checks/overview) you should avoid network interception as much as possible. + +The goal of end-to-end testing and synthetic monitoring is to test the entire stack ranging from the backend systems to the last third-party JavaScript snippet being loaded in the frontend. + +- You won't learn about your image CDN's downtime if your tests block image requests to save bandwidth. +- You will never learn about your flaky checkout API flow if you mock all the `/order` requests. +- You won't be notified when a tracking script breaks your page layout if you block third-parties in your tests. + +Investing in fully end-to-end testing and monitoring can be challenging but it'll provide you the safety net you're aiming for. + ## Further reading 1. Official documentation on this topic from [Playwright](https://playwright.dev/docs/network). 2. [Mocks Aren't Stubs](https://martinfowler.com/articles/mocksArentStubs.html) by Martin Fowler. + + diff --git a/learn/playwright/login-automation.mdx b/learn/playwright/login-automation.mdx index 81c2eb79..393616b1 100644 --- a/learn/playwright/login-automation.mdx +++ b/learn/playwright/login-automation.mdx @@ -14,6 +14,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -65,3 +66,4 @@ npx playwright test login.spec.ts 1. Use environment variables to inject secrets. 2. You might need to wait for the navigation as you are redirected to the login screen/modal. + diff --git a/learn/playwright/microsoft-login-automation.mdx b/learn/playwright/microsoft-login-automation.mdx index eeadfd53..e7641ec4 100644 --- a/learn/playwright/microsoft-login-automation.mdx +++ b/learn/playwright/microsoft-login-automation.mdx @@ -14,6 +14,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -67,7 +68,4 @@ npx playwright test ms-account-login.spec.ts 2. Wait for the navigation as you are redirected to Microsoft. 3. Wait for the navigation as you are redirected back to the start site. - - - - + diff --git a/learn/playwright/mock-api.mdx b/learn/playwright/mock-api.mdx index d089fe94..965a5142 100644 --- a/learn/playwright/mock-api.mdx +++ b/learn/playwright/mock-api.mdx @@ -15,6 +15,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -215,3 +216,5 @@ With Playwright's powerful API mocking capabilities, you gain precise control ov - **Over-Mocking**: Avoid mocking everything, as this can lead to tests that don’t reflect real-world behavior. Use mocking strategically to complement, not replace, real API testing. Playwright’s API mocking capabilities empower you to create robust, reliable, and efficient tests for dynamic web applications. By combining mocking with other testing strategies—such as visual regression testing and production monitoring—you can ensure your application delivers a consistent and high-quality user experience. Whether you’re testing edge cases, improving test speed, or ensuring UI consistency, Playwright provides the tools you need to build confidence in your application’s behavior. + + diff --git a/learn/playwright/multitab-flows.mdx b/learn/playwright/multitab-flows.mdx index b4a8ddd5..b70cadc7 100644 --- a/learn/playwright/multitab-flows.mdx +++ b/learn/playwright/multitab-flows.mdx @@ -13,6 +13,7 @@ learn_playwright: parent: "Basics" --- +import SignUpCta from "/snippets/sign-up-cta.mdx" import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" @@ -79,3 +80,5 @@ test('open multiple tabs', async ({ browser }) => { ## Further reading 1. Official documentation on [Playwright's multi-tab scenarios](https://playwright.dev/docs/multi-pages) + + diff --git a/learn/playwright/navigation.mdx b/learn/playwright/navigation.mdx index 52830d01..e9b5297c 100644 --- a/learn/playwright/navigation.mdx +++ b/learn/playwright/navigation.mdx @@ -18,6 +18,7 @@ learn_playwright: parent: "Interaction" --- +import SignUpCta from "/snippets/sign-up-cta.mdx" import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" @@ -31,7 +32,7 @@ Every script that we will write will almost certainly do three key things: ## Navigating -Initial navigation to any page is pretty much the same for both frameworks and can happen in multiple ways. +Initial navigation to any page can happen in multiple ways. - Whenever your code does a `page.goto()`, or a `page.click()` on a link, you explicitly trigger a navigation. - The webpage you are on can also trigger a navigation by executing `location.href= 'https://example.com'` or using the @@ -60,7 +61,7 @@ npx playwright test basic-browser-navigation.spec.ts ## Waiting -waiting for something to happen is a crucial part of any automation script. In most cases, this is handled automatically +Waiting for something to happen is a crucial part of any automation script. In most cases, this is handled automatically by Playwright. For example, when you click a button, Playwright will wait for that button to be clickable before it actually clicks it. In the example below, we type an email address into an input field on a login modal. Playwright's `fill` method comes with @@ -83,14 +84,17 @@ Run this example as follows: npx playwright test basic-browser-waiting.spec.ts ``` -However, there are cases where you need to wait for something specific to happen. For example, you might want to wait for a specific element to appear on the page. -In this case you may want to use the `page.waitForSelector()` method. +Playwright actions perform so-called [actionability checks](https://playwright.dev/docs/actionability#introduction) before interacting with DOM elements. -This method waits for an element to appear in the page. This is your bread and butter and should be used whenever something -needs to be loaded after clicking, hovering, navigating etc. You can pass it an object with a `timeout` attribute -to override the default 30 seconds. +If you call `click()` on a locator, Playwright will ensure that: -This works exactly the same for the `page.waitForXpath()` function is you are using XPath selectors instead of CSS selectors. +- your locator resolves to exactly one element. +- the matching element is visible. +- the matching element is stable. +- the matching element can receive events and is not covered or obscured by other elements. +- the matching element is enabled. + +Playwright's auto-waiting and actionability checks allow you to focus on the end-to-end test flow without worrying when and if elements become visible. Playwright evaluates this for you. ## Timeouts @@ -110,34 +114,22 @@ using this if you do not explicitly need to. These two options are directly related to the events your browser emits when it has reached a certain loading stage. -- `load`: This is the default and very strict: your whole page including all dependent resources, i.e. images, scripts, css etc. +- `load`: This is the `page.goto()` default and very strict: your whole page including all dependent resources, i.e. images, scripts, css etc. - `domcontentloaded`: less strict: when your HTML has loaded. -Note: the load option is the default. - **2b. Heuristic based** -These two options are based on the heuristic that if (almost) all network connections your browser has are no longer active, +This option is based on the heuristic that if (almost) all network connections your browser has are no longer active, your page has probably finished loading. -- `networkidle0`: consider navigation to be finished when there are no more than 0 network connections for at least 500 ms. -- `networkidle2`: consider navigation to be finished when there are no more than 2 network connections for at least 500 ms. - -Playwright has done away with the distinction between `networkidle0` and `networkidle2` and just has: - - `networkidle`: consider navigation to be finished when there are no more than 0 network connections for at least 500 ms. -Both options 2a and 2b are passed using the `waitUntil` property, e.g. `page.waitForNavigation({ waitUntil: 'networkidle2' })` +Relying on `networkidle` is discouraged because it slows down your end-to-end tests. It's recommended to rely on auto-waiting and application state to evaluate when a page is ready. -Which of these options is useful to you depends on your situation: - -- Does your SPA need to be fully rendered and finish all XHR calls? Go with `load` -- You server render and load in some non-crucial element in a lazy fashion? go for one of the `networkidle` variant. - - -Now that we know how to start a browser and navigate to a URL, the clear next step is to learn how to [interact with a webpage](/learn/playwright/clicking-typing-hovering/). + ## Further reading + 1. [Waits and Timeouts](/learn/playwright/waits-and-timeouts/) 2. [Playwright general navigation docs](https://playwright.dev/docs/navigations) 3. [Playwright auto waiting](/learn/playwright/interaction/waits/) diff --git a/learn/playwright/performance.mdx b/learn/playwright/performance.mdx index 8dfc0388..33d4c9f0 100644 --- a/learn/playwright/performance.mdx +++ b/learn/playwright/performance.mdx @@ -15,6 +15,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -354,7 +355,7 @@ The DevTools Protocol is quite extensive. We recommend exploring the [documentat Lighthouse can easily be used programmatically with Playwright to gather values and scores for different metrics, like [Time To Interactive (TTI)](https://web.dev/interactive/): -```js +```js const chromeLauncher = require('chrome-launcher') const { chromium } = require('playwright') const lighthouse = require('lighthouse') @@ -400,3 +401,5 @@ $ node measure-performance.js 3. [web.dev's performance section](https://web.dev/learn/#performance) 4. [Getting started with Chrome DevTools Protocol](https://github.com/aslushnikov/getting-started-with-cdp) by Andrey Lushnikov 5. [Get Started with Google Lighthouse](https://developers.google.com/web/tools/lighthouse#get-started) + + diff --git a/learn/playwright/scraping-behind-login.mdx b/learn/playwright/scraping-behind-login.mdx index 28a100e5..b98e7db9 100644 --- a/learn/playwright/scraping-behind-login.mdx +++ b/learn/playwright/scraping-behind-login.mdx @@ -13,6 +13,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -125,3 +126,5 @@ node scraping-example-purchases.js ## Further reading 1. [Basic scraping](/learn/playwright/web-scraping/) with Playwright + + diff --git a/learn/playwright/script-recorders.mdx b/learn/playwright/script-recorders.mdx index ab0cc2fd..a74162e3 100644 --- a/learn/playwright/script-recorders.mdx +++ b/learn/playwright/script-recorders.mdx @@ -13,6 +13,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -49,3 +50,5 @@ Double-check the newly created scripts and tweak it when necessary, especially k ## Further reading 1. [Playwright Codegen](https://playwright.dev/docs/codegen-intro#running-codegen) documentation. + + diff --git a/learn/playwright/selectors.mdx b/learn/playwright/selectors.mdx index 49852d76..68a3a572 100644 --- a/learn/playwright/selectors.mdx +++ b/learn/playwright/selectors.mdx @@ -16,7 +16,9 @@ learn_playwright: parent: "Interaction" --- +import SignUpCta from "/snippets/sign-up-cta.mdx" import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import { YoutubeEmbed } from "/snippets/youtube-embed.jsx" @@ -29,7 +31,7 @@ Consider a simple web page with a headline, a button, and a status update box. C ![a demo page](/images/samples/images/user-first1.png) ## Why we don't want to find a page element with CSS selectors -If you're used to some older systems for automation and page manipulation like JQuery, we might be tempted to use CSS selectors. If we inspect this page we'll find, sure enough, that there is a class applied to this button that should select it in the page. +If you're used to some older systems for automation and page manipulation like jQuery, we might be tempted to use CSS selectors. If we inspect this page we'll find, sure enough, that there is a class applied to this button that should select it in the page. ![examining the page with an inspector](/images/samples/images/user-first2.png) @@ -43,7 +45,7 @@ If our button text is coming from a CMS, and it breaks, the button text could ch Due to the reasons above, the Playwright project encourages you to not use CSS locators, and it's a good idea to follow the standards set down in the project! ### Instead of CSS selectors, try User-First Locators -Playwright offers a number of locators that are based on page role, a more functional view of the page than finding by CSS or HTML. Use built-in locators like `getByRole`, `getByText`, and `getByLabel`, which will all work the same in the test that they will for the user, even if the user is using an unusual browser build, mobile device, or even a screen reader! +Playwright offers a number of locators that are based on page role, a more functional view of the page than finding by CSS or HTML. Use [the recommended built-in locators](https://playwright.dev/docs/locators#quick-guide) like `getByRole`, `getByText`, and `getByLabel`, which will all work the same in the test that they will for the user, even if the user is using an unusual browser build, mobile device, or even a screen reader! ## User-First Locators in Action Let's replace `page.locator` with `getByRole` to locate the button by its role and accessible name: @@ -64,19 +66,25 @@ This change means that if the button label changes to something like "HEROBUTTON ### What to do when `getByRole` and `getByLabel` won't work on your page -One of the reasons I support using user-first locators is what happens when you realize that these selectors don't work on your page. If role and label aren't set for many of your page items, or you find that all your page items have the same labels and roles, it indicates that your page has some serious accessibility issues. After all, if nothing has unique labels it means that screen readers and keyboard navigation tools won't work correctly on the page, meaning many users won't be able to navigate your pages. That should start a conversation among developers and QA people about improving the structure of your pages, which will fix testing and the experience for all users. +One of the reasons I support using user-first locators is what happens when you realize that these selectors don't work on your page. If role and label aren't set for many of your page items, or you find that all your page items have the same labels and roles, it indicates that your page has some serious accessibility issues. + +After all, if nothing has unique labels it means that screen readers and keyboard navigation tools won't work correctly on the page, meaning many users won't be able to navigate your pages. That should start a conversation among developers and QA people about improving the structure of your pages, which will fix testing and the experience for all users. In the short term, take a look at all of Playwright's locators, as there are definitely techniques that will find any element on your page, but I encourage you to use this as a jumping off point for tech debt conversations in the future. ### Handling Multiple Matching Elements If a locator matches multiple elements, Playwright's strict mode will fail. For example, using `getByRole('button')` might match several buttons. You'll get an error that reads something like: -`Error: locator.click: Error: strict mode violation: getByRole('button', { name: 'click' }) resolved to 2 elements:` +``` +Error: locator.click: Error: strict mode violation: + getByRole('button', { name: 'click' }) resolved to 2 elements: + ... +``` Note that in strict mode this test will fail even if the first result, or all the results, passes the rest of the test. Resolve this by specifying the position or filtering elements. -### Position-Based Selection +#### Position-Based Selection When we first run into this error, the easiest solution is just to specify a position in a list. The simplest being to take the first result: ```ts @@ -93,7 +101,7 @@ await page.getByRole('button').nth(3).click() The .nth() function is zero-indexed, so .nth(3) will select the fourth item in the results. Positional selectors work, but they can be brittle, if we have dynamic page content, selecting anything but the first result may present a false positive. To be really sure that we're pointing to the correct element in a dynamic list, do a bit of element filtering. -## Element Filtering in Playwright +#### Element Filtering in Playwright If we imagine an e-store interface, with a number of results only some of which are available, we can see that a position selector isn't going to test reliably. ![too many matches](/images/samples/images/user-first4.png) @@ -120,8 +128,14 @@ There is no one-size-fits-all solution for locators. Here are some tips: ## See user-first locators in action -Putting all these pieces together, [check out Stefan’s video for a demonstration of user-first locators.](https://www.youtube.com/watch?v=9RJMNU4eNEc) +Putting all these pieces together, [check out this video for a demonstration of user-first locators.](https://www.youtube.com/watch?v=9RJMNU4eNEc) + + ### Conclusion -Choosing the right locators is key to creating stable and maintainable Playwright tests. User-first locators reduce flakiness and encourage good development practices. If you're interested in joining a community of Playwright developers, join us on the [Checkly Slack](https://www.checklyhq.com/slack/). And if you use Playwright for [end-to-end testing](https://www.checklyhq.com/guides/playwright-testing-to-monitoring/), consider using Checkly for monitoring your production site, we’ve got a great story for empowering your developers with [Monitoring as Code](https://www.checklyhq.com/guides/monitoring-as-code/). +Choosing the right locators is key to creating stable and maintainable Playwright tests. User-first locators reduce flakiness and encourage good development practices. + +And if you use Playwright for [end-to-end testing](https://www.checklyhq.com/guides/playwright-testing-to-monitoring/), consider using Checkly for monitoring your production site, we’ve got a great story for empowering your developers with [Monitoring as Code](/guides/getting-started-with-monitoring-as-code). + + diff --git a/learn/playwright/steps-decorators.mdx b/learn/playwright/steps-decorators.mdx index b75423e4..fc393c70 100644 --- a/learn/playwright/steps-decorators.mdx +++ b/learn/playwright/steps-decorators.mdx @@ -14,6 +14,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" import { YoutubeEmbed } from "/snippets/youtube-embed.jsx" @@ -348,3 +349,5 @@ What do you think? Is implementing decorators for Playwright test steps worth th The decorator code is quite complicated JavaScript / TypeScript, but you'll rarely touch this code. It's a typical "set up once and forget about it" case, and I bet you'll fall in love with the easy-to-use decoratorar one-liners quickly. If you want to see this decorator implementation, find [a complete example implementation next to more Playwright example code on GitHub](https://github.com/checkly/playwright-examples/), and if you have any questions or comments, drop into the [Checkly community](https://www.checklyhq.com/slack/). We're a lovely bunch and happy to help! + + diff --git a/learn/playwright/taking-screenshots.mdx b/learn/playwright/taking-screenshots.mdx index d0732067..cadd9a8a 100644 --- a/learn/playwright/taking-screenshots.mdx +++ b/learn/playwright/taking-screenshots.mdx @@ -13,6 +13,7 @@ learn_playwright: parent: "Basics" --- +import SignUpCta from "/snippets/sign-up-cta.mdx" import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" @@ -98,3 +99,5 @@ test('visual regression', async ({ page }) => { 1. Official documentation for taking screenshots with [Playwright](https://playwright.dev/docs/verification?_highlight=screenshot#screenshots) 2. Blog post from baseweb.design on the whys and hows of [visual regression testing](https://baseweb.design/blog/visual-regression-testing/) 3. Blog post from Gideon Pyzer looking at different visual [regression testing tools](https://gideonpyzer.dev/blog/2018/06/25/visual-regression-testing/) + + diff --git a/learn/playwright/test-fixtures.mdx b/learn/playwright/test-fixtures.mdx index 2deeb10c..126d0603 100644 --- a/learn/playwright/test-fixtures.mdx +++ b/learn/playwright/test-fixtures.mdx @@ -16,6 +16,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -232,3 +233,4 @@ Custom test fixtures in Playwright streamline test setup and teardown, fostering To discover more practical fixture examples, check out our [YouTube playlist](https://www.youtube.com/watch?v=hegZS46J0rA&list=PLMZDRUOi3a8N067UNvkxXEThKlTII_OJ-), which covers fixtures in even more depth. + diff --git a/learn/playwright/testing-apis.mdx b/learn/playwright/testing-apis.mdx index 585103f7..8d1cab6d 100644 --- a/learn/playwright/testing-apis.mdx +++ b/learn/playwright/testing-apis.mdx @@ -14,6 +14,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" import { YoutubeEmbed } from "/snippets/youtube-embed.jsx" @@ -154,3 +155,5 @@ As a bonus, Checkly’s API checks are cheaper to run than browser checks. Playwright isn’t just for browser testing; it’s also a powerful tool for API testing. By combining it with a monitoring service like Checkly, you can ensure that your APIs are reliable and catch issues before your users do. If you’d like to see how a Checkly works with Playwright to give you a total picture of the state of your services check out our pricing, or join our Slack to meet other engineers going further with Playwright. + + diff --git a/learn/playwright/testing-coupons.mdx b/learn/playwright/testing-coupons.mdx index 4d123040..055bad5f 100644 --- a/learn/playwright/testing-coupons.mdx +++ b/learn/playwright/testing-coupons.mdx @@ -14,6 +14,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -64,25 +65,21 @@ const productsNumber = process.env.PRODUCTS_NUMBER || 3 ``` - Run this example as follows: - ```sh PRODUCTS_NUMBER=3 node coupon.js ``` - ```sh SET PRODUCTS_NUMBER=3 node coupon.js ``` - - ## Takeaways 1. We can simply verify that coupons are accepted, or also check that they command the right discount. 2. Assertion libraries are useful when non-trivial [assertions](https://www.checklyhq.com/docs/api-checks/assertions/) are required. + diff --git a/learn/playwright/testing-file-uploads.mdx b/learn/playwright/testing-file-uploads.mdx index ffae2c4e..cf029ff2 100644 --- a/learn/playwright/testing-file-uploads.mdx +++ b/learn/playwright/testing-file-uploads.mdx @@ -16,6 +16,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -75,3 +76,5 @@ Here, we are simply checking for a message giving us feedback on the status of t ## Further reading 1. Official documentation from [Playwright](https://playwright.dev/docs/input#upload-files) + + diff --git a/learn/playwright/testing-in-parallel.mdx b/learn/playwright/testing-in-parallel.mdx index 8c1554eb..5d7a9202 100644 --- a/learn/playwright/testing-in-parallel.mdx +++ b/learn/playwright/testing-in-parallel.mdx @@ -14,6 +14,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" import { YoutubeEmbed } from "/snippets/youtube-embed.jsx" @@ -185,6 +186,8 @@ Playwright's design accommodates various testing strategies, allowing developers Choosing between parallel and sequential execution in Playwright tests hinges on understanding your tests' nature and their impact on the application environment. By categorizing tests into stateful and stateless, developers can apply the appropriate execution strategy, ensuring efficiency and reliability in their E2E testing processes. -Over on [the Checkly YouTube channel](https://www.youtube.com/checklyhq), Stefan gets hands-on with Playwright test Parallelism and execution modes: +Over on [the Checkly YouTube channel](https://www.youtube.com/checklyhq), Stefan gets hands-on with Playwright test Parallelism and execution modes. + + diff --git a/learn/playwright/user-signup-automation.mdx b/learn/playwright/user-signup-automation.mdx index bb639fe5..c14411fa 100644 --- a/learn/playwright/user-signup-automation.mdx +++ b/learn/playwright/user-signup-automation.mdx @@ -14,6 +14,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -86,3 +87,5 @@ await page.setUserAgent('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 \ 1. Use environment variables to inject secrets. 2. You might need to go through additional steps in case email confirmation or similar is required. + + diff --git a/learn/playwright/waits-and-timeouts.mdx b/learn/playwright/waits-and-timeouts.mdx index a264e9b1..3a81d717 100644 --- a/learn/playwright/waits-and-timeouts.mdx +++ b/learn/playwright/waits-and-timeouts.mdx @@ -13,6 +13,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -35,7 +36,7 @@ await page.waitFor(1000) // hard wait for 1000ms await page.click('#button-login') ``` -In such a situation, the following can happen: +In such a situation, the following two scenarios can happen: 1. You end up waiting a shorter time than the element takes to load! @@ -55,7 +56,7 @@ Flakiness, a higher-than-acceptable and unpredictable failure rate, is a major p **Your tests and automation scripts must be stable and hard waits should never appear in your end-to-end testing and monitoring scripts**. -## Avoiding hard waits by relying on Playwright's auto-waiting +## Avoiding hard waits by relying on Playwright's auto-waiting actions and web-first assertions To avoid these issues, you should forget that hard waits exist and adopt tools like [Playwright, which provide auto-waiting mechanisms](https://playwright.dev/docs/actionability). Let's revisit the previous example and use Playwright's core functionality. @@ -89,29 +90,76 @@ This auto-waiting approach has two main advantages: 1. Your Playwright scripts will be as quick as possible because Playwright will interact with elements whenever they're ready. 2. You can focus on defining UI actions and the expected results instead of worrying about network calls and timings. +### Playwright's web-first assertions + +Auto-waiting Playwright actions help to avoid using hard waits when interacting with elements. But what if you want to wait for an element to appear on the page or reach a specific state before proceeding with your script? + +Playwright's web-first assertions (`toBe*`) also provide auto-waiting capabilities. For example, to wait for an element to become visible, it's recommended to use Playwright's `toBeVisible` assertions. `toBeVisible`, `toBeEnabled`, `toBeChecked` and many more included assertions are asynchronous and wait for the elements to reach a certain state. + +```ts +// wait for this button to be visible, stable, ... and click it +await page.getByRole('button', { name: 'Login' }).click() +// wait for this button to be disabled +await expect(page.getByRole('button', {name: 'Login'})).toBeDisabled() +// wait for this button to be gone +await expect(page.getByRole('button', {name: 'Login'})).toBeHidden() +``` + +If you pair web-first assertions with Playwright's auto-waiting actions, your scripts will be expressive, human-readable, and, most importantly, not include any hard timeouts. + + +It's important to understand that auto-waiting web-first assertions also have synchronous counterparts. + +``` +// check if this element is visible at this moment (true/false) +await page.getByRole('button').isVisible() + +// wait for this element to become visible +await expect(page.getByRole('button')).toBeVisible() +``` + +It's recommended to reach for web-first assertions whenever possible to avoid flakiness. + + +If you're not using Playwright Test (web-first assertions are only available in `@playwright/test`) and you want to wait for an element to be visible, use `waitFor`. + +```ts +const button = page.getByRole('button', { name: 'Login' }) +// wait for this button to be visible +await button.waitFor() +``` + +In any case, a good knowledge of [locators](/learn/playwright/selectors/) is key to enable you to select precisely the element we need to wait for. + ## Other waiting mechanisms Generally, **it's recommended to rely on Playwright's auto-waiting and built-in web-first assertions**, but if you must, here are some other waiting mechanisms. ### Waiting on navigations and network conditions in Playwright -When you can't wait for an element to appear on a page and want to explicitly wait for the network use the following. +When you can't wait for an element to appear on a page and want to explicitly wait for the network, one of the other `waitFor` methods. + +#### `page.waitForLoadState` -`` waits until the required load state has been reached. It defaults to the page `load` event but can also be configured to wait for `domcontentloaded` or `networkidle` (discouraged). +`waitForLoadState` waits until the required load state has been reached. It defaults to the page `load` event but can also be configured to wait for `domcontentloaded` or `networkidle` (discouraged). ```ts // wait for a page `load` event await page.waitForLoadState() ``` -`` waits until a navigation to the target URL. It also defaults to the page `load` event but can be configured to wait for `commit`, `domcontentloaded` or `networkidle` (discouraged). +#### `page.waitForURL` + +`waitForURL` waits until a navigation to the target URL. It also defaults to the page `load` event but can be configured to wait for `commit`, `domcontentloaded` or `networkidle` (discouraged). ```ts // wait for the page `load` event of the `/login` URL await page.waitForURL('**/login') ``` -You can also wait until a request is sent or a response is received with ``. These two methods are key for implementing [request and response interception](/learn/playwright/intercept-requests/). +#### `page.waitForRequest` / `page.waitForResponse` + +You can also wait until a request is sent or a response is received with `waitForRequest` and `waitForResponse`. These two methods are key for implementing [request and response interception](/learn/playwright/intercept-requests/). ```ts // wait for a request being made after clicking a button @@ -125,34 +173,9 @@ await page.getByRole('button', { name: 'Login' }).click() const loginResponse = await loginResponsePromise ``` -### Waiting for an element in Playwright - -There are multiple ways to wait for a specific element to appear on the page. To wait for an element to be visible or reach a particular state it's recommended to use Playwright's web-first assertions. `toBeVisible`, `toBeEnabled`, `toBeChecked` and many more included assertions are asynchronous and wait for the elements to change, appear or disappear. - -```ts -// wait for this button to be visible, stable, ... and click it -await page.getByRole('button', { name: 'Login' }).click() -// wait for this button to be disabled -await expect(page.getByRole('button', {name: 'Login'})).toBeDisabled() -// wait for this button to be gone -await expect(page.getByRole('button', {name: 'Login'})).toBeHidden() -``` - -If you pair web-first assertions with Playwright's auto-waiting actions, your scripts will be expressive, human-readable, and, most importantly, not include any hard timeouts. - -If you're not using Playwright Test (web-first assertions are only available in `@playwright/test`) and you want to wait for an element to be visible, use ``. - -```ts -const button = page.getByRole('button', { name: 'Login' }).click() -// wait for this button to be visible -await button.waitFor() -``` - -In any case, a good knowledge of [locators](/learn/playwright/selectors/) is key to enable you to select precisely the element we need to wait for. - ### Waiting for page events -With Playwright, you can also directly wait for `. +With Playwright, you can also directly wait for `waitForEvent`. ```ts // wait for a new window or popup to open after clicking a button @@ -163,7 +186,7 @@ const popup = await popupPromise ### Waiting for page functions -And for more advanced cases, you can pass a function to be evaluated within the browser context via ``. +And for more advanced cases, you can pass a function to be evaluated within the browser context via `waitForFunction`. ```ts // wait for a specific state in the browser window after clicking a button @@ -179,3 +202,5 @@ await secretInternalState 1. Never use hard waits or timeouts. 2. Use auto-waiting instead. 3. Combine auto-waiting actions with web-first assertions to test UI state instead of implementation details. + + diff --git a/learn/playwright/web-scraping.mdx b/learn/playwright/web-scraping.mdx index 27795f2d..97d439e6 100644 --- a/learn/playwright/web-scraping.mdx +++ b/learn/playwright/web-scraping.mdx @@ -16,6 +16,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -190,3 +191,4 @@ $ node scraping.js 1. [Playwright](https://playwright.dev/docs/assertions#text-content)'s official API reference on the topic 2. An [E2E example test](/learn/playwright/testing-coupons/) asserting against an element's `innerText` + diff --git a/learn/playwright/what-is-playwright.mdx b/learn/playwright/what-is-playwright.mdx index c15929a6..a64a38b4 100644 --- a/learn/playwright/what-is-playwright.mdx +++ b/learn/playwright/what-is-playwright.mdx @@ -17,6 +17,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -41,13 +42,14 @@ While taking a simplified approach to its design, Playwright offers many feature 1. **Mobile Emulation**: Playwright allows you to emulate mobile devices, such as iPhones and iPads, and test how your web application behaves on different screen sizes and orientations. 2. **Headless Mode**: You can run your tests in a headless browser, which is useful for CI/CD pipelines and for running tests in environments where a graphical interface is not available. -3. **Video Recording**: Playwright automatically records videos of your tests, which can be useful for debugging and for creating visual regression tests. -4. **Cross Browser Testing**: Playwright supports multiple browsers, including Chromium, Firefox, and WebKit, allowing you to test your application across different browsers. -5. **Programming Language Support**: Playwright is available in several programming languages, including JavaScript, TypeScript, Python, .NET, and Java, making it accessible to a wide range of developers. -6. **Comprehensive API**: Playwright provides a comprehensive API for automating browser actions, such as navigation, page interaction, and element manipulation. -7. **CI/CD Integration**: Playwright integrates seamlessly with popular CI/CD platforms, such as GitHub Actions, Jenkins, and CircleCI, allowing you to run your tests as part of your continuous integration and delivery process. -8. **Visual Testing**: Playwright supports visual testing, allowing you to compare screenshots of your web application and detect visual changes. -9. **Code Generation**: Playwright includes a code generator that can generate code for your tests, saving you time and reducing the risk of errors. +3. **Video Recording**: Playwright can record videos of your tests, which can be useful for debugging. +4. **Tracing**: Playwright can capture your application state at every step of your tests to provide detailed insights when debugging. +5. **Cross Browser Testing**: Playwright supports multiple browsers, including Chromium, Firefox, and WebKit, allowing you to test your application across different browsers. +6. **Programming Language Support**: Playwright is available in several programming languages, including JavaScript, TypeScript, Python, .NET, and Java, making it accessible to a wide range of developers. +7. **Comprehensive API**: Playwright provides a comprehensive API for automating browser actions, such as navigation, page interaction, and element manipulation. +8. **CI/CD Integration**: Playwright integrates seamlessly with popular CI/CD platforms, such as GitHub Actions, Jenkins, and CircleCI, allowing you to run your tests as part of your continuous integration and delivery process. +9. **Visual Testing**: Playwright supports visual testing, allowing you to compare screenshots of your web application and detect visual changes. +10. **Code Generation**: Playwright includes a code generator that can generate code for your tests, saving you time and reducing the risk of errors. @@ -58,11 +60,15 @@ While taking a simplified approach to its design, Playwright offers many feature 4. **Scraping web sites for data:** extracting data from websites for later retrieval or analysis. 5. **Automating interaction of web pages:** speed up and scale any sort of sequence of actions we would like to perform on a website automatically. -In this guide you will find multiple examples showing how to leverage Playwright, with a focus on test automation / active reliability. - ## Growth and Adoption -Since its release in January 2020 by Microsoft, Playwright has experienced a surge in usage and popularity. As of March 2023, its GitHub repository has received 48.4k stars and 2.4k forks, and is currently averaging more than 1.2 million NPM downloads per week. Playwright is used by enterprise and open-source development projects alike, including Adobe Spectrum, Visual Studio Code, and React Navigation. +Since its release in January 2020 by Microsoft, Playwright has experienced a surge in usage and popularity. As of January 2026, its GitHub repository has received 80k stars and 5k forks, and is currently averaging more than 32 million NPM downloads per week. Playwright is used by enterprise and open-source development projects alike, including Adobe Spectrum, Visual Studio Code, and React Navigation. + +## Playwright as part of Checkly + +At Checkly, we believe that end-to-end testing is only one part of shipping reliable software. That's why we enable you to use your Playwright codebase not only for testing, but also for monitoring and automating your web applications. With Checkly, you can run your Playwright scripts in the cloud, on a schedule, and get alerted when something goes wrong. This way, you can ensure that your web applications are always up and running, and that your users have a stellar experience. + + ## Further reading 1. [Official Playwright API documentation](https://playwright.dev/) diff --git a/learn/playwright/writing-tests.mdx b/learn/playwright/writing-tests.mdx index 64afaf14..97b5ce0f 100644 --- a/learn/playwright/writing-tests.mdx +++ b/learn/playwright/writing-tests.mdx @@ -14,6 +14,7 @@ learn_playwright: --- import PlaywrightCheckSuiteTryOut from "/snippets/playwright-check-suite-tryout.mdx" +import SignUpCta from "/snippets/sign-up-cta.mdx" @@ -111,3 +112,5 @@ Where: ## Further reading 1. [Gergely Orosz](https://blog.pragmaticengineer.com/readable-code/) on writing readable code. + + diff --git a/snippets/sign-up-cta.mdx b/snippets/sign-up-cta.mdx new file mode 100644 index 00000000..8eb487f0 --- /dev/null +++ b/snippets/sign-up-cta.mdx @@ -0,0 +1,8 @@ +
+
+ Bugs don't stop at CI/CD. Why would Playwright? Playwright logo +
+
+ Sign up and start using Playwright for end-to-end monitoring with Checkly. +
+