All jobs

Find Untested Code in a NestJS App

Yes. An agent runs your NestJS test suite with coverage in its own sandbox and reports the riskiest untested code, without changing anything.

What the agent does

The agent clones the app into its own cloud sandbox and reads how it tests before it runs anything. In a project like nestjs/typescript-starter, package.json shows type: module, a test script of vitest run and a test:cov of vitest run --coverage, with @vitest/coverage-v8 already in devDependencies. vitest.config.ts includes **/*.spec.ts and vitest.config.e2e.ts includes **/*.e2e-spec.ts. The agent installs dependencies, notes that the only unit spec is src/app.controller.spec.ts and the only end-to-end spec is test/app.e2e-spec.ts, and runs npm run test:cov so the numbers come from a real run rather than a guess.

With the V8 coverage report in hand it reads the source behind the numbers. The starter is small on purpose: src/app.controller.ts and src/app.service.ts are covered by the spec, while src/main.ts (which calls NestFactory.create and app.listen) and the ObserveModule.forRoot wiring in src/app.module.ts are exercised only by the end-to-end test if at all. The agent lists each file with uncovered lines, reads what those lines do, and keeps the ones that matter: code that writes data, checks authentication or moves money, over a getter that returns a constant string.

It ranks the gaps the prompt asks for by how much depends on them. In a larger NestJS app this is where controllers with no spec, guards and interceptors that run on every request, and services that call the database rise to the top, while a DTO with only decorators or a module file with only wiring falls to the bottom. For each of the ten it writes one sentence naming the test that would cover it: a controller spec that asserts the status and shape of a response, a guard spec that denies an unauthenticated request, a service spec that checks the branch a null result takes.

The prompt says to change no code, so the agent runs the suite and reads the report but writes no tests and opens no pull request. The coverage run, its output and the ranking all stay in the session transcript, and the result is coverage-gaps.md returned as an artifact on the session. Because the starter is small enough to check by hand, the report's ranking can be verified against the actual files.

Start it with one API call

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

{
  "agent": "claude",
  "input": "Clone https://github.com/nestjs/typescript-starter, install dependencies and run its test suite with coverage in the sandbox (npm run test:cov, which runs vitest with @vitest/coverage-v8). Write coverage-gaps.md: the overall coverage percentage, the ten files with the most uncovered lines that matter (data writes, auth, money), and one sentence each on what test would cover them. Rank them by how much other code depends on them. Change no code and open no pull request."
}
  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 coverage-gaps.md as an artifact on the session, which the session read returns with a download link good for an hour. It opens with the overall coverage percentage from the real vitest --coverage run and the command that produced it, so a reader knows the number is measured rather than estimated. Then it lists the ten riskiest untested files, most depended-on first.

Each row names the file, the count of uncovered lines and which they are, says in one sentence what that code does and why its risk rank is what it is, and gives the one test that would cover it. The ranking favours code other modules call over leaf code, so a reader can point a test-writing agent at the top of the list and get the most protection for the first few tests written.

A reviewer checks the report against the repository before acting on it: that the coverage number matches a run they do themselves, that the cited files really lack tests, and that the risk ranking fits their own sense of what is dangerous in the app. Because the sandbox still holds the installed project, a follow-up message to the same session can ask the agent to write the top few tests and open a pull request.

Run it on every a pull request to the default branch

Run it on every change so coverage does not quietly slide. An automation with a GitHub trigger can send this request for each pull request, and the report posts back as a comment, so a branch that adds an untested controller shows up before it merges.

Set a webhook URL on the API key and Rush POSTs run.completed when the turn finishes, with the session_url. Your server reads the session, takes the link to coverage-gaps.md from its artifacts, and attaches it or opens a tracking issue, so the test backlog is kept from evidence rather than from memory.

The use case this job follows, with its automation and trigger: Produce a report or file, no repo.

Why run it on Rush?

Running coverage on a laptop means installing dependencies, letting the suite run, and reading an HTML report, all while the machine is tied up and the result is easy to lose. In a Rush sandbox the agent installs, runs vitest --coverage and reads the report on its own disk, and the numbers and the ranking come back as a file you keep, with the command that produced them beside each claim.

A coverage report is only useful if you trust the number and the priorities. Because the run and its output are in the session transcript, the person reading coverage-gaps.md can confirm the percentage and spot-check any file instead of taking it on faith. Several reports can run at once, one per service, up to the key's concurrent-run limit.

Frequently asked questions

Will it change anything in my repository?

No. The prompt says to change no code and open no pull request. The agent runs the suite with coverage and reads the report. What comes back is a Markdown report you download from the session's artifacts.

Does it work with Vitest and Jest?

Yes. The starter uses Vitest with @vitest/coverage-v8, and the agent runs whatever the test:cov script names. In a Jest project it runs jest --coverage instead; it reads the package.json scripts first so it uses the project's own runner.

My app has very few tests. Is the report still useful?

Yes, and that is the case it is built for. When coverage is low the report still ranks the untested files by how much depends on them, so you learn which handful of tests to write first instead of being told everything is uncovered.

Can it run against a private repository?

Yes. Install the Rush GitHub App on the repository and add it to the request as a resource, {"url": "https://github.com/your-org/your-app"}, instead of a public URL. The agent starts with that repository already cloned and runs its suite the same way.