> ## Documentation Index
> Fetch the complete documentation index at: https://momentic.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> The canonical docs host is https://momentic.ai/docs. Append .md to any page URL for clean Markdown. Fetch https://momentic.ai/docs/llms.txt for the page index and https://momentic.ai/docs/llms-full.txt for every page in one file.
> For an unattended setup, run `npx --yes @momentic/wizard@latest -y --platform web --editor-tools skills` (use `--platform ios` or `--platform android` for mobile). Never run an interactive command in a non-TTY shell.
> Mo is the AI QA engineer, a separate product from the YAML test framework: its npm package and CLI are `qa` (not `mo` — `npx mo` is a different project). Install with `npm install -g qa`, authenticate the same MOMENTIC_API_KEY way, install repo skills with `qa skills -y`, and start a session with `qa start "<brief>"` or `qa <url>`. Docs: https://momentic.ai/docs/mo.md.
> You cannot complete the browser sign-in yourself. Read the API key from the exact MOMENTIC_API_KEY environment variable (similarly named vars like BILT_MOMENTIC_API_KEY are ignored), or ask the user to create one at https://app.momentic.ai/settings/api-keys and paste it back.
> Momentic's capability summary for agents is at https://momentic.ai/docs/skill.md. Install the skills with `npx momentic skills --yes` (or `npx momentic-mobile skills --yes` for mobile).
> Tests are YAML files in the user's repository. Use only the step names listed at https://momentic.ai/docs/reference/commands.md and the file structure at https://momentic.ai/docs/core-concepts/file-format.md. Do not invent step names, config keys, or CLI flags.
> Web tests run on Chromium, iOS tests on simulators, and Android tests on emulators. Physical devices are not supported.

# From Playwright

> Port a Playwright suite to Momentic, including page objects, fixtures, storage state, network mocks, and reporters.

Move one Playwright flow at a time, preserving its setup, actions, assertions,
and cleanup. Momentic tests are YAML files with natural-language or CSS targets.
Use a coding agent with the [MCP server](/docs/coding-agents/mcp-server) and
[coding agent skills](/docs/coding-agents/skills) to draft the files, then review
them against the source spec before changing your CI gate.

## Before and after

This example assumes a test shop, an empty cart, and a fresh authenticated state
file generated by your existing Playwright setup. Both tests create an order;
use a test account and isolate or reset its server-side data between runs.

```ts checkout.spec.ts theme={null}
import { expect, test } from "@playwright/test";

test.use({ storageState: "playwright/.auth/user.json" });

test.describe("checkout", () => {
  test.beforeEach(async ({ page }) => {
    await page.goto("https://shop.example.com/products/42");
  });

  test("signed-in shopper can buy a blanket", async ({ page }) => {
    await page.getByRole("button", { name: "Add to cart" }).click();
    await page.getByTestId("cart-icon").click();
    await expect(page.getByText("Gravity Blanket")).toBeVisible();
    await page.getByRole("button", { name: "Checkout" }).click();
    await page.getByLabel("Email").fill("jeff@example.com");
    await page.getByRole("button", { name: "Place order" }).click();
    await expect(page).toHaveURL(/^https:\/\/shop\.example\.com\/orders\/\w+/);
    await expect(page.getByText("Order confirmed")).toBeVisible();
  });
});
```

The same user-flow checks in Momentic. This file sits at the repository root, so
the auth path resolves to `playwright/.auth/user.json`:

```yaml checkout.test.yaml theme={null}
fileType: momentic/test/v2
id: signed-in-checkout
url: https://shop.example.com/products/42
labels: [checkout]
before:
  - authLoad: ./playwright/.auth/user.json
  - navigate: https://shop.example.com/products/42
steps:
  - click: Add to cart
  - click: the cart icon
  - checkElementVisible: the text "Gravity Blanket"
  - click: Checkout
  - fill:
      text: jeff@example.com
      into: the Email field
  - click: Place order
  - waitForUrl:
      regex: ^https://shop\.example\.com/orders/\w+
  - checkElementVisible: the text "Order confirmed"
```

Lint and run the new file alone. Start with whole-test retries disabled so a
second attempt does not hide a setup or assertion mismatch:

```bash theme={null}
npx momentic lint checkout.test.yaml
npx momentic run checkout.test.yaml --parallel 1 --retries 0 --upload-results
```

`authLoad` refreshes the current page after restoring state. The following
`navigate` makes the starting page explicit if unauthenticated navigation
redirected to login. If you move the YAML under `tests/`, adjust the auth path
relative to that file. YAML `regex` values are pattern strings, without
JavaScript's surrounding `/.../` delimiters.

## API mapping

