/** * 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 fs from 'fs'; import path from 'path'; import { test, expect, eventsPage } from './cli-fixtures'; test('open', async ({ cli, server }) => { const { output, snapshot } = await cli('open', server.HELLO_WORLD); expect(output).toContain(`### Page - Page URL: ${server.HELLO_WORLD} - Page Title: Title`); expect(snapshot).toContain(`- generic [active] [ref=e1]: Hello, world!`); }); test('close', async ({ cli, server }) => { await cli('open', server.HELLO_WORLD); const { output } = await cli('close'); expect(output).toContain(`Browser 'default' closed`); }); test('preserves URL with & query params', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright-cli/issues/403' } }, async ({ cli, server }) => { const url = `${server.HELLO_WORLD}?a=1&b=2`; const { output } = await cli('open', url); expect(output).toContain(`Page URL: ${url}`); }); test('click button', async ({ cli, server }) => { server.setContent('/', ``, 'text/html'); const { snapshot } = await cli('open', server.PREFIX); expect(snapshot).toContain(`- button "Submit" [ref=e2]`); const { output, snapshot: clickSnapshot } = await cli('click', 'e2'); expect(clickSnapshot).toBeTruthy(); expect(output).toContain(`### Ran Playwright code \`\`\`js await page.getByRole('button', { name: 'Submit' }).click(); \`\`\``); }); test('click link', async ({ cli, server }) => { server.setContent('/', `Hello, world!`, 'text/html'); const { snapshot } = await cli('open', server.PREFIX); expect(snapshot).toContain(`- link \"Hello, world!\" [ref=e2]`); const { output: clickOutput, snapshot: clickSnapshot } = await cli('click', 'e2'); expect(clickOutput).toContain(`### Page - Page URL: ${server.HELLO_WORLD} - Page Title: Title`); expect(clickSnapshot).toContain('Hello, world!'); }); test('dblclick', async ({ cli, server }) => { server.setContent('/', eventsPage, 'text/html'); await cli('open', server.PREFIX); const { snapshot } = await cli('dblclick', 'e2'); expect(snapshot).toContain('dblclick 0'); }); test('click with --modifiers', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright-cli/issues/406' } }, async ({ cli, server }) => { server.setContent('/', ``, 'text/html'); await cli('open', server.PREFIX); const single = await cli('click', 'e2', '--modifiers', 'Control'); expect(single.output).toContain(`await page.getByRole('button', { name: 'Submit' }).click({\n modifiers: ['Control']\n});`); const repeated = await cli('click', 'e2', '--modifiers', 'Control', '--modifiers', 'Shift'); expect(repeated.output).toContain(`await page.getByRole('button', { name: 'Submit' }).click({\n modifiers: ['Control', 'Shift']\n});`); }); test('type', async ({ cli, server }) => { server.setContent('/', ``, 'text/html'); const { snapshot } = await cli('open', server.PREFIX); expect(snapshot).toContain(`- textbox [ref=e2]`); const { snapshot: typeSnapshot } = await cli('type', 'Hello, world!', '--submit'); expect(typeSnapshot).toBe(`- textbox [ref=e2]`); }); test('fill', async ({ cli, server }) => { server.setContent('/', ``, 'text/html'); const { snapshot } = await cli('open', server.PREFIX); expect(snapshot).toContain(`- textbox [ref=e2]`); const { snapshot: fillSnapshot } = await cli('fill', 'e2', 'Hello, world!', '--submit'); expect(fillSnapshot).toBe(`- textbox [active] [ref=e2]: Hello, world!`); }); test('fill numeric', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright-cli/issues/235' } }, async ({ cli, server }) => { server.setContent('/', ``, 'text/html'); const { snapshot } = await cli('open', server.PREFIX); expect(snapshot).toContain(`- textbox [ref=e2]`); const { snapshot: fillSnapshot } = await cli('fill', 'e2', '42', '--submit'); expect(fillSnapshot).toContain(`[ref=e2]: "42"`); }); test('hover', async ({ cli, server }) => { server.setContent('/', eventsPage, 'text/html'); await cli('open', server.PREFIX); await cli('hover', 'e2'); const { inlineSnapshot } = await cli('snapshot'); expect(inlineSnapshot).toContain('mouse move 50 50'); }); test('select', async ({ cli, server }) => { server.setContent('/', ``, 'text/html'); await cli('open', server.PREFIX); await cli('select', 'e2', 'Two'); const { inlineSnapshot } = await cli('snapshot'); expect(inlineSnapshot).toContain('- option "Two" [selected]'); }); test('check', async ({ cli, server, mcpBrowser }) => { const active = mcpBrowser === 'webkit' && process.platform !== 'linux' ? '' : '[active] '; server.setContent('/', ``, 'text/html'); await cli('open', server.PREFIX); await cli('check', 'e2'); const { inlineSnapshot } = await cli('snapshot'); expect(inlineSnapshot).toContain(`- checkbox [checked] ${active}[ref=e2]`); }); test('uncheck', async ({ cli, server, mcpBrowser }) => { const active = mcpBrowser === 'webkit' && process.platform !== 'linux' ? '' : '[active] '; server.setContent('/', ``, 'text/html'); await cli('open', server.PREFIX); await cli('uncheck', 'e2'); const { inlineSnapshot } = await cli('snapshot'); expect(inlineSnapshot).toContain(`- checkbox ${active}[ref=e2]`); }); test('eval', async ({ cli, server }) => { await cli('open', server.HELLO_WORLD); const { output } = await cli('eval', '() => document.title'); expect(output).toContain('"Title"'); }); test('eval no arrow', async ({ cli, server }) => { await cli('open', server.HELLO_WORLD); const { output } = await cli('eval', 'document.title'); expect(output).toContain('"Title"'); }); test('eval ', async ({ cli, server }) => { server.setContent('/', ``, 'text/html'); await cli('open', server.PREFIX); const { output } = await cli('eval', 'element => element.nodeName', 'e2'); expect(output).toContain('"BUTTON"'); }); test('dialog-accept', async ({ cli, server }) => { server.setContent('/', ``, 'text/html'); await cli('open', server.PREFIX); const { output } = await cli('click', 'e2'); expect(output).toContain('MyAlert'); expect(output).toContain('["alert" dialog with message "MyAlert"]: can be handled by dialog-accept or dialog-dismiss'); await cli('dialog-accept'); const { inlineSnapshot } = await cli('snapshot'); expect(inlineSnapshot).not.toContain('MyAlert'); }); test('dialog-dismiss', async ({ cli, server }) => { server.setContent('/', ``, 'text/html'); await cli('open', server.PREFIX); const { output } = await cli('click', 'e2'); expect(output).toContain('MyAlert'); await cli('dialog-dismiss'); const { inlineSnapshot } = await cli('snapshot'); expect(inlineSnapshot).not.toContain('MyAlert'); }); test('dialog-accept ', async ({ cli, server }) => { server.setContent('/', ``, 'text/html'); await cli('open', server.PREFIX); await cli('click', 'e2'); await cli('dialog-accept', 'my reply'); const { inlineSnapshot } = await cli('snapshot'); expect(inlineSnapshot).toContain('my reply'); }); test('resize', async ({ cli, server }) => { await cli('open', server.PREFIX); await cli('resize', '480', '320'); const { output } = await cli('eval', '() => window.innerWidth + "x" + window.innerHeight'); expect(output).toContain('480x320'); }); test('snapshot', async ({ cli, server }, testInfo) => { { const { output } = await cli('open', server.HELLO_WORLD); expect(output).toContain('.playwright-cli' + path.sep + 'page-'); } { const nested = testInfo.outputPath('nested'); await fs.promises.mkdir(nested, { recursive: true }); const { output } = await cli('goto', server.HELLO_WORLD, { cwd: nested }); expect(output).toContain('..' + path.sep + '.playwright-cli' + path.sep + 'page-'); } }); test('click in iframe', async ({ cli, server }) => { server.setContent('/', `

Hello

`, 'text/html'); const { snapshot } = await cli('open', server.PREFIX); expect(snapshot).toContain(`- button "World" [ref=f1e2]`); const { output, snapshot: clickSnapshot } = await cli('click', 'f1e2'); expect(clickSnapshot).toBeTruthy(); expect(output).toContain(`### Ran Playwright code \`\`\`js await page.locator('iframe').first().contentFrame().getByRole('button', { name: 'World' }).click(); \`\`\``); }); test('click button with CSS selector', async ({ cli, server }) => { server.setContent('/', ``, 'text/html'); const { snapshot } = await cli('open', server.PREFIX); expect(snapshot).toContain(`- button "Submit" [ref=e2]`); const { output, snapshot: clickSnapshot } = await cli('click', 'button'); expect(clickSnapshot).toBeTruthy(); expect(output).toContain(`### Ran Playwright code \`\`\`js await page.locator('button').click(); \`\`\``); }); test('click button with role locator', async ({ cli, server }) => { server.setContent('/', ``, 'text/html'); const { snapshot } = await cli('open', server.PREFIX); expect(snapshot).toContain(`- button "Submit" [ref=e2]`); const { output, snapshot: clickSnapshot } = await cli('click', 'getByRole("button", { name: "Submit" })'); expect(clickSnapshot).toBeTruthy(); expect(output).toContain(`### Ran Playwright code \`\`\`js await page.getByRole('button', { name: 'Submit' }).click(); \`\`\``); }); test('click button with test id locator', async ({ cli, server }) => { server.setContent('/', `
`, 'text/html'); const { snapshot } = await cli('open', server.PREFIX); expect(snapshot).toContain(`- button "Submit" [ref=e3]`); const { output, snapshot: clickSnapshot } = await cli('click', 'getByTestId("main").getByRole("button")'); expect(clickSnapshot).toBeTruthy(); expect(output).toContain(`### Ran Playwright code \`\`\`js await page.getByTestId('main').getByRole('button').click(); \`\`\``); }); test('click button with wrong css selector', async ({ cli, server }) => { server.setContent('/', ``, 'text/html'); const { snapshot } = await cli('open', server.PREFIX); expect(snapshot).toContain(`- button "Submit" [ref=e2]`); const { output } = await cli('click', '#target'); expect(output).toContain(`"#target" does not match any elements.`); }); test('partial snapshot', async ({ cli, server }) => { server.setContent('/', ``, 'text/html'); const { snapshot } = await cli('open', server.PREFIX); expect(snapshot).toContain('- button "Submit" [ref=e2]'); expect(snapshot).toContain('- button "Cancel" [ref=e3]'); const { inlineSnapshot: partialSnapshot } = await cli('snapshot', '#two'); expect(partialSnapshot).toBe(`- button "Cancel" [ref=e3]`); const { output: strictError } = await cli('snapshot', 'button'); expect(strictError).toContain(`strict mode violation`); const { output: noMatchError } = await cli('snapshot', '#target'); expect(noMatchError).toContain(`"#target" does not match any element`); }); test('partial snapshot by ref', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright-cli/issues/347' } }, async ({ cli, server }) => { server.setContent('/', ``, 'text/html'); const { snapshot } = await cli('open', server.PREFIX); expect(snapshot).toContain('- button "Submit" [ref=e2]'); expect(snapshot).toContain('- button "Cancel" [ref=e3]'); const { inlineSnapshot: partialSnapshot } = await cli('snapshot', 'e3'); expect(partialSnapshot).toBe(`- button "Cancel" [ref=e3]`); const { output: missingRefError } = await cli('snapshot', 'e999'); expect(missingRefError).toContain(`Ref e999 not found in the current page snapshot.`); }); test('snapshot depth', async ({ cli, server }) => { server.setContent('/', ``, 'text/html'); await cli('open', server.PREFIX); const { inlineSnapshot: limitedSnapshot } = await cli('snapshot', '--depth=1'); expect(limitedSnapshot).toBe(`- list [ref=e2]: - listitem [ref=e3] - listitem [ref=e5]`); const { inlineSnapshot: fullSnapshot } = await cli('snapshot', '--depth=100'); expect(fullSnapshot).toBe(`- list [ref=e2]: - listitem [ref=e3]: - button "Submit" [ref=e4] - listitem [ref=e5]: - button "Cancel" [ref=e6]`); }); test('snapshot --boxes', async ({ cli, server }) => { server.setContent('/', ` `, 'text/html'); await cli('open', server.PREFIX); const { inlineSnapshot } = await cli('snapshot', '--boxes'); expect(inlineSnapshot).toContain(`- button "click" [ref=e1] [box=100,50,80,40]`); const { inlineSnapshot: plain } = await cli('snapshot'); expect(plain).not.toMatch(/\[box=/); }); test('eval --raw', async ({ cli, server }) => { await cli('open', server.HELLO_WORLD); const { output } = await cli('eval', '--raw', '() => document.title'); expect(output).toBe('"Title"'); }); test('eval --raw with error', async ({ cli, server }) => { await cli('open', server.HELLO_WORLD); const { output } = await cli('eval', '--raw', '() => { throw new Error("my error") }'); expect(output).toContain('my error'); expect(output).not.toContain('##'); }); test('snapshot --raw', async ({ cli, server }) => { server.setContent('/', ``, 'text/html'); await cli('open', server.PREFIX); const { output } = await cli('snapshot', '--raw'); expect(output).toBe('- button "Submit" [ref=e2]'); }); test('--raw on command without output', async ({ cli, server }) => { server.setContent('/', ``, 'text/html'); await cli('open', server.PREFIX); const { output } = await cli('click', '--raw', 'e2'); expect(output).not.toContain('### '); expect(output).not.toContain('Page URL'); });