You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Update k6 browser homepage to use k6 new command
* Create a write your first browser test page
* Fix alias on using k6 browser homepage
* Fix weight on k6 browser page section
* Add section for how to write k6 browser tests
* Move interact with elements on a webpage to its own page
* Move asynchronous operation section to a separate page
* Update hybrid performance testing page
Move some of the content that was in the Running browser tests page to Hybrid approach to performance
* Update page weight
* Update recommended practices weight
* Update Asynchronous operations page
Add changes based on Ankur's feedback, update page to mention most browser methods return promises. Add example of using waitFor
* Skip code block
* Skip code blocks
* Update Write your first browser test
Add content to Write your first browser test based on the Write your first test page, and the k6 new browser template script
* Fix hybrid performance code example
* Skip code block
* Update docs/sources/k6/next/using-k6-browser/how-to-write-browser-tests/asynchronous-operations.md
Co-authored-by: Ankur <[email protected]>
* Add heading link to JavaScript promises
* Add small example at the top of the page
* Update docs/sources/k6/next/using-k6-browser/how-to-write-browser-tests/asynchronous-operations.md
* Apply to v1.1
* Apply to v1.0
---------
Co-authored-by: Ankur <[email protected]>
description: 'The browser module brings browser automation and end-to-end testing to k6 while supporting core k6 features. Interact with real browsers and collect frontend metrics as part of your k6 tests.'
6
6
weight: 300
@@ -31,58 +31,26 @@ The main use case for the browser module is to test performance on the browser l
31
31
- Are all my elements interactive on the frontend?
32
32
- Are there any loading spinners that take a long time to disappear?
-[Install k6](https://grafana.com/docs/k6/<K6_VERSION>/set-up/install-k6/) in your machine.
39
+
- Install a Chromium-based browser, such as Google Chrome, in your machine.
80
40
81
-
The preceding code launches a Chromium-based browser, visits the application and mimics a user logging in to the application. Once submitted, it checks if the text of the header matches what is expected.
41
+
After, run the `k6 new` command with the `--template` option set to `browser`:
82
42
83
-
After running the test, the following [browser metrics](https://grafana.com/docs/k6/<K6_VERSION>/using-k6-browser/metrics) will be reported.
43
+
```bash
44
+
k6 new --template browser browser-script.js
45
+
```
84
46
85
-
{{< code >}}
47
+
The command creates a test script you can run right away with the `k6 run` command:
48
+
49
+
```bash
50
+
k6 run browser-script.js
51
+
```
52
+
53
+
After running the test, you can see the [end of test results](https://grafana.com/docs/k6/<K6_VERSION>/results-output/end-of-test/). It contains metrics that show the performance of the website on the script.
86
54
87
55
```bash
88
56
/\ Grafana /‾‾/
@@ -91,38 +59,69 @@ After running the test, the following [browser metrics](https://grafana.com/docs
91
59
/ \ | ( | (‾) |
92
60
/ __________ \ |_|\_\ \_____/
93
61
94
-
execution: local
95
-
script: test.js
96
-
output: -
97
-
98
-
scenarios: (100.00%) 1 scenario, 1 max VUs, 10m30s max duration (incl. graceful stop):
99
-
* default: 1 iterations for each of 1 VUs (maxDuration: 10m0s, gracefulStop: 30s)
100
-
101
-
102
-
running (00m01.3s), 0/1 VUs, 1 complete and 0 interrupted iterations
description: 'Learn how the k6 browser module uses asynchronous operations.'
4
+
weight: 100
5
+
---
6
+
7
+
# Asynchronous operations
8
+
9
+
Most methods in the browser module return [JavaScript promises](#why-the-browser-module-uses-asynchronous-apis), and k6 scripts must be written to handle this properly. This usually means using the `await` keyword to wait for the async operation to complete.
In addition to using `await`, another important part of writing k6 browser tests is handling page navigations. There are two recommended methods for doing that: using `Promise.all` or using the `waitFor` method.
26
+
27
+
## Promise.all
28
+
29
+
To avoid timing errors or other race conditions in your script, if you have actions that load up a different page, you need to make sure that you wait for that action to finish before continuing.
The preceding code uses `Promise.all([])` to wait for the two promises to be resolved before continuing. Since clicking the submit button causes page navigation, `page.waitForNavigation()` is needed because the page won't be ready until the navigation completes. This is required because there can be a race condition if these two actions don't happen simultaneously.
78
+
79
+
Then, you can use [`check`](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6/check) from the k6 API to assert the text content of a specific element. Finally, you close the page and the browser.
80
+
81
+
## Wait for specific elements
82
+
83
+
We also encourage the use of `locator.waitFor` where possible. When you navigate to a website, there are usually one or more elements that are important for your test. Once those elements load, you can safely proceed to the next step. For example, in a search scenario:
84
+
85
+
1. Navigate to the search site
86
+
1. Wait for the search bar and submit button to appear
This avoids the use of `Promise.all` which can be confusing to work with, and instead makes the script easier to follow.
113
+
114
+
## Why the browser module uses asynchronous APIs
115
+
116
+
The browser module uses asynchronous APIs that require `await` for several reasons:
117
+
118
+
1. JavaScript is single-threaded with a single event loop. Asynchronous APIs prevent blocking the thread and event loop with long-running or I/O-based tasks.
119
+
1. Consistency with [Playwright](https://playwright.dev/), a popular browser automation library.
120
+
1. Alignment with how developers expect to work with modern JavaScript APIs.
API calls that interact with Chromium are asynchronous and require `await` to ensure completion before proceeding. Synchronous APIs, such as `page.locator`, do not require `await`, but using it does not cause issues since the JavaScript runtime will simply return the value immediately.
137
+
138
+
If you don't add `await` on asynchronous APIs, it can cause the script to finish before the test completes, resulting in errors like `"Uncaught (in promise) TypeError: Object has no member 'goto'"`. That can happen because the page object from `browser.newPage()` without an `await` is actually a JavaScript promise. You can try and see the error using the following code snippet:
139
+
140
+
<!-- eslint-skip -->
141
+
142
+
```js
143
+
constpage=browser.newPage();
144
+
145
+
page.goto('https://quickpizza.grafana.com/'); // An error should occur since we're not using await in the line above.
0 commit comments