# Write Playwright Tests for an Angular App

Yes. An agent writes Playwright specs for your Angular app's key flows, runs them headless against ng serve in its sandbox, and opens a pull request.

[Run this on Rush](https://cloud.getrush.ai/run/write-playwright-tests/angular/), in a Project that has your repository.

## What the agent does

The agent first works out what the repository already has, because an Angular app often has more test wiring than tests. In realworld-apps/angular-realworld-example-app, `package.json` pins Angular 21.2 and `@playwright/test` 1.58, uses Bun (`bun.lock`, `bun run setup`), and runs unit tests with Vitest through `@analogjs/vite-plugin-angular`, whose `vitest.config.ts` only picks up `src/**/*.spec.ts`. There is a `playwright.config.ts`, but its `testDir` is `./realworld/specs/e2e` and it imports `baseConfig` from the `realworld` git submodule. A fresh clone without `git submodule update` has an empty `realworld/`, so `bun run test:e2e` finds no tests and no config to load.

So it writes the app's own specs under `e2e/` with a config of its own, `playwright.config.ts` pointing at `./e2e` and no longer importing from the submodule, with `webServer` running `npm run start` (`ng serve`) on `http://localhost:4200` and `reuseExistingServer` off in CI, as the existing config already sets. It installs Chromium with `npx playwright install --with-deps chromium` and keeps `test:e2e` working for the new location.

The specs follow the app's real routes in `app.routes.ts` and its real form controls. Sign-in fills the `Email` and `Password` placeholders on `/login`, waits for the header to show the username, and checks `/settings` is reachable while `/editor` redirects to `/login` for a signed-out visitor through `requireAuth`. The editor spec fills `Article Title`, `What's this article about?`, the markdown body and `Enter tags`, publishes, and checks the article page renders the title and tags. The comments spec posts a comment on that article, reloads, and deletes it. For waiting on auth, the agent uses the `window.__conduit_debug__` hook `app.config.ts` installs (`getAuthState()` returns `authenticated`) instead of fixed sleeps.

Every request goes to `https://api.realworld.show/api` (`api.interceptor.ts` hard-codes it), a shared public backend. The agent registers a fresh user per test run with a unique username so specs never collide with other people's data, and keeps every article it creates traceable to that user. It runs the suite headless several times to catch flakiness, and where a test fails because of the app rather than the test, it marks it `test.fail()` with the reason.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "Write Playwright end-to-end tests for sign-in, the editor and comments in this Angular app. Put them in e2e/ with a playwright.config that starts the dev server, run them headless, and open a pull request with the passing suite. If a test exposes a real bug, mark it expected to fail and explain it in the description.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-angular-app"
    }
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

What comes back is a pull request that adds `e2e/auth.spec.ts`, `e2e/editor.spec.ts` and `e2e/comments.spec.ts`, a small fixture that registers a unique user and signs it in, and a `playwright.config.ts` whose `testDir` is `./e2e` with the `ng serve` web server. `package.json` keeps its existing scripts; `test:e2e` now runs the new specs without needing the submodule.

The description lists each spec and the flow it proves, how to run the suite locally, and every test marked `test.fail()` with what it found and the file that causes it. The session's trajectory keeps each `npx playwright test` run with its full output, including the failure message of every test marked as expected to fail.

Before merging, a reviewer checks whether the team wants the specs to keep using the public RealWorld API or a local backend, whether the old submodule-based config should be removed or kept beside the new one, and whether each expected failure is a bug to fix next. Adding the suite to CI is a one-step follow-up.

## Run it on every pull request that changes a route

A GitHub webhook for `pull_request` can send a request when a pull request touches `app.routes.ts` or a page component, with that pull request in `resources`, asking the agent to extend or fix the e2e specs for the changed flow. It works on that pull request's branch in its own sandbox and runs the suite there.

Set a webhook URL on the API key and Rush POSTs `run.completed` or `run.failed` when the turn finishes, with the session URL, so your server can post the result on the pull request.

## Why run it on Rush?

Writing Playwright tests for an Angular app on a laptop ties up a port, a dev server and a browser while you iterate, and a spec that passes once on your machine can still flake. In its own sandbox the agent runs `ng serve`, installs Chromium and runs the suite headless repeatedly, so what reaches you is a suite that has passed more than once.

The proof travels with the pull request: the trajectory has every `playwright test` command with its output, failures included. Because each run is isolated, the same request can add end-to-end tests to several Angular front ends at once without their dev servers fighting over port 4200.

## Frequently asked questions

### My repo already has a playwright.config.ts. Will it be overwritten?

It changes it only as far as the request needs, and the diff shows exactly how. In this app the existing config pointed at a submodule's shared specs, so the agent points `testDir` at `./e2e` and explains why in the description. If you want to keep both suites, ask for a second Playwright project instead.

### Does it test against my real backend?

It uses whatever URL the app calls. Here `api.interceptor.ts` hard-codes the public RealWorld API, so the specs register their own throwaway users there. For a private backend, name its URL or a local server command in the prompt, and the agent starts it before the tests.

### Will it use the Vitest setup the app already has?

No. Vitest stays for the unit specs under `src/`, and Playwright runs the end-to-end specs in `e2e/`. The two do not share files or config, so `bun run test` and `bun run test:e2e` keep working separately.

### What happens when a test finds a real bug?

The spec stays in the suite, marked `test.fail()` with a comment naming the cause, so the suite is green and the bug is still recorded. The pull request description lists each one, and a follow-up on the same session can fix it and remove the mark.
