mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-09 16:02:36 +01:00
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:
1 parent
da34bcd48d
commit
e7fb554647
1 file changed
+17
-11
@@ -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(() => {
|
||||
|
||||
Reference in new issue
Block a user