All jobs

Add Missing Tests to Every Pull Request in a Next.js App

Yes. An agent reads each pull request to your Next.js app, writes Vitest tests for the posts editor and API routes it changes and pushes them back.

Run this on RushIn a Project that has your repository.

What the agent does

The agent reads the pull request's diff and finds the route handlers and components it changes. In a Next.js app-router app like shadcn-ui/taxonomy the posts API is app/api/posts/route.ts (GET lists the signed-in user's posts, POST creates one) and app/api/posts/[postId]/route.ts (PATCH and DELETE), each checking the session with getServerSession(authOptions) and validating input with zod. The editor is components/editor.tsx, which posts its form to /api/posts/${post.id}, with its schema in lib/validations/post.ts. It notes rules the diff adds or changes, such as the free-plan limit in POST, where a user who is not on a pro plan gets 402 Requires Pro Plan after three posts.

Then it finds that taxonomy has no tests and no test runner at all: package.json has dev, build, lint and preview scripts, no test, and no Vitest or Jest in devDependencies. So the first run on a repository like this adds the smallest setup that runs: vitest as a dev dependency installed with pnpm (the repository has pnpm-lock.yaml at lockfileVersion: '6.0'), a vitest.config.ts that maps the @/ import alias from tsconfig.json's paths, and a test script of vitest run. It says in its comment that it added these and why, because a reviewer should decide whether to keep a new tool.

The route tests import the handlers directly and call them with a Request and a { params: { postId } } context, the shape routeContextSchema parses. The handlers read a session, a Prisma client from lib/db.ts and a subscription plan from lib/subscription.ts, and env.mjs validates more than a dozen server variables with @t3-oss/env-nextjs at import, so the agent substitutes those modules at the test boundary with vi.mock and sets test values for the environment. Each test then checks one rule a client depends on: 403 with no session, 422 with the zod issues for a title shorter than 3 characters, 402 on the fourth post on the free plan, 204 after a delete by the owner.

It runs npx vitest run until the new tests pass, and pnpm lint so the new files meet the existing next lint setup. A test that fails because the handler is wrong stays out of the commit, since the prompt forbids application changes, and the agent describes the failing request and response in its comment.

Start it with one API call

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

{
  "agent": "claude",
  "input": "This pull request changes the posts editor and API routes. Read the diff against the base branch and list the new or changed behavior in app/api/posts, components/editor.tsx and lib/validations/post.ts that no existing test covers. If the repository has no test runner, add Vitest with pnpm, a vitest.config.ts that maps the @/ alias from tsconfig.json and a test script, and say so in your comment. Write Vitest tests next to the code they cover: call the route handlers with a Request and route params, replace the session, the Prisma client and the subscription lookup with vi.mock at the module boundary, and set test values for env.mjs. Run npx vitest run until the new tests pass. Do not change application code: if a test fails because the code is wrong, leave it out and describe the failure. Push the tests to this pull request's branch and post a comment listing each test and the behavior it covers.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app/pull/123"
    }
  ]
}
  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 commit on the pull request's branch. On a repository with no test setup, like taxonomy, it adds vitest.config.ts, a test script and the vitest entry in package.json and pnpm-lock.yaml, plus test files such as app/api/posts/route.test.ts and app/api/posts/[postId]/route.test.ts, and a test for postPatchSchema when the pull request changed it. On a repository that already has Vitest, the commit is only the new test files. Application files are not touched.

The agent's comment on the pull request lists each test with the status code or rule it checks, names any setup it added, and gives the command it ran. If a test found a defect, for example a PATCH that lets a user edit a post they do not own, the comment shows the request, the response and the line in the route handler. Once the test script exists, add it to your CI so later pull requests run these tests as a check.

Before merging, a reviewer checks that the mocked modules stand in only for the session, the database and Stripe, so each test still exercises the real handler and the real zod schema, and that the test environment values in the setup are placeholders, never real keys.

Run it on every pull request opened

Create an automation on the Project bound to your Next.js repository with this prompt and a GitHub trigger on pull_request.opened. Each pull request opened by someone with write access starts its own run, and the run's prompt carries its number, URL, title, author and base branch. After the first run adds Vitest, the same prompt finds the runner already there and only adds tests. Pull requests from forks never fire the trigger.

To start runs from your own code, handle GitHub's pull_request webhook and, on opened, send this request with the pull request's URL in resources, which clones its branch. Send the delivery id as Idempotency-Key so a redelivery returns the run it already started.

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

Why run it on Rush?

Adding tests to a Next.js app that has none is a setup problem before it is a writing problem: the alias, the environment validation at import and the server-only modules all have to be handled before the first test runs. On Rush the agent works that out in its own sandbox, installing with pnpm and running Vitest at the pull request's branch, while your dev server and your .env stay untouched on your machine.

The run hands back proof rather than a claim. Its trajectory keeps every install and vitest run with its output, including the first failing attempts, and the comment says which setup was added and why. Since each pull request gets its own run, a week of pull requests leaves the app with tests for each change instead of a single large backfill nobody reviews.

Frequently asked questions

Why Vitest and not Jest?

The prompt asks for Vitest because it reads TypeScript and the @/ alias with one small config and no Babel setup. If your repository already uses Jest, change the prompt to Jest and the agent writes tests for the setup you have instead of adding a second runner.

Does it test React components like the editor?

When the pull request changes component logic, yes, with a DOM environment such as jsdom and Testing Library added alongside Vitest. For taxonomy's editor, most of the behavior worth pinning sits in the API route and the zod schema it posts to, so those get tests first.

Does it need my database or Stripe account?

No. The tests replace the Prisma client, the session and the subscription lookup at the module boundary and set placeholder values for the variables env.mjs requires. Nothing connects to your database, NextAuth provider or Stripe.

Will it add the test step to my CI?

Not unless you ask, because the prompt limits it to test files and the runner they need. The comment suggests adding pnpm test to your workflow so the tests run on every later pull request.