Skip to content

Conversation

ankur22
Copy link
Contributor

@ankur22 ankur22 commented Oct 7, 2025

What?

A migration document guiding users how to work with k6 when migrating their scripts from Playwright.

Checklist

  • I have used a meaningful title for the PR.
  • I have described the changes I've made in the "What?" section above.
  • I have performed a self-review of my changes.
  • I have run the npm start command locally and verified that the changes look good.
  • I have made my changes in the docs/sources/k6/next folder of the documentation.
  • I have reflected my changes in the docs/sources/k6/v{most_recent_release} folder of the documentation.
  • I have reflected my changes in the relevant folders of the two previous k6 versions of the documentation (if still applicable to previous versions).
  • I have made my changes in the docs/sources/k6/next folder of the documentation.

Related PR(s)/Issue(s)

Mainly to assess the structure and content, as well as how to deal with
links to other docs e.g. docs to hybrid tests.
@ankur22 ankur22 requested review from a team and heitortsergent as code owners October 7, 2025 09:39
@ankur22 ankur22 requested review from AgnesToulet and mstoykov and removed request for a team October 7, 2025 09:39
@ankur22 ankur22 marked this pull request as draft October 7, 2025 09:39
Copy link
Contributor

github-actions bot commented Oct 7, 2025

@heitortsergent heitortsergent added the Area: browser The browser module label Oct 9, 2025

## Introduction

- Playwright has many use cases:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this meant to remain a bullet list? Otherwise, I think it would be more impactful to turn it into a set of sections and paragraphs. This also forces us to tell a compelling story.

---
title: 'Migrating from Playwright'
description: 'A migration guide to ease the process of transitioning from Playwright to k6'
weight: 600
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the preview, and considering this is such an important ask from our users, I would suggest to bump this page in the section's rank much higher, I'm almost tempted to put it in second, but more realistically, right before "recommended practices" would be a no brainer from my perspective 🙇🏻

weight: 600
---

# Migrating from Playwright
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A general comment as I read through this guide on the preview is that this introduction felt very overwhelming, and if I'm honest with myself triggered a bit of a TLDR syndrome on me 😅

If the goal is to make this a guide, I’d suggest focusing on making it as actionable as possible, and moving most of the background/context either later in the guide or only where it’s needed.

As a reader, I came here expecting something that helps me convert my Playwright script into a k6 script — more of a “when you do X in Playwright, you do Y in k6” kind of format. So maybe the introduction could set that expectation more clearly.

For example:

  • “You have a Playwright script — this guide will help you turn it into a k6 script.”
  • “Here are the key differences and what to watch for: X, Y, Z (e.g., ‘the test helper doesn’t exist, do X instead’).”
  • “Here’s where functionality differs, how to work around it, and what we might improve in the future.”

Then, the rest of the guide could go into details and add context “just in time” for the reader.

Overall, I’d aim for a guide that feels condensed, pragmatic, and easy to skim — something I can quickly use to get my Playwright script running in k6, and later revisit for specific reminders or examples.

Comment on lines +34 to +47
## Migration steps

Let's work with this Playwright test script:

```js
import { test, expect } from '@playwright/test';

test('has title', async ({ page }) => {
await page.goto('https://playwright.dev/');

// Expect a title "to contain" a substring.
await expect(page).toHaveTitle(/Playwright/);
});
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As hinted at in a previous comment, it could make sense to frame this as "your existing playwright test suite most likely looks something along those lines", and treat the example we give as a reference point for the rest of the migration guide, like it's already done in the rest of the PR.

In the spirit of helping users relate to the example as much as possible, I also wondered if it would make sense addressing the case of multiple test cases in playwright tests, and how to reproduce that in k6, from the get go, in the top-level example (I see we talk about that later).

Comment on lines +279 to +335
## Key Differences & Limitations

- Browser context restrictions;

Unlike in Playwright, k6 can only work with a single `browserContext` at a time. So in k6 you won't be able to do:

```js
const bc1 = await browser.newContext();
// This next call will result in an error "existing browser context must be closed before creating a new one"
const bc2 = await browser.newContext();
```

You'll have to close the existing `browserContext` first, before creating a new one.

- Fixtures isn't supported in k6 browser as well as no test framework. Abstractions will need to be hand coded.
- Test isolation patterns -- in k6 there is [scenarios](https://grafana.com/docs/k6/latest/using-k6/scenarios/) whereas in Playwright there is a dedicated test framework. The difference stems from k6 being a load testing tool. We are [evaluating](https://github.com/grafana/k6-jslib-testing/issues/30) a test framework, but it's still early days.
- File uploads/downloads
- It's not supported in k6 browser. We are evaluating the possibility and have issues for this:
- https://github.com/grafana/k6/issues/4233
- https://github.com/grafana/k6/issues/4485
- https://github.com/grafana/k6/issues/4197
- https://github.com/grafana/k6/issues/4170
- https://github.com/grafana/k6/issues/4129
- Screenshots and recordings
- We have screenshot support in local runs as well in Grafana cloud. We are evaluating a session recording feature for SM, load testing and Faro.
- not being able to share data between VUs and iterations:
- Work with a single executed immutable [sharedarray](https://grafana.com/docs/k6/latest/javascript-api/k6-data/sharedarray/)
- Work with the [xk6-redis extension](https://grafana.com/docs/k6/latest/javascript-api/k6-experimental/redis/) which is currently experimental but will be non-experimental very soon.
- All browserContexts are incognito. An evaluation and more feedback is needed to understand its use case [issue](https://github.com/grafana/k6/issues/4378).
- Files can only be read during the init phase and not during the test runtime with the [experimental fs module](https://grafana.com/docs/k6/latest/javascript-api/k6-experimental/fs/).
- web vitals will be reported on; we are evaluating further work to bring about more measurements such as JS heap size, long task and more.

## Configuration Migration

- Playwright config → k6 options mapping
- k6 browser doesn't work with a work directory, so you need to supply the exact script to run relative to the current directory.
- Scenarios are independent of each other -- they are parallel by default. Add `startTime` to make them [sequential](https://grafana.com/docs/k6/latest/using-k6/scenarios/#scenarios).
- test.only -- no equivalent
- retries: No auto retry mechanism
- workers -- depends on the number of scenarios, which is like a single playwright worker, but also very different.
- reporter -- to change the output of the result take a look [here](https://grafana.com/docs/k6/latest/results-output/end-of-test/) for end of test summary, [here](https://grafana.com/docs/k6/latest/results-output/real-time/) for real time, [web dashboard](https://grafana.com/docs/k6/latest/results-output/web-dashboard/) and [grafana dashboard](https://grafana.com/docs/k6/latest/results-output/grafana-dashboards/).
- baseURL -- no such equivalent
- trace -- work with grafana k6 to see a timeline view of the test run
- projects -- no such equivalent
- webServer -- no such equivalent
- outputDir -- depends on the output you use
- globalSetup -- no such equivalent
- globalTeardown -- no such equivalent
- timeout -- use K6_BROWSER_TIMEOUT env var
- expect.timeout -- no way to set this as a config, needs to be done in the main test block
- expect.toHaveScreenshot -- no such equivalent
- expect.toMatchSnapshot -- no such equivalent
- sharding -- work with grafana k6 for easy multi region, multi load generator setup, with results automatically merged into a single report.
- typescript is supported
- Browser launch options
- https://grafana.com/docs/k6/latest/using-k6-browser/options/
- K6_BROWSER_WS_URL to work with an existing CDP ws url presented by chromium.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question as above, do we mean to keep this as a bullet list, or is it here as a preparation step? 🤓

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: browser The browser module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants