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

# Playwright Nx Monorepo Setup

> Run Playwright e2e targets across an Nx monorepo and stream their results to TestDino, grouped into one run.

Nx runs Playwright end-to-end tests per project through the `@nx/playwright` plugin. The `@testdino/playwright` reporter streams each target's results to TestDino during the run and groups them into one run.

## Prerequisites

* A <a href="https://app.testdino.com" target="_blank" rel="noopener noreferrer">TestDino account <Icon icon="arrow-up-right-from-square" size={12} /></a> with a project created
* A TestDino API key ([Generate API Keys](/guides/generate-api-keys))
* An Nx workspace with `@nx/playwright` and one or more e2e projects
* `@testdino/playwright` installed:

```bash theme={null}
npm install @testdino/playwright
```

## Configure the Reporter

Add `@testdino/playwright` to the reporter array in the Playwright config, layered on top of the Nx preset. Share this config across projects, or import it per project.

```typescript playwright.config.ts theme={null}
import { nxE2EPreset } from '@nx/playwright/preset';
import { defineConfig } from '@playwright/test';

const nxConf = nxE2EPreset(__filename);

export default defineConfig({
  ...nxConf,
  reporter: [
    ['@testdino/playwright', {
      token: process.env.TESTDINO_TOKEN,
    }],
  ],
});
```

## Configure the e2e Target

Each e2e project runs through the `@nx/playwright:playwright` executor in its `project.json`.

```json project.json theme={null}
{
  "$schema": "../../node_modules/nx/schemas/project-schema.json",
  "name": "e2e-app",
  "projectType": "application",
  "targets": {
    "e2e": {
      "executor": "@nx/playwright:playwright",
      "options": {
        "config": "{projectRoot}/playwright.config.ts",
        "output": "{workspaceRoot}/playwright-report/{projectName}"
      }
    }
  }
}
```

## Run Tests

Set the token and a shared run id, then run every `e2e` target. Each project streams its results to TestDino, and a shared `TESTDINO_CI_RUN_ID` groups them into one run.

```bash theme={null}
export TESTDINO_TOKEN="your-api-key"
export TESTDINO_CI_RUN_ID="$(date +%s)"
nx run-many -t e2e --parallel=2
```

| Variable             | Purpose                                                                                                       |
| :------------------- | :------------------------------------------------------------------------------------------------------------ |
| `TESTDINO_TOKEN`     | Streaming key from [Generate API Keys](/guides/generate-api-keys).                                            |
| `TESTDINO_CI_RUN_ID` | The same value across targets groups them into one run. `@testdino/playwright` reads it from the environment. |
| `--parallel=2`       | Number of e2e targets Nx runs at once.                                                                        |

## Run in CI (GitHub Actions)

Store `TESTDINO_TOKEN` as a repository secret and use the workflow run id as `TESTDINO_CI_RUN_ID` so every target groups into one run.

```yaml .github/workflows/e2e.yml theme={null}
name: E2E

on:
  push:
    branches: [main]
  pull_request:

jobs:
  e2e:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npx playwright install --with-deps
      - name: Run e2e with TestDino
        env:
          TESTDINO_TOKEN: ${{ secrets.TESTDINO_TOKEN }}
          TESTDINO_CI_RUN_ID: ${{ github.run_id }}
        run: npx nx run-many -t e2e --parallel=2
```

## Shard a Single Project

To split one large project across machines, pass Playwright's `--shard` through the Nx target and keep the same `TESTDINO_CI_RUN_ID` on every shard. Arguments after `--` pass straight to Playwright.

```yaml .github/workflows/e2e-sharded.yml theme={null}
jobs:
  e2e:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        shard: [1, 2, 3]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npx playwright install --with-deps
      - name: Run shard ${{ matrix.shard }}
        env:
          TESTDINO_TOKEN: ${{ secrets.TESTDINO_TOKEN }}
          TESTDINO_CI_RUN_ID: ${{ github.run_id }}
        run: npx nx e2e e2e-app -- --shard=${{ matrix.shard }}/3
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="Results not appearing on the dashboard">
    Confirm `@testdino/playwright` is in the `reporter` array of the Playwright config the target loads, and `TESTDINO_TOKEN` is set in the environment. Results stream during the run, so no separate upload step is required.
  </Accordion>

  <Accordion title="Targets show up as separate runs">
    Set `TESTDINO_CI_RUN_ID` to the same value for every target and shard. A per-target value creates one run each.
  </Accordion>

  <Accordion title="Nx serves a cached result instead of running the tests">
    e2e targets reach the network, so they should not be cached. Remove `e2e` from `cacheableOperations` (or the target's `cache` option), or run with `--skip-nx-cache`.
  </Accordion>
</AccordionGroup>

## Related

<CardGroup cols={2}>
  <Card title="GitHub Actions" icon="github" href="/guides/playwright-github-actions">
    Full GitHub Actions setup and status checks
  </Card>

  <Card title="CI Optimization" icon="gauge-high" href="/guides/playwright-ci-optimization">
    Reduce CI time with smart reruns
  </Card>

  <Card title="Environment Mapping" icon="code-branch" href="/guides/environment-mapping">
    Route test results to Dev, Staging, or Production by branch
  </Card>

  <Card title="TestDino MCP" icon="plug" href="/mcp/overview">
    Access test results and fix issues with AI agents
  </Card>
</CardGroup>
