# Debug a Single Failing Test in JavaScript with Atlas (2026)

> Atlas debugs a failing JavaScript test by running it alone with pnpm vitest and a -t filter, walking the call path with the lsp tool, then fixing the code rather than the assertion.

Atlas debugs a single failing JavaScript test by running that one test in isolation with the bash tool, usually pnpm vitest run src/auth/token.test.js with a -t filter so the output is small enough to reason about. Atlas then reads the assertion and the module it exercises, walks the call path with the lsp tool's goToDefinition and findReferences operations, and only then edits. The goal is to fix the JavaScript code, not to loosen the assertion until it passes.

## Key takeaways

- Filter first: pnpm vitest run <file> -t "<test name>" through the bash tool shrinks a failing JavaScript suite to the 1 test that matters.
- The lsp tool's goToDefinition and findReferences operations walk a JavaScript call path through default exports, index.js barrels, and CommonJS require without guessing.
- Because bash is a real shell, a temporary console.log, a verbose flag, or an env var prefix all work exactly as they do in your own terminal.
- apply_patch handles a multi-hunk JavaScript fix, such as converting callbacks to async and await, in one patch instead of five brittle edits.
- Atlas computes a unified diff for every file edit and surfaces it for approval before writing to src/.
- Fix the code, not the assertion, then run pnpm exec prettier on the changed files and delete every temporary log.

## How does Atlas debug a single failing JavaScript test?

Atlas debugs one failing JavaScript test with 5 moves: run just that test with pnpm vitest and a -t filter through the bash tool, read the assertion, walk the call path with the lsp tool, form and check a hypothesis, then fix the module rather than the expectation.

The job is to find why one specific test fails and fix the code, not the assertion. Atlas starts by shrinking the problem. A full vitest run across a JavaScript monorepo prints thousands of lines, and no model reasons well over that. Running pnpm vitest run src/auth/token.test.js -t "refreshes an expired token" produces a handful of lines: the expected value, the received value, and a stack frame pointing into src/auth/token.js. Atlas tools this workflow uses are bash, read, lsp, edit, and apply_patch. Because bash is a real shell, the same debugging levers you would use by hand, extra console.log lines, a focused test filter, a verbose flag, are all available inside the session.

## How do you run one vitest test in isolation with pnpm?

Atlas runs a single JavaScript test through the bash tool with the framework's filter flag, for example pnpm vitest run src/auth/token.test.js -t "refreshes an expired token". Filtering to 1 test keeps the output small enough to reason about instead of drowning the session in a full suite log.

JavaScript projects hide their real test command in package.json, so Atlas reads the scripts block first and uses what is actually defined rather than guessing. If the repo defines a test:unit script, pnpm test:unit is the honest entry point and the -t filter still applies. Atlas passes the path to the exact spec file, which in a JavaScript repo is typically a .test.js or .spec.js file living beside the module or under a __tests__ directory. Every Atlas tool call is permission-gated against allow, ask, and deny rules before it runs, so the vitest invocation through bash stops for approval unless you have allowed pnpm commands in advance.

## How does Atlas trace a failing JavaScript assertion back to the code?

Atlas reads the failing JavaScript test and the module it exercises, then uses the lsp tool's goToDefinition and findReferences operations to walk the call path. A vitest assertion diff names 2 things, the expected value and the received value, and the lsp tool turns that gap into a chain of real files.

JavaScript makes the call path hard to eyeball, because a value can arrive through a default export, a re-export barrel in index.js, a CommonJS require, or an ESM import rewritten by your bundler config. Rather than guessing, Atlas calls goToDefinition on the function the assertion touched and lands on the real implementation, then calls findReferences to see every callsite that can reach it. Atlas searches code with hybrid semantic and keyword retrieval fused by reciprocal rank fusion, and Atlas indexes code by AST declarations using tree-sitter, not blind line windows, so the function you care about is retrieved as a declaration rather than as a lucky 20-line window.

## How do you test a hypothesis about a failing JavaScript test?

Atlas forms a hypothesis about the JavaScript failure and then checks it 2 ways: adding temporary logging with the edit tool, or re-running through the bash tool with a verbose flag. Guessing is cheap and wrong, so Atlas confirms the actual runtime value before changing any production module.

Typical JavaScript hypotheses are specific and testable. An async function was called without await, so a Promise is compared against a plain object. A callback fired after the assertion ran. A Date or a floating point value differs by milliseconds. Atlas adds a temporary console.log inside src/auth/token.js with edit, re-runs pnpm vitest run src/auth/token.test.js -t "refreshes an expired token" through bash, and reads what actually arrived. Because bash is a real shell, a verbose flag or an environment variable prefix works exactly as it would in your own terminal. Every temporary log is removed before the change is finished.

## How does Atlas fix the JavaScript code without touching the assertion?

