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

# Record end-to-end tests

> Turn end-to-end test runs into Jams. Upload a failed Playwright test from CI, or record a headless browser while the tests run.

A failed end-to-end test in CI usually leaves a stack trace and a guess. A Jam leaves the video, with the run's console logs and network requests on the same timeline. Reviewers watch the failure instead of rerunning it.

Pick one of two approaches:

| Approach | Use it when |
| - | - |
| [Upload a failed Playwright test](#upload-a-failed-playwright-test) | You use Playwright and want a Jam only when a test fails. Nothing changes in your tests. |
| [Record tests live](#record-tests-live) | You want a Jam of every run, with the test's clicks and typing recorded live. |

<Info>
  CI needs a [personal access token](/docs/personal-access-tokens) in the `JAM_TOKEN` environment variable. The CLI never writes it to disk.
</Info>

## Upload a failed Playwright test

Playwright already saves a video and a trace for failed tests. `jam create jam` reads both. The Jam plays the video with the console and network from the trace, and shows what the test typed with sensitive fields masked.

<Steps>
  <Step title="Keep the video and trace for failed tests">
    In `playwright.config.ts`:

    ```ts theme={"theme":"css-variables"}
    use: { video: "retain-on-failure", trace: "retain-on-failure" }
    ```
  </Step>

  <Step title="Install the CLI in your CI job">
    ```bash theme={"theme":"css-variables"}
    curl -fsSL https://native.jam.dev/install | bash
    export PATH="$HOME/.local/bin:$PATH"
    ```
  </Step>

  <Step title="Upload each failure after the tests">
    Run this when the test step fails:

    ```bash theme={"theme":"css-variables"}
    for dir in test-results/*/; do
      jq -n --arg dir "$dir" --arg name "$(basename "$dir")" '{
        kind: "video",
        url: "https://example.com/checkout",
        title: $name,
        videoPath: "\($dir)video.webm",
        playwrightTracePath: "\($dir)trace.zip",
        screenDimensions: { width: 1280, height: 720 }
      }' | jam create jam
    done
    ```

    Playwright writes each failed test into its own folder under `test-results/`, so the loop creates one Jam per failure, titled with the folder name. `jq` builds the payload, and `jam create jam` reads it from stdin. Install `jq` first if your runner does not have it.
  </Step>

  <Step title="Post the link">
    Each `jam create jam` prints a Jam's `url`. Post the links where your team reviews the run, such as the pull request.
  </Step>
</Steps>

## Record tests live

`jam record run` records a browser while your test command runs. With `--cdp`, the video, console, and network come from the browser itself, so a headless browser on a CI runner records too.

<Steps>
  <Step title="Start Chrome with a debug port">
    ```bash theme={"theme":"css-variables"}
    google-chrome --headless=new --remote-debugging-port=9222 --user-data-dir=/tmp/jam-chrome about:blank &
    until curl -s http://127.0.0.1:9222/json/version > /dev/null; do sleep 0.5; done
    ```

    The loop waits until Chrome accepts connections, so the recording does not start too early.
  </Step>

  <Step title="Wrap the tests in jam record run">
    ```bash theme={"theme":"css-variables"}
    jam record run --cdp 9222 --title "Checkout e2e" -- node e2e/checkout.js
    ```

    The wrapped command gets the recorder's address in `JAM_CDP_PROXY`. Connect your test to it so its clicks and typing show up as user actions in the Jam:

    ```js theme={"theme":"css-variables"}
    const browser = await chromium.connectOverCDP(process.env.JAM_CDP_PROXY);
    ```
  </Step>
</Steps>

The command keeps the test's exit code, so a failing test still fails the job and still leaves a Jam. Recording a browser page needs `ffmpeg` on the runner.

## Next

* For Playwright payload fields, including `--speedup` to cut idle time, see [Create and update Jams](/docs/cli-reference#create-and-update-jams).
* To connect Puppeteer, agent-browser, or an MCP browser tool, see [Record an agent's browser](/docs/cli-record-browser).


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