| Playwright | Momentic |
| - | - |
| `page.goto(url)` | `navigate: <url>` |
| `getByRole/getByText/getByTestId` + `.click()` | `click: <natural language>` or `click: { css: "..." }` |
| `.fill(value)` / `.pressSequentially(value)` | `fill` replaces a value; `type` emits keystrokes. Set `clear: never` to append. |
| `.press("Enter")` | `press: Enter` |
| `.hover()` / `.dblclick()` | `hover` / `doubleClick` |
| `selectOption` | `select` step, `click` the option, or an `act` goal for styled dropdowns |
| `expect(locator).toBeVisible()` | `checkElementVisible: <target>` or `assert:` for semantic checks |
| `expect(page).toHaveURL()` | `waitForUrl: { substring/glob/regex }` |
| `expect(page).toHaveTitle()` | Browser `javascript` that checks `document.title` and throws on a mismatch |
| `waitForSelector` / `waitFor` | `checkElementVisible` with `timeout`; use `wait: <ms>` only for a fixed delay |
| `page.route()` interception | [`mock`](/docs/reference/commands/mock) with `substring`/`glob`/`regex`/`method` |
| `page.waitForRequest`/`waitForResponse` | `registerRequestListener` + `awaitListener` (captures request and response) |
| `request`/`response` event log | `recordRequests` + `getRecordedRequests` |
| `page.on('dialog')` | `dialog: ACCEPT` or `DISMISS`, placed before the step that raises it |
| `page.screenshot()` | automatic per-step screenshots; video needs `recordVideo` in the config |
| `context.addCookies()` | `cookie` for individual cookies, or `authLoad` for a storage-state object |
| `localStorage` read/write | `localStorage` step writes a key; browser `javascript` for reads or clears |
| `context.setExtraHTTPHeaders` | `header` step or `--custom-headers` on the CLI |
| `context.setOffline()` | `offline` / `online` steps |
| `storageState` / `context.storageState()` | `authLoad: <path>` imports cookies and local storage; verify other storage separately |
| `page.evaluate()` | `javascript` step with `environment: browser` |
| Screenshot comparisons | `assertVisually` / `visualDiff`; compare baselines rather than copying them |
| `page.waitForLoadState` | steps wait for their targets; keep explicit waits for other readiness conditions |

## Fixture and helper mapping

| Playwright construct | Momentic |
| - | - |
| `test.beforeEach` | `before:` steps on the test |
| `test.afterEach` | `after:` steps (run even when main steps fail) |
| `test.beforeAll` / worker fixtures | Keep shared setup in a CI script; an ordinary module in `before` runs per test attempt |
| Custom fixtures / page object | [Modules](/docs/core-concepts/modules) reuse browser steps; preserve fixture scope and teardown separately |
| `test.describe` grouping | Directory layout plus `labels:` |
| `test.only` / `test.skip` | Pass a test path or `--labels` to select tests; `disabled: true` skips a test |
| `use.baseURL` | `environments[].baseUrl` in `momentic.config.yaml` |
| `projects:` matrix | `--env` for deployments; browser/viewport settings and separate CI jobs for supported variants |
| `retries` config | Test/config `retries` or `--retries` reruns the whole test; step `retries` has narrower scope |
| `test.use({ viewport })` | top-level test `viewport`, such as `{ width: 1280, height: 720 }` |
| Reporters (`html`, `junit`) | Local report/dashboard plus `--reporter junit`, `json`, `allure`, or `playwright-json` |

## What keeps working unchanged

