diff --git a/tests/capabilities.spec.ts b/tests/capabilities.spec.ts
index 6daf467..83af532 100644
--- a/tests/capabilities.spec.ts
+++ b/tests/capabilities.spec.ts
@@ -77,7 +77,7 @@ test('test vision tool list', async ({ visionClient }) => {
});
test('test capabilities', async ({ startClient }) => {
- const client = await startClient({
+ const { client } = await startClient({
args: ['--caps="core"'],
});
const { tools } = await client.listTools();
diff --git a/tests/cdp.spec.ts b/tests/cdp.spec.ts
index 23f2cea..a5a58c2 100644
--- a/tests/cdp.spec.ts
+++ b/tests/cdp.spec.ts
@@ -18,7 +18,7 @@ import { test, expect } from './fixtures.js';
test('cdp server', async ({ cdpServer, startClient, server }) => {
await cdpServer.start();
- const client = await startClient({ args: [`--cdp-endpoint=${cdpServer.endpoint}`] });
+ const { client } = await startClient({ args: [`--cdp-endpoint=${cdpServer.endpoint}`] });
expect(await client.callTool({
name: 'browser_navigate',
arguments: { url: server.HELLO_WORLD },
@@ -27,7 +27,7 @@ test('cdp server', async ({ cdpServer, startClient, server }) => {
test('cdp server reuse tab', async ({ cdpServer, startClient, server }) => {
const browserContext = await cdpServer.start();
- const client = await startClient({ args: [`--cdp-endpoint=${cdpServer.endpoint}`] });
+ const { client } = await startClient({ args: [`--cdp-endpoint=${cdpServer.endpoint}`] });
const [page] = browserContext.pages();
await page.goto(server.HELLO_WORLD);
@@ -58,7 +58,7 @@ test('cdp server reuse tab', async ({ cdpServer, startClient, server }) => {
});
test('should throw connection error and allow re-connecting', async ({ cdpServer, startClient, server }) => {
- const client = await startClient({ args: [`--cdp-endpoint=${cdpServer.endpoint}`] });
+ const { client } = await startClient({ args: [`--cdp-endpoint=${cdpServer.endpoint}`] });
server.setContent('/', `
Title
diff --git a/tests/config.spec.ts b/tests/config.spec.ts
index 03c3d81..4478347 100644
--- a/tests/config.spec.ts
+++ b/tests/config.spec.ts
@@ -33,7 +33,7 @@ test('config user data dir', async ({ startClient, server }, testInfo) => {
const configPath = testInfo.outputPath('config.json');
await fs.promises.writeFile(configPath, JSON.stringify(config, null, 2));
- const client = await startClient({ args: ['--config', configPath] });
+ const { client } = await startClient({ args: ['--config', configPath] });
expect(await client.callTool({
name: 'browser_navigate',
arguments: { url: server.PREFIX },
@@ -54,7 +54,7 @@ test.describe(() => {
const configPath = testInfo.outputPath('config.json');
await fs.promises.writeFile(configPath, JSON.stringify(config, null, 2));
- const client = await startClient({ args: ['--config', configPath] });
+ const { client } = await startClient({ args: ['--config', configPath] });
expect(await client.callTool({
name: 'browser_navigate',
arguments: { url: 'data:text/html,' },
diff --git a/tests/device.spec.ts b/tests/device.spec.ts
index 3fe2933..32ceecb 100644
--- a/tests/device.spec.ts
+++ b/tests/device.spec.ts
@@ -17,7 +17,7 @@
import { test, expect } from './fixtures.js';
test('--device should work', async ({ startClient, server }) => {
- const client = await startClient({
+ const { client } = await startClient({
args: ['--device', 'iPhone 15'],
});
diff --git a/tests/files.spec.ts b/tests/files.spec.ts
index 600d54f..3653bca 100644
--- a/tests/files.spec.ts
+++ b/tests/files.spec.ts
@@ -101,7 +101,7 @@ The tool "browser_file_upload" can only be used when there is related modal stat
});
test('clicking on download link emits download', async ({ startClient, server }, testInfo) => {
- const client = await startClient({
+ const { client } = await startClient({
config: { outputDir: testInfo.outputPath('output') },
});
@@ -125,7 +125,7 @@ test('clicking on download link emits download', async ({ startClient, server },
});
test('navigating to download link emits download', async ({ startClient, server, mcpBrowser }, testInfo) => {
- const client = await startClient({
+ const { client } = await startClient({
config: { outputDir: testInfo.outputPath('output') },
});
diff --git a/tests/fixtures.ts b/tests/fixtures.ts
index 598af17..e207d7e 100644
--- a/tests/fixtures.ts
+++ b/tests/fixtures.ts
@@ -40,7 +40,7 @@ type CDPServer = {
type TestFixtures = {
client: Client;
visionClient: Client;
- startClient: (options?: { clientName?: string, args?: string[], config?: Config }) => Promise;
+ startClient: (options?: { clientName?: string, args?: string[], config?: Config }) => Promise<{ client: Client, stderr: () => string }>;
wsEndpoint: string;
cdpServer: CDPServer;
server: TestServer;
@@ -55,11 +55,13 @@ type WorkerFixtures = {
export const test = baseTest.extend({
client: async ({ startClient }, use) => {
- await use(await startClient());
+ const { client } = await startClient();
+ await use(client);
},
visionClient: async ({ startClient }, use) => {
- await use(await startClient({ args: ['--vision'] }));
+ const { client } = await startClient({ args: ['--vision'] });
+ await use(client);
},
startClient: async ({ mcpHeadless, mcpBrowser, mcpMode }, use, testInfo) => {
@@ -85,9 +87,13 @@ export const test = baseTest.extend(
client = new Client({ name: options?.clientName ?? 'test', version: '1.0.0' });
const transport = createTransport(args, mcpMode);
+ let stderr = '';
+ transport.stderr?.on('data', data => {
+ stderr += data.toString();
+ });
await client.connect(transport);
await client.ping();
- return client;
+ return { client, stderr: () => stderr };
});
await client?.close();
@@ -168,7 +174,13 @@ function createTransport(args: string[], mcpMode: TestOptions['mcpMode']) {
command: 'node',
args: [path.join(path.dirname(__filename), '../cli.js'), ...args],
cwd: path.join(path.dirname(__filename), '..'),
- env: process.env as Record,
+ stderr: 'pipe',
+ env: {
+ ...process.env,
+ DEBUG: 'pw:mcp:test',
+ DEBUG_COLORS: '0',
+ DEBUG_HIDE_DATE: '1',
+ },
});
}
@@ -225,3 +237,7 @@ export const expect = baseExpect.extend({
};
},
});
+
+export function formatOutput(output: string): string[] {
+ return output.split('\n').map(line => line.replace(/^pw:mcp:test /, '').replace(/test-results.*/, '').trim()).filter(Boolean);
+}
diff --git a/tests/launch.spec.ts b/tests/launch.spec.ts
index 713e412..f0ad4b2 100644
--- a/tests/launch.spec.ts
+++ b/tests/launch.spec.ts
@@ -16,9 +16,10 @@
import fs from 'fs';
-import { test, expect } from './fixtures.js';
+import { test, expect, formatOutput } from './fixtures.js';
-test('test reopen browser', async ({ client, server }) => {
+test('test reopen browser', async ({ startClient, server }) => {
+ const { client, stderr } = await startClient();
await client.callTool({
name: 'browser_navigate',
arguments: { url: server.HELLO_WORLD },
@@ -32,10 +33,31 @@ test('test reopen browser', async ({ client, server }) => {
name: 'browser_navigate',
arguments: { url: server.HELLO_WORLD },
})).toContainTextContent(`- generic [ref=e1]: Hello, world!`);
+
+ await client.close();
+
+ if (process.platform === 'win32')
+ return;
+
+ await expect.poll(() => formatOutput(stderr()), { timeout: 0 }).toEqual([
+ 'create context',
+ 'create browser context (persistent)',
+ 'lock user data dir',
+ 'close context',
+ 'close browser context (persistent)',
+ 'release user data dir',
+ 'close browser context complete (persistent)',
+ 'create browser context (persistent)',
+ 'lock user data dir',
+ 'close context',
+ 'close browser context (persistent)',
+ 'release user data dir',
+ 'close browser context complete (persistent)',
+ ]);
});
test('executable path', async ({ startClient, server }) => {
- const client = await startClient({ args: [`--executable-path=bogus`] });
+ const { client } = await startClient({ args: [`--executable-path=bogus`] });
const response = await client.callTool({
name: 'browser_navigate',
arguments: { url: server.HELLO_WORLD },
@@ -53,7 +75,7 @@ test('persistent context', async ({ startClient, server }) => {
`, 'text/html');
- const client = await startClient();
+ const { client } = await startClient();
const response = await client.callTool({
name: 'browser_navigate',
arguments: { url: server.PREFIX },
@@ -66,7 +88,7 @@ test('persistent context', async ({ startClient, server }) => {
name: 'browser_close',
});
- const client2 = await startClient();
+ const { client: client2 } = await startClient();
const response2 = await client2.callTool({
name: 'browser_navigate',
arguments: { url: server.PREFIX },
@@ -85,18 +107,18 @@ test('isolated context', async ({ startClient, server }) => {
`, 'text/html');
- const client = await startClient({ args: [`--isolated`] });
- const response = await client.callTool({
+ const { client: client1 } = await startClient({ args: [`--isolated`] });
+ const response = await client1.callTool({
name: 'browser_navigate',
arguments: { url: server.PREFIX },
});
expect(response).toContainTextContent(`Storage: NO`);
- await client.callTool({
+ await client1.callTool({
name: 'browser_close',
});
- const client2 = await startClient({ args: [`--isolated`] });
+ const { client: client2 } = await startClient({ args: [`--isolated`] });
const response2 = await client2.callTool({
name: 'browser_navigate',
arguments: { url: server.PREFIX },
@@ -123,7 +145,7 @@ test('isolated context with storage state', async ({ startClient, server }, test
`, 'text/html');
- const client = await startClient({ args: [
+ const { client } = await startClient({ args: [
`--isolated`,
`--storage-state=${storageStatePath}`,
] });
diff --git a/tests/pdf.spec.ts b/tests/pdf.spec.ts
index 7b599c8..8af4667 100644
--- a/tests/pdf.spec.ts
+++ b/tests/pdf.spec.ts
@@ -19,7 +19,7 @@ import fs from 'fs';
import { test, expect } from './fixtures.js';
test('save as pdf unavailable', async ({ startClient, server }) => {
- const client = await startClient({ args: ['--caps="no-pdf"'] });
+ const { client } = await startClient({ args: ['--caps="no-pdf"'] });
await client.callTool({
name: 'browser_navigate',
arguments: { url: server.HELLO_WORLD },
@@ -31,7 +31,7 @@ test('save as pdf unavailable', async ({ startClient, server }) => {
});
test('save as pdf', async ({ startClient, mcpBrowser, server }, testInfo) => {
- const client = await startClient({
+ const { client } = await startClient({
config: { outputDir: testInfo.outputPath('output') },
});
@@ -51,7 +51,7 @@ test('save as pdf', async ({ startClient, mcpBrowser, server }, testInfo) => {
test('save as pdf (filename: output.pdf)', async ({ startClient, mcpBrowser, server }, testInfo) => {
const outputDir = testInfo.outputPath('output');
test.skip(!!mcpBrowser && !['chromium', 'chrome', 'msedge'].includes(mcpBrowser), 'Save as PDF is only supported in Chromium.');
- const client = await startClient({
+ const { client } = await startClient({
config: { outputDir },
});
diff --git a/tests/request-blocking.spec.ts b/tests/request-blocking.spec.ts
index 7d0a016..21a7185 100644
--- a/tests/request-blocking.spec.ts
+++ b/tests/request-blocking.spec.ts
@@ -37,7 +37,7 @@ test('default to allow all', async ({ server, client }) => {
});
test('blocked works', async ({ startClient }) => {
- const client = await startClient({
+ const { client } = await startClient({
args: ['--blocked-origins', 'microsoft.com;example.com;playwright.dev']
});
const result = await fetchPage(client, 'https://example.com/');
@@ -46,7 +46,7 @@ test('blocked works', async ({ startClient }) => {
test('allowed works', async ({ server, startClient }) => {
server.setContent('/ppp', 'content:PPP', 'text/html');
- const client = await startClient({
+ const { client } = await startClient({
args: ['--allowed-origins', `microsoft.com;${new URL(server.PREFIX).host};playwright.dev`]
});
const result = await fetchPage(client, server.PREFIX + 'ppp');
@@ -54,7 +54,7 @@ test('allowed works', async ({ server, startClient }) => {
});
test('blocked takes precedence', async ({ startClient }) => {
- const client = await startClient({
+ const { client } = await startClient({
args: [
'--blocked-origins', 'example.com',
'--allowed-origins', 'example.com',
@@ -65,7 +65,7 @@ test('blocked takes precedence', async ({ startClient }) => {
});
test('allowed without blocked blocks all non-explicitly specified origins', async ({ startClient }) => {
- const client = await startClient({
+ const { client } = await startClient({
args: ['--allowed-origins', 'playwright.dev'],
});
const result = await fetchPage(client, 'https://example.com/');
@@ -74,7 +74,7 @@ test('allowed without blocked blocks all non-explicitly specified origins', asyn
test('blocked without allowed allows non-explicitly specified origins', async ({ server, startClient }) => {
server.setContent('/ppp', 'content:PPP', 'text/html');
- const client = await startClient({
+ const { client } = await startClient({
args: ['--blocked-origins', 'example.com'],
});
const result = await fetchPage(client, server.PREFIX + 'ppp');
diff --git a/tests/screenshot.spec.ts b/tests/screenshot.spec.ts
index d771359..b83e10a 100644
--- a/tests/screenshot.spec.ts
+++ b/tests/screenshot.spec.ts
@@ -19,7 +19,7 @@ import fs from 'fs';
import { test, expect } from './fixtures.js';
test('browser_take_screenshot (viewport)', async ({ startClient, server }, testInfo) => {
- const client = await startClient({
+ const { client } = await startClient({
config: { outputDir: testInfo.outputPath('output') },
});
expect(await client.callTool({
@@ -45,7 +45,7 @@ test('browser_take_screenshot (viewport)', async ({ startClient, server }, testI
});
test('browser_take_screenshot (element)', async ({ startClient, server }, testInfo) => {
- const client = await startClient({
+ const { client } = await startClient({
config: { outputDir: testInfo.outputPath('output') },
});
expect(await client.callTool({
@@ -76,7 +76,7 @@ test('browser_take_screenshot (element)', async ({ startClient, server }, testIn
test('--output-dir should work', async ({ startClient, server }, testInfo) => {
const outputDir = testInfo.outputPath('output');
- const client = await startClient({
+ const { client } = await startClient({
config: { outputDir },
});
expect(await client.callTool({
@@ -98,7 +98,7 @@ for (const raw of [undefined, true]) {
test(`browser_take_screenshot (raw: ${raw})`, async ({ startClient, server }, testInfo) => {
const outputDir = testInfo.outputPath('output');
const ext = raw ? 'png' : 'jpeg';
- const client = await startClient({
+ const { client } = await startClient({
config: { outputDir },
});
expect(await client.callTool({
@@ -138,7 +138,7 @@ for (const raw of [undefined, true]) {
test('browser_take_screenshot (filename: "output.jpeg")', async ({ startClient, server }, testInfo) => {
const outputDir = testInfo.outputPath('output');
- const client = await startClient({
+ const { client } = await startClient({
config: { outputDir },
});
expect(await client.callTool({
@@ -174,7 +174,7 @@ test('browser_take_screenshot (filename: "output.jpeg")', async ({ startClient,
test('browser_take_screenshot (imageResponses=omit)', async ({ startClient, server }, testInfo) => {
const outputDir = testInfo.outputPath('output');
- const client = await startClient({
+ const { client } = await startClient({
config: {
outputDir,
imageResponses: 'omit',
@@ -205,7 +205,7 @@ test('browser_take_screenshot (imageResponses=omit)', async ({ startClient, serv
test('browser_take_screenshot (cursor)', async ({ startClient, server }, testInfo) => {
const outputDir = testInfo.outputPath('output');
- const client = await startClient({
+ const { client } = await startClient({
clientName: 'cursor:vscode',
config: { outputDir },
});
diff --git a/tests/tabs.spec.ts b/tests/tabs.spec.ts
index 3242aa4..08afd63 100644
--- a/tests/tabs.spec.ts
+++ b/tests/tabs.spec.ts
@@ -141,7 +141,7 @@ test('reuse first tab when navigating', async ({ startClient, cdpServer, server
const browserContext = await cdpServer.start();
const pages = browserContext.pages();
- const client = await startClient({ args: [`--cdp-endpoint=${cdpServer.endpoint}`] });
+ const { client } = await startClient({ args: [`--cdp-endpoint=${cdpServer.endpoint}`] });
await client.callTool({
name: 'browser_navigate',
arguments: { url: server.HELLO_WORLD },
diff --git a/tests/trace.spec.ts b/tests/trace.spec.ts
index b3e78b7..13e9d4f 100644
--- a/tests/trace.spec.ts
+++ b/tests/trace.spec.ts
@@ -22,7 +22,7 @@ import { test, expect } from './fixtures.js';
test('check that trace is saved', async ({ startClient, server }, testInfo) => {
const outputDir = testInfo.outputPath('output');
- const client = await startClient({
+ const { client } = await startClient({
args: ['--save-trace', `--output-dir=${outputDir}`],
});