Stacks

Write Unit Tests for Untested Code in TypeScript with Atlas (2026)

Updated 8 min read

Atlas writes unit tests for untested TypeScript by reading the module, enumerating its exported symbols with the lsp tool's documentSymbol operation so no public function is missed, and copying the conventions your repo already uses instead of inventing new ones. Atlas greps for an existing .test.ts file to match the framework, import style, and naming pattern, writes the new spec with the write tool, which shows the diff in the permission prompt before anything lands on disk, and then actually runs it with vitest through bash. The run is the point: a test that was never executed is not a test.

How do you write unit tests for an untested TypeScript module?

Atlas writes unit tests for an untested TypeScript module in 5 moves: read the module, enumerate every export with the lsp tool's documentSymbol operation, grep for an existing .test.ts to copy conventions, write the spec, then run vitest through bash. Step two is what stops a public function from being silently skipped.

The usual failure of AI-written TypeScript tests is coverage theater: the model tests the two functions it happened to notice in the file it read, produces a confident summary, and leaves three exported helpers untested. Atlas closes that gap structurally. The lsp tool's documentSymbol operation returns the module's symbol table, so the exported functions, the exported class methods, and the exported types are enumerated from the language server rather than from a skim. When src/lib/pricing.ts exports calculateSubtotal, applyDiscount, and formatCurrency, all three end up in the spec, and any overload or default-exported factory shows up too. Atlas then reads the module body to understand what each export actually does before asserting on it, because the point is testing behavior, not restating the type signature that tsc already checks.

How does Atlas match my repo's existing vitest conventions?

Atlas greps for an existing test file before writing a new one, so the new spec copies 3 things from your repo: the framework, the import style, and the naming convention. In a TypeScript repo that also means matching how tsconfig path aliases are imported and whether specs live beside the source or under tests/.

TypeScript repos are opinionated in ways that are invisible to a model that has not looked. Some import the subject with a tsconfig path alias like @/lib/pricing, others use a relative ../pricing, and getting it wrong means vitest cannot resolve the module at all. Some name files pricing.test.ts, others pricing.spec.ts, and a vitest include pattern will silently ignore the wrong one, producing a spec that never runs and a suite that stays green for the wrong reason. Some repos mock with vi.mock at the top of the file, others inject fakes through the constructor. Atlas greps an existing spec, reads it, and mirrors it. The result is a file that looks like the ones a human on the team wrote, which is the difference between a test that gets maintained and a test that gets deleted in the next cleanup pass.

Does Atlas run the TypeScript tests it writes, or just write them?

Atlas runs the tests it writes. After the write tool lands the new spec, Atlas invokes vitest through the bash tool and reads the failures. Output over 2000 lines or 50 KB is truncated and the complete log is saved to a file Atlas can read, so a noisy vitest run still gets triaged in full.

A generated test that has never been executed is a liability, not an asset. It may not compile under your tsconfig strict settings. It may assert on a shape that does not match what the function returns, and the mismatch is invisible until CI catches it three commits later. Atlas therefore treats the vitest run as part of writing the test, not as an optional afterthought. The first run of a freshly written spec commonly fails, and that is useful information: a red test proves the assertion is actually exercising the code path. Atlas iterates with the edit tool until pnpm vitest reports green, keeping progress in a todowrite list when the module is large enough that a dozen exports need separate cases. When the vitest output overruns the inline cap, the retained log file means no failure is lost to a truncated tail.

Where does Atlas put a new spec file in a TypeScript project?

Atlas puts the new spec wherever your TypeScript repo already puts them, which grep tells it in 1 call. If src/lib/pricing.ts is covered by src/lib/pricing.test.ts, Atlas writes src/lib/cart.test.ts next to src/lib/cart.ts. If specs live under tests/unit/, Atlas writes there instead.

Placement is not a style question in a TypeScript project, it is a resolution question. vitest picks up specs by an include glob, tsconfig decides whether test files are inside the compiled project or excluded, and path aliases resolve differently depending on the file's location in the tree. Writing a spec in the wrong directory produces a file that either fails to typecheck or never runs. Atlas derives the answer from evidence rather than convention: grep for existing .test.ts and .spec.ts files, read the closest one, and place the new file the same way. Atlas indexes code by AST declarations using tree-sitter, so the search for the sibling spec finds real declarations rather than arbitrary matches. Run prettier on the new file so it matches the formatting the rest of the repo enforces.

How do I review TypeScript tests an AI agent wrote before they land?

In 2026, Atlas surfaces the spec in the write tool's permission prompt as a diff before anything lands on disk, and every Atlas tool call is permission-gated against allow, ask, and deny rules before it runs. Approving a new src/lib/cart.test.ts is therefore an explicit act, not a discovery you make later in git status.

Reviewing an AI-written TypeScript spec takes about ninety seconds and is worth every one of them. Read for three things. Does the test assert on behavior, or does it assert on the implementation, mocking so much that a rewrite of the function would break the test without breaking the product? Does it cover every export documentSymbol listed, including the error branches, or only the happy path? Does it type-check under your tsconfig without an any or a cast smuggled in to make an assertion pass? Atlas gives you the diff up front, and Atlas snapshots file changes as git patches, so a spec you decide against can be diffed and rolled back cleanly. Once the spec is right, pnpm vitest is the arbiter and prettier keeps the file consistent with the rest of the repo.

