chore: make recorder tests match order of codegen calls (#32716)

This commit is contained in:
Pavel Feldman 2024-09-19 10:31:44 -07:00 committed by GitHub
parent 2b2a57abad
commit a00e1c9c4b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 142 additions and 141 deletions

View File

@ -20,8 +20,8 @@ import type { ConsoleMessage } from 'playwright';
test.describe('cli codegen', () => {
test.skip(({ mode }) => mode !== 'default');
test('should click', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should click', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<button onclick="console.log('click')">Submit</button>`);
@ -52,8 +52,8 @@ await page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).ClickAsync();`)
expect(message.text()).toBe('click');
});
test('should double click', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should double click', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<button onclick="console.log('click ' + event.detail)" ondblclick="console.log('dblclick ' + event.detail)">Submit</button>`);
@ -93,8 +93,8 @@ await page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).DblClickAsync()
]);
});
test('should ignore programmatic events', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should ignore programmatic events', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<button onclick="console.log('click')">Submit</button>`);
@ -113,8 +113,8 @@ await page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).DblClickAsync()
expect(clicks.length).toBe(1);
});
test('should click after same-document navigation', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
test('should click after same-document navigation', async ({ openRecorder, server }) => {
const { page, recorder } = await openRecorder();
server.setRoute('/foo.html', (req, res) => {
res.setHeader('Content-Type', 'text/html; charset=utf-8');
@ -143,8 +143,8 @@ await page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).DblClickAsync()
expect(message.text()).toBe('click');
});
test('should make a positioned click on a canvas', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should make a positioned click on a canvas', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<canvas width="500" height="500" style="margin: 42px"/>
@ -196,8 +196,8 @@ await page.Locator("canvas").ClickAsync(new LocatorClickOptions
expect(message.text()).toBe('click 250 250');
});
test('should work with TrustedTypes', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should work with TrustedTypes', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<head>
@ -234,8 +234,8 @@ await page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).ClickAsync();`)
expect(message.text()).toBe('click');
});
test('should not target selector preview by text regexp', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should not target selector preview by text regexp', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<span>dummy</span>`);
@ -265,8 +265,8 @@ await page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).ClickAsync();`)
expect(message.text()).toBe('click');
});
test('should fill', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should fill', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<input id="input" name="name" oninput="console.log(input.value)"></input>`);
const locator = await recorder.focusElement('input');
@ -295,8 +295,8 @@ await page.Locator("#input").FillAsync(\"John\");`);
expect(message.text()).toBe('John');
});
test('should fill japanese text', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should fill japanese text', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
// In Japanese, "てすと" or "テスト" means "test".
await recorder.setContentAndWait(`<input id="input" name="name" oninput="input.value === 'てすと' && console.log(input.value)"></input>`);
@ -329,8 +329,8 @@ await page.Locator("#input").FillAsync(\"てすと\");`);
expect(message.text()).toBe('てすと');
});
test('should fill textarea', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should fill textarea', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<textarea id="textarea" name="name" oninput="console.log(textarea.value)"></textarea>`);
const locator = await recorder.focusElement('textarea');
@ -346,9 +346,9 @@ await page.Locator("#input").FillAsync(\"てすと\");`);
expect(message.text()).toBe('John');
});
test('should fill textarea with new lines at the end', async ({ page, openRecorder }) => {
test('should fill textarea with new lines at the end', async ({ openRecorder }) => {
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/23774' });
const recorder = await openRecorder();
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<textarea id="textarea"></textarea>`);
const textarea = page.locator('textarea');
await textarea.evaluate<void, HTMLTextAreaElement>(e => e.addEventListener('input', () => (window as any).lastInputValue = e.value));
@ -361,8 +361,8 @@ await page.Locator("#input").FillAsync(\"てすと\");`);
expect(sources.get('JavaScript')!.text).not.toContain(`Enter`);
});
test('should fill [contentEditable]', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should fill [contentEditable]', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<div id="content" contenteditable="" oninput="console.log(content.innerText)"/>`);
const locator = await recorder.focusElement('div');
@ -378,8 +378,8 @@ await page.Locator("#input").FillAsync(\"てすと\");`);
expect(message.text()).toBe('John Doe');
});
test('should press', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should press', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<input name="name" onkeypress="console.log('press')"></input>`);
@ -412,8 +412,8 @@ await page.GetByRole(AriaRole.Textbox).PressAsync("Shift+Enter");`);
expect(messages[0].text()).toBe('press');
});
test('should update selected element after pressing Tab', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should update selected element after pressing Tab', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<input name="one"></input>
@ -441,8 +441,8 @@ await page.GetByRole(AriaRole.Textbox).PressAsync("Shift+Enter");`);
await page.locator('input[name="two"]').fill('barfoo321');`);
});
test('should record ArrowDown', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should record ArrowDown', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<input name="name" onkeydown="console.log('press:' + event.key)"></input>`);
@ -463,8 +463,8 @@ await page.GetByRole(AriaRole.Textbox).PressAsync("Shift+Enter");`);
expect(messages[0].text()).toBe('press:ArrowDown');
});
test('should emit single keyup on ArrowDown', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should emit single keyup on ArrowDown', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<input name="name" onkeydown="console.log('down:' + event.key)" onkeyup="console.log('up:' + event.key)"></input>`);
@ -488,8 +488,8 @@ await page.GetByRole(AriaRole.Textbox).PressAsync("Shift+Enter");`);
expect(messages[1].text()).toBe('up:ArrowDown');
});
test('should check', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should check', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<input id="checkbox" type="checkbox" name="accept" onchange="console.log(checkbox.checked)"></input>`);
@ -520,8 +520,8 @@ await page.Locator("#checkbox").CheckAsync();`);
expect(message.text()).toBe('true');
});
test('should check a radio button', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should check a radio button', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<input id="checkbox" type="radio" name="accept" onchange="console.log(checkbox.checked)"></input>`);
@ -539,8 +539,8 @@ await page.Locator("#checkbox").CheckAsync();`);
expect(message.text()).toBe('true');
});
test('should check with keyboard', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should check with keyboard', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<input id="checkbox" type="checkbox" name="accept" onchange="console.log(checkbox.checked)"></input>`);
@ -558,8 +558,8 @@ await page.Locator("#checkbox").CheckAsync();`);
expect(message.text()).toBe('true');
});
test('should uncheck', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should uncheck', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<input id="checkbox" type="checkbox" checked name="accept" onchange="console.log(checkbox.checked)"></input>`);
@ -590,8 +590,8 @@ await page.Locator("#checkbox").UncheckAsync();`);
expect(message.text()).toBe('false');
});
test('should select', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should select', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait('<select id="age" onchange="console.log(age.selectedOptions[0].value)"><option value="1"><option value="2"></select>');
@ -623,8 +623,8 @@ await page.Locator("#age").SelectOptionAsync(new[] { "2" });`);
expect(message.text()).toBe('2');
});
test('should select with size attribute', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should select with size attribute', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<style>
@ -664,8 +664,8 @@ await page.Locator(\"#age\").SelectOptionAsync(new[] { \"2\" });`);
expect(message.text()).toBe('2');
});
test('should await popup', async ({ page, openRecorder, browserName, headless }) => {
const recorder = await openRecorder();
test('should await popup', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait('<a target=_blank rel=noopener href="about:blank">link</a>');
const locator = await recorder.hoverOverElement('a');
@ -706,8 +706,8 @@ var page1 = await page.RunAndWaitForPopupAsync(async () =>
expect(popup.url()).toBe('about:blank');
});
test('should attribute navigation to click', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should attribute navigation to click', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<a onclick="window.location.href='about:blank#foo'">link</a>`);
@ -763,7 +763,7 @@ await page.GetByText("link").ClickAsync();`);
test('should ignore AltGraph', async ({ openRecorder, browserName }) => {
test.skip(browserName === 'firefox', 'The TextInputProcessor in Firefox does not work with AltGraph.');
const recorder = await openRecorder();
const { recorder } = await openRecorder();
await recorder.setContentAndWait(`<input></input>`);
await recorder.page.type('input', 'playwright');
@ -775,8 +775,8 @@ await page.GetByText("link").ClickAsync();`);
expect(recorder.sources().get('JavaScript')!.text).toContain(`await page.getByRole('textbox').fill('playwright@example.com');`);
});
test('should middle click', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
test('should middle click', async ({ openRecorder, server }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<a href${JSON.stringify(server.EMPTY_PAGE)}>Click me</a>`);
@ -807,8 +807,8 @@ await page.GetByText("Click me").ClickAsync(new LocatorClickOptions
});`);
});
test('should record slider', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should record slider', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<input type="range" min="0" max="10" value="5">`);
@ -846,10 +846,10 @@ await page.GetByText("Click me").ClickAsync(new LocatorClickOptions
await page.GetByRole(AriaRole.Slider).FillAsync("10");`);
});
test('should click button with nested div', async ({ page, openRecorder }) => {
test('should click button with nested div', async ({ openRecorder }) => {
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/29067' });
const recorder = await openRecorder();
const { recorder } = await openRecorder();
await recorder.setContentAndWait(`<button><div role="none">Submit</div></button>`);
@ -878,8 +878,8 @@ await page.GetByRole(AriaRole.Slider).FillAsync("10");`);
await page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).ClickAsync();`);
});
test('should record omnibox navigations after performAction', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
test('should record omnibox navigations after performAction', async ({ openRecorder, server }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<button>Submit</button>`);
await Promise.all([
recorder.waitForOutput('JavaScript', 'click'),
@ -890,8 +890,8 @@ await page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).ClickAsync();`)
await recorder.waitForOutput('JavaScript', `await page.goto('${server.PREFIX}/empty.html');`);
});
test('should record omnibox navigations after recordAction', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
test('should record omnibox navigations after recordAction', async ({ openRecorder, server }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<textarea></textarea>`);
await Promise.all([
recorder.waitForOutput('JavaScript', 'fill'),
@ -902,8 +902,8 @@ await page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).ClickAsync();`)
await recorder.waitForOutput('JavaScript', `await page.goto('${server.PREFIX}/empty.html');`);
});
test('should not throw csp directive violation errors', async ({ page, openRecorder, server }) => {
await openRecorder();
test('should not throw csp directive violation errors', async ({ openRecorder, server }) => {
const { page } = await openRecorder();
await page.goto(server.PREFIX + '/csp.html');
const predicate = (msg: ConsoleMessage) => msg.type() === 'error' && /Content[\- ]Security[\- ]Policy/i.test(msg.text());
await expect(page.waitForEvent('console', { predicate, timeout: 1000 })).rejects.toThrow();

View File

@ -22,7 +22,7 @@ test.describe('cli codegen', () => {
test.skip(({ mode }) => mode !== 'default');
test('should contain open page', async ({ openRecorder }) => {
const recorder = await openRecorder();
const { recorder } = await openRecorder();
await recorder.setContentAndWait(``);
const sources = await recorder.waitForOutput('JavaScript', `page.goto`);
@ -43,8 +43,8 @@ test.describe('cli codegen', () => {
var page = await context.NewPageAsync();`);
});
test('should contain second page', async ({ openRecorder, page }) => {
const recorder = await openRecorder();
test('should contain second page', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(``);
await page.context().newPage();
@ -66,8 +66,8 @@ var page = await context.NewPageAsync();`);
var page1 = await context.NewPageAsync();`);
});
test('should contain close page', async ({ openRecorder, page }) => {
const recorder = await openRecorder();
test('should contain close page', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(``);
await page.context().newPage();
@ -90,8 +90,8 @@ var page1 = await context.NewPageAsync();`);
await page.CloseAsync();`);
});
test('should not lead to an error if html gets clicked', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should not lead to an error if html gets clicked', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait('');
await page.context().newPage();
@ -104,9 +104,9 @@ await page.CloseAsync();`);
expect(errors.length).toBe(0);
});
test('should upload a single file', async ({ page, openRecorder, browserName, asset, isLinux }) => {
test('should upload a single file', async ({ openRecorder, browserName, asset, isLinux }) => {
test.fixme(browserName === 'firefox' && isLinux, 'https://bugzilla.mozilla.org/show_bug.cgi?id=1827551');
const recorder = await openRecorder();
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<form>
<input type="file">
@ -135,9 +135,9 @@ await page.CloseAsync();`);
await page.GetByRole(AriaRole.Textbox).SetInputFilesAsync(new[] { \"file-to-upload.txt\" });`);
});
test('should upload multiple files', async ({ page, openRecorder, browserName, asset, isLinux }) => {
test('should upload multiple files', async ({ openRecorder, browserName, asset, isLinux }) => {
test.fixme(browserName === 'firefox' && isLinux, 'https://bugzilla.mozilla.org/show_bug.cgi?id=1827551');
const recorder = await openRecorder();
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<form>
<input type="file" multiple>
@ -166,9 +166,9 @@ await page.GetByRole(AriaRole.Textbox).SetInputFilesAsync(new[] { \"file-to-uplo
await page.GetByRole(AriaRole.Textbox).SetInputFilesAsync(new[] { \"file-to-upload.txt\", \"file-to-upload-2.txt\" });`);
});
test('should clear files', async ({ page, openRecorder, browserName, asset, isLinux }) => {
test('should clear files', async ({ openRecorder, browserName, asset, isLinux }) => {
test.fixme(browserName === 'firefox' && isLinux, 'https://bugzilla.mozilla.org/show_bug.cgi?id=1827551');
const recorder = await openRecorder();
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<form>
<input type="file" multiple>
@ -197,8 +197,8 @@ await page.GetByRole(AriaRole.Textbox).SetInputFilesAsync(new[] { \"file-to-uplo
await page.GetByRole(AriaRole.Textbox).SetInputFilesAsync(new[] { });`);
});
test('should download files', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
test('should download files', async ({ openRecorder, server }) => {
const { page, recorder } = await openRecorder();
server.setRoute('/download', (req, res) => {
const pathName = url.parse(req.url!).path;
@ -273,8 +273,8 @@ var download1 = await page.RunAndWaitForDownloadAsync(async () =>
});`);
});
test('should handle dialogs', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should handle dialogs', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<button onclick="alert()">click me</button>
@ -321,8 +321,8 @@ await page.GetByRole(AriaRole.Button, new() { Name = "click me" }).ClickAsync();
});
test('should handle history.postData', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
test('should handle history.postData', async ({ openRecorder, server }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<script>
@ -337,8 +337,8 @@ await page.GetByRole(AriaRole.Button, new() { Name = "click me" }).ClickAsync();
}
});
test('should record open in a new tab with url', async ({ page, openRecorder, browserName }) => {
const recorder = await openRecorder();
test('should record open in a new tab with url', async ({ openRecorder, browserName }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<a href="about:blank?foo">link</a>`);
const locator = await recorder.hoverOverElement('a');
@ -367,8 +367,8 @@ await page1.GotoAsync("about:blank?foo");`);
}
});
test('should not clash pages', async ({ page, openRecorder, browserName }) => {
const recorder = await openRecorder();
test('should not clash pages', async ({ openRecorder, browserName }) => {
const { page, recorder } = await openRecorder();
const [popup1] = await Promise.all([
page.context().waitForEvent('page'),
page.evaluate(`window.open('about:blank')`)
@ -404,8 +404,8 @@ await page1.GotoAsync("about:blank?foo");`);
expect(sources.get('C#')!.text).toContain(`await page2.Locator("#name").FillAsync("TextB");`);
});
test('click should emit events in order', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('click should emit events in order', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<button id=button>
@ -428,8 +428,8 @@ await page1.GotoAsync("about:blank?foo");`);
expect(messages).toEqual(['mousedown', 'mouseup', 'click']);
});
test('should update hover model on action', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should update hover model on action', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<input id="checkbox" type="checkbox" name="accept" onchange="checkbox.name='updated'"></input>`);
const [models] = await Promise.all([
@ -439,8 +439,8 @@ await page1.GotoAsync("about:blank?foo");`);
expect(models.hovered).toBe('#checkbox');
});
test('should reset hover model on action when element detaches', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should reset hover model on action when element detaches', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<input id="checkbox" onclick="document.getElementById('checkbox').remove()">`);
const [models] = await Promise.all([
@ -450,10 +450,10 @@ await page1.GotoAsync("about:blank?foo");`);
expect(models.hovered).toBe(null);
});
test('should update active model on action', async ({ page, openRecorder, browserName, headless }) => {
test('should update active model on action', async ({ openRecorder, browserName, headless }) => {
test.fixme(browserName === 'webkit');
const recorder = await openRecorder();
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<input id="checkbox" type="checkbox" name="accept" onchange="checkbox.name='updated'"></input>`);
const [models] = await Promise.all([
recorder.waitForActionPerformed(),
@ -462,8 +462,8 @@ await page1.GotoAsync("about:blank?foo");`);
expect(models.active).toBe('#checkbox');
});
test('should check input with chaining id', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should check input with chaining id', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<input id="checkbox" type="checkbox" name="accept" onchange="checkbox.name = 'updated'"></input>`);
await Promise.all([
recorder.waitForActionPerformed(),
@ -471,8 +471,8 @@ await page1.GotoAsync("about:blank?foo");`);
]);
});
test('should record navigations after identical pushState', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
test('should record navigations after identical pushState', async ({ openRecorder, server }) => {
const { page, recorder } = await openRecorder();
server.setRoute('/page2.html', (req, res) => {
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.end('Hello world');
@ -515,8 +515,8 @@ await page1.GotoAsync("about:blank?foo");`);
expect(fs.existsSync(harFileName)).toBeTruthy();
});
test('should fill tricky characters', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should fill tricky characters', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<textarea spellcheck=false id="textarea" name="name" oninput="console.log(textarea.value)"></textarea>`);
const locator = await recorder.focusElement('textarea');
@ -548,8 +548,8 @@ await page.Locator("#textarea").FillAsync(\"Hello'\\"\`\\nWorld\");`);
});
test('should --test-id-attribute', async ({ page, openRecorder }) => {
const recorder = await openRecorder({ testIdAttributeName: 'my-test-id' });
test('should --test-id-attribute', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder({ testIdAttributeName: 'my-test-id' });
await recorder.setContentAndWait(`<div my-test-id="foo">Hello</div>`);
await page.click('[my-test-id=foo]');

View File

@ -19,8 +19,8 @@ import { test, expect } from './inspectorTest';
test.describe('cli codegen', () => {
test.skip(({ mode }) => mode !== 'default');
test('should click locator.first', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should click locator.first', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<button onclick="console.log('click1')">Submit</button>
@ -54,8 +54,8 @@ await page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).First.ClickAsyn
expect(message.text()).toBe('click1');
});
test('should click locator.nth', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should click locator.nth', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<button onclick="console.log('click1')">Submit</button>
@ -89,8 +89,8 @@ await page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).Nth(1).ClickAsy
expect(message.text()).toBe('click2');
});
test('should generate frame locators', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
test('should generate frame locators', async ({ openRecorder, server }) => {
const { page, recorder } = await openRecorder();
/*
iframe
div Hello1
@ -198,8 +198,8 @@ await page.Locator("#frame1").ContentFrame.Locator("iframe").ContentFrame.Locato
await page.Locator("#frame1").ContentFrame.Locator("iframe").ContentFrame.Locator("iframe").Nth(2).ContentFrame.GetByText("HelloNameAnonymous").ClickAsync();`);
});
test('should generate frame locators with special characters in name attribute', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
test('should generate frame locators with special characters in name attribute', async ({ openRecorder, server }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<iframe srcdoc="<button>Click me</button>">
`, server.EMPTY_PAGE, 2);
@ -226,8 +226,8 @@ await page.Locator("#frame1").ContentFrame.Locator("iframe").ContentFrame.Locato
await page.Locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").ContentFrame.GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();`);
});
test('should generate frame locators with title attribute', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
test('should generate frame locators with title attribute', async ({ openRecorder, server }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<iframe title="hello world" srcdoc="<button>Click me</button>"></iframe>
`, server.EMPTY_PAGE, 1);
@ -258,8 +258,8 @@ await page.Locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").Cont
);
});
test('should generate frame locators with name attribute', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
test('should generate frame locators with name attribute', async ({ openRecorder, server }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<iframe name="hello world" srcdoc="<button>Click me</button>"></iframe>
`, server.EMPTY_PAGE, 1);
@ -290,8 +290,8 @@ await page.Locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").Cont
);
});
test('should generate frame locators with id attribute', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
test('should generate frame locators with id attribute', async ({ openRecorder, server }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<iframe id="hello-world" srcdoc="<button>Click me</button>"></iframe>
`, server.EMPTY_PAGE, 1);
@ -322,8 +322,8 @@ await page.Locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").Cont
);
});
test('should generate frame locators with testId', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
test('should generate frame locators with testId', async ({ openRecorder, server }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<iframe data-testid="my-testid" srcdoc="<button>Click me</button>"></iframe>
`, server.EMPTY_PAGE, 1);
@ -354,8 +354,8 @@ await page.Locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").Cont
);
});
test('should generate role locators undef frame locators', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
test('should generate role locators undef frame locators', async ({ openRecorder, server }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<iframe id=frame1 srcdoc="<button>Submit</button>">`, server.EMPTY_PAGE, 2);
const frame = page.mainFrame().childFrames()[0];
@ -380,8 +380,8 @@ await page.Locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").Cont
await page.Locator("#frame1").ContentFrame.GetByRole(AriaRole.Button, new() { Name = "Submit" }).ClickAsync();`);
});
test('should generate getByTestId', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should generate getByTestId', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`<div data-testid=testid onclick="console.log('click')">Submit</div>`);
@ -412,8 +412,8 @@ await page.GetByTestId("testid").ClickAsync();`);
expect(message.text()).toBe('click');
});
test('should generate getByPlaceholder', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should generate getByPlaceholder', async ({ openRecorder }) => {
const { recorder } = await openRecorder();
await recorder.setContentAndWait(`<input placeholder="Country"></input>`);
@ -441,8 +441,8 @@ await page.GetByTestId("testid").ClickAsync();`);
await page.GetByPlaceholder("Country").ClickAsync();`);
});
test('should generate getByAltText', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should generate getByAltText', async ({ openRecorder }) => {
const { recorder } = await openRecorder();
await recorder.setContentAndWait(`<input alt="Country"></input>`);
@ -470,8 +470,8 @@ await page.GetByPlaceholder("Country").ClickAsync();`);
await page.GetByAltText("Country").ClickAsync();`);
});
test('should generate getByLabel', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should generate getByLabel', async ({ openRecorder }) => {
const { recorder } = await openRecorder();
await recorder.setContentAndWait(`<label for=target>Country</label><input id=target>`);
@ -499,8 +499,8 @@ await page.GetByAltText("Country").ClickAsync();`);
await page.GetByLabel("Country").ClickAsync();`);
});
test('should generate getByLabel without regex', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should generate getByLabel without regex', async ({ openRecorder }) => {
const { recorder } = await openRecorder();
await recorder.setContentAndWait(`<label for=target>Coun"try</label><input id=target>`);
@ -528,8 +528,8 @@ await page.GetByLabel("Country").ClickAsync();`);
await page.GetByLabel("Coun\\"try").ClickAsync();`);
});
test('should consume pointer events', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
test('should consume pointer events', async ({ openRecorder }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<button onclick="console.log('clicked')">Submit</button>
@ -559,8 +559,8 @@ await page.GetByLabel("Coun\\"try").ClickAsync();`);
]);
});
test('should consume contextmenu events, despite a custom context menu', async ({ page, openRecorder, browserName, platform }) => {
const recorder = await openRecorder();
test('should consume contextmenu events, despite a custom context menu', async ({ openRecorder, browserName, platform }) => {
const { page, recorder } = await openRecorder();
await recorder.setContentAndWait(`
<button>Right click me.</button>
@ -630,7 +630,7 @@ await page.GetByLabel("Coun\\"try").ClickAsync();`);
});
test('should assert value', async ({ openRecorder }) => {
const recorder = await openRecorder();
const { recorder } = await openRecorder();
await recorder.setContentAndWait(`
<input id=first value=foo>
@ -679,7 +679,7 @@ await page.GetByLabel("Coun\\"try").ClickAsync();`);
test('should assert value on disabled input', async ({ openRecorder, browserName }) => {
test.fixme(browserName === 'firefox', 'pointerup event is not dispatched on a disabled input');
const recorder = await openRecorder();
const { recorder } = await openRecorder();
await recorder.setContentAndWait(`
<input id=first value=foo>
@ -702,7 +702,7 @@ await page.GetByLabel("Coun\\"try").ClickAsync();`);
});
test('should assert value on disabled select', async ({ openRecorder, browserName }) => {
const recorder = await openRecorder();
const { recorder } = await openRecorder();
await recorder.setContentAndWait(`
<select id=first><option value=foo1>Foo1</option><option value=bar1>Bar1</option></select>
@ -723,7 +723,7 @@ await page.GetByLabel("Coun\\"try").ClickAsync();`);
});
test('should assert visibility', async ({ openRecorder }) => {
const recorder = await openRecorder();
const { recorder } = await openRecorder();
await recorder.setContentAndWait(`<input>`);
@ -741,7 +741,7 @@ await page.GetByLabel("Coun\\"try").ClickAsync();`);
});
test('should keep toolbar visible even if webpage erases content in hydration', async ({ openRecorder }) => {
const recorder = await openRecorder();
const { recorder } = await openRecorder();
const hydrate = () => {
window.builtinSetTimeout(() => {

View File

@ -27,7 +27,7 @@ export { expect } from '@playwright/test';
type CLITestArgs = {
recorderPageGetter: () => Promise<Page>;
closeRecorder: () => Promise<void>;
openRecorder: (options?: { testIdAttributeName: string }) => Promise<Recorder>;
openRecorder: (options?: { testIdAttributeName: string }) => Promise<{ recorder: Recorder, page: Page }>;
runCLI: (args: string[], options?: { autoExitWhen?: string }) => CLIMock;
};
@ -77,10 +77,11 @@ export const test = contextTest.extend<CLITestArgs>({
});
},
openRecorder: async ({ page, recorderPageGetter }, run) => {
openRecorder: async ({ context, recorderPageGetter }, run) => {
await run(async (options?: { testIdAttributeName?: string }) => {
await (page.context() as any)._enableRecorder({ language: 'javascript', mode: 'recording', ...options });
return new Recorder(page, await recorderPageGetter());
await (context as any)._enableRecorder({ language: 'javascript', mode: 'recording', ...options });
const page = await context.newPage();
return { page, recorder: new Recorder(page, await recorderPageGetter()) };
});
},
});