test(e2e): retry tools-dev namespace startup collisions

This commit is contained in:
Denis Redozubov 2026-05-28 21:58:49 +04:00
parent a5f09334a2
commit de6c0d498e
3 changed files with 23 additions and 1 deletions

View file

@ -142,6 +142,8 @@ async function runToolsDevSuite(
break;
} catch (error) {
if (attempt === 3 || !toolsDev.isToolsDevPortConflict(error)) throw error;
await runtime.release().catch(() => {});
await toolsDev.stopToolsDevWeb(suite).catch(() => {});
runtime = await toolsDev.allocateToolsDevRuntime();
}
}

View file

@ -161,7 +161,8 @@ export function isToolsDevPortConflict(error: unknown): boolean {
const text = error instanceof Error
? `${error.message}\n${error.stack ?? ''}`
: String(error);
return text.includes('EADDRINUSE');
return text.includes('EADDRINUSE') ||
(text.includes('is already running in namespace') && text.includes('stop it or choose another namespace'));
}
async function runToolsDevJson<T>(suite: SmokeSuite, args: string[]): Promise<T> {

View file

@ -0,0 +1,19 @@
// @vitest-environment node
import { describe, expect, test } from 'vitest';
import { isToolsDevPortConflict } from '@/vitest/tools-dev';
describe('tools-dev startup conflict detection', () => {
test('classifies port and namespace startup collisions as retryable', () => {
expect(isToolsDevPortConflict(new Error('listen EADDRINUSE: address already in use 127.0.0.1:30123'))).toBe(true);
expect(
isToolsDevPortConflict(
new Error(
'daemon is already running in namespace e2e-orbit-run-123 at http://127.0.0.1:36695; stop it or choose another namespace',
),
),
).toBe(true);
expect(isToolsDevPortConflict(new Error('daemon exited before readiness'))).toBe(false);
});
});