diff --git a/site/content/learn/playwright/checkout-testing-guide.md b/site/content/learn/playwright/checkout-testing-guide.md index e8e168609..3ed7497cb 100644 --- a/site/content/learn/playwright/checkout-testing-guide.md +++ b/site/content/learn/playwright/checkout-testing-guide.md @@ -52,7 +52,7 @@ node checkout.js {{< /tab >}} {{< /tabs >}} -Note: In some cases, users will need to [log in](/learn/headless/e2e-login/) before they can proceed to a purchase. When users are allowed to buy both with and without having a pre-existing account on the platform, it might be worthwhile to test both flows separately. +Note: In some cases, users will need to [log in](/learn/playwright/login-automation/) before they can proceed to a purchase. When users are allowed to buy both with and without having a pre-existing account on the platform, it might be worthwhile to test both flows separately. ## Limitations diff --git a/site/content/learn/playwright/clicking-typing-hovering.md b/site/content/learn/playwright/clicking-typing-hovering.md index 0ab258cba..5715f86c5 100644 --- a/site/content/learn/playwright/clicking-typing-hovering.md +++ b/site/content/learn/playwright/clicking-typing-hovering.md @@ -107,4 +107,4 @@ $ node basic-click-type.js ## Further reading 1. The related official documentation of [Playwright](https://playwright.dev/docs/input#mouse-click) -2. [Finding effective selectors](/learn/headless/basics-selectors/) +2. [Finding effective selectors](/learn/playwright/selectors/) diff --git a/site/content/learn/playwright/debugging-errors.md b/site/content/learn/playwright/debugging-errors.md index aac376d19..9df2ff0ce 100644 --- a/site/content/learn/playwright/debugging-errors.md +++ b/site/content/learn/playwright/debugging-errors.md @@ -33,7 +33,7 @@ More often than not, beginners will be looking for a solution to the "obvious" c To help avoid stressful and unsuccessful debugging sessions, it might help to consider different possible causes depending on the error you are confronted with: -1. [Error: element not found](/learn/headless/error-element-not-found/) -2. [Error: element not visible](/learn/headless/error-element-not-visible/) -3. [Error: target closed](/learn/headless/error-target-closed/) -4. [Error: wait not respected](/learn/headless/error-wait-not-respected/) +1. [Error: element not found](/learn/playwright/error-element-not-found/) +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/site/content/learn/playwright/debugging.md b/site/content/learn/playwright/debugging.md index 0f6001dc8..cfca5f2fa 100644 --- a/site/content/learn/playwright/debugging.md +++ b/site/content/learn/playwright/debugging.md @@ -34,7 +34,7 @@ When approaching a debugging session, make sure the above points are taken care Error messages are not present in every scenario: we might be trying to understand why a script _passes_, or why it takes longer than expected. But when we have access to an error message, we can use it to guide us. -The error, in and of its own, is not always enough to understand what is going wrong with your script. Oftentimes, there can be multiple degrees of separation between the error and its root cause. For example: an ["Element not found"](/learn/headless/error-element-not-found/) error might be alerting you to the fact that an element is not being found on the page, but that itself might be because the browser was made to load the wrong URL in the first place. +The error, in and of its own, is not always enough to understand what is going wrong with your script. Oftentimes, there can be multiple degrees of separation between the error and its root cause. For example: an ["Element not found"](/learn/playwright/error-element-not-found/) error might be alerting you to the fact that an element is not being found on the page, but that itself might be because the browser was made to load the wrong URL in the first place. Do not fall into the easy trap of reading the error message and immediately jumping to conclusions. Rather, take the error message, research it if needed, combine it with your [knowledge of script and app under test](#awareness-comes-first) and treat it as the first piece to the puzzle, rather than the point of arrival of your investigation. @@ -104,7 +104,7 @@ If we are using Playwright, we can also run in debug mode with `PWDEBUG=console The Playwright Inspector is a GUI tool which exposes additional debugging functionality, and can be launched using `PWDEBUG=1 npm run test`. -The Inspector allows us to easily step through each instruction of our script, while giving us clear information on the duration, outcome, and functioning of each. This can be helpful in [getting to the root cause](/learn/headless/debugging-challenges/) of some of the more generic errors. +The Inspector allows us to easily step through each instruction of our script, while giving us clear information on the duration, outcome, and functioning of each. This can be helpful in [getting to the root cause](/learn/playwright/debugging-errors/) of some of the more generic errors. ![playwright inspector debugging](/samples/images/debugging-inspector.png) @@ -112,5 +112,5 @@ The Inspector allows us to easily step through each instruction of our script, w ## Further reading -1. [Debugging challenges](/learn/headless/debugging-challenges/) -2. [Working with selectors](/learn/headless/basics-selectors/) +1. [Debugging challenges](/learn/playwright/debugging-errors/) +2. [Working with selectors](/learn/playwright/selectors/) diff --git a/site/content/learn/playwright/emulating-mobile-devices.md b/site/content/learn/playwright/emulating-mobile-devices.md index 15b4dc1d4..8c55e74ed 100644 --- a/site/content/learn/playwright/emulating-mobile-devices.md +++ b/site/content/learn/playwright/emulating-mobile-devices.md @@ -104,5 +104,5 @@ const iPhone = devices['iPhone SE']; ## Further reading -1. [Measuring page performance](/learn/headless/basics-performance/) +1. [Measuring page performance](/learn/playwright/performance/) 2. [Playwright's emulation documentation](https://playwright.dev/docs/emulation) diff --git a/site/content/learn/playwright/error-element-not-found.md b/site/content/learn/playwright/error-element-not-found.md index 0b1f4e31f..26f775bf2 100644 --- a/site/content/learn/playwright/error-element-not-found.md +++ b/site/content/learn/playwright/error-element-not-found.md @@ -21,9 +21,9 @@ UnhandledPromiseRejectionWarning: Error: No node found for selector: ... ## Possible causes -- **Obvious possible cause #1:** the selector is wrong. See [working with selectors](/learn/headless/basics-selectors/). -- **Obvious possible cause #2:** the element is not on the page and the automation tool is not automatically waiting for it to appear. An [explicit wait](/learn/headless/basics-navigation/) might fix the problem. -- **Not-so-obvious possible cause:** the click on the previous element [did not actually go through](/learn/headless/error-click-not-executed/). From the perspective of our automation tool, everything went fine, but from ours what happened is more similar to a silent failure. We are now looking for the right element but are on the wrong page (or the page is in the wrong state), and the target element is therefore not found. +- **Obvious possible cause #1:** the selector is wrong. See [working with selectors](/learn/playwright/selectors/). +- **Obvious possible cause #2:** the element is not on the page and the automation tool is not automatically waiting for it to appear. An [explicit wait](/learn/playwright/navigation/) might fix the problem. +- **Not-so-obvious possible cause:** the click on the previous element [did not actually go through](/learn/playwright/error-click-not-executed/). From the perspective of our automation tool, everything went fine, but from ours what happened is more similar to a silent failure. We are now looking for the right element but are on the wrong page (or the page is in the wrong state), and the target element is therefore not found. ## How to avoid confusion diff --git a/site/content/learn/playwright/file-download.md b/site/content/learn/playwright/file-download.md index 136751eb0..27ddbdec0 100644 --- a/site/content/learn/playwright/file-download.md +++ b/site/content/learn/playwright/file-download.md @@ -26,9 +26,9 @@ This example runs against our [test webshop](https://danube-web.shop/) and proce 2. Navigating to the account page 3. Downloading a linked file -We will check that the downloaded file is as expected by comparing it to a [fixture file](/learn/headless/test-data-intro/) in our final assertion. +We will check that the downloaded file is as expected by comparing it to a [fixture file](/learn/playwright/handling-test-data/) in our final assertion. -We can approach this scenario in different ways. One possibility is to perform the first two steps, then [extract](/learn/headless/basics-scraping/) the `href` value and use it to retrieve the file with a `GET` request (performed with [axios](https://github.com/axios/axios), for example). +We can approach this scenario in different ways. One possibility is to perform the first two steps, then [extract](/learn/playwright/web-scraping/) the `href` value and use it to retrieve the file with a `GET` request (performed with [axios](https://github.com/axios/axios), for example). {{< tabs "1" >}} {{< tab "Playwright" >}} diff --git a/site/content/learn/playwright/getting-started.md b/site/content/learn/playwright/getting-started.md index a0b7104c6..d977278f1 100644 --- a/site/content/learn/playwright/getting-started.md +++ b/site/content/learn/playwright/getting-started.md @@ -17,11 +17,27 @@ menu: The [official documentation](https://playwright.dev/) for Playwright reads: -> Playwright provides a set of APIs to automate Chromium, Firefox and WebKit browsers. By using the Playwright API, you can write JavaScript, Typescript [and other languages](https://playwright.dev/docs/languages) to create new browser pages, navigate to URLs and then interact with elements on a page. Our focus in this guide will be on the Javascript & Typescript side of things. + + +Playwright is an open-source framework for cross-browser automation and end-to-end web application testing. It was designed to be a fast, reliable, robust, and evergreen test automation framework. Playwright provides a set of APIs to automate Chromium, Firefox and WebKit browsers. By using the Playwright API, you can write JavaScript, Typescript [and other languages](https://playwright.dev/docs/languages) to create new browser pages, navigate to URLs and then interact with elements on a page. Our focus in this guide will be on the Javascript & Typescript side of things. You can import Playwright's provided [`test`](https://playwright.dev/docs/api/class-test) and [`expect`](https://jestjs.io/docs/expect) functions to declare tests and add assertions. We'll be using these throughout our e2e examples as a best practice. +## Playwright Features + +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. + + + ## Main use cases 1. **Test automation in modern web applications:** verifying that the features we are exposing our users/customers to are actually behaving as expected. 2. **Cross-browser testing:** ensuring applications are working consistently across browsers and rendering engines. @@ -31,6 +47,10 @@ You can import Playwright's provided [`test`](https://playwright.dev/docs/api/cl 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. + ## Further reading 1. [Official Playwright API documentation](https://playwright.dev/) 2. [Official Playwright GitHub repo](https://github.com/microsoft/playwright) diff --git a/site/content/learn/playwright/intercept-requests.md b/site/content/learn/playwright/intercept-requests.md index ffd3afdb5..48bc60cab 100644 --- a/site/content/learn/playwright/intercept-requests.md +++ b/site/content/learn/playwright/intercept-requests.md @@ -34,7 +34,7 @@ Request interception enables us to observe which requests and responses are bein {{< /tab >}} {{< /tabs >}} -We might want to intervene and filter the outgoing requests. For example, when [scraping web pages](/learn/headless/basics-scraping/), we might want to block unnecessary elements from loading in order to speed up the procedure and lower bandwidth usage. +We might want to intervene and filter the outgoing requests. For example, when [scraping web pages](/learn/playwright/web-scraping/), we might want to block unnecessary elements from loading in order to speed up the procedure and lower bandwidth usage. {{< tabs "2" >}} diff --git a/site/content/learn/playwright/managing-cookies.md b/site/content/learn/playwright/managing-cookies.md index 2bc54807c..04502c30a 100644 --- a/site/content/learn/playwright/managing-cookies.md +++ b/site/content/learn/playwright/managing-cookies.md @@ -92,7 +92,7 @@ In case you need to clear cookies, you can use [`browserContext.clearCookies()`] ## localStorage and sessionStorage -Cookies are sent with every request, potentially deteriorating [performance](/learn/headless/basics-performance/) if used for storing large amounts of data. The [localStorage and sessionStorage](https://javascript.info/localstorage) APIs can help us offload some of this data to the browser. Just like with cookies, Playwright makes accessing localStorage and sessionStorage straightforward. +Cookies are sent with every request, potentially deteriorating [performance](/learn/playwright/performance/) if used for storing large amounts of data. The [localStorage and sessionStorage](https://javascript.info/localstorage) APIs can help us offload some of this data to the browser. Just like with cookies, Playwright makes accessing localStorage and sessionStorage straightforward. Our test site, [Danube](https://danube-web.shop/), actually uses localStorage to keep track of things such as the content of your cart. Let's see how we can access this state and then replicate it in a later session. diff --git a/site/content/learn/playwright/navigation.md b/site/content/learn/playwright/navigation.md index ec3782ac7..155d3f1b9 100644 --- a/site/content/learn/playwright/navigation.md +++ b/site/content/learn/playwright/navigation.md @@ -134,7 +134,7 @@ Which of these options is useful to you depends on your situation: - 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/headless/basics-clicking-typing/). +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. [Playwright general navigation docs](https://playwright.dev/docs/navigations) diff --git a/site/content/learn/playwright/playwright-vs-others.md b/site/content/learn/playwright/playwright-vs-others.md index f3fa2f935..f002233f9 100644 --- a/site/content/learn/playwright/playwright-vs-others.md +++ b/site/content/learn/playwright/playwright-vs-others.md @@ -18,7 +18,7 @@ menu: ## Puppeteer vs Playwright -The resemblance to Google's [Puppeteer](/learn/headless/basics-puppeteer-intro/) is striking, and for good reason. +The resemblance to Google's [Puppeteer](https://developer.chrome.com/docs/puppeteer) is striking, and for good reason. In the words of the authors: diff --git a/site/content/learn/playwright/scraping-behind-login.md b/site/content/learn/playwright/scraping-behind-login.md index 6f6d5366e..5e025cbb4 100644 --- a/site/content/learn/playwright/scraping-behind-login.md +++ b/site/content/learn/playwright/scraping-behind-login.md @@ -56,11 +56,11 @@ node scraping-example-purchases.js > Under the hood, Amazon can change quite quickly. You might need to adjust the locators and/or flow slightly to have the script work for you. -> ⚠️ Websites might [restrict headless browser traffic](/learn/headless/challenging-flows/) in order to protect their users from fraud. 2FA will also interfere with the script if enabled. +> ⚠️ Websites might [restrict headless browser traffic](/learn/playwright/challenging-flows/) in order to protect their users from fraud. 2FA will also interfere with the script if enabled. ## Takeaways 1. We can scrape information available behind a login wall with Playwright. 2. Some websites might not allow scraping. Always make sure you check their terms of service beforehand. ## Further reading -1. [Basic scraping](/learn/headless/basics-scraping/) with Playwright +1. [Basic scraping](/learn/playwright/web-scraping/) with Playwright diff --git a/site/content/learn/playwright/script-recorders.md b/site/content/learn/playwright/script-recorders.md index 4c15cb3d4..9e49239a0 100644 --- a/site/content/learn/playwright/script-recorders.md +++ b/site/content/learn/playwright/script-recorders.md @@ -36,8 +36,8 @@ Regardless of your chosen approach, you will want to inspect the output scripts Double-check the newly created scripts and tweak it when necessary, especially keeping an eye out for: -1. Selectors, which should be in line with common [best practices](/learn/headless/basics-selectors/). -2. [Waits](/learn/headless/basics-navigation/), which should ensure the right element is present and/or ready for interaction at the right time; also, make sure you get rid of unnecessary waits. +1. Selectors, which should be in line with common [best practices](/learn/playwright/selectors/). +2. [Waits](/learn/playwright/navigation/), which should ensure the right element is present and/or ready for interaction at the right time; also, make sure you get rid of unnecessary waits. 3. Any sort of needless duplication. ## Takeaways diff --git a/site/content/learn/playwright/waits-and-timeouts.md b/site/content/learn/playwright/waits-and-timeouts.md index 40229c779..2b5ddc4b6 100644 --- a/site/content/learn/playwright/waits-and-timeouts.md +++ b/site/content/learn/playwright/waits-and-timeouts.md @@ -36,7 +36,7 @@ In such a situation, the following can happen: ![playwright hard wait time too short](/learn/images/over_assumption_01@2x.png) -In this case, our hard wait terminates and our click action is attempted too early. The script terminates with an error, possibly of the ["Element not found"](/learn/headless/error-element-not-found/) sort. +In this case, our hard wait terminates and our click action is attempted too early. The script terminates with an error, possibly of the ["Element not found"](/learn/playwright/error-element-not-found/) sort. 2. The element can load before our hard wait has expired. @@ -86,11 +86,11 @@ All the above default to waiting for the `{{< newtabref title="load" href="https > {{< newtabref title="Lazy-loaded pages" href="https://developer.mozilla.org/en-US/docs/Web/Performance/Lazy_loading" >}} might require extra attention when waiting for the content to load, often demanding explicitly waiting for specific UI elements. See the following section. -Additionally, we can also wait until a specific request is sent out or a specific response is received with `{{< newtabref title="page.waitForRequest" href="https://playwright.dev/docs/api/class-page#page-wait-for-request" >}}` and `{{< newtabref title="page.waitForResponse" href="https://playwright.dev/docs/api/class-page#page-wait-for-response" >}}`. These two methods are key for implementing [request and response interception](/learn/headless/request-interception/). +Additionally, we can also wait until a specific request is sent out or a specific response is received with `{{< newtabref title="page.waitForRequest" href="https://playwright.dev/docs/api/class-page#page-wait-for-request" >}}` and `{{< newtabref title="page.waitForResponse" href="https://playwright.dev/docs/api/class-page#page-wait-for-response" >}}`. These two methods are key for implementing [request and response interception](/learn/playwright/intercept-requests/). ### Waiting for an element -We can also explicitly wait for a specific element to appear on the page. This is normally done via `{{< newtabref title="page.waitForSelector" href="https://playwright.dev/docs/api/class-page#page-wait-for-selector" >}}`. A good knowledge of [selectors](/learn/headless/basics-selectors/) is key to enable us to select precisely the element we need to wait for. +We can also explicitly wait for a specific element to appear on the page. This is normally done via `{{< newtabref title="page.waitForSelector" href="https://playwright.dev/docs/api/class-page#page-wait-for-selector" >}}`. A good knowledge of [selectors](/learn/playwright/selectors/) is key to enable us to select precisely the element we need to wait for. ### Waiting on page events diff --git a/site/content/learn/playwright/web-scraping.md b/site/content/learn/playwright/web-scraping.md index 5ccfeef6d..7050c930f 100644 --- a/site/content/learn/playwright/web-scraping.md +++ b/site/content/learn/playwright/web-scraping.md @@ -130,5 +130,5 @@ $ node scraping.js ## Further reading 1. [Playwright](https://playwright.dev/docs/assertions#text-content)'s official API reference on the topic -2. An [E2E example test](/learn/headless/e2e-coupon/) asserting agains an element's `innerText` +2. An [E2E example test](/learn/playwright/testing-coupons/) asserting agains an element's `innerText` diff --git a/site/content/learn/playwright/writing-tests.md b/site/content/learn/playwright/writing-tests.md index 63c98185d..8bdbcb637 100644 --- a/site/content/learn/playwright/writing-tests.md +++ b/site/content/learn/playwright/writing-tests.md @@ -46,7 +46,7 @@ Automated tests are effective if they: The last point is often overlooked. Scripts by themselves have no meaning if their results mean nothing to whoever is looking at them. Ideally, we want the opposite: interpreting a test success or failure should be close to instantaneous and give us a clear understanding of what is working and what is not. -Oftentimes this is impeded by the tendency to have tests do too much. We can draw an example from two scenarios running against our [test site](https://danube-web.shop/): [E2E Checkout](/learn/headless/e2e-checkout/) and [E2E Coupon](/learn/headless/e2e-coupon/). While these two have part of their flow in common, and we might be tempted to combine them to avoid a certain degree of duplication, merging them into a single test would obfuscate the meaning of a test failure as we would be testing two different features. If that combined test were to run red, we would be unable to tell whether the entire checkout is not working as expected, or whether users are just unable to redeem coupon codes. Unless we were to devote additional time to diving deep into the failure - which is exactly what we are trying to avoid. +Oftentimes this is impeded by the tendency to have tests do too much. We can draw an example from two scenarios running against our [test site](https://danube-web.shop/): [E2E Checkout](/learn/playwright/testing-checkout/) and [E2E Coupon](/learn/playwright/testing-coupons/). While these two have part of their flow in common, and we might be tempted to combine them to avoid a certain degree of duplication, merging them into a single test would obfuscate the meaning of a test failure as we would be testing two different features. If that combined test were to run red, we would be unable to tell whether the entire checkout is not working as expected, or whether users are just unable to redeem coupon codes. Unless we were to devote additional time to diving deep into the failure - which is exactly what we are trying to avoid. We can avoid this pitfall by making sure our tests are verifying only one feature each.