From bdfdb34afd4d38df27169b15b14da401ec63468e Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Thu, 10 Sep 2026 17:19:36 -0700 Subject: [PATCH 1/2] feat(mcp): add media emulation Fixes: https://github.com/microsoft/playwright/issues/42243 --- .../src/tools/backend/emulation.ts | 50 +++++++++++++ .../src/tools/backend/tools.ts | 2 + .../src/tools/cli-daemon/command.ts | 2 +- .../src/tools/cli-daemon/commands.ts | 62 ++++++++++++++++ .../src/tools/cli-daemon/helpGenerator.ts | 1 + .../src/tools/skills/playwright-cli/SKILL.md | 10 +++ tests/mcp/capabilities.spec.ts | 1 + tests/mcp/cli-emulation.spec.ts | 37 ++++++++++ tests/mcp/cli-help.spec.ts | 12 +++ tests/mcp/config-resolve.spec.ts | 17 +++++ tests/mcp/emulation.spec.ts | 73 +++++++++++++++++++ 11 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 packages/playwright-core/src/tools/backend/emulation.ts create mode 100644 tests/mcp/cli-emulation.spec.ts create mode 100644 tests/mcp/emulation.spec.ts diff --git a/packages/playwright-core/src/tools/backend/emulation.ts b/packages/playwright-core/src/tools/backend/emulation.ts new file mode 100644 index 0000000000000..58e8c59d84d9a --- /dev/null +++ b/packages/playwright-core/src/tools/backend/emulation.ts @@ -0,0 +1,50 @@ +/** + * 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 * as z from 'zod'; +import { formatObject } from '@isomorphic/stringUtils'; + +import { defineTabTool } from './tool'; + +const emulateMedia = defineTabTool({ + capability: 'core', + schema: { + name: 'browser_emulate_media', + title: 'Emulate media features', + description: 'Emulate CSS media features for the page, for example switch between the light and dark color scheme. Omitted parameters are left unchanged.', + inputSchema: z.object({ + colorScheme: z.enum(['light', 'dark']).optional().describe('Emulates the prefers-color-scheme media feature'), + reducedMotion: z.enum(['reduce', 'no-preference']).optional().describe('Emulates the prefers-reduced-motion media feature'), + forcedColors: z.enum(['active', 'none']).optional().describe('Emulates the forced-colors media feature'), + contrast: z.enum(['more', 'no-preference']).optional().describe('Emulates the prefers-contrast media feature'), + media: z.enum(['screen', 'print']).optional().describe('Changes the CSS media type of the page'), + }), + type: 'action', + }, + + handle: async (tab, params, response) => { + if (Object.values(params).every(value => value === undefined)) { + response.addError('Error: Specify at least one media feature to emulate.'); + return; + } + response.addCode(`await page.emulateMedia(${formatObject(params, ' ', 'oneline')});`); + await tab.page.emulateMedia(params); + }, +}); + +export default [ + emulateMedia, +]; diff --git a/packages/playwright-core/src/tools/backend/tools.ts b/packages/playwright-core/src/tools/backend/tools.ts index 212c98fcfa6f7..7024c30b38766 100644 --- a/packages/playwright-core/src/tools/backend/tools.ts +++ b/packages/playwright-core/src/tools/backend/tools.ts @@ -21,6 +21,7 @@ import console from './console'; import cookies from './cookies'; import devtools from './devtools'; import dialogs from './dialogs'; +import emulation from './emulation'; import evaluate from './evaluate'; import files from './files'; import find from './find'; @@ -54,6 +55,7 @@ export const browserTools: Tool[] = [ ...cookies, ...devtools, ...dialogs, + ...emulation, ...evaluate, ...files, ...find, diff --git a/packages/playwright-core/src/tools/cli-daemon/command.ts b/packages/playwright-core/src/tools/cli-daemon/command.ts index dff63f2801a3a..e3b8336e9f3a8 100644 --- a/packages/playwright-core/src/tools/cli-daemon/command.ts +++ b/packages/playwright-core/src/tools/cli-daemon/command.ts @@ -17,7 +17,7 @@ import * as z from 'zod'; import type zodType from 'zod'; -export type Category = 'core' | 'navigation' | 'keyboard' | 'mouse' | 'export' | 'storage' | 'tabs' | 'network' | 'devtools' | 'browsers' | 'config' | 'install' | 'webmcp'; +export type Category = 'core' | 'navigation' | 'keyboard' | 'mouse' | 'export' | 'storage' | 'emulation' | 'tabs' | 'network' | 'devtools' | 'browsers' | 'config' | 'install' | 'webmcp'; export type CommandSchema = { name: string; diff --git a/packages/playwright-core/src/tools/cli-daemon/commands.ts b/packages/playwright-core/src/tools/cli-daemon/commands.ts index 5eb00f8835f52..f336d0be78934 100644 --- a/packages/playwright-core/src/tools/cli-daemon/commands.ts +++ b/packages/playwright-core/src/tools/cli-daemon/commands.ts @@ -474,6 +474,61 @@ const resize = declareCommand({ toolParams: ({ w: width, h: height }) => ({ width, height }), }); +const setColorScheme = declareCommand({ + name: 'set-color-scheme', + description: 'Emulate the light or dark color scheme', + category: 'emulation', + args: z.object({ + scheme: z.enum(['light', 'dark']).describe('Color scheme to emulate'), + }), + toolName: 'browser_emulate_media', + toolParams: ({ scheme: colorScheme }) => ({ colorScheme }), +}); + +const setReducedMotion = declareCommand({ + name: 'set-reduced-motion', + description: 'Emulate the reduced motion preference', + category: 'emulation', + args: z.object({ + motion: z.enum(['reduce', 'no-preference']).describe('Reduced motion preference to emulate'), + }), + toolName: 'browser_emulate_media', + toolParams: ({ motion: reducedMotion }) => ({ reducedMotion }), +}); + +const setForcedColors = declareCommand({ + name: 'set-forced-colors', + description: 'Emulate forced colors mode', + category: 'emulation', + args: z.object({ + colors: z.enum(['active', 'none']).describe('Forced colors mode to emulate'), + }), + toolName: 'browser_emulate_media', + toolParams: ({ colors: forcedColors }) => ({ forcedColors }), +}); + +const setContrast = declareCommand({ + name: 'set-contrast', + description: 'Emulate the preferred contrast', + category: 'emulation', + args: z.object({ + contrast: z.enum(['more', 'no-preference']).describe('Contrast preference to emulate'), + }), + toolName: 'browser_emulate_media', + toolParams: ({ contrast }) => ({ contrast }), +}); + +const setMedia = declareCommand({ + name: 'set-media', + description: 'Emulate the CSS media type', + category: 'emulation', + args: z.object({ + media: z.enum(['screen', 'print']).describe('CSS media type to emulate'), + }), + toolName: 'browser_emulate_media', + toolParams: ({ media }) => ({ media }), +}); + const runCode = declareCommand({ name: 'run-code', description: 'Run Playwright code snippet', @@ -1277,6 +1332,13 @@ const commandsArray: AnyCommandSchema[] = [ sessionStorageDelete, sessionStorageClear, + // emulation category + setColorScheme, + setReducedMotion, + setForcedColors, + setContrast, + setMedia, + // network category networkRequests, networkRequest, diff --git a/packages/playwright-core/src/tools/cli-daemon/helpGenerator.ts b/packages/playwright-core/src/tools/cli-daemon/helpGenerator.ts index 23e3df62e43a7..a764802b687e3 100644 --- a/packages/playwright-core/src/tools/cli-daemon/helpGenerator.ts +++ b/packages/playwright-core/src/tools/cli-daemon/helpGenerator.ts @@ -83,6 +83,7 @@ const categories: { name: Category, title: string }[] = [ { name: 'export', title: 'Save as' }, { name: 'tabs', title: 'Tabs' }, { name: 'storage', title: 'Storage' }, + { name: 'emulation', title: 'Emulation' }, { name: 'network', title: 'Network' }, { name: 'devtools', title: 'DevTools' }, { name: 'webmcp', title: 'WebMCP' }, diff --git a/packages/playwright-core/src/tools/skills/playwright-cli/SKILL.md b/packages/playwright-core/src/tools/skills/playwright-cli/SKILL.md index b67c94028834b..bb8992cefec8f 100644 --- a/packages/playwright-core/src/tools/skills/playwright-cli/SKILL.md +++ b/packages/playwright-core/src/tools/skills/playwright-cli/SKILL.md @@ -144,6 +144,16 @@ playwright-cli sessionstorage-delete step playwright-cli sessionstorage-clear ``` +### Emulation + +```bash +playwright-cli set-color-scheme dark +playwright-cli set-reduced-motion reduce +playwright-cli set-forced-colors active +playwright-cli set-contrast more +playwright-cli set-media print +``` + ### Network ```bash diff --git a/tests/mcp/capabilities.spec.ts b/tests/mcp/capabilities.spec.ts index cc8e0eb36a1e9..0f53998534df8 100644 --- a/tests/mcp/capabilities.spec.ts +++ b/tests/mcp/capabilities.spec.ts @@ -32,6 +32,7 @@ test('test snapshot tool list', async ({ client }) => { 'browser_select_option', 'browser_type', 'browser_close', + 'browser_emulate_media', 'browser_navigate_back', 'browser_navigate', 'browser_network_request', diff --git a/tests/mcp/cli-emulation.spec.ts b/tests/mcp/cli-emulation.spec.ts new file mode 100644 index 0000000000000..93d7faf9ec3eb --- /dev/null +++ b/tests/mcp/cli-emulation.spec.ts @@ -0,0 +1,37 @@ +/** + * 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 './cli-fixtures'; + +test('set media features', async ({ cli, server }) => { + await cli('open', server.PREFIX); + + const expectMatches = async (query: string) => { + const { output } = await cli('eval', `() => matchMedia('${query}').matches`); + expect(output).toContain('true'); + }; + + await cli('set-color-scheme', 'dark'); + await expectMatches('(prefers-color-scheme: dark)'); + await cli('set-reduced-motion', 'reduce'); + await expectMatches('(prefers-reduced-motion: reduce)'); + await cli('set-forced-colors', 'active'); + await expectMatches('(forced-colors: active)'); + await cli('set-contrast', 'more'); + await expectMatches('(prefers-contrast: more)'); + await cli('set-media', 'print'); + await expectMatches('print'); +}); diff --git a/tests/mcp/cli-help.spec.ts b/tests/mcp/cli-help.spec.ts index be25ffbe13296..f260608a0815c 100644 --- a/tests/mcp/cli-help.spec.ts +++ b/tests/mcp/cli-help.spec.ts @@ -21,6 +21,18 @@ test('prints help', async ({ cli }) => { expect(output).toContain('Usage: playwright-cli '); }); +test('prints emulation help after storage', async ({ cli }) => { + const { output } = await cli('--help'); + const headings = output.split('\n').filter(line => /^[A-Z].*:$/.test(line)); + expect(headings.indexOf('Emulation:')).toBe(headings.indexOf('Storage:') + 1); + const emulationHelp = output.slice(output.indexOf('\nEmulation:'), output.indexOf('\nNetwork:')); + expect(emulationHelp).toContain('set-color-scheme'); + expect(emulationHelp).toContain('set-reduced-motion'); + expect(emulationHelp).toContain('set-forced-colors'); + expect(emulationHelp).toContain('set-contrast'); + expect(emulationHelp).toContain('set-media'); +}); + test('prints help by default', async ({ cli }) => { const { output } = await cli(); expect(output).toContain('Usage: playwright-cli '); diff --git a/tests/mcp/config-resolve.spec.ts b/tests/mcp/config-resolve.spec.ts index 9123930e51562..7ba4e2d5da47b 100644 --- a/tests/mcp/config-resolve.spec.ts +++ b/tests/mcp/config-resolve.spec.ts @@ -254,6 +254,23 @@ test.describe('viewport', () => { }); }); +test('config file preserves context media preferences', async ({}, testInfo) => { + const configFile = testInfo.outputPath('config.json'); + const fileConfig: Config = { + browser: { + contextOptions: { + colorScheme: 'dark', + contrast: 'more', + forcedColors: 'active', + reducedMotion: 'reduce', + }, + }, + }; + await fs.promises.writeFile(configFile, JSON.stringify(fileConfig)); + const config = await resolveCLIConfigForMCP({ config: configFile }, emptyEnv); + expect(config.browser.contextOptions).toMatchObject(fileConfig.browser!.contextOptions!); +}); + test.describe('mobile', () => { test('--mobile defaults to a Chromium mobile device', async () => { const config = await resolveCLIConfigForMCP({ mobile: true }, emptyEnv); diff --git a/tests/mcp/emulation.spec.ts b/tests/mcp/emulation.spec.ts new file mode 100644 index 0000000000000..179d76d3c80cd --- /dev/null +++ b/tests/mcp/emulation.spec.ts @@ -0,0 +1,73 @@ +/** + * 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('browser_emulate_media', async ({ client, server }) => { + server.setContent('/', ` +
+ + `, 'text/html'); + await client.callTool({ + name: 'browser_navigate', + arguments: { url: server.PREFIX }, + }); + + expect(await client.callTool({ + name: 'browser_emulate_media', + arguments: { colorScheme: 'dark' }, + })).toHaveResponse({ + code: `await page.emulateMedia({ colorScheme: 'dark' });`, + }); + await expect.poll(() => client.callTool({ name: 'browser_snapshot' })).toHaveResponse({ + inlineSnapshot: expect.stringContaining(`Color scheme: dark`), + }); + + expect(await client.callTool({ + name: 'browser_emulate_media', + arguments: { media: 'screen', reducedMotion: 'reduce' }, + })).toHaveResponse({ + code: `await page.emulateMedia({ media: 'screen', reducedMotion: 'reduce' });`, + }); + await expect.poll(() => client.callTool({ name: 'browser_snapshot' })).toHaveResponse({ + inlineSnapshot: expect.stringContaining(`Color scheme: dark`), + }); + + expect(await client.callTool({ + name: 'browser_emulate_media', + arguments: { colorScheme: 'light' }, + })).toHaveResponse({ + code: `await page.emulateMedia({ colorScheme: 'light' });`, + }); + await expect.poll(() => client.callTool({ name: 'browser_snapshot' })).toHaveResponse({ + inlineSnapshot: expect.stringContaining(`Color scheme: light`), + }); +}); + +test('browser_emulate_media requires a media feature', async ({ client }) => { + expect(await client.callTool({ + name: 'browser_emulate_media', + arguments: {}, + })).toHaveResponse({ + error: expect.stringContaining('Specify at least one media feature to emulate.'), + isError: true, + }); +}); From 682b10b29a08b1c123051f9c31a506b8bddffda0 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Fri, 11 Sep 2026 15:46:18 -0700 Subject: [PATCH 2/2] feat(mcp): clear media emulation --- packages/isomorphic/stringUtils.ts | 2 + .../src/tools/backend/emulation.ts | 12 ++--- .../src/tools/cli-daemon/commands.ts | 50 +++++++++++++++++++ .../src/tools/skills/playwright-cli/SKILL.md | 5 ++ tests/mcp/cli-emulation.spec.ts | 18 ++++++- tests/mcp/cli-help.spec.ts | 5 ++ tests/mcp/emulation.spec.ts | 28 ++++++++--- 7 files changed, 106 insertions(+), 14 deletions(-) diff --git a/packages/isomorphic/stringUtils.ts b/packages/isomorphic/stringUtils.ts index 8629b3813db03..4bddaffbda09f 100644 --- a/packages/isomorphic/stringUtils.ts +++ b/packages/isomorphic/stringUtils.ts @@ -48,6 +48,8 @@ export function toSnakeCase(name: string): string { } export function formatObject(value: any, indent = ' ', mode: 'multiline' | 'oneline' = 'multiline'): string { + if (value === null) + return 'null'; if (typeof value === 'string') return escapeWithQuotes(value, '\''); if (Array.isArray(value)) diff --git a/packages/playwright-core/src/tools/backend/emulation.ts b/packages/playwright-core/src/tools/backend/emulation.ts index 58e8c59d84d9a..58d593d73fa92 100644 --- a/packages/playwright-core/src/tools/backend/emulation.ts +++ b/packages/playwright-core/src/tools/backend/emulation.ts @@ -24,13 +24,13 @@ const emulateMedia = defineTabTool({ schema: { name: 'browser_emulate_media', title: 'Emulate media features', - description: 'Emulate CSS media features for the page, for example switch between the light and dark color scheme. Omitted parameters are left unchanged.', + description: 'Emulate CSS media features for the page, for example switch between the light and dark color scheme. Omitted parameters are left unchanged; null clears an override.', inputSchema: z.object({ - colorScheme: z.enum(['light', 'dark']).optional().describe('Emulates the prefers-color-scheme media feature'), - reducedMotion: z.enum(['reduce', 'no-preference']).optional().describe('Emulates the prefers-reduced-motion media feature'), - forcedColors: z.enum(['active', 'none']).optional().describe('Emulates the forced-colors media feature'), - contrast: z.enum(['more', 'no-preference']).optional().describe('Emulates the prefers-contrast media feature'), - media: z.enum(['screen', 'print']).optional().describe('Changes the CSS media type of the page'), + colorScheme: z.enum(['light', 'dark']).nullable().optional().describe('Emulates the prefers-color-scheme media feature'), + reducedMotion: z.enum(['reduce', 'no-preference']).nullable().optional().describe('Emulates the prefers-reduced-motion media feature'), + forcedColors: z.enum(['active', 'none']).nullable().optional().describe('Emulates the forced-colors media feature'), + contrast: z.enum(['more', 'no-preference']).nullable().optional().describe('Emulates the prefers-contrast media feature'), + media: z.enum(['screen', 'print']).nullable().optional().describe('Changes the CSS media type of the page'), }), type: 'action', }, diff --git a/packages/playwright-core/src/tools/cli-daemon/commands.ts b/packages/playwright-core/src/tools/cli-daemon/commands.ts index f336d0be78934..5494537982703 100644 --- a/packages/playwright-core/src/tools/cli-daemon/commands.ts +++ b/packages/playwright-core/src/tools/cli-daemon/commands.ts @@ -529,6 +529,51 @@ const setMedia = declareCommand({ toolParams: ({ media }) => ({ media }), }); +const clearColorScheme = declareCommand({ + name: 'clear-color-scheme', + description: 'Clear color scheme emulation', + category: 'emulation', + args: z.object({}), + toolName: 'browser_emulate_media', + toolParams: () => ({ colorScheme: null }), +}); + +const clearReducedMotion = declareCommand({ + name: 'clear-reduced-motion', + description: 'Clear reduced motion emulation', + category: 'emulation', + args: z.object({}), + toolName: 'browser_emulate_media', + toolParams: () => ({ reducedMotion: null }), +}); + +const clearForcedColors = declareCommand({ + name: 'clear-forced-colors', + description: 'Clear forced colors emulation', + category: 'emulation', + args: z.object({}), + toolName: 'browser_emulate_media', + toolParams: () => ({ forcedColors: null }), +}); + +const clearContrast = declareCommand({ + name: 'clear-contrast', + description: 'Clear preferred contrast emulation', + category: 'emulation', + args: z.object({}), + toolName: 'browser_emulate_media', + toolParams: () => ({ contrast: null }), +}); + +const clearMedia = declareCommand({ + name: 'clear-media', + description: 'Clear CSS media type emulation', + category: 'emulation', + args: z.object({}), + toolName: 'browser_emulate_media', + toolParams: () => ({ media: null }), +}); + const runCode = declareCommand({ name: 'run-code', description: 'Run Playwright code snippet', @@ -1338,6 +1383,11 @@ const commandsArray: AnyCommandSchema[] = [ setForcedColors, setContrast, setMedia, + clearColorScheme, + clearReducedMotion, + clearForcedColors, + clearContrast, + clearMedia, // network category networkRequests, diff --git a/packages/playwright-core/src/tools/skills/playwright-cli/SKILL.md b/packages/playwright-core/src/tools/skills/playwright-cli/SKILL.md index bb8992cefec8f..c312fa8fde9e2 100644 --- a/packages/playwright-core/src/tools/skills/playwright-cli/SKILL.md +++ b/packages/playwright-core/src/tools/skills/playwright-cli/SKILL.md @@ -148,10 +148,15 @@ playwright-cli sessionstorage-clear ```bash playwright-cli set-color-scheme dark +playwright-cli clear-color-scheme playwright-cli set-reduced-motion reduce +playwright-cli clear-reduced-motion playwright-cli set-forced-colors active +playwright-cli clear-forced-colors playwright-cli set-contrast more +playwright-cli clear-contrast playwright-cli set-media print +playwright-cli clear-media ``` ### Network diff --git a/tests/mcp/cli-emulation.spec.ts b/tests/mcp/cli-emulation.spec.ts index 93d7faf9ec3eb..738b4ed559a8a 100644 --- a/tests/mcp/cli-emulation.spec.ts +++ b/tests/mcp/cli-emulation.spec.ts @@ -16,22 +16,36 @@ import { test, expect } from './cli-fixtures'; -test('set media features', async ({ cli, server }) => { +test('set and clear media features', async ({ cli, server }) => { await cli('open', server.PREFIX); const expectMatches = async (query: string) => { const { output } = await cli('eval', `() => matchMedia('${query}').matches`); - expect(output).toContain('true'); + expect(output).toContain('### Result\ntrue'); + }; + + const expectClear = async (command: string, option: string) => { + const { output } = await cli(command); + expect(output).toContain(`await page.emulateMedia({ ${option}: null });`); }; await cli('set-color-scheme', 'dark'); await expectMatches('(prefers-color-scheme: dark)'); + await expectClear('clear-color-scheme', 'colorScheme'); + await cli('set-reduced-motion', 'reduce'); await expectMatches('(prefers-reduced-motion: reduce)'); + await expectClear('clear-reduced-motion', 'reducedMotion'); + await cli('set-forced-colors', 'active'); await expectMatches('(forced-colors: active)'); + await expectClear('clear-forced-colors', 'forcedColors'); + await cli('set-contrast', 'more'); await expectMatches('(prefers-contrast: more)'); + await expectClear('clear-contrast', 'contrast'); + await cli('set-media', 'print'); await expectMatches('print'); + await expectClear('clear-media', 'media'); }); diff --git a/tests/mcp/cli-help.spec.ts b/tests/mcp/cli-help.spec.ts index f260608a0815c..20cce78bb3f69 100644 --- a/tests/mcp/cli-help.spec.ts +++ b/tests/mcp/cli-help.spec.ts @@ -27,10 +27,15 @@ test('prints emulation help after storage', async ({ cli }) => { expect(headings.indexOf('Emulation:')).toBe(headings.indexOf('Storage:') + 1); const emulationHelp = output.slice(output.indexOf('\nEmulation:'), output.indexOf('\nNetwork:')); expect(emulationHelp).toContain('set-color-scheme'); + expect(emulationHelp).toContain('clear-color-scheme'); expect(emulationHelp).toContain('set-reduced-motion'); + expect(emulationHelp).toContain('clear-reduced-motion'); expect(emulationHelp).toContain('set-forced-colors'); + expect(emulationHelp).toContain('clear-forced-colors'); expect(emulationHelp).toContain('set-contrast'); + expect(emulationHelp).toContain('clear-contrast'); expect(emulationHelp).toContain('set-media'); + expect(emulationHelp).toContain('clear-media'); }); test('prints help by default', async ({ cli }) => { diff --git a/tests/mcp/emulation.spec.ts b/tests/mcp/emulation.spec.ts index 179d76d3c80cd..ff2392f2ea441 100644 --- a/tests/mcp/emulation.spec.ts +++ b/tests/mcp/emulation.spec.ts @@ -19,10 +19,16 @@ import { test, expect } from './fixtures'; test('browser_emulate_media', async ({ client, server }) => { server.setContent('/', `
+
`, 'text/html'); @@ -53,12 +59,22 @@ test('browser_emulate_media', async ({ client, server }) => { expect(await client.callTool({ name: 'browser_emulate_media', - arguments: { colorScheme: 'light' }, + arguments: { media: 'print' }, })).toHaveResponse({ - code: `await page.emulateMedia({ colorScheme: 'light' });`, + code: `await page.emulateMedia({ media: 'print' });`, }); await expect.poll(() => client.callTool({ name: 'browser_snapshot' })).toHaveResponse({ - inlineSnapshot: expect.stringContaining(`Color scheme: light`), + inlineSnapshot: expect.stringContaining(`Media type: print`), + }); + + expect(await client.callTool({ + name: 'browser_emulate_media', + arguments: { colorScheme: null, contrast: null, forcedColors: null, media: null, reducedMotion: null }, + })).toHaveResponse({ + code: `await page.emulateMedia({ colorScheme: null, contrast: null, forcedColors: null, media: null, reducedMotion: null });`, + }); + await expect.poll(() => client.callTool({ name: 'browser_snapshot' })).toHaveResponse({ + inlineSnapshot: expect.stringContaining(`Media type: screen`), }); });