Step by step

  1. 01Start atlas in the project root, the directory with tsconfig.json, so the index picks up your type definitions, path aliases, and strictness settings.
  2. 02Have Atlas read the untested module, for example src/lib/cart.ts, so the tests assert on real behavior rather than on the type signature.
  3. 03Use the lsp tool's documentSymbol operation to enumerate the module's exported symbols so no public function is missed.
  4. 04Grep for an existing .test.ts or .spec.ts file to copy the repo's framework, import style, path-alias usage, and naming convention.
  5. 05Let Atlas write the new spec with the write tool, and read the diff in the permission prompt before it lands on disk.
  6. 06Run the suite with the bash tool: pnpm vitest. Output over 2000 lines or 50 KB is truncated and the full log is saved to a file Atlas can read.
  7. 07Iterate with the edit tool until vitest is green, keeping one todowrite entry per untested export when the module is large.
  8. 08Run prettier on the new spec so it matches the repo's formatting, then approve the final diff.

Frequently asked questions

Can an AI agent write vitest tests for a TypeScript file that has none?
Yes. Atlas reads the module, enumerates its exports with the lsp tool's documentSymbol operation, greps an existing .test.ts for conventions, writes the spec with the write tool, and runs pnpm vitest through bash until the suite is green.
How do I make sure an AI agent covers every exported function in a TypeScript module?
Use the symbol table, not a skim. Atlas calls the lsp tool's documentSymbol operation to enumerate exported symbols, so every exported function, class method, and factory in src/lib/cart.ts appears in the spec rather than only the ones the model happened to notice.
Will Atlas use my existing test conventions or invent new ones?
Atlas copies your existing conventions. It greps for an existing test file first, then matches the framework, the import style including tsconfig path aliases, the file naming pattern, and the mocking approach the repo already uses.
Does Atlas actually run the TypeScript tests it generates?
Yes. Atlas runs the spec with the bash tool and reads the failures. Output over 2000 lines or 50 KB is truncated and the complete log is saved to a file, so a noisy vitest run is triaged in full and Atlas iterates with edit until it passes.
Where should vitest spec files live in a TypeScript project?
Wherever the repo already puts them, because vitest resolves specs by an include glob and tsconfig decides what is in the project. Atlas greps for existing .test.ts and .spec.ts files and places the new spec the same way, then runs prettier on it.
How do I review a test file an AI agent wrote before it hits my repo?
The write tool shows the spec as a diff in the permission prompt before anything lands on disk, and every Atlas tool call is permission-gated against allow, ask, and deny rules. Atlas also snapshots file changes as git patches, so a rejected spec can be rolled back.
Can Atlas write tests for a large TypeScript module without losing track?
Yes. Atlas keeps progress in a todowrite list when the module is large, typically one entry per untested export, so a module with fifteen exports does not end up with tests for the first four and a confident summary about the rest.

Try Atlas in your terminal

The terminal-native AI coding agent. Free core, single binary.

Install Atlas

Related guides

Write Unit Tests for Untested Code with Atlas in 2026

How to write unit tests for untested code with Atlas in 2026: the lsp tool enumerates exported symbols, grep copies repo conventions, and bash actually runs the suite.

Atlas for TypeScript in 2026

In 2026, TypeScript developers leverage Atlas, the terminal-native AI coding agent, to enhance productivity. Atlas understands your types, ensures code quality, and offers robust safety features.

Debug a Single Failing Test in TypeScript with Atlas (2026)

Fix one failing TypeScript test in 2026 without loosening the assertion: Atlas isolates it with pnpm vitest, follows the types with lsp, and edits the module, not the expectation.

Upgrade a Dependency and Fix the Breakage in TypeScript with Atlas (2026)

Bump a TypeScript dependency to a new major in 2026. Atlas drives pnpm through bash, fetches the changelog with webfetch, and fixes every tsc error until vitest is green.

Refactor a legacy module in TypeScript with Atlas (2026)

Refactor a legacy TypeScript module in 2026 with Atlas: map callsites with lsp findReferences, restructure with apply_patch, and prove behavior with vitest.

Run Atlas Headless in CI in TypeScript with Atlas (2026)

Run Atlas headless in CI on a TypeScript repo in 2026: atlas run is non-interactive by default, supports --format json, and needs pre-approved permissions to reach vitest.

Run the Test Suite and Triage the Failures in TypeScript with Atlas (2026)

Turn a wall of red vitest output into a ranked list of root causes in 2026: Atlas truncates at 2000 lines, saves the full log, and greps it into a todowrite triage list.

Extract a Shared Helper From Duplicated Code in TypeScript With Atlas (2026)

How to extract a shared helper from duplicated TypeScript code with Atlas in 2026: codebase_search finds the copies, apply_patch swaps them, vitest proves it.

Browse this resource hub