Skip to content

Commit f9a4598

Browse files
committed
cleanups
1 parent 6679996 commit f9a4598

File tree

8 files changed

+47
-50
lines changed

8 files changed

+47
-50
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"ctest": "playwright test --project=chrome",
2525
"ftest": "playwright test --project=firefox",
2626
"wtest": "playwright test --project=webkit",
27+
"etest": "playwright test --project=chromium-extension",
2728
"run-server": "node lib/browserServer.js",
2829
"clean": "rm -rf lib",
2930
"npm-publish": "npm run clean && npm run build && npm run test && npm publish"

src/browserContextFactory.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ import type { BrowserInfo, LaunchBrowserRequest } from './browserServer.js';
2828

2929
const testDebug = debug('pw:mcp:test');
3030

31-
export function contextFactory(browserConfig: FullConfig['browser']): BrowserContextFactory {
31+
export function contextFactory(browserConfig: FullConfig['browser'], { forceCdp }: { forceCdp?: boolean } = {}): BrowserContextFactory {
3232
if (browserConfig.remoteEndpoint)
3333
return new RemoteContextFactory(browserConfig);
34-
if (browserConfig.cdpEndpoint)
34+
if (browserConfig.cdpEndpoint || forceCdp)
3535
return new CdpContextFactory(browserConfig);
3636
if (browserConfig.isolated)
3737
return new IsolatedContextFactory(browserConfig);

src/cdp-relay.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ export class CDPBridgeServer extends EventEmitter {
3838
sessionId: string;
3939
} | undefined;
4040

41-
public readonly CDP_PATH = '/cdp';
42-
public readonly EXTENSION_PATH = '/extension';
41+
public static readonly CDP_PATH = '/cdp';
42+
public static readonly EXTENSION_PATH = '/extension';
4343

4444
constructor(server: http.Server) {
4545
super();
@@ -57,9 +57,9 @@ export class CDPBridgeServer extends EventEmitter {
5757

5858
debugLogger(`New connection to ${url.pathname}`);
5959

60-
if (url.pathname === this.CDP_PATH) {
60+
if (url.pathname === CDPBridgeServer.CDP_PATH) {
6161
this._handlePlaywrightConnection(ws);
62-
} else if (url.pathname === this.EXTENSION_PATH) {
62+
} else if (url.pathname === CDPBridgeServer.EXTENSION_PATH) {
6363
this._handleExtensionConnection(ws);
6464
} else {
6565
debugLogger(`Invalid path: ${url.pathname}`);
@@ -293,8 +293,8 @@ if (import.meta.url === `file://${process.argv[1]}`) {
293293
const server = new CDPBridgeServer(httpServer);
294294

295295
console.error(`CDP Bridge Server listening on ws://localhost:${port}`);
296-
console.error(`- Playwright MCP: ws://localhost:${port}${server.CDP_PATH}`);
297-
console.error(`- Extension: ws://localhost:${port}${server.EXTENSION_PATH}`);
296+
console.error(`- Playwright MCP: ws://localhost:${port}${CDPBridgeServer.CDP_PATH}`);
297+
console.error(`- Extension: ws://localhost:${port}${CDPBridgeServer.EXTENSION_PATH}`);
298298

299299
process.on('SIGINT', () => {
300300
debugLogger('\nShutting down bridge server...');

src/program.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,11 @@ import { program } from 'commander';
1919
// @ts-ignore
2020
import { startTraceViewerServer } from 'playwright-core/lib/server';
2121

22-
import { startHttpTransport, startStdioTransport } from './transport.js';
22+
import { httpAddressToString, startHttpTransport, startStdioTransport } from './transport.js';
2323
import { resolveCLIConfig } from './config.js';
2424
import { Server } from './server.js';
2525
import { packageJSON } from './package.js';
2626
import { CDPBridgeServer } from './cdp-relay.js';
27-
import { AddressInfo } from 'net';
2827

2928
program
3029
.version('Version ' + packageJSON.version)
@@ -58,11 +57,7 @@ program
5857
.option('--extension', 'Allow connecting to a running browser instance (Edge/Chrome only). Requires the \'Playwright MCP\' browser extension to be installed.')
5958
.action(async options => {
6059
const config = await resolveCLIConfig(options);
61-
if (config.extension)
62-
// TODO: The issue is that inside 'new Server' we create the ContextFactory
63-
// instances based on if there is a CDP address given.
64-
config.browser.cdpEndpoint = '1';
65-
const server = new Server(config);
60+
const server = new Server(config, { forceCdp: !!config.extension });
6661
server.setupExitWatchdog();
6762

6863
let httpServer: http.Server | undefined = undefined;
@@ -79,12 +74,12 @@ program
7974
console.error('\nTrace viewer listening on ' + url);
8075
}
8176
if (config.extension && httpServer) {
82-
config.browser.cdpEndpoint = `ws://127.0.0.1:${(httpServer.address() as AddressInfo).port}/cdp`;
77+
const wsAddress = httpAddressToString(httpServer.address()).replace('http', 'ws');
78+
config.browser.cdpEndpoint = `${wsAddress}${CDPBridgeServer.CDP_PATH}`;
8379
const cdpRelayServer = new CDPBridgeServer(httpServer);
84-
// TODO: use watchdog to stop the server on exit
8580
process.on('exit', () => cdpRelayServer.stop());
8681
// eslint-disable-next-line no-console
87-
console.error(`CDP relay server started on ws://127.0.0.1:${(httpServer.address() as AddressInfo).port}/extension - Connect to it using the browser extension.`);
82+
console.error(`CDP relay server started on ${wsAddress}${CDPBridgeServer.EXTENSION_PATH} - Connect to it using the browser extension.`);
8883
}
8984
});
9085

src/server.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ export class Server {
2828
private _browserConfig: FullConfig['browser'];
2929
private _contextFactory: BrowserContextFactory;
3030

31-
constructor(config: FullConfig) {
31+
constructor(config: FullConfig, { forceCdp }: { forceCdp: boolean }) {
3232
this.config = config;
3333
this._browserConfig = config.browser;
34-
this._contextFactory = contextFactory(this._browserConfig);
34+
this._contextFactory = contextFactory(this._browserConfig, { forceCdp });
3535
}
3636

3737
async createConnection(transport: Transport): Promise<Connection> {

src/transport.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
import http from 'node:http';
18+
import type { AddressInfo } from 'node:net';
1819
import assert from 'node:assert';
1920
import crypto from 'node:crypto';
2021

@@ -108,18 +109,7 @@ export async function startHttpTransport(server: Server): Promise<http.Server> {
108109
});
109110
const { host, port } = server.config.server;
110111
await new Promise<void>(resolve => httpServer.listen(port, host, resolve));
111-
const address = httpServer.address();
112-
assert(address, 'Could not bind server socket');
113-
let url: string;
114-
if (typeof address === 'string') {
115-
url = address;
116-
} else {
117-
const resolvedPort = address.port;
118-
let resolvedHost = address.family === 'IPv4' ? address.address : `[${address.address}]`;
119-
if (resolvedHost === '0.0.0.0' || resolvedHost === '[::]')
120-
resolvedHost = 'localhost';
121-
url = `http://${resolvedHost}:${resolvedPort}`;
122-
}
112+
const url = httpAddressToString(httpServer.address());
123113
const message = [
124114
`Listening on ${url}`,
125115
'Put this in your client config:',
@@ -136,3 +126,14 @@ export async function startHttpTransport(server: Server): Promise<http.Server> {
136126
console.error(message);
137127
return httpServer;
138128
}
129+
130+
export function httpAddressToString(address: string | AddressInfo | null): string {
131+
assert(address, 'Could not bind server socket');
132+
if (typeof address === 'string')
133+
return address;
134+
const resolvedPort = address.port;
135+
let resolvedHost = address.family === 'IPv4' ? address.address : `[${address.address}]`;
136+
if (resolvedHost === '0.0.0.0' || resolvedHost === '[::]')
137+
resolvedHost = 'localhost';
138+
return `http://${resolvedHost}:${resolvedPort}`;
139+
}

tests/fixtures.ts

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,6 @@ export const test = baseTest.extend<TestFixtures & TestOptions, WorkerFixtures>(
7878
let dispose: (() => void) | undefined;
7979

8080
await use(async options => {
81-
if (client)
82-
throw new Error('Client already started');
8381
const args: string[] = [];
8482
if (userDataDir)
8583
args.push('--user-data-dir', userDataDir);
@@ -222,9 +220,6 @@ async function createTransport(args: string[], mcpMode: TestOptions['mcpMode']):
222220
command: 'docker',
223221
args: [...dockerArgs, 'playwright-mcp-dev:latest', ...args],
224222
});
225-
transport.stderr?.on('data', data => {
226-
stderrBuffer += data.toString();
227-
});
228223
return {
229224
transport,
230225
stderr,
@@ -260,19 +255,23 @@ async function createTransport(args: string[], mcpMode: TestOptions['mcpMode']):
260255
};
261256
}
262257

258+
const transport = new StdioClientTransport({
259+
command: 'node',
260+
args: [path.join(path.dirname(__filename), '../cli.js'), ...args],
261+
cwd: path.join(path.dirname(__filename), '..'),
262+
stderr: 'pipe',
263+
env: {
264+
...process.env,
265+
DEBUG: 'pw:mcp:test',
266+
DEBUG_COLORS: '0',
267+
DEBUG_HIDE_DATE: '1',
268+
},
269+
});
270+
transport.stderr?.on('data', data => {
271+
stderrBuffer += data.toString();
272+
});
263273
return {
264-
transport: new StdioClientTransport({
265-
command: 'node',
266-
args: [path.join(path.dirname(__filename), '../cli.js'), ...args],
267-
cwd: path.join(path.dirname(__filename), '..'),
268-
stderr: 'pipe',
269-
env: {
270-
...process.env,
271-
DEBUG: 'pw:mcp:test',
272-
DEBUG_COLORS: '0',
273-
DEBUG_HIDE_DATE: '1',
274-
},
275-
}),
274+
transport,
276275
stderr,
277276
};
278277
}

tests/pdf.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ test('save as pdf unavailable', async ({ startClient, server }) => {
3030
})).toHaveTextContent(/Tool \"browser_pdf_save\" not found/);
3131
});
3232

33-
test('save as pdf', async ({ startClient, mcpBrowser, server, mcpExtensionPage }, testInfo) => {
33+
test('save as pdf', async ({ startClient, mcpBrowser, server }, testInfo) => {
3434
const { client } = await startClient({
3535
config: { outputDir: testInfo.outputPath('output') },
3636
});
@@ -41,6 +41,7 @@ test('save as pdf', async ({ startClient, mcpBrowser, server, mcpExtensionPage }
4141
name: 'browser_navigate',
4242
arguments: { url: server.HELLO_WORLD },
4343
})).toContainTextContent(`- generic [ref=e1]: Hello, world!`);
44+
4445
const response = await client.callTool({
4546
name: 'browser_pdf_save',
4647
});

0 commit comments

Comments
 (0)