All jobs

Write Playwright Tests for a Vue App

Yes. An agent writes Playwright specs for your Vue app's main flows, runs them headless against the Vite dev server in its sandbox, and opens a pull request.

Run this on RushIn a Project that has your repository.

What the agent does

The agent starts from the test wiring the repository already has. In realworld-apps/vue-realworld-example-app, package.json has Vue 3.5, Pinia 3, vue-router 5, Vite 8 and @playwright/test ^1.60, uses Bun (bun.lock), and its test script is playwright test. But playwright.config.ts sets testDir: './realworld/specs/e2e' and imports baseConfig from the realworld git submodule, so the only specs are a shared suite that a clone without git submodule update does not have. Nothing in the repository tests this app's own Pinia stores or components in a browser.

It also reads the server settings before writing the config, because they decide whether the first run even connects. vite.config.js binds 127.0.0.1:8080 with strictPort: true, and its comment explains why: under Bun, localhost can resolve to ::1 while the readiness probe uses IPv4. The existing config's webServer.url is http://127.0.0.1:8080 but use.baseURL is http://localhost:8080. The agent's new e2e/ config uses 127.0.0.1 in both, runs bun run serve as the web server, and points testDir at ./e2e.

The specs follow the app's routes in src/router/index.js and its stores. Sign-in fills Email and Password on /login, checks the header shows the username, and checks the token lands in localStorage under jwtToken, the key src/common/jwt.service.js uses. The feed spec checks the Global Feed loads articles, that Your Feed (/?feed=following) only appears when signed in and shows the empty-feed message for a new user, and that a tag link filters the list. The favoriting spec favorites an article from the home list and from the article page, checks the counter goes up by one in both places (the updateArticleInList path in src/store/home.js), and checks a signed-out click goes to /login, as ArticleMeta.vue does.

The API base is VITE_API_URL or https://api.realworld.show/api (src/common/config.js), a public backend shared with other users, so each run registers its own users. The agent runs the suite headless several times, including a fast double click on the favorite button, and any test that fails because of the app stays in the suite as test.fail() with its cause.

Start it with one API call

POST https://api.prix.dev/o/{org}/sessions with this body:

{
  "agent": "claude",
  "input": "Write Playwright end-to-end tests for sign-in, the article feed and favoriting in this Vue 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-vue-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/feed.spec.ts and e2e/favorite.spec.ts, a fixture that registers a unique user and stores its signed-in state, and a playwright.config.ts with testDir: './e2e', bun run serve as its web server and 127.0.0.1:8080 as both its URL and baseURL. src/ is untouched.

The description lists each spec and the store or component it exercises, explains the localhost to 127.0.0.1 change, and names every test marked test.fail() with the file behind it. The session's trajectory keeps every npx playwright test run with its output, so a reviewer can see the suite passing on more than one run.

Before merging, a reviewer decides whether to keep the submodule's shared suite as a second Playwright project, whether the specs should set VITE_API_URL to a backend the team controls, and which expected failures to fix. Adding the suite to CI is a follow-up on the same session.

Run it on every Vite or Vue major upgrade

When a dependency bot opens a pull request that moves Vite, Vue, Pinia or vue-router to a new major, a GitHub webhook can send this request with that pull request in resources, asking the agent to run the e2e suite and fix what broke. Router and store upgrades are what change sign-in redirects and list updates, which are exactly what these specs check.

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 the upgrade pull request gets a comment before anyone merges it.

The use case this job follows, with its automation and trigger: Write the missing tests.

Why run it on Rush?

End-to-end tests for a Vue app need a dev server on a fixed port, a browser, and a backend, and small things like localhost resolving to IPv6 under Bun break the first run on some machines and not others. In its own sandbox the agent starts the server, installs Chromium and runs the suite from a clean environment, so the config it hands back is one that worked from nothing.

Every command and its output is in the trajectory, so the pull request carries its own proof. Because runs are isolated, the same request can add end-to-end tests to each of your Vue front ends at once, and strictPort on 8080 never conflicts between them.

Frequently asked questions

Will it replace the shared RealWorld spec suite?

It points the default config at the app's own e2e/ specs so the suite runs without the submodule, and says so in the description. If you want both, ask for two Playwright projects, one per test directory, and the agent keeps the shared suite as the second.

Can it test against my own API instead of the public one?

Yes. The app reads VITE_API_URL, so name your backend's URL or the command that starts it locally in the prompt. The agent sets it for the web server and the specs then create their users there.

Does it work with npm or pnpm instead of Bun?

It uses whatever the lockfile says. This repository has bun.lock and serves with bun run serve, so the config uses that. With package-lock.json or pnpm-lock.yaml, the web server command changes to match.

Why does the config use 127.0.0.1 instead of localhost?

vite.config.js binds the server to 127.0.0.1 only. Under Bun, localhost can resolve to the IPv6 address ::1, where nothing is listening, so tests using localhost as baseURL can fail to connect. Using one address for both the server check and the tests removes that difference.