* `authLoad` imports cookies and local storage from Playwright storage-state
  JSON. Keep your [auth bootstrap](https://playwright.dev/docs/auth) running
  before the Momentic job and regenerate expired state. Keep state files out of
  Git. Playwright's per-origin IndexedDB snapshot fields are not imported;
  validate any auth that depends on them separately.
* A Node `javascript` step provides `fetch`, `faker`, and the documented
  [JavaScript globals](/docs/integrations/javascript). Port seed endpoint calls into
  those steps. Existing helpers with imports or fixture dependencies need
  adaptation; you can keep them in a separate script before the CLI run.
* Momentic installs and runs in the same GitHub Actions job; see
  [Run in CI](/docs/running-tests/ci/github-actions).
* `--reporter junit` emits JUnit XML. Check the suite names, test names, and
  artifact paths expected by your existing analytics.

## Preserve isolation and failure behavior

Momentic initializes a browser for each whole-test attempt. Put per-test setup
in `before` and cleanup in `after`; teardown runs after setup or main-step
failures, and a teardown failure fails the run. It cannot clean up a run that
never reached setup, such as an initial navigation failure. Keep cleanup
idempotent and use a separate cleanup job for shared server-side resources.

Playwright
[worker fixtures](https://playwright.dev/docs/test-fixtures#worker-scoped-fixtures)
and `beforeAll` are not equivalent to a Momentic module. Moving their contents
into `before` repeats them on each test attempt. Keep shared services and seed
data outside the test, or make per-test setup safe to repeat. Use separate
accounts or unique records for concurrent tests that mutate server state.

Preserve exact checks for URL, text, counts, and response fields. Use preset
checks or JavaScript that throws when the condition fails; returning a value
alone is not an assertion. Review any replacement AI assertion against the
original expected state. Carry forward the role, accessible name, text matching
rules, and scope of `getByRole`/`getByText`. Keep an explicit CSS target when a
description cannot preserve those constraints. A visibility check does not
replace an assertion about how many elements match. Compare
[whole-test retries](https://playwright.dev/docs/test-retries), step retries,
and [failure recovery](/docs/reliability/auto-maintenance#failure-recovery)
separately; passing after recovery does not establish first-attempt parity.

## What does not map

* Momentic re-resolves a target from its description each run (with a
  [step cache](/docs/reliability/step-cache) to skip the model call when the page has
  not changed). Element handles and locator chains do not port: express the
  intent in the target text instead.
* Firefox and WebKit projects have no equivalent browser target. Momentic web
  tests support Chromium-based browsers. Keep those existing browser jobs;
  `--env` selects deployment variables, not a browser engine or a project
  dependency graph.
* Momentic manages the browser context, so `browserContext` control does not
  port. `newTab`, `closeTab`, and `navigate` cover tab workflows, but you do not
  create isolated contexts mid-test. Use separate tests or `authLoad` per test
  for different identities.
* Custom `page.on("console")` event handlers do not port. Replace assertions
  that depend on them with explicit observable checks, or retain that coverage
  in Playwright.
* The local editor and AI authoring cover what Codegen records; there is no
  recorder that emits Playwright-API code to copy back.

## Incremental strategy

1. Keep Playwright and its CI gate. Use the [web setup](/docs/quickstart/web) to add
   Momentic, preserving an existing `momentic.config.yaml`. Commit the
   dependency lockfile and include globs that discover the new test files.
2. Record each flow's fixtures, test account, mocks, expected outcomes, browser
   variants, and cleanup. Port one critical flow and label it `migrated`.
3. Lint it, then run it alone with `--parallel 1 --retries 0`. Confirm its
   assertions fail for a deliberate mismatch in your test environment, then
   restore the expected state. Review screenshots and any recovery or
   classification before accepting parity.
4. Add a separate Momentic CI job with its own output directory and test data.
   Keep the Playwright job required while you compare results. Generate the auth
   file before the new job and make it available at the path the YAML expects.
   `--filter` selects a workspace project; it does not select a spec.
5. Switch the gate flow by flow after repeated passes and a reviewed expected
   failure. Preserve the original specs and CI configuration in Git so you can
   restore the previous gate. Remove Playwright only after its remaining
   browser, fixture, and reporter coverage has a replacement.

Inspect the selected paths before running the overlap job:

```bash theme={null}
npx momentic lint
npx momentic list --labels migrated
npx momentic run --labels migrated --parallel 1 --retries 0 --ignore-quarantine --output-dir ./momentic-migration-results --upload-results --reporter junit
npx momentic results check ./momentic-migration-results
```

By default, `results check` rejects non-quarantined runs that failed, were
cancelled, recovered, or had a failure classification. It ignores quarantined
runs and accepts an archive with zero tests. The recipe uses
`--ignore-quarantine` so quarantine does not mask the selected tests' statuses;
confirm the list and run totals contain the enabled tests you intend to port.
See [results checks](/docs/cli-reference/momentic/commands/results#check) and
[GitHub Actions](/docs/running-tests/ci/github-actions) for CI setup.

## Porting at scale with a coding agent

Point your coding agent at the spec files and the
[`momentic-test` skill](/docs/coding-agents/skills). A prompt that works well:

```text theme={null}
Port the Playwright specs in e2e/checkout.spec.ts to Momentic tests.
Read the momentic-test skill first. Write one *.test.yaml per Playwright
test() under tests/, keep the describe names as directory structure, reuse
playwright/.auth/user.json via authLoad, and run each new test with
npx momentic run <file> before moving on.
```

Review the generated targets and assertions against the source spec, lint the
YAML, and run each ported flow before replacing its existing CI gate.

## Related

* [Test portability](/docs/get-started/test-portability)
* [Web steps reference](/docs/reference/commands/index)
* [JavaScript integration](/docs/integrations/javascript)
* [Authentication guides](/docs/guides/auth/overview)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.