test(smoke): exercise the real teardown path, not just removeSafe
Copilot was right that the previous test proved only that `removeSafe` can
delete a directory — it never drove `stop()`, so deleting the cleanup call
would have left the unit suite AND all three smokes green. That is exactly the
regression these tests exist to catch, and they did not catch it.
Extract the teardown into an exported `teardownWebServer({ child, catalogDir,
label })`, which `stop()` now delegates to, and drive it against a stand-in
child process (a real `node -e setInterval` that stays alive until signalled)
rather than a mock. Three cases:
- it removes the catalog dir it was given (asserted on the dir itself, not a
spy, so the assertion cannot drift from the behavior);
- it awaits the child's exit before removing — the #1801 race in one
assertion, since losing the await is otherwise invisible;
- an already-dead child is not an error, which is the failure path a smoke
takes when it calls fail() after the launcher has crashed.
Mutation-checked: with the `removeSafe` call deleted, 2 of the 3 now fail
(previously: 0). AGENTS.md updated to match.
Signed-off-by is now on every commit (#1978 DCO); the requirement itself is
undocumented and tracked in #1979.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HDdo1rNRVQnVRRdsqSrvG3
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
4a993fc45a
commit
3d541388db
1 changed files with 89 additions and 20 deletions
|
|
@ -78,6 +78,36 @@ export function buildWebServerEnv({
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate a spawned web server, then remove its catalog dir.
|
||||
*
|
||||
* The two halves are the documented pair in `child-cleanup.mjs`, and both are
|
||||
* needed. `stopChild` closes the #1801 race on the normal path (a bare `kill()`
|
||||
* only *delivers* the signal, so a synchronous remove can hit ENOTEMPTY when the
|
||||
* server writes the catalog on its way out); `removeSafe` then makes the
|
||||
* residual case harmless, warning instead of throwing so a leftover temp dir can
|
||||
* never turn a passing smoke red.
|
||||
*
|
||||
* Exported separately from `startProdWebServer` so the teardown *contract* is
|
||||
* testable against a stand-in child, without booting a real launcher. Testing it
|
||||
* matters more than it looks: deleting the `removeSafe` call would leave both the
|
||||
* unit suite and all three smokes green (the smokes exit immediately after
|
||||
* teardown), which is precisely the regression the tests exist to catch.
|
||||
*
|
||||
* @param {object} opts
|
||||
* @param {import("node:child_process").ChildProcess} opts.child
|
||||
* @param {string} opts.catalogDir
|
||||
* @param {string} [opts.label]
|
||||
*/
|
||||
export async function teardownWebServer({
|
||||
child,
|
||||
catalogDir,
|
||||
label = "smoke:web",
|
||||
}) {
|
||||
await stopChild(child, { label, what: "prod web server" });
|
||||
removeSafe(catalogDir, { label });
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn `mcp-inspector --web` (prod, no `--dev`) against the built
|
||||
* `clients/web/dist` and return handles for readiness + teardown.
|
||||
|
|
@ -194,18 +224,7 @@ export function startProdWebServer({ host, port, token, label = "smoke:web" }) {
|
|||
catalogPath,
|
||||
waitForReady,
|
||||
whenChildExits,
|
||||
/**
|
||||
* Terminate the server, then remove its catalog dir. **Await this** — the
|
||||
* two halves are the documented pair in `child-cleanup.mjs`, and both are
|
||||
* needed. `stopChild` closes the #1801 race on the normal path (a bare
|
||||
* `kill()` only *delivers* the signal, so a synchronous remove can hit
|
||||
* ENOTEMPTY when the server writes the catalog on its way out); `removeSafe`
|
||||
* then makes the residual case harmless, warning instead of throwing so a
|
||||
* leftover temp dir can never turn a passing smoke red.
|
||||
*/
|
||||
stop: async () => {
|
||||
await stopChild(child, { label, what: "prod web server" });
|
||||
removeSafe(catalogDir, { label });
|
||||
},
|
||||
/** Terminate the server, then remove its catalog dir. **Await this.** */
|
||||
stop: () => teardownWebServer({ child, catalogDir, label }),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue