diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json
index 6fa27ab5af4c3..c1af96ccba44c 100644
--- a/packages/playwright-core/browsers.json
+++ b/packages/playwright-core/browsers.json
@@ -45,7 +45,7 @@
},
{
"name": "webkit",
- "revision": "2318",
+ "revision": "2319",
"installByDefault": true,
"revisionOverrides": {
"mac14": "2251",
diff --git a/packages/playwright-core/src/cli/DEPS.list b/packages/playwright-core/src/cli/DEPS.list
index 956f4210d5952..f71bab90aa05f 100644
--- a/packages/playwright-core/src/cli/DEPS.list
+++ b/packages/playwright-core/src/cli/DEPS.list
@@ -8,6 +8,7 @@
../remote/
../server/trace/viewer/
../tools/cli-client/program.ts
+../tools/mcp/program.ts
../tools/trace/traceCli.ts
../bootstrap.ts
node_modules/commander
diff --git a/packages/playwright-core/src/cli/program.ts b/packages/playwright-core/src/cli/program.ts
index b5d63420c3445..64ea909101883 100644
--- a/packages/playwright-core/src/cli/program.ts
+++ b/packages/playwright-core/src/cli/program.ts
@@ -29,6 +29,7 @@ import { installBrowsers, uninstallBrowsers, installDeps } from './installAction
import { runTraceInBrowser, runTraceViewerApp } from '../server/trace/viewer/traceViewer';
import { screenshot, pdf } from './browserActions';
import { program as cliProgram } from '../tools/cli-client/program';
+import { decorateMCPCommand } from '../tools/mcp/program';
import type { TraceViewerServerOptions } from '../server/trace/viewer/traceViewer';
import type { Command } from 'commander';
@@ -236,7 +237,8 @@ export function decorateProgram(program: Command) {
addTraceCommands(program, logErrorAndExit);
program
- .command('cli', { hidden: true })
+ .command('cli')
+ .description('run playwright cli commands from terminal')
.allowExcessArguments(true)
.allowUnknownOption(true)
.helpOption(false)
@@ -244,6 +246,10 @@ export function decorateProgram(program: Command) {
process.argv.splice(process.argv.indexOf('cli'), 1);
cliProgram().catch(logErrorAndExit);
});
+
+ decorateMCPCommand(program
+ .command('mcp')
+ .description('run the Playwright MCP server'));
}
function logErrorAndExit(e: Error) {
diff --git a/packages/playwright-core/src/tools/mcp/program.ts b/packages/playwright-core/src/tools/mcp/program.ts
index e29d72fed016c..f074c961e2b41 100644
--- a/packages/playwright-core/src/tools/mcp/program.ts
+++ b/packages/playwright-core/src/tools/mcp/program.ts
@@ -132,12 +132,18 @@ export function decorateMCPCommand(command: Command) {
},
disposed: async backend => {
clientCount--;
- if (sharedBrowserPromise && clientCount > 0)
+ const browserContext = (backend as BrowserBackend).browserContext;
+
+ if (sharedBrowserPromise && clientCount > 0) {
+ if (config.browser.isolated) {
+ testDebug('close context');
+ await browserContext.close().catch(() => { });
+ }
return;
+ }
testDebug('close browser');
sharedBrowserPromise = undefined;
- const browserContext = (backend as BrowserBackend).browserContext;
await browserContext.close().catch(() => { });
await browserContext.browser()?.close().catch(() => { });
}
diff --git a/tests/library/modernizr.spec.ts b/tests/library/modernizr.spec.ts
index 27a2ba720cc31..303833fb9c134 100644
--- a/tests/library/modernizr.spec.ts
+++ b/tests/library/modernizr.spec.ts
@@ -32,7 +32,7 @@ async function checkFeatures(name: string, context: BrowserContext, server: Test
}
}
-it('Safari Desktop', async ({ browser, browserName, platform, httpsServer, headless, channel, isFrozenWebkit }) => {
+it('Safari Desktop', async ({ browser, browserName, platform, httpsServer, channel, isFrozenWebkit }) => {
it.skip(browserName !== 'webkit');
it.skip(browserName === 'webkit' && platform === 'darwin' && os.arch() === 'x64', 'Modernizr uses WebGL which is not available on Intel macOS - https://bugs.webkit.org/show_bug.cgi?id=278277');
it.skip(isFrozenWebkit);
@@ -58,8 +58,7 @@ it('Safari Desktop', async ({ browser, browserName, platform, httpsServer, headl
if (platform === 'linux' || channel === 'webkit-wsl') {
expected.speechrecognition = false;
expected.mediastream = false;
- if (headless)
- expected.todataurlwebp = true;
+ expected.todataurlwebp = true;
// GHA
delete actual.variablefonts;
@@ -90,7 +89,7 @@ it('Safari Desktop', async ({ browser, browserName, platform, httpsServer, headl
expect(actual).toEqual(expected);
});
-it('Mobile Safari', async ({ playwright, browser, browserName, platform, httpsServer, headless, channel, isFrozenWebkit }) => {
+it('Mobile Safari', async ({ playwright, browser, browserName, platform, httpsServer, channel, isFrozenWebkit }) => {
it.skip(browserName !== 'webkit');
it.skip(browserName === 'webkit' && platform === 'darwin' && os.arch() === 'x64', 'Modernizr uses WebGL which is not available on Intel macOS - https://bugs.webkit.org/show_bug.cgi?id=278277');
it.skip(isFrozenWebkit);
@@ -122,8 +121,7 @@ it('Mobile Safari', async ({ playwright, browser, browserName, platform, httpsSe
if (platform === 'linux' || channel === 'webkit-wsl') {
expected.speechrecognition = false;
expected.mediastream = false;
- if (headless)
- expected.todataurlwebp = true;
+ expected.todataurlwebp = true;
// GHA
delete actual.variablefonts;
diff --git a/tests/mcp/http.spec.ts b/tests/mcp/http.spec.ts
index 292e7e1275aea..85dca4f8773e6 100644
--- a/tests/mcp/http.spec.ts
+++ b/tests/mcp/http.spec.ts
@@ -161,7 +161,7 @@ test('http transport browser sigint', async ({ serverEndpoint, server }) => {
});
});
-test('http transport browser lifecycle (isolated, multiclient)', async ({ serverEndpoint, server }) => {
+test('http transport browser lifecycle (isolated, multiclient)', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/41539' } }, async ({ serverEndpoint, server }) => {
const { url, stderr } = await serverEndpoint({ args: ['--isolated'] });
const transport1 = new StreamableHTTPClientTransport(new URL('/mcp', url));
@@ -200,6 +200,7 @@ test('http transport browser lifecycle (isolated, multiclient)', async ({ server
'delete http session': 3,
'create context': 3,
'create browser (isolated)': 1,
+ 'close context': 2,
'close browser': 1,
});
});
@@ -229,6 +230,7 @@ test('http transport browser lifecycle (isolated, concurrent clients)', { annota
'delete http session': 3,
'create context': 3,
'create browser (isolated)': 1,
+ 'close context': 2,
'close browser': 1,
});
});
diff --git a/tests/mcp/sse.spec.ts b/tests/mcp/sse.spec.ts
index 753b233d2839a..2ea74f488e1d6 100644
--- a/tests/mcp/sse.spec.ts
+++ b/tests/mcp/sse.spec.ts
@@ -161,6 +161,7 @@ test('sse transport browser lifecycle (isolated, multiclient)', async ({ serverE
'delete SSE session': 3,
'create context': 3,
'create browser (isolated)': 1,
+ 'close context': 2,
'close browser': 1,
});
});
diff --git a/tests/page/page-click.spec.ts b/tests/page/page-click.spec.ts
index fde976f76e71d..bfe0691e5cf4d 100644
--- a/tests/page/page-click.spec.ts
+++ b/tests/page/page-click.spec.ts
@@ -1223,6 +1223,22 @@ it('should fire contextmenu event on right click in correct order', async ({ pag
await expect.poll(() => entries).toEqual(['mousedown', 'contextmenu', 'mouseup']);
});
+it('should click after a right click', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/39246' } }, async ({ page, browserName }) => {
+ // On webkit the native context menu opened by the right click swallows the
+ // following left click, so the button never receives it.
+ it.fixme(browserName === 'webkit');
+ await page.setContent(`
+
+
+ `);
+ await page.getByRole('button').click({ button: 'right' });
+ await page.getByRole('button').click();
+ await expect(page.getByRole('button')).toHaveText('Clicked!');
+});
+
it('should set PointerEvent.pressure on pointerdown', async ({ page, isLinux, headless }) => {
it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/35844' });
await page.setContent(`