test(web): remove two timing races that hung CI for a minute each
Both failures showed up as "Test timed out in 30000ms" followed by "Hook timed out in 30000ms" on loaded PR runners, in files nobody had touched. relay host-client: the scripted client dialed its WebSocket before awaiting its WebCrypto setup and only then attached the open/message listeners. On a loaded runner the loopback socket opened while key generation was still queued on the threadpool, the open event found no listener, no hello was sent, and the client waited forever. The socket is now dialed after the key material is ready, in the same tick as the listeners. The fake relay also terminates leftover sockets on stop so a failure is reported once, not twice. walkthrough routes: each test slept 20 ms and assumed the request had reached the route by then. The tests now wait until the service has been asked to generate one more time than before the request, and afterEach closes idle keep-alive connections so server.close() cannot hang on a response a failed test never received. Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
This commit is contained in:
@@ -98,6 +98,9 @@ const startFakeRelay = () => {
|
||||
wsUrl: `ws://127.0.0.1:${port}`,
|
||||
state,
|
||||
stop: () => new Promise((r) => {
|
||||
// A socket a failed test left open would hold server.close() until
|
||||
// the hook timeout; drop them so a failure is reported once.
|
||||
for (const client of wss.clients) client.terminate();
|
||||
wss.close();
|
||||
server.close(() => r());
|
||||
}),
|
||||
@@ -162,7 +165,6 @@ const runScriptedClient = async ({ relayUrl, serverId, hostEncPubJwk }) => {
|
||||
url.searchParams.set('role', 'client');
|
||||
url.searchParams.set('serverId', serverId);
|
||||
url.searchParams.set('connectionId', connectionId);
|
||||
const ws = new WebSocket(url.toString());
|
||||
|
||||
const hostPub = await globalThis.crypto.subtle.importKey(
|
||||
'jwk',
|
||||
@@ -182,6 +184,12 @@ const runScriptedClient = async ({ relayUrl, serverId, hostEncPubJwk }) => {
|
||||
resolveDone = resolve;
|
||||
});
|
||||
|
||||
// Dialed only now, with the key material ready and the listeners attached
|
||||
// in the same tick. Dialing before the WebCrypto awaits above let a loopback
|
||||
// socket open while the key generation was still queued on the threadpool,
|
||||
// and an `open` event with no listener means no hello, no ready, and a
|
||||
// client that waits forever. Loaded CI runners hit exactly that.
|
||||
const ws = new WebSocket(url.toString());
|
||||
ws.on('open', async () => {
|
||||
ws.send(JSON.stringify({
|
||||
t: 'hello',
|
||||
|
||||
Reference in New Issue
Block a user