test(server): load setup-token route modules during suite setup (#19398)

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The setup-token login route lets an owner sign in to Claude for a
sandbox environment
> - The route suite `server/src/routes/setup-token-route.test.ts` fails
on CI in pull requests that do not touch it
> - The first test in the suite times out at 15000 ms, and the other 29
tests pass
> - The first test pays the one-time import cost of the agent route
graph inside its own test budget
> - This pull request moves that import to suite setup, which has a
30000 ms hook budget
> - The benefit is a stable server shard with no change to what the
tests prove

## Linked Issues or Issue Description

**What happened?**

A survey of failed `PR` workflow runs found intermittent failures of one
test in pull requests that do not touch this area:

```
FAIL src/routes/setup-token-route.test.ts > company-and-environment setup-token route — full path > drives start, status, prompt, code, and completion with no agent id
Error: Test timed out in 15000ms.
```

Examples: jobs 127423956746 and 127457298585 (shard
`general-server-without-chat` 12/12). The survey counted 5 such
failures.

**Expected behavior**

The full-path test passes on every run. The test budget measures the
route behavior, not the module import.

**Steps to reproduce**

Run the unchanged suite on master while all CPU cores are busy:

```sh
cd server
node load.mjs 24 pnpm exec vitest run src/routes/setup-token-route.test.ts --reporter=verbose
```

`load.mjs` starts 24 busy-loop Node processes and runs the command. The
first test fails at 15005 ms.

**Root cause**

`createApp()` called `vi.importActual("../routes/agents.js")` and four
other modules on each call. The first call loads and transforms the full
agent route graph. I timed it: `createApp()` took 11670 ms of the 11698
ms test on an idle machine. The HTTP steps took less than 30 ms. On a
loaded CI runner the import alone crossed the 15000 ms test budget.
Later tests reused the module cache, so only the first test failed.

## What Changed

- Add `loadRouteModules()`, which imports the route and logger modules.
- Call it once in the suite `beforeAll`, after `vi.resetModules()` and
the mock registration. The hook budget is 30000 ms in
`server/vitest.config.ts`.
- `createApp()` now reuses the loaded modules. Each test still builds a
fresh Express app, a fresh transport, and a fresh log capture.
- This follows the pattern in
`server/src/__tests__/agent-skills-routes.test.ts` (#16396).
- No timeout changes, no retries, no skips.

## Verification

Red, on master, with 24 busy-loop processes on an 18-core machine:

```
× ... drives start, status, prompt, code, and completion with no agent id 15005ms
```

Also red on an idle machine on 1 of 3 runs (15006 ms; the other runs
took 11790 ms and 13748 ms).

Green, with this change:

- Idle, 3 runs: 30/30 tests pass. The first test takes 42 to 46 ms.
- With 24 busy-loop processes: 30/30 tests pass. The first test takes 40
ms. The file takes 19.4 s in total.

```sh
cd server
pnpm exec vitest run src/routes/setup-token-route.test.ts --reporter=verbose
```

`tsc --noEmit -p server` reports no errors in this file.

## Risks

- Low risk. The change touches one test file only.
- The import cost now counts against the 30000 ms hook budget. Locally
it is 12 to 15 s idle. The mocks register before the import, as before,
so each test sees the same mocked services.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, used through Claude
Code with tool use (shell, file edits) and extended reasoning.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
DottaandClaude Opus 5.5 authored and GitHub committed 2026-11-05 22:23:35 -06:00
1 parent da34bcd48d
commit e7fb554647
1 file changed
+17 -11
+17 -11
View File
@@ -361,6 +361,20 @@ function buildTransport(opts: { onSubmit?: "complete" | "throw" | "pending" } =
// --- App builder with a capturing request logger -----------------------------
function loadRouteModules() {
return Promise.all([
vi.importActual<typeof import("../routes/agents.js")>("../routes/agents.js"),
vi.importActual<typeof import("../middleware/index.js")>("../middleware/index.js"),
vi.importActual<typeof import("pino")>("pino"),
vi.importActual<typeof import("pino-http")>("pino-http"),
vi.importActual<typeof import("../middleware/redact-sensitive.js")>(
"../middleware/redact-sensitive.js",
),
]);
}
let routeModules: Awaited<ReturnType<typeof loadRouteModules>>;
interface AppHandle {
app: express.Express;
logLines: string[];
@@ -372,16 +386,7 @@ async function createApp(opts: {
confidentialEdgeTlsTerminated?: boolean;
transport?: TransportHandle;
} = {}): Promise<AppHandle> {
const [{ agentRoutes }, { errorHandler }, pinoModule, pinoHttpModule, redactModule] =
await Promise.all([
vi.importActual<typeof import("../routes/agents.js")>("../routes/agents.js"),
vi.importActual<typeof import("../middleware/index.js")>("../middleware/index.js"),
vi.importActual<typeof import("pino")>("pino"),
vi.importActual<typeof import("pino-http")>("pino-http"),
vi.importActual<typeof import("../middleware/redact-sensitive.js")>(
"../middleware/redact-sensitive.js",
),
]);
const [{ agentRoutes }, { errorHandler }, pinoModule, pinoHttpModule, redactModule] = routeModules;
const { pino } = pinoModule;
const { pinoHttp } = pinoHttpModule;
const { redactSensitive } = redactModule;
@@ -465,9 +470,10 @@ async function settle(): Promise<void> {
}
}
beforeAll(() => {
beforeAll(async () => {
vi.resetModules();
registerModuleMocks();
routeModules = await loadRouteModules();
});
beforeEach(() => {