Awesome
ℹ️
This is not supported by the k6 team, and is worked on by a(n) individual contributor(s). It may also break in the future as both xk6 and playwright-go evolve. Any issues with the tool should be raised here.
It is not production ready yet, but definitely works as intended! Please enjoy the tool!
<br><br>
<div align="center"> <img src="images/xk6_logo.PNG" width="400" alt="xk6-playwright"/><br> <h1><b>xk6 playwright</b></h1><br> <p>k6 extension that adds support for browser automation and end-to-end web testing using <a href="https://github.com/mxschmitt/playwright-go" target="_blank">playwright-go</a></p> <p>Special thanks to all the contributors over at <a href="https://github.com/grafana/k6/graphs/contributors" target="_blank">k6</a> and <a href="https://github.com/mxschmitt/playwright-go/graphs/contributors" target="_blank">playwright-go</a> <p>Here's to open source!</p><a href="https://github.com/nicholasvuono/xk6-playwright/releases"><img alt="GitHub license" src="https://img.shields.io/badge/release-v0.3.3-blue"></a> <a href="https://goreportcard.com/report/github.com/wosp-io/xk6-playwright"><img src="https://goreportcard.com/badge/github.com/wosp-io/xk6-playwright?dummy=unused" alt="Go Report Card"></a> <a href="https://github.com/wosp-io/xk6-playwright/blob/main/LICENSE"><img alt="GitHub license" src="https://img.shields.io/github/license/wosp-io/xk6-playwright?color=red"></a>
</div><br><br>
Origin Story
This project was inspired by <a href="https://github.com/grafana/xk6-browser" target="_blank">xk6-browser</a>. Having previously worked with <a href="https://github.com/mxschmitt/playwright-go" target="_blank">playwright-go</a> we thought it would be a great idea to create an alternative extension around browser automation for the k6 community. Thus <a href="https://github.com/wosp-io/xk6-playwright" target="_blank">xk6 playwright</a> was born!
Note</br>
Although xk6-browser is still experimental it is pretty awesome and now comes bundled with k6 v0.46.0 and greater! In case this doesn't fit all your needs, go check that out!
</br>Build the executable
To build a k6
binary with this extension, first ensure you have the prerequisites:
- Docker
Then:
- Build the binary:
docker run --rm -e GOOS=darwin -u "$(id -u):$(id -g)" -v "${PWD}:/xk6" \
grafana/xk6 build \
--with github.com/wosp-io/xk6-playwright
on Windows:
docker run --rm -e GOOS=windows -u "$(id -u):$(id -g)" -v "${PWD}:/xk6" `
grafana/xk6 build --output k6.exe `
--with github.com/wosp-io/xk6-playwright
This will create a k6
binary file in the current working directory. This file can be used exactly the same as the main k6
binary, with the addition of being able to run xk6-playwright scripts.
- For the tool to work, the browsers and OS dependencies must be installed locally. You can use the following command for this:
go run github.com/playwright-community/playwright-go/cmd/playwright@v0.2000.1 install --with-deps
- Run scripts that import
k6/x/playwright
with the newk6
binary. On Linux and macOS make sure this is done by referencing the file in the current directory, e.g../k6 run <script>
, or you can place it somewhere in yourPATH
so that it can be run from anywhere on your system.
Simplest Working Example
import pw from 'k6/x/playwright';
export default function () {
try {
pw.launch();
pw.newPage();
pw.goto('https://test.k6.io/my_messages.php', { waitUntil: 'networkidle' });
pw.waitForSelector("input[name='login']", { state: 'visible' });
} catch (err) {
console.log(err);
} finally {
pw.kill();
}
}
</br>
Simplest Headful Example
import pw from 'k6/x/playwright';
export default function () {
try {
pw.launch({ headless: false });
pw.newPage();
pw.goto('https://test.k6.io/my_messages.php', { waitUntil: 'networkidle' });
pw.waitForSelector("input[name='login']", { state: 'visible' });
} catch (err) {
console.log(err);
} finally {
pw.kill();
}
}
Monitor Real User Metrics
import pw from 'k6/x/playwright';
export default function () {
try {
pw.launch()
pw.newPage()
pw.goto('https://test.k6.io/my_messages.php', { waitUntil: 'networkidle' });
pw.waitForSelector("input[name='login']", { state: 'visible' });
pw.type("input[name='login']", "admin")
pw.sleep(500)//give a chance for the browser apis to catch up
//print out real user metrics of the google search page
console.log(`First Paint: ${pw.firstPaint()}ms`)
console.log(`First Contentful Paint: ${pw.firstContentfulPaint()}ms`)
console.log(`Time to Minimally Interactive: ${pw.timeToMinimallyInteractive()}ms`)
console.log(`First Input Delay: ${pw.firstInputDelay()}ms`)
} catch (err) {
console.log(err);
} finally {
pw.kill();
}
}
</br>
Examples
More example can be found in the ./examples
directory
Currently Supported Actions
Playwright API coverage is as follows:
Action | Encompassed Playwright Function(s) | Description |
---|---|---|
launch() | Run() & Launch() | starts playwright client and launches Chromium browser |
connect() | Run() & Connect() | attaches playwright client to existing browser instance |
newPage() | NewPage() | opens up a new page within the browser |
goto() | Goto() | navigates to a specified url |
waitForSelector() | WaitForSelector() | waits for an element to be on the page based on the provided selector |
click() | Click() | clicks an element on the page based on the provided selector |
type() | Type() | types in an 'input' element on the page based on the provided selector and string to be entered |
pressKey() | PressKey() | simulates pressing a key, types in an 'input' element on the page based on a key to be entered |
sleep() | Sleep() | waits for a specified amount of time in milliseconds |
screenshot() | Screenshot() | attempts to take and save a png image of the current screen |
focus() | Focus() | focuses a spcific element based on the provided selector |
fill() | Fill() | fills an 'input' element on the page based on the provided selector and string to be entered |
selectOptions() | SelectOption() | selects an 'input' element from a list or dropdown of options on the page based on the provided selector and values to be selected |
check() | Check() | checks an element on the page based on the provided selector |
uncheck() | Uncheck() | unchecks an element on the page based on the provided selector |
dragAndDrop() | DragAndDrop() | drag an item from one place to another based on two selectors |
evaluate() | Evaluate() | evaluate an expresion or function and get the return value |
reload() | Reload() | reloads the current page |
cookies() | Cookies() | get all the cookies available for the default browser context. |
firstPaint() | N/A this function is unique to xk6-playwright What is First Paint? | captures the first paint metric of the current page milliseconds |
firstContentfulPaint() | N/A this function is unique to xk6-playwright What is First Contentful Paint? | captures the first contentful paint metric of the current page milliseconds |
timeToMinimallyInteractive() | N/A this function is unique to xk6-playwright - This is based on the first input registerd on the current page - NOTE: this is how we personally like to determine when a page is minimally interactive. | captures the time to minimally interactive metric of the current page milliseconds |
firstInputDelay() | N/A this function is unique to xk6-playwright What is First Input Delay? | captures the first input delay metric of the current page in milliseconds |
The above 'Encompassed Playwright Function(s)' will link to the playwright-go package documentation to give an in-depth overview of how these functions will behave from a low-level perspective.
If you would like a high-level perspective on how these actions work you will be better served with the Playwright API Documentation
</br>Contributing
- Fork it (https://github.com/your-github-user/xk6-playwright/fork)
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request
Contributors
Nick Vuono - creator and maintainer