diff --git a/tests/mcp/fixtures.ts b/tests/mcp/fixtures.ts index 98ffc26e144ce..57e82003046cd 100644 --- a/tests/mcp/fixtures.ts +++ b/tests/mcp/fixtures.ts @@ -61,7 +61,7 @@ export type StartClient = (options?: { rootsResponseDelay?: number, env?: NodeJS.ProcessEnv, noTimeoutForTest?: boolean, -}) => Promise<{ client: Client, stderr: () => string }>; +}) => Promise<{ client: Client, stderr: () => string, closeTransport: () => Promise }>; type TestFixtures = { @@ -95,6 +95,7 @@ export const test = serverTest.extend { const configDir = path.dirname(test.info().config.configFile!); const clients: Client[] = []; + const disconnectedClients = new Set(); await use(async options => { let args: string[] = mcpArgs ?? []; @@ -151,10 +152,24 @@ export const test = serverTest.extend stderrBuffer }; + return { + client, + stderr: () => stderrBuffer, + closeTransport: async () => { + disconnectedClients.add(client); + await transport.close(); + }, + }; }); - await Promise.all(clients.map(client => client.close())); + await Promise.all(clients.map(async client => { + try { + await client.close(); + } catch (e) { + if (!disconnectedClients.has(client)) + throw e; + } + })); }, wsEndpoint: async ({ }, use) => { diff --git a/tests/mcp/launch.spec.ts b/tests/mcp/launch.spec.ts index 9e410e3c796e8..04b0940b51369 100644 --- a/tests/mcp/launch.spec.ts +++ b/tests/mcp/launch.spec.ts @@ -161,6 +161,29 @@ test('isolated context', async ({ startClient, server }) => { }); }); +test('isolated stdio server closes browser on client transport disconnect', async ({ startClient, server }) => { + const { client, stderr, closeTransport } = await startClient({ + args: [`--isolated`], + env: { DEBUG: 'pw:mcp:test' }, + }); + + expect(await client.callTool({ + name: 'browser_navigate', + arguments: { url: server.HELLO_WORLD }, + })).toHaveResponse({ + snapshot: expect.stringContaining(`Hello, world!`), + }); + + await closeTransport(); + + await expect.poll(() => formatLog(stderr())).toEqual({ + 'create browser (isolated)': 1, + 'create context': 1, + 'close browser': 1, + 'gracefully closing 1': 1, + }); +}); + test('isolated context relaunches the browser after it dies', async ({ startClient, server, mcpBrowser }, testInfo) => { test.skip(!['chrome', 'msedge', 'chromium'].includes(mcpBrowser!), 'The test kills the browser over CDP');