mirror of
https://github.com/microsoft/playwright-mcp.git
synced 2025-07-25 16:02:26 +08:00
chore: roll playwright to latest (#269)
This commit is contained in:
parent
bf7dbabca4
commit
b02370df2f
26
package-lock.json
generated
26
package-lock.json
generated
@ -11,7 +11,7 @@
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.10.1",
|
||||
"commander": "^13.1.0",
|
||||
"playwright": "1.53.0-alpha-1745357020000",
|
||||
"playwright": "1.53.0-alpha-2025-04-25",
|
||||
"yaml": "^2.7.1",
|
||||
"zod-to-json-schema": "^3.24.4"
|
||||
},
|
||||
@ -21,7 +21,7 @@
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@eslint/js": "^9.19.0",
|
||||
"@playwright/test": "1.53.0-alpha-1745357020000",
|
||||
"@playwright/test": "1.53.0-alpha-2025-04-25",
|
||||
"@stylistic/eslint-plugin": "^3.0.1",
|
||||
"@types/node": "^22.13.10",
|
||||
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
||||
@ -287,13 +287,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.53.0-alpha-1745357020000",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.53.0-alpha-1745357020000.tgz",
|
||||
"integrity": "sha512-7xQRHhsS//elVJVt2WybJPXAy++WiE8yJzMtVFcnzdQNg9VNSbpqo4b61io5IIG1nEfB22N4BhjQ/8jPrUyu9A==",
|
||||
"version": "1.53.0-alpha-2025-04-25",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.53.0-alpha-2025-04-25.tgz",
|
||||
"integrity": "sha512-3y4C2ZjAc2oUpwavC2yG2JzH53TOKgcMZvWb5GmpxnOa6fhuSVXK0kIsiIaImKmdffIVM1agsqNHp8yldeBTHQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"playwright": "1.53.0-alpha-1745357020000"
|
||||
"playwright": "1.53.0-alpha-2025-04-25"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
@ -3299,12 +3299,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/playwright": {
|
||||
"version": "1.53.0-alpha-1745357020000",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.53.0-alpha-1745357020000.tgz",
|
||||
"integrity": "sha512-evnZJIB1CRSA1HfwCkLhyqyGZybSWdNwfyyUWhBoez9ISbYMuYrTtidx75oiGVXtbKr5s8iC0+opuvagu4L1vA==",
|
||||
"version": "1.53.0-alpha-2025-04-25",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.53.0-alpha-2025-04-25.tgz",
|
||||
"integrity": "sha512-b5VT4lWgyhhy99zHeCoUBt/FQckPxeQVA5ksvxBv0HeqcEvzZzhuyqrrcZewJyflE+5U+bmvqI+yoU0ks8mE3Q==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"playwright-core": "1.53.0-alpha-1745357020000"
|
||||
"playwright-core": "1.53.0-alpha-2025-04-25"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
@ -3317,9 +3317,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.53.0-alpha-1745357020000",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.53.0-alpha-1745357020000.tgz",
|
||||
"integrity": "sha512-3oPzOUwJ/yhNWUs3fh5UbmI1Mf18sHUDo3gxzuPwqxN3QCSFKx9Ncg7cSB+FyJCkgz7ZD8fUlzJ75YsDE+PMfA==",
|
||||
"version": "1.53.0-alpha-2025-04-25",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.53.0-alpha-2025-04-25.tgz",
|
||||
"integrity": "sha512-gjV01l6A4q/zg+/pwEX50k9lhYWaE9NcDVypSDD331jB3EYrdk0LeDQxqz5XFDOzq/tC/8QTouDs9a/s/p95hA==",
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"playwright-core": "cli.js"
|
||||
|
@ -36,14 +36,14 @@
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.10.1",
|
||||
"commander": "^13.1.0",
|
||||
"playwright": "1.53.0-alpha-1745357020000",
|
||||
"playwright": "1.53.0-alpha-2025-04-25",
|
||||
"yaml": "^2.7.1",
|
||||
"zod-to-json-schema": "^3.24.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@eslint/js": "^9.19.0",
|
||||
"@playwright/test": "1.53.0-alpha-1745357020000",
|
||||
"@playwright/test": "1.53.0-alpha-2025-04-25",
|
||||
"@stylistic/eslint-plugin": "^3.0.1",
|
||||
"@types/node": "^22.13.10",
|
||||
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
||||
|
@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import net from 'net';
|
||||
|
||||
import * as playwright from 'playwright';
|
||||
import yaml from 'yaml';
|
||||
|
||||
@ -26,7 +28,7 @@ import type { ModalState, Tool, ToolActionResult } from './tools/tool';
|
||||
export type ContextOptions = {
|
||||
browserName?: 'chromium' | 'firefox' | 'webkit';
|
||||
userDataDir: string;
|
||||
launchOptions?: playwright.LaunchOptions;
|
||||
launchOptions?: playwright.LaunchOptions & playwright.BrowserContextOptions;
|
||||
cdpEndpoint?: string;
|
||||
remoteEndpoint?: string;
|
||||
};
|
||||
@ -42,6 +44,7 @@ export class Context {
|
||||
readonly options: ContextOptions;
|
||||
private _browser: playwright.Browser | undefined;
|
||||
private _browserContext: playwright.BrowserContext | undefined;
|
||||
private _createBrowserContextPromise: Promise<{ browser?: playwright.Browser, browserContext: playwright.BrowserContext }> | undefined;
|
||||
private _tabs: Tab[] = [];
|
||||
private _currentTab: Tab | undefined;
|
||||
private _modalStates: (ModalState & { tab: Tab })[] = [];
|
||||
@ -259,6 +262,7 @@ ${code.join('\n')}
|
||||
return;
|
||||
const browserContext = this._browserContext;
|
||||
const browser = this._browser;
|
||||
this._createBrowserContextPromise = undefined;
|
||||
this._browserContext = undefined;
|
||||
this._browser = undefined;
|
||||
|
||||
@ -280,6 +284,15 @@ ${code.join('\n')}
|
||||
}
|
||||
|
||||
private async _createBrowserContext(): Promise<{ browser?: playwright.Browser, browserContext: playwright.BrowserContext }> {
|
||||
if (!this._createBrowserContextPromise)
|
||||
this._createBrowserContextPromise = this._innerCreateBrowserContext();
|
||||
return this._createBrowserContextPromise;
|
||||
}
|
||||
|
||||
private async _innerCreateBrowserContext(): Promise<{ browser?: playwright.Browser, browserContext: playwright.BrowserContext }> {
|
||||
if (this.options.browserName === 'chromium')
|
||||
(this.options.launchOptions as any).webSocketPort = await findFreePort();
|
||||
|
||||
if (this.options.remoteEndpoint) {
|
||||
const url = new URL(this.options.remoteEndpoint);
|
||||
if (this.options.browserName)
|
||||
@ -468,3 +481,14 @@ class PageSnapshot {
|
||||
export async function generateLocator(locator: playwright.Locator): Promise<string> {
|
||||
return (locator as any)._generateLocatorString();
|
||||
}
|
||||
|
||||
async function findFreePort() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const server = net.createServer();
|
||||
server.listen(0, () => {
|
||||
const { port } = server.address() as net.AddressInfo;
|
||||
server.close(() => resolve(port));
|
||||
});
|
||||
server.on('error', reject);
|
||||
});
|
||||
}
|
||||
|
10
src/index.ts
10
src/index.ts
@ -34,7 +34,7 @@ import screen from './tools/screen';
|
||||
|
||||
import type { Tool, ToolCapability } from './tools/tool';
|
||||
import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
||||
import type { LaunchOptions } from 'playwright';
|
||||
import type { LaunchOptions, BrowserContextOptions } from 'playwright';
|
||||
|
||||
const snapshotTools: Tool<any>[] = [
|
||||
...common(true),
|
||||
@ -84,6 +84,7 @@ export async function createServer(options?: Options): Promise<Server> {
|
||||
case 'chrome-beta':
|
||||
case 'chrome-canary':
|
||||
case 'chrome-dev':
|
||||
case 'chromium':
|
||||
case 'msedge':
|
||||
case 'msedge-beta':
|
||||
case 'msedge-canary':
|
||||
@ -91,9 +92,6 @@ export async function createServer(options?: Options): Promise<Server> {
|
||||
browserName = 'chromium';
|
||||
channel = options.browser;
|
||||
break;
|
||||
case 'chromium':
|
||||
browserName = 'chromium';
|
||||
break;
|
||||
case 'firefox':
|
||||
browserName = 'firefox';
|
||||
break;
|
||||
@ -106,10 +104,12 @@ export async function createServer(options?: Options): Promise<Server> {
|
||||
}
|
||||
const userDataDir = options?.userDataDir ?? await createUserDataDir(browserName);
|
||||
|
||||
const launchOptions: LaunchOptions = {
|
||||
const launchOptions: LaunchOptions & BrowserContextOptions = {
|
||||
headless: !!(options?.headless ?? (os.platform() === 'linux' && !process.env.DISPLAY)),
|
||||
channel,
|
||||
executablePath: options?.executablePath,
|
||||
viewport: null,
|
||||
...{ assistantMode: true },
|
||||
};
|
||||
|
||||
const allTools = options?.vision ? screenshotTools : snapshotTools;
|
||||
|
38
tests/webdriver.spec.ts
Normal file
38
tests/webdriver.spec.ts
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { test, expect } from './fixtures';
|
||||
|
||||
test('do not falsely advertise user agent as a test driver', async ({ client, server, mcpBrowser }) => {
|
||||
test.skip(mcpBrowser === 'firefox');
|
||||
test.skip(mcpBrowser === 'webkit');
|
||||
server.route('/', (req, res) => {
|
||||
res.writeHead(200, { 'Content-Type': 'text/html' });
|
||||
res.end(`
|
||||
<body></body>
|
||||
<script>
|
||||
document.body.textContent = 'webdriver: ' + navigator.webdriver;
|
||||
</script>
|
||||
`);
|
||||
});
|
||||
|
||||
expect(await client.callTool({
|
||||
name: 'browser_navigate',
|
||||
arguments: {
|
||||
url: server.PREFIX,
|
||||
},
|
||||
})).toContainTextContent('webdriver: false');
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user