Atlas fixes the JavaScript production module with the edit tool, and when the change spans 3 or more hunks Atlas uses apply_patch instead of chaining brittle edits. Atlas computes a unified diff for every file edit and surfaces it for approval before writing, so you see the change to src/auth/token.js before it lands.

Loosening the assertion is the failure mode this workflow exists to prevent. If the test says an expired token should refresh, and it does not, the bug is in src/auth/token.js, not in expect(). Atlas edits the module. When the fix touches an async chain across several functions, for example converting a callback to async and await and updating each caller, apply_patch applies the whole set as one patch rather than five fragile string replacements. Run pnpm exec prettier --write on the changed files afterwards so the diff does not carry formatting noise into review.

## How do you verify a JavaScript test fix and clean up?

Atlas re-runs the single JavaScript test with pnpm vitest and the -t filter, confirms it passes, then runs the full vitest suite to catch collateral damage. Atlas also removes every temporary console.log added during the hunt, which is step 5 of the documented workflow and the one most often skipped.

Verification in a JavaScript repo has two levels. The narrow one is the single vitest test that started red and must end green under exactly the same command. The wide one is the full suite through pnpm, because a fix inside a shared module such as src/auth/token.js can break a browser bundle test that never appeared in the filtered run. For review, Atlas snapshots file changes as git patches so edits can be diffed and rolled back, and Atlas reads git branches, status, and diffs, so the fix and its verification land as one reviewable commit rather than a pile of unexplained edits.

## Steps

1. Run just the failing JavaScript test with the bash tool using vitest's filter flag, for example pnpm vitest run src/auth/token.test.js -t "refreshes an expired token", so the output is small enough to reason about.
2. Read the package.json scripts block first so Atlas uses the repo's real test command instead of guessing at one.
3. Read the failing .test.js file and the module it exercises, then use the lsp tool's goToDefinition and findReferences operations to walk the call path through your imports and re-export barrels.
4. Form a hypothesis (an unawaited Promise, a callback firing late, a stale bundler alias) and check it by adding a temporary console.log with edit or re-running with a verbose flag through bash.
5. Fix the production JavaScript module with edit; if the change spans several hunks, such as converting a callback chain to async and await, use apply_patch instead of chaining brittle edits.
6. Review the unified diff Atlas surfaces before approving the write to src/.
7. Run pnpm exec prettier --write on the changed files so formatting noise stays out of the diff.
8. Re-run the single test with pnpm vitest, then the full suite, and remove every temporary console.log you added.

## FAQ

### how do I run a single failing test in vitest

Pass the spec path plus vitest's -t filter, for example pnpm vitest run src/auth/token.test.js -t "refreshes an expired token". Atlas runs exactly this through its bash tool so the output stays small enough to reason about instead of printing the whole JavaScript suite.

### can an AI agent debug a failing javascript test for me

Yes. Atlas runs the single test with bash, reads the assertion and the module it exercises, walks the call path with the lsp tool's goToDefinition and findReferences operations, and then edits the production code. Every Atlas tool call is permission-gated against allow, ask, and deny rules before it runs.

### why does my javascript test compare a promise instead of a value

An async function called without await returns a Promise, so the assertion compares a Promise against a plain object. Confirm it by adding a temporary console.log with Atlas's edit tool and re-running pnpm vitest with the -t filter, then fix the missing await in the module rather than relaxing the expectation.

### how do I stop an AI agent from just changing the assertion to make a test pass

The point of this workflow is to find why one specific test fails and fix the code, not the assertion. Atlas computes a unified diff for every file edit and surfaces it for approval before writing, so an edit that touches expect() instead of src/ is visible in the diff before it lands.

### does atlas work with pnpm workspaces and package.json scripts

Yes. Run atlas where your package.json lives and let Atlas map your modules, npm scripts, and bundler config. Atlas reads the scripts block and uses the repo's real command, so pnpm test:unit is used when that is what the project defines.

### how do I find every caller of a javascript function

Use the lsp tool's findReferences operation, which Atlas calls directly during debugging. Atlas also searches code with hybrid semantic and keyword retrieval fused by reciprocal rank fusion and indexes code by AST declarations using tree-sitter, so callers hidden behind barrel re-exports still surface.

### how do I clean up console.log statements an AI agent added while debugging

Removing temporary logging is the final documented step of the workflow, and Atlas snapshots file changes as git patches so edits can be diffed and rolled back. Run pnpm exec prettier --write on the changed files and review the git diff before committing.

### should I use apply_patch or edit for a javascript fix

Use edit for a single hunk and apply_patch when the fix spans several hunks, such as converting a callback chain to async and await across a module and its callers. Chaining brittle edits across many sites is exactly what apply_patch replaces.

---

Canonical HTML: https://runatlas.sh/resources/stacks/debug-a-failing-test-in-javascript
Source of truth: aeo_pages row `/resources/stacks/debug-a-failing-test-in-javascript` (segment: Stacks) (this file is generated from it, never hand-edited).
Licence: Atlas is proprietary with a free core. It is not open source and there is no public source repository.
