Skip to content

Commit 24db89b

Browse files
authored
Revert "feat(cli): add annotate command (#40520)" (#40540)
1 parent 4b4d038 commit 24db89b

6 files changed

Lines changed: 31 additions & 33 deletions

File tree

packages/playwright-core/src/tools/cli-client/program.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,13 @@ export async function program(options?: { embedderVersion?: string}) {
216216
await new Promise<void>(resolve => child.on('exit', () => resolve()));
217217
return;
218218
}
219+
if (args.annotate) {
220+
const dashboard = spawn(process.execPath, daemonArgs, { detached: true, stdio: 'ignore' });
221+
dashboard.unref();
222+
const annotate = spawn(process.execPath, [...daemonArgs, '--annotate'], { stdio: 'inherit' });
223+
await new Promise<void>(resolve => annotate.on('exit', () => resolve()));
224+
return;
225+
}
219226
const foreground = args.port !== undefined;
220227
const child = spawn(process.execPath, daemonArgs, {
221228
detached: !foreground,

packages/playwright-core/src/tools/cli-client/skill/SKILL.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,8 @@ playwright-cli video-start video.webm
163163
playwright-cli video-chapter "Chapter Title" --description="Details" --duration=2000
164164
playwright-cli video-stop
165165

166-
# launch the dashboard for UI review / design feedback — user annotates the page, you receive the annotated screenshot, snapshot, and notes
167-
playwright-cli annotate
166+
# launch the dashboard with annotation prompt to ask the user for input
167+
playwright-cli show --annotate
168168

169169
# generate a Playwright locator for an element from its ref or selector
170170
playwright-cli generate-locator e5 --raw
@@ -367,11 +367,11 @@ playwright-cli close
367367

368368
## Example: Interactive session
369369

370-
Ask the user for UI review or design feedback. The user draws boxes on the live page and types comments; you receive the annotated screenshot, the snapshot of the marked region, and the user's notes. Use this whenever the user asks for "UI review", "design feedback", or to "ask the user what they think / want / mean":
370+
Ask the user to annotate the UI. User can provide contextual tasks or ask contextual questions using annotations:
371371

372372
```bash
373373
playwright-cli open https://example.com
374-
playwright-cli annotate
374+
playwright-cli show --annotate
375375
```
376376

377377
## Specific tasks

packages/playwright-core/src/tools/cli-client/skill/references/spec-driven-testing.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ playwright-cli resume # resume so that seed test runs fully
8888
playwright-cli snapshot # inventory of interactive elements
8989
playwright-cli click e5 # follow a flow
9090
playwright-cli eval "location.href" # read URL / state
91-
playwright-cli annotate # ask the user to point at something
91+
playwright-cli show --annotate # ask the user to point at something
9292
```
9393

9494
Map out:
@@ -262,7 +262,7 @@ The test is paused at the start. Step forward or run to until just before the fa
262262
playwright-cli snapshot # did the element change / move / rename?
263263
playwright-cli console # app-side errors?
264264
playwright-cli network # failed request? wrong payload?
265-
playwright-cli annotate # ask the user to point somewhere
265+
playwright-cli show --annotate # ask the user to point somewhere
266266
```
267267

268268
Common causes: selector drift, new wrapper element, label/ARIA rename, timing (transition, async load), assertion text updated in the app, test data leaking between runs.

packages/playwright-core/src/tools/cli-daemon/commands.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -977,22 +977,13 @@ const dashboardShow = declareCommand({
977977
options: z.object({
978978
port: numberArg.optional().describe('Start as a blocking HTTP server on this port (use 0 for a random port)'),
979979
host: z.string().optional().describe('Host to bind to when using --port (defaults to localhost)'),
980+
annotate: z.boolean().optional().describe('Switch the dashboard into annotation mode.'),
980981
kill: z.boolean().optional().describe('Kill the dashboard daemon.'),
981982
}),
982983
toolName: '',
983984
toolParams: () => ({}),
984985
});
985986

986-
const annotate = declareCommand({
987-
name: 'annotate',
988-
description: 'Ask the user to annotate the current page.',
989-
category: 'devtools',
990-
raw: true,
991-
args: z.object({}),
992-
toolName: 'browser_annotate',
993-
toolParams: () => ({}),
994-
});
995-
996987
const resume = declareCommand({
997988
name: 'resume',
998989
description: 'Resume the test execution',
@@ -1207,7 +1198,6 @@ const commandsArray: AnyCommandSchema[] = [
12071198
videoStop,
12081199
videoChapter,
12091200
dashboardShow,
1210-
annotate,
12111201
pauseAt,
12121202
resume,
12131203
stepOver,

packages/playwright-core/src/tools/cli-daemon/daemon.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,6 @@ export async function startCliDaemonServer(
7878

7979
const server = net.createServer(socket => {
8080
const connection = new SocketConnection(socket);
81-
const abortController = new AbortController();
82-
connection.onclose = () => abortController.abort();
8381
connection.onmessage = async message => {
8482
const { id, method, params } = message;
8583
try {
@@ -93,7 +91,7 @@ export async function startCliDaemonServer(
9391
} else if (method === 'run') {
9492
const { toolName, toolParams } = parseCliCommand(params.args);
9593
toolParams._meta = { cwd: params.cwd, raw: params.raw || params.json, json: !!params.json };
96-
const response = await backend.callTool(toolName, toolParams, abortController.signal);
94+
const response = await backend.callTool(toolName, toolParams);
9795
await connection.send({ id, result: formatResult(response) });
9896
} else {
9997
throw new Error(`Unknown method: ${method}`);

tests/mcp/dashboard.spec.ts

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -152,23 +152,24 @@ async function drawAndSubmitAnnotation(dashboard: import('playwright-core').Page
152152
}
153153

154154
function verifyAnnotateOutput(output: string, expectedText: string, outputDir: string) {
155-
expect(output).toMatch(new RegExp(`\\{ x: \\d+, y: \\d+, width: \\d+, height: \\d+ \\}: ${expectedText}`));
156-
const imageMatch = output.match(/- \[Annotation image\]\((\.playwright-cli[\\/]annotations-.*\.png)\)/);
157-
expect(imageMatch).not.toBeNull();
158-
const pngPath = path.resolve(outputDir, imageMatch![1]);
155+
const lines = output.trim().split('\n');
156+
expect(lines[0]).toMatch(new RegExp(`^\\{ x: \\d+, y: \\d+, width: \\d+, height: \\d+ \\}: ${expectedText}$`));
157+
expect(lines[lines.length - 1]).toMatch(/^image: \.playwright-cli[\\/]annotations-.*\.png$/);
158+
const pngRel = lines[lines.length - 1].replace(/^image: /, '');
159+
const pngPath = path.resolve(outputDir, pngRel);
159160
expect(fs.existsSync(pngPath)).toBe(true);
160161
expect(fs.statSync(pngPath).size).toBeGreaterThan(0);
161162
}
162163

163-
test('should capture annotations via annotate', async ({ connectToDashboard, cli, server }) => {
164+
test('should capture annotations via show --annotate', async ({ connectToDashboard, cli, server }) => {
164165
await cli('open', server.EMPTY_PAGE);
165166
await cli('show');
166167
const browser = await connectToDashboard();
167168

168169
const dashboard = browser.contexts()[0].pages()[0];
169170
await dashboard.getByRole('navigation', { name: 'Sessions' }).getByRole('option').first().click();
170171

171-
const annotatePromise = cli('annotate');
172+
const annotatePromise = cli('show', '--annotate');
172173
let done = false;
173174
void annotatePromise.finally(() => { done = true; });
174175

@@ -183,7 +184,8 @@ test('should capture annotations via annotate', async ({ connectToDashboard, cli
183184
test('should start dashboard and annotate when no dashboard is running', async ({ connectToDashboard, cli, server }) => {
184185
await cli('open', server.EMPTY_PAGE);
185186

186-
const annotatePromise = cli('annotate');
187+
const bindTitle = `--playwright-internal--${crypto.randomUUID()}`;
188+
const annotatePromise = cli('show', '--annotate', { bindTitle });
187189
let done = false;
188190
void annotatePromise.finally(() => { done = true; });
189191

@@ -201,11 +203,12 @@ test('should start dashboard and annotate when no dashboard is running', async (
201203
verifyAnnotateOutput(output, 'hi', test.info().outputDir);
202204
});
203205

204-
test('should enter annotate mode on fresh dashboard.tsx mount with -s annotate', async ({ connectToDashboard, cli, server }) => {
206+
test('should enter annotate mode on fresh dashboard.tsx mount with -s --annotate', async ({ connectToDashboard, cli, server }) => {
205207
await cli('-s=first', 'open', server.EMPTY_PAGE);
206208
await cli('-s=second', 'open', server.EMPTY_PAGE);
207209

208-
const annotatePromise = cli('-s=second', 'annotate');
210+
const bindTitle = `--playwright-internal--${crypto.randomUUID()}`;
211+
const annotatePromise = cli('-s=second', 'show', '--annotate', { bindTitle });
209212
let done = false;
210213
void annotatePromise.finally(() => { done = true; });
211214

@@ -305,7 +308,7 @@ test('should cancel browser_annotate when the MCP client disconnects', async ({
305308
});
306309

307310

308-
test('should switch screencast to -s session on annotate', async ({ connectToDashboard, cli, server }) => {
311+
test('should switch screencast to -s session on show --annotate', async ({ connectToDashboard, cli, server }) => {
309312
server.setContent('/red', '<html><head><style>html,body{margin:0;height:100vh;background:#ff0000}</style></head><body></body></html>', 'text/html');
310313
server.setContent('/green', '<html><head><style>html,body{margin:0;height:100vh;background:#00ff00}</style></head><body></body></html>', 'text/html');
311314

@@ -335,7 +338,7 @@ test('should switch screencast to -s session on annotate', async ({ connectToDas
335338
return !!(c && c.r > 200 && c.g < 50);
336339
}, { timeout: 15000 }).toBe(true);
337340

338-
const annotatePromise = cli('-s=second', 'annotate');
341+
const annotatePromise = cli('-s=second', 'show', '--annotate');
339342
let done = false;
340343
void annotatePromise.finally(() => { done = true; });
341344

@@ -353,7 +356,7 @@ test('should switch screencast to -s session on annotate', async ({ connectToDas
353356
expect(exitCode).toBe(0);
354357
});
355358

356-
test('should disengage annotate mode when annotate client disconnects', async ({ connectToDashboard, cli, childProcess, cliEnv, mcpBrowser, mcpHeadless, server }) => {
359+
test('should disengage annotate mode when --annotate client disconnects', async ({ connectToDashboard, cli, childProcess, cliEnv, mcpBrowser, mcpHeadless, server }) => {
357360
await cli('open', server.EMPTY_PAGE);
358361
await cli('show');
359362
const browser = await connectToDashboard();
@@ -362,7 +365,7 @@ test('should disengage annotate mode when annotate client disconnects', async ({
362365
await dashboard.getByRole('navigation', { name: 'Sessions' }).getByRole('option').first().click();
363366

364367
const annotateClient = childProcess({
365-
command: [process.execPath, require.resolve('../../packages/playwright-core/lib/tools/cli-client/cli.js'), 'annotate'],
368+
command: [process.execPath, require.resolve('../../packages/playwright-core/lib/tools/cli-client/cli.js'), 'show', '--annotate'],
366369
cwd: test.info().outputPath(),
367370
env: inheritAndCleanEnv({
368371
...cliEnv,

0 commit comments

Comments
 (0)