feat(codegen): allow generating tests (#7049)

This commit is contained in:
Pavel Feldman 2021-06-10 16:52:59 -07:00 committed by GitHub
parent ab4398e60a
commit 3b1bae8a40
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 344 additions and 202 deletions

View file

@ -86,7 +86,7 @@ commandWithOpenOptions('open [url]', 'open page in browser specified via -b, --b
commandWithOpenOptions('codegen [url]', 'open page and generate code for user actions', commandWithOpenOptions('codegen [url]', 'open page and generate code for user actions',
[ [
['-o, --output <file name>', 'saves the generated script to a file'], ['-o, --output <file name>', 'saves the generated script to a file'],
['--target <language>', `language to use, one of javascript, python, python-async, csharp`, language()], ['--target <language>', `language to generate, one of javascript, test, python, python-async, csharp`, language()],
]).action(function(url, command) { ]).action(function(url, command) {
codegen(command, url, command.target, command.output).catch(logErrorAndExit); codegen(command, url, command.target, command.output).catch(logErrorAndExit);
}).on('--help', function() { }).on('--help', function() {
@ -554,7 +554,7 @@ function logErrorAndExit(e: Error) {
} }
function language(): string { function language(): string {
return process.env.PW_CLI_TARGET_LANG || 'javascript'; return process.env.PW_CLI_TARGET_LANG || 'test';
} }
function commandWithOpenOptions(command: string, description: string, options: any[][]): program.Command { function commandWithOpenOptions(command: string, description: string, options: any[][]): program.Command {

View file

@ -168,8 +168,11 @@ export class CodeGenerator extends EventEmitter {
const text = []; const text = [];
if (this._options.generateHeaders) if (this._options.generateHeaders)
text.push(languageGenerator.generateHeader(this._options)); text.push(languageGenerator.generateHeader(this._options));
for (const action of this._actions) for (const action of this._actions) {
text.push(languageGenerator.generateAction(action)); const actionText = languageGenerator.generateAction(action);
if (actionText)
text.push(actionText);
}
if (this._options.generateHeaders) if (this._options.generateHeaders)
text.push(languageGenerator.generateFooter(this._options.saveStorage)); text.push(languageGenerator.generateFooter(this._options.saveStorage));
return text.join('\n'); return text.join('\n');

View file

@ -23,7 +23,7 @@ import deviceDescriptors from '../../deviceDescriptors';
export class CSharpLanguageGenerator implements LanguageGenerator { export class CSharpLanguageGenerator implements LanguageGenerator {
id = 'csharp'; id = 'csharp';
fileName = '<csharp>'; fileName = 'C#';
highlighter = 'csharp'; highlighter = 'csharp';
generateAction(actionInContext: ActionInContext): string { generateAction(actionInContext: ActionInContext): string {

View file

@ -24,7 +24,7 @@ import { JavaScriptFormatter } from './javascript';
export class JavaLanguageGenerator implements LanguageGenerator { export class JavaLanguageGenerator implements LanguageGenerator {
id = 'java'; id = 'java';
fileName = '<java>'; fileName = 'Java';
highlighter = 'java'; highlighter = 'java';
generateAction(actionInContext: ActionInContext): string { generateAction(actionInContext: ActionInContext): string {

View file

@ -22,9 +22,16 @@ import { MouseClickOptions, toModifiers } from './utils';
import deviceDescriptors from '../../deviceDescriptors'; import deviceDescriptors from '../../deviceDescriptors';
export class JavaScriptLanguageGenerator implements LanguageGenerator { export class JavaScriptLanguageGenerator implements LanguageGenerator {
id = 'javascript'; id: string;
fileName = '<javascript>'; fileName: string;
highlighter = 'javascript'; highlighter = 'javascript';
private _isTest: boolean;
constructor(isTest: boolean) {
this.id = isTest ? 'test' : 'javascript';
this.fileName = isTest ? 'Playwright Test' : 'JavaScript';
this._isTest = isTest;
}
generateAction(actionInContext: ActionInContext): string { generateAction(actionInContext: ActionInContext): string {
const { action, pageAlias } = actionInContext; const { action, pageAlias } = actionInContext;
@ -33,6 +40,8 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator {
formatter.add('// ' + actionTitle(action)); formatter.add('// ' + actionTitle(action));
if (action.name === 'openPage') { if (action.name === 'openPage') {
if (this._isTest)
return '';
formatter.add(`const ${pageAlias} = await context.newPage();`); formatter.add(`const ${pageAlias} = await context.newPage();`);
if (action.url && action.url !== 'about:blank' && action.url !== 'chrome://newtab/') if (action.url && action.url !== 'about:blank' && action.url !== 'chrome://newtab/')
formatter.add(`await ${pageAlias}.goto(${quote(action.url)});`); formatter.add(`await ${pageAlias}.goto(${quote(action.url)});`);
@ -84,8 +93,12 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator {
if (emitPromiseAll) if (emitPromiseAll)
formatter.add(`]);`); formatter.add(`]);`);
else if (signals.assertNavigation) else if (signals.assertNavigation) {
formatter.add(` // assert.equal(${pageAlias}.url(), ${quote(signals.assertNavigation.url)});`); if (this._isTest)
formatter.add(` expect(${pageAlias}.url()).toBe(${quote(signals.assertNavigation.url)});`);
else
formatter.add(` // assert.equal(${pageAlias}.url(), ${quote(signals.assertNavigation.url)});`);
}
return formatter.format(); return formatter.format();
} }
@ -131,6 +144,32 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator {
} }
generateHeader(options: LanguageGeneratorOptions): string { generateHeader(options: LanguageGeneratorOptions): string {
if (this._isTest)
return this.generateTestHeader(options);
return this.generateStandaloneHeader(options);
}
generateFooter(saveStorage: string | undefined): string {
if (this._isTest)
return this.generateTestFooter(saveStorage);
return this.generateStandaloneFooter(saveStorage);
}
generateTestHeader(options: LanguageGeneratorOptions): string {
const formatter = new JavaScriptFormatter();
const useText = formatContextOptions(options.contextOptions, options.deviceName);
formatter.add(`
const { test, expect${options.deviceName ? ', devices' : ''} } = require('@playwright/test');
${useText ? '\ntest.use(' + useText + ');\n' : ''}
test('test', async ({ page }) => {`);
return formatter.format();
}
generateTestFooter(saveStorage: string | undefined): string {
return `\n});`;
}
generateStandaloneHeader(options: LanguageGeneratorOptions): string {
const formatter = new JavaScriptFormatter(); const formatter = new JavaScriptFormatter();
formatter.add(` formatter.add(`
const { ${options.browserName}${options.deviceName ? ', devices' : ''} } = require('playwright'); const { ${options.browserName}${options.deviceName ? ', devices' : ''} } = require('playwright');
@ -141,7 +180,7 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator {
return formatter.format(); return formatter.format();
} }
generateFooter(saveStorage: string | undefined): string { generateStandaloneFooter(saveStorage: string | undefined): string {
const storageStateLine = saveStorage ? `\n await context.storageState({ path: '${saveStorage}' });` : ''; const storageStateLine = saveStorage ? `\n await context.storageState({ path: '${saveStorage}' });` : '';
return `\n // ---------------------${storageStateLine} return `\n // ---------------------${storageStateLine}
await context.close(); await context.close();

View file

@ -23,7 +23,7 @@ import deviceDescriptors from '../../deviceDescriptors';
export class PythonLanguageGenerator implements LanguageGenerator { export class PythonLanguageGenerator implements LanguageGenerator {
id = 'python'; id = 'python';
fileName = '<python>'; fileName = 'Python';
highlighter = 'python'; highlighter = 'python';
private _awaitPrefix: '' | 'await '; private _awaitPrefix: '' | 'await ';
@ -32,7 +32,7 @@ export class PythonLanguageGenerator implements LanguageGenerator {
constructor(isAsync: boolean) { constructor(isAsync: boolean) {
this.id = isAsync ? 'python-async' : 'python'; this.id = isAsync ? 'python-async' : 'python';
this.fileName = isAsync ? '<async python>' : '<python>'; this.fileName = isAsync ? 'Python Async' : 'Python';
this._isAsync = isAsync; this._isAsync = isAsync;
this._awaitPrefix = isAsync ? 'await ' : ''; this._awaitPrefix = isAsync ? 'await ' : '';
this._asyncPrefix = isAsync ? 'async ' : ''; this._asyncPrefix = isAsync ? 'async ' : '';

View file

@ -82,7 +82,8 @@ export class RecorderSupplement implements InstrumentationListener {
const languages = new Set([ const languages = new Set([
new JavaLanguageGenerator(), new JavaLanguageGenerator(),
new JavaScriptLanguageGenerator(), new JavaScriptLanguageGenerator(false),
new JavaScriptLanguageGenerator(true),
new PythonLanguageGenerator(false), new PythonLanguageGenerator(false),
new PythonLanguageGenerator(true), new PythonLanguageGenerator(true),
new CSharpLanguageGenerator(), new CSharpLanguageGenerator(),

View file

@ -35,7 +35,7 @@
background: none; background: none;
outline: none; outline: none;
color: var(--toolbar-color); color: var(--toolbar-color);
margin-left: 16px; min-width: 100px;
} }
.recorder .toolbar-button.toggled.microscope { .recorder .toolbar-button.toggled.microscope {

View file

@ -95,6 +95,8 @@ export const Recorder: React.FC<RecorderProps> = ({
<ToolbarButton icon='debug-step-over' title='Step over' disabled={!paused} onClick={() => { <ToolbarButton icon='debug-step-over' title='Step over' disabled={!paused} onClick={() => {
window.dispatch({ event: 'step' }); window.dispatch({ event: 'step' });
}}></ToolbarButton> }}></ToolbarButton>
<div style={{flex: 'auto'}}></div>
<div>Target:</div>
<select className='recorder-chooser' hidden={!sources.length} value={file} onChange={event => { <select className='recorder-chooser' hidden={!sources.length} value={file} onChange={event => {
setFile(event.target.selectedOptions[0].value); setFile(event.target.selectedOptions[0].value);
}}>{ }}>{
@ -104,7 +106,6 @@ export const Recorder: React.FC<RecorderProps> = ({
}) })
} }
</select> </select>
<div style={{flex: 'auto'}}></div>
<ToolbarButton icon='clear-all' title='Clear' disabled={!source || !source.text} onClick={() => { <ToolbarButton icon='clear-all' title='Clear' disabled={!source || !source.text} onClick={() => {
window.dispatch({ event: 'clear' }); window.dispatch({ event: 'clear' });
}}></ToolbarButton> }}></ToolbarButton>

View file

@ -30,27 +30,27 @@ test.describe('cli codegen', () => {
const [message, sources] = await Promise.all([ const [message, sources] = await Promise.all([
page.waitForEvent('console', msg => msg.type() !== 'error'), page.waitForEvent('console', msg => msg.type() !== 'error'),
recorder.waitForOutput('<javascript>', 'click'), recorder.waitForOutput('JavaScript', 'click'),
page.dispatchEvent('button', 'click', { detail: 1 }) page.dispatchEvent('button', 'click', { detail: 1 })
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Click text=Submit // Click text=Submit
await page.click('text=Submit');`); await page.click('text=Submit');`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Click text=Submit # Click text=Submit
page.click("text=Submit")`); page.click("text=Submit")`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Click text=Submit # Click text=Submit
await page.click("text=Submit")`); await page.click("text=Submit")`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Click text=Submit // Click text=Submit
page.click("text=Submit");`); page.click("text=Submit");`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Click text=Submit // Click text=Submit
await page.ClickAsync("text=Submit");`); await page.ClickAsync("text=Submit");`);
@ -78,11 +78,11 @@ test.describe('cli codegen', () => {
const [message, sources] = await Promise.all([ const [message, sources] = await Promise.all([
page.waitForEvent('console', msg => msg.type() !== 'error'), page.waitForEvent('console', msg => msg.type() !== 'error'),
recorder.waitForOutput('<javascript>', 'click'), recorder.waitForOutput('JavaScript', 'click'),
page.dispatchEvent('button', 'click', { detail: 1 }) page.dispatchEvent('button', 'click', { detail: 1 })
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Click text=Submit // Click text=Submit
await page.click('text=Submit');`); await page.click('text=Submit');`);
expect(message.text()).toBe('click'); expect(message.text()).toBe('click');
@ -104,27 +104,27 @@ test.describe('cli codegen', () => {
const [message, sources] = await Promise.all([ const [message, sources] = await Promise.all([
page.waitForEvent('console', msg => msg.type() !== 'error'), page.waitForEvent('console', msg => msg.type() !== 'error'),
recorder.waitForOutput('<javascript>', 'click'), recorder.waitForOutput('JavaScript', 'click'),
page.dispatchEvent('button', 'click', { detail: 1 }) page.dispatchEvent('button', 'click', { detail: 1 })
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Click text=Submit // Click text=Submit
await page.click('text=Submit');`); await page.click('text=Submit');`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Click text=Submit # Click text=Submit
page.click("text=Submit")`); page.click("text=Submit")`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Click text=Submit # Click text=Submit
await page.click("text=Submit")`); await page.click("text=Submit")`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Click text=Submit // Click text=Submit
page.click("text=Submit");`); page.click("text=Submit");`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Click text=Submit // Click text=Submit
await page.ClickAsync("text=Submit");`); await page.ClickAsync("text=Submit");`);
@ -156,10 +156,10 @@ test.describe('cli codegen', () => {
const [message, sources] = await Promise.all([ const [message, sources] = await Promise.all([
page.waitForEvent('console', msg => msg.type() !== 'error'), page.waitForEvent('console', msg => msg.type() !== 'error'),
recorder.waitForOutput('<javascript>', 'click'), recorder.waitForOutput('JavaScript', 'click'),
page.dispatchEvent('div', 'click', { detail: 1 }) page.dispatchEvent('div', 'click', { detail: 1 })
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Click text=Some long text here // Click text=Some long text here
await page.click('text=Some long text here');`); await page.click('text=Some long text here');`);
expect(message.text()).toBe('click'); expect(message.text()).toBe('click');
@ -174,26 +174,26 @@ test.describe('cli codegen', () => {
const [message, sources] = await Promise.all([ const [message, sources] = await Promise.all([
page.waitForEvent('console', msg => msg.type() !== 'error'), page.waitForEvent('console', msg => msg.type() !== 'error'),
recorder.waitForOutput('<javascript>', 'fill'), recorder.waitForOutput('JavaScript', 'fill'),
page.fill('input', 'John') page.fill('input', 'John')
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Fill input[name="name"] // Fill input[name="name"]
await page.fill('input[name="name"]', 'John');`); await page.fill('input[name="name"]', 'John');`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Fill input[name="name"] // Fill input[name="name"]
page.fill("input[name=\\\"name\\\"]", "John");`); page.fill("input[name=\\\"name\\\"]", "John");`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Fill input[name="name"] # Fill input[name="name"]
page.fill(\"input[name=\\\"name\\\"]\", \"John\")`); page.fill(\"input[name=\\\"name\\\"]\", \"John\")`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Fill input[name="name"] # Fill input[name="name"]
await page.fill(\"input[name=\\\"name\\\"]\", \"John\")`); await page.fill(\"input[name=\\\"name\\\"]\", \"John\")`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Fill input[name="name"] // Fill input[name="name"]
await page.FillAsync(\"input[name=\\\"name\\\"]\", \"John\");`); await page.FillAsync(\"input[name=\\\"name\\\"]\", \"John\");`);
@ -209,10 +209,10 @@ test.describe('cli codegen', () => {
const [message, sources] = await Promise.all([ const [message, sources] = await Promise.all([
page.waitForEvent('console', msg => msg.type() !== 'error'), page.waitForEvent('console', msg => msg.type() !== 'error'),
recorder.waitForOutput('<javascript>', 'fill'), recorder.waitForOutput('JavaScript', 'fill'),
page.fill('textarea', 'John') page.fill('textarea', 'John')
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Fill textarea[name="name"] // Fill textarea[name="name"]
await page.fill('textarea[name="name"]', 'John');`); await page.fill('textarea[name="name"]', 'John');`);
expect(message.text()).toBe('John'); expect(message.text()).toBe('John');
@ -230,27 +230,27 @@ test.describe('cli codegen', () => {
page.on('console', message => messages.push(message)); page.on('console', message => messages.push(message));
const [, sources] = await Promise.all([ const [, sources] = await Promise.all([
recorder.waitForActionPerformed(), recorder.waitForActionPerformed(),
recorder.waitForOutput('<javascript>', 'press'), recorder.waitForOutput('JavaScript', 'press'),
page.press('input', 'Shift+Enter') page.press('input', 'Shift+Enter')
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Press Enter with modifiers // Press Enter with modifiers
await page.press('input[name="name"]', 'Shift+Enter');`); await page.press('input[name="name"]', 'Shift+Enter');`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Press Enter with modifiers // Press Enter with modifiers
page.press("input[name=\\\"name\\\"]", "Shift+Enter");`); page.press("input[name=\\\"name\\\"]", "Shift+Enter");`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Press Enter with modifiers # Press Enter with modifiers
page.press(\"input[name=\\\"name\\\"]\", \"Shift+Enter\")`); page.press(\"input[name=\\\"name\\\"]\", \"Shift+Enter\")`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Press Enter with modifiers # Press Enter with modifiers
await page.press(\"input[name=\\\"name\\\"]\", \"Shift+Enter\")`); await page.press(\"input[name=\\\"name\\\"]\", \"Shift+Enter\")`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Press Enter with modifiers // Press Enter with modifiers
await page.PressAsync(\"input[name=\\\"name\\\"]\", \"Shift+Enter\");`); await page.PressAsync(\"input[name=\\\"name\\\"]\", \"Shift+Enter\");`);
@ -266,16 +266,16 @@ test.describe('cli codegen', () => {
`); `);
await page.click('input[name="one"]'); await page.click('input[name="one"]');
await recorder.waitForOutput('<javascript>', 'click'); await recorder.waitForOutput('JavaScript', 'click');
await page.keyboard.type('foobar123'); await page.keyboard.type('foobar123');
await recorder.waitForOutput('<javascript>', 'foobar123'); await recorder.waitForOutput('JavaScript', 'foobar123');
await page.keyboard.press('Tab'); await page.keyboard.press('Tab');
await recorder.waitForOutput('<javascript>', 'Tab'); await recorder.waitForOutput('JavaScript', 'Tab');
await page.keyboard.type('barfoo321'); await page.keyboard.type('barfoo321');
await recorder.waitForOutput('<javascript>', 'barfoo321'); await recorder.waitForOutput('JavaScript', 'barfoo321');
const text = recorder.sources().get('<javascript>').text; const text = recorder.sources().get('JavaScript').text;
expect(text).toContain(` expect(text).toContain(`
// Fill input[name="one"] // Fill input[name="one"]
await page.fill('input[name="one"]', 'foobar123');`); await page.fill('input[name="one"]', 'foobar123');`);
@ -303,10 +303,10 @@ test.describe('cli codegen', () => {
}); });
const [, sources] = await Promise.all([ const [, sources] = await Promise.all([
recorder.waitForActionPerformed(), recorder.waitForActionPerformed(),
recorder.waitForOutput('<javascript>', 'press'), recorder.waitForOutput('JavaScript', 'press'),
page.press('input', 'ArrowDown') page.press('input', 'ArrowDown')
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Press ArrowDown // Press ArrowDown
await page.press('input[name="name"]', 'ArrowDown');`); await page.press('input[name="name"]', 'ArrowDown');`);
expect(messages[0].text()).toBe('press:ArrowDown'); expect(messages[0].text()).toBe('press:ArrowDown');
@ -327,10 +327,10 @@ test.describe('cli codegen', () => {
}); });
const [, sources] = await Promise.all([ const [, sources] = await Promise.all([
recorder.waitForActionPerformed(), recorder.waitForActionPerformed(),
recorder.waitForOutput('<javascript>', 'press'), recorder.waitForOutput('JavaScript', 'press'),
page.press('input', 'ArrowDown') page.press('input', 'ArrowDown')
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Press ArrowDown // Press ArrowDown
await page.press('input[name="name"]', 'ArrowDown');`); await page.press('input[name="name"]', 'ArrowDown');`);
expect(messages.length).toBe(2); expect(messages.length).toBe(2);
@ -348,27 +348,27 @@ test.describe('cli codegen', () => {
const [message, sources] = await Promise.all([ const [message, sources] = await Promise.all([
page.waitForEvent('console', msg => msg.type() !== 'error'), page.waitForEvent('console', msg => msg.type() !== 'error'),
recorder.waitForOutput('<javascript>', 'check'), recorder.waitForOutput('JavaScript', 'check'),
page.click('input') page.click('input')
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Check input[name="accept"] // Check input[name="accept"]
await page.check('input[name="accept"]');`); await page.check('input[name="accept"]');`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Check input[name="accept"] // Check input[name="accept"]
page.check("input[name=\\\"accept\\\"]");`); page.check("input[name=\\\"accept\\\"]");`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Check input[name="accept"] # Check input[name="accept"]
page.check(\"input[name=\\\"accept\\\"]\")`); page.check(\"input[name=\\\"accept\\\"]\")`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Check input[name="accept"] # Check input[name="accept"]
await page.check(\"input[name=\\\"accept\\\"]\")`); await page.check(\"input[name=\\\"accept\\\"]\")`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Check input[name="accept"] // Check input[name="accept"]
await page.CheckAsync(\"input[name=\\\"accept\\\"]\");`); await page.CheckAsync(\"input[name=\\\"accept\\\"]\");`);
@ -385,11 +385,11 @@ test.describe('cli codegen', () => {
const [message, sources] = await Promise.all([ const [message, sources] = await Promise.all([
page.waitForEvent('console', msg => msg.type() !== 'error'), page.waitForEvent('console', msg => msg.type() !== 'error'),
recorder.waitForOutput('<javascript>', 'check'), recorder.waitForOutput('JavaScript', 'check'),
page.keyboard.press('Space') page.keyboard.press('Space')
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Check input[name="accept"] // Check input[name="accept"]
await page.check('input[name="accept"]');`); await page.check('input[name="accept"]');`);
expect(message.text()).toBe('true'); expect(message.text()).toBe('true');
@ -405,27 +405,27 @@ test.describe('cli codegen', () => {
const [message, sources] = await Promise.all([ const [message, sources] = await Promise.all([
page.waitForEvent('console', msg => msg.type() !== 'error'), page.waitForEvent('console', msg => msg.type() !== 'error'),
recorder.waitForOutput('<javascript>', 'uncheck'), recorder.waitForOutput('JavaScript', 'uncheck'),
page.click('input') page.click('input')
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Uncheck input[name="accept"] // Uncheck input[name="accept"]
await page.uncheck('input[name="accept"]');`); await page.uncheck('input[name="accept"]');`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Uncheck input[name="accept"] // Uncheck input[name="accept"]
page.uncheck("input[name=\\\"accept\\\"]");`); page.uncheck("input[name=\\\"accept\\\"]");`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Uncheck input[name="accept"] # Uncheck input[name="accept"]
page.uncheck(\"input[name=\\\"accept\\\"]\")`); page.uncheck(\"input[name=\\\"accept\\\"]\")`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Uncheck input[name="accept"] # Uncheck input[name="accept"]
await page.uncheck(\"input[name=\\\"accept\\\"]\")`); await page.uncheck(\"input[name=\\\"accept\\\"]\")`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Uncheck input[name="accept"] // Uncheck input[name="accept"]
await page.UncheckAsync(\"input[name=\\\"accept\\\"]\");`); await page.UncheckAsync(\"input[name=\\\"accept\\\"]\");`);
@ -442,27 +442,27 @@ test.describe('cli codegen', () => {
const [message, sources] = await Promise.all([ const [message, sources] = await Promise.all([
page.waitForEvent('console', msg => msg.type() !== 'error'), page.waitForEvent('console', msg => msg.type() !== 'error'),
recorder.waitForOutput('<javascript>', 'select'), recorder.waitForOutput('JavaScript', 'select'),
page.selectOption('select', '2') page.selectOption('select', '2')
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Select 2 // Select 2
await page.selectOption('select', '2');`); await page.selectOption('select', '2');`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Select 2 // Select 2
page.selectOption("select", "2");`); page.selectOption("select", "2");`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Select 2 # Select 2
page.select_option(\"select\", \"2\")`); page.select_option(\"select\", \"2\")`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Select 2 # Select 2
await page.select_option(\"select\", \"2\")`); await page.select_option(\"select\", \"2\")`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Select 2 // Select 2
await page.SelectOptionAsync(\"select\", new[] { \"2\" });`); await page.SelectOptionAsync(\"select\", new[] { \"2\" });`);
@ -480,36 +480,36 @@ test.describe('cli codegen', () => {
const [popup, sources] = await Promise.all([ const [popup, sources] = await Promise.all([
page.context().waitForEvent('page'), page.context().waitForEvent('page'),
recorder.waitForOutput('<javascript>', 'waitForEvent'), recorder.waitForOutput('JavaScript', 'waitForEvent'),
page.dispatchEvent('a', 'click', { detail: 1 }) page.dispatchEvent('a', 'click', { detail: 1 })
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Click text=link // Click text=link
const [page1] = await Promise.all([ const [page1] = await Promise.all([
page.waitForEvent('popup'), page.waitForEvent('popup'),
page.click('text=link') page.click('text=link')
]);`); ]);`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Click text=link // Click text=link
Page page1 = page.waitForPopup(() -> { Page page1 = page.waitForPopup(() -> {
page.click("text=link"); page.click("text=link");
});`); });`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Click text=link # Click text=link
with page.expect_popup() as popup_info: with page.expect_popup() as popup_info:
page.click(\"text=link\") page.click(\"text=link\")
page1 = popup_info.value`); page1 = popup_info.value`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Click text=link # Click text=link
async with page.expect_popup() as popup_info: async with page.expect_popup() as popup_info:
await page.click(\"text=link\") await page.click(\"text=link\")
page1 = await popup_info.value`); page1 = await popup_info.value`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
var page1 = await page.RunAndWaitForPopupAsync(async () => var page1 = await page.RunAndWaitForPopupAsync(async () =>
{ {
await page.ClickAsync(\"text=link\"); await page.ClickAsync(\"text=link\");
@ -527,31 +527,36 @@ test.describe('cli codegen', () => {
expect(selector).toBe('text=link'); expect(selector).toBe('text=link');
const [, sources] = await Promise.all([ const [, sources] = await Promise.all([
page.waitForNavigation(), page.waitForNavigation(),
recorder.waitForOutput('<javascript>', 'assert'), recorder.waitForOutput('JavaScript', 'assert'),
page.dispatchEvent('a', 'click', { detail: 1 }) page.dispatchEvent('a', 'click', { detail: 1 })
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Click text=link // Click text=link
await page.click('text=link'); await page.click('text=link');
// assert.equal(page.url(), 'about:blank#foo');`); // assert.equal(page.url(), 'about:blank#foo');`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Playwright Test').text).toContain(`
// Click text=link
await page.click('text=link');
expect(page.url()).toBe('about:blank#foo');`);
expect(sources.get('Java').text).toContain(`
// Click text=link // Click text=link
page.click("text=link"); page.click("text=link");
// assert page.url().equals("about:blank#foo");`); // assert page.url().equals("about:blank#foo");`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Click text=link # Click text=link
page.click(\"text=link\") page.click(\"text=link\")
# assert page.url == \"about:blank#foo\"`); # assert page.url == \"about:blank#foo\"`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Click text=link # Click text=link
await page.click(\"text=link\") await page.click(\"text=link\")
# assert page.url == \"about:blank#foo\"`); # assert page.url == \"about:blank#foo\"`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Click text=link // Click text=link
await page.ClickAsync(\"text=link\"); await page.ClickAsync(\"text=link\");
// Assert.Equal(\"about:blank#foo\", page.Url);`); // Assert.Equal(\"about:blank#foo\", page.Url);`);
@ -570,37 +575,37 @@ test.describe('cli codegen', () => {
const [, sources] = await Promise.all([ const [, sources] = await Promise.all([
page.waitForNavigation(), page.waitForNavigation(),
recorder.waitForOutput('<javascript>', 'waitForNavigation'), recorder.waitForOutput('JavaScript', 'waitForNavigation'),
page.dispatchEvent('a', 'click', { detail: 1 }) page.dispatchEvent('a', 'click', { detail: 1 })
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Click text=link // Click text=link
await Promise.all([ await Promise.all([
page.waitForNavigation(/*{ url: 'about:blank#foo' }*/), page.waitForNavigation(/*{ url: 'about:blank#foo' }*/),
page.click('text=link') page.click('text=link')
]);`); ]);`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Click text=link // Click text=link
// page.waitForNavigation(new Page.WaitForNavigationOptions().setUrl("about:blank#foo"), () -> // page.waitForNavigation(new Page.WaitForNavigationOptions().setUrl("about:blank#foo"), () ->
page.waitForNavigation(() -> { page.waitForNavigation(() -> {
page.click("text=link"); page.click("text=link");
});`); });`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Click text=link # Click text=link
# with page.expect_navigation(url=\"about:blank#foo\"): # with page.expect_navigation(url=\"about:blank#foo\"):
with page.expect_navigation(): with page.expect_navigation():
page.click(\"text=link\")`); page.click(\"text=link\")`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Click text=link # Click text=link
# async with page.expect_navigation(url=\"about:blank#foo\"): # async with page.expect_navigation(url=\"about:blank#foo\"):
async with page.expect_navigation(): async with page.expect_navigation():
await page.click(\"text=link\")`); await page.click(\"text=link\")`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Click text=link // Click text=link
await page.RunAndWaitForNavigationAsync(async () => await page.RunAndWaitForNavigationAsync(async () =>
{ {
@ -622,9 +627,9 @@ test.describe('cli codegen', () => {
await recorder.page.keyboard.press('AltGraph'); await recorder.page.keyboard.press('AltGraph');
await recorder.page.keyboard.insertText('@'); await recorder.page.keyboard.insertText('@');
await recorder.page.keyboard.type('example.com'); await recorder.page.keyboard.type('example.com');
await recorder.waitForOutput('<javascript>', 'example.com'); await recorder.waitForOutput('JavaScript', 'example.com');
expect(recorder.sources().get('<javascript>').text).not.toContain(`await page.press('input', 'AltGraph');`); expect(recorder.sources().get('JavaScript').text).not.toContain(`await page.press('input', 'AltGraph');`);
expect(recorder.sources().get('<javascript>').text).toContain(`await page.fill('input', 'playwright@example.com');`); expect(recorder.sources().get('JavaScript').text).toContain(`await page.fill('input', 'playwright@example.com');`);
}); });
test('should middle click', async ({ page, openRecorder, server }) => { test('should middle click', async ({ page, openRecorder, server }) => {
@ -633,26 +638,26 @@ test.describe('cli codegen', () => {
await recorder.setContentAndWait(`<a href${JSON.stringify(server.EMPTY_PAGE)}>Click me</a>`); await recorder.setContentAndWait(`<a href${JSON.stringify(server.EMPTY_PAGE)}>Click me</a>`);
const [sources] = await Promise.all([ const [sources] = await Promise.all([
recorder.waitForOutput('<javascript>', 'click'), recorder.waitForOutput('JavaScript', 'click'),
page.click('a', { button: 'middle' }), page.click('a', { button: 'middle' }),
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
await page.click('text=Click me', { await page.click('text=Click me', {
button: 'middle' button: 'middle'
});`); });`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
page.click("text=Click me", button="middle")`); page.click("text=Click me", button="middle")`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
await page.click("text=Click me", button="middle")`); await page.click("text=Click me", button="middle")`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
page.click("text=Click me", new Page.ClickOptions() page.click("text=Click me", new Page.ClickOptions()
.setButton(MouseButton.MIDDLE));`); .setButton(MouseButton.MIDDLE));`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
await page.ClickAsync("text=Click me", new PageClickOptions await page.ClickAsync("text=Click me", new PageClickOptions
{ {
Button = MouseButton.Middle, Button = MouseButton.Middle,

View file

@ -24,25 +24,25 @@ test.describe('cli codegen', () => {
const recorder = await openRecorder(); const recorder = await openRecorder();
await recorder.setContentAndWait(``); await recorder.setContentAndWait(``);
const sources = await recorder.waitForOutput('<javascript>', `page.goto`); const sources = await recorder.waitForOutput('JavaScript', `page.goto`);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Open new page // Open new page
const page = await context.newPage();`); const page = await context.newPage();`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Open new page // Open new page
Page page = context.newPage();`); Page page = context.newPage();`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Open new page # Open new page
page = context.new_page()`); page = context.new_page()`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Open new page # Open new page
page = await context.new_page()`); page = await context.new_page()`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Open new page // Open new page
var page = await context.NewPageAsync();`); var page = await context.NewPageAsync();`);
}); });
@ -52,25 +52,25 @@ test.describe('cli codegen', () => {
await recorder.setContentAndWait(``); await recorder.setContentAndWait(``);
await page.context().newPage(); await page.context().newPage();
const sources = await recorder.waitForOutput('<javascript>', 'page1'); const sources = await recorder.waitForOutput('JavaScript', 'page1');
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Open new page // Open new page
const page1 = await context.newPage();`); const page1 = await context.newPage();`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Open new page // Open new page
Page page1 = context.newPage();`); Page page1 = context.newPage();`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Open new page # Open new page
page1 = context.new_page()`); page1 = context.new_page()`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Open new page # Open new page
page1 = await context.new_page()`); page1 = await context.new_page()`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Open new page // Open new page
var page1 = await context.NewPageAsync();`); var page1 = await context.NewPageAsync();`);
}); });
@ -81,21 +81,21 @@ test.describe('cli codegen', () => {
await recorder.setContentAndWait(``); await recorder.setContentAndWait(``);
await page.context().newPage(); await page.context().newPage();
await recorder.page.close(); await recorder.page.close();
const sources = await recorder.waitForOutput('<javascript>', 'page.close();'); const sources = await recorder.waitForOutput('JavaScript', 'page.close();');
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
await page.close();`); await page.close();`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
page.close();`); page.close();`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
page.close()`); page.close()`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
await page.close()`); await page.close()`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
await page.CloseAsync();`); await page.CloseAsync();`);
}); });
@ -110,7 +110,7 @@ test.describe('cli codegen', () => {
const selector = await recorder.hoverOverElement('html'); const selector = await recorder.hoverOverElement('html');
expect(selector).toBe('html'); expect(selector).toBe('html');
await recorder.page.close(); await recorder.page.close();
await recorder.waitForOutput('<javascript>', 'page.close();'); await recorder.waitForOutput('JavaScript', 'page.close();');
expect(errors.length).toBe(0); expect(errors.length).toBe(0);
}); });
@ -128,25 +128,25 @@ test.describe('cli codegen', () => {
await page.setInputFiles('input[type=file]', asset('file-to-upload.txt')); await page.setInputFiles('input[type=file]', asset('file-to-upload.txt'));
await page.click('input[type=file]'); await page.click('input[type=file]');
const sources = await recorder.waitForOutput('<javascript>', 'setInputFiles'); const sources = await recorder.waitForOutput('JavaScript', 'setInputFiles');
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Upload file-to-upload.txt // Upload file-to-upload.txt
await page.setInputFiles('input[type="file"]', 'file-to-upload.txt');`); await page.setInputFiles('input[type="file"]', 'file-to-upload.txt');`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Upload file-to-upload.txt // Upload file-to-upload.txt
page.setInputFiles("input[type=\\\"file\\\"]", Paths.get("file-to-upload.txt"));`); page.setInputFiles("input[type=\\\"file\\\"]", Paths.get("file-to-upload.txt"));`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Upload file-to-upload.txt # Upload file-to-upload.txt
page.set_input_files(\"input[type=\\\"file\\\"]\", \"file-to-upload.txt\")`); page.set_input_files(\"input[type=\\\"file\\\"]\", \"file-to-upload.txt\")`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Upload file-to-upload.txt # Upload file-to-upload.txt
await page.set_input_files(\"input[type=\\\"file\\\"]\", \"file-to-upload.txt\")`); await page.set_input_files(\"input[type=\\\"file\\\"]\", \"file-to-upload.txt\")`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Upload file-to-upload.txt // Upload file-to-upload.txt
await page.SetInputFilesAsync(\"input[type=\\\"file\\\"]\", new[] { \"file-to-upload.txt\" });`); await page.SetInputFilesAsync(\"input[type=\\\"file\\\"]\", new[] { \"file-to-upload.txt\" });`);
}); });
@ -165,25 +165,25 @@ test.describe('cli codegen', () => {
await page.setInputFiles('input[type=file]', [asset('file-to-upload.txt'), asset('file-to-upload-2.txt')]); await page.setInputFiles('input[type=file]', [asset('file-to-upload.txt'), asset('file-to-upload-2.txt')]);
await page.click('input[type=file]'); await page.click('input[type=file]');
const sources = await recorder.waitForOutput('<javascript>', 'setInputFiles'); const sources = await recorder.waitForOutput('JavaScript', 'setInputFiles');
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Upload file-to-upload.txt, file-to-upload-2.txt // Upload file-to-upload.txt, file-to-upload-2.txt
await page.setInputFiles('input[type=\"file\"]', ['file-to-upload.txt', 'file-to-upload-2.txt']);`); await page.setInputFiles('input[type=\"file\"]', ['file-to-upload.txt', 'file-to-upload-2.txt']);`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Upload file-to-upload.txt, file-to-upload-2.txt // Upload file-to-upload.txt, file-to-upload-2.txt
page.setInputFiles("input[type=\\\"file\\\"]", new Path[] {Paths.get("file-to-upload.txt"), Paths.get("file-to-upload-2.txt")});`); page.setInputFiles("input[type=\\\"file\\\"]", new Path[] {Paths.get("file-to-upload.txt"), Paths.get("file-to-upload-2.txt")});`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Upload file-to-upload.txt, file-to-upload-2.txt # Upload file-to-upload.txt, file-to-upload-2.txt
page.set_input_files(\"input[type=\\\"file\\\"]\", [\"file-to-upload.txt\", \"file-to-upload-2.txt\"]`); page.set_input_files(\"input[type=\\\"file\\\"]\", [\"file-to-upload.txt\", \"file-to-upload-2.txt\"]`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Upload file-to-upload.txt, file-to-upload-2.txt # Upload file-to-upload.txt, file-to-upload-2.txt
await page.set_input_files(\"input[type=\\\"file\\\"]\", [\"file-to-upload.txt\", \"file-to-upload-2.txt\"]`); await page.set_input_files(\"input[type=\\\"file\\\"]\", [\"file-to-upload.txt\", \"file-to-upload-2.txt\"]`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Upload file-to-upload.txt, file-to-upload-2.txt // Upload file-to-upload.txt, file-to-upload-2.txt
await page.SetInputFilesAsync(\"input[type=\\\"file\\\"]\", new[] { \"file-to-upload.txt\", \"file-to-upload-2.txt\" });`); await page.SetInputFilesAsync(\"input[type=\\\"file\\\"]\", new[] { \"file-to-upload.txt\", \"file-to-upload-2.txt\" });`);
}); });
@ -202,25 +202,25 @@ test.describe('cli codegen', () => {
await page.setInputFiles('input[type=file]', []); await page.setInputFiles('input[type=file]', []);
await page.click('input[type=file]'); await page.click('input[type=file]');
const sources = await recorder.waitForOutput('<javascript>', 'setInputFiles'); const sources = await recorder.waitForOutput('JavaScript', 'setInputFiles');
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Clear selected files // Clear selected files
await page.setInputFiles('input[type=\"file\"]', []);`); await page.setInputFiles('input[type=\"file\"]', []);`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Clear selected files // Clear selected files
page.setInputFiles("input[type=\\\"file\\\"]", new Path[0]);`); page.setInputFiles("input[type=\\\"file\\\"]", new Path[0]);`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Clear selected files # Clear selected files
page.set_input_files(\"input[type=\\\"file\\\"]\", []`); page.set_input_files(\"input[type=\\\"file\\\"]\", []`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Clear selected files # Clear selected files
await page.set_input_files(\"input[type=\\\"file\\\"]\", []`); await page.set_input_files(\"input[type=\\\"file\\\"]\", []`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Clear selected files // Clear selected files
await page.SetInputFilesAsync(\"input[type=\\\"file\\\"]\", new[] { });`); await page.SetInputFilesAsync(\"input[type=\\\"file\\\"]\", new[] { });`);
@ -248,50 +248,50 @@ test.describe('cli codegen', () => {
page.waitForEvent('download'), page.waitForEvent('download'),
page.click('text=Download') page.click('text=Download')
]); ]);
const sources = await recorder.waitForOutput('<javascript>', 'waitForEvent'); const sources = await recorder.waitForOutput('JavaScript', 'waitForEvent');
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
const context = await browser.newContext({ const context = await browser.newContext({
acceptDownloads: true acceptDownloads: true
});`); });`);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Click text=Download // Click text=Download
const [download] = await Promise.all([ const [download] = await Promise.all([
page.waitForEvent('download'), page.waitForEvent('download'),
page.click('text=Download') page.click('text=Download')
]);`); ]);`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
BrowserContext context = browser.newContext(new Browser.NewContextOptions() BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.setAcceptDownloads(true));`); .setAcceptDownloads(true));`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Click text=Download // Click text=Download
Download download = page.waitForDownload(() -> { Download download = page.waitForDownload(() -> {
page.click("text=Download"); page.click("text=Download");
});`); });`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
context = browser.new_context(accept_downloads=True)`); context = browser.new_context(accept_downloads=True)`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Click text=Download # Click text=Download
with page.expect_download() as download_info: with page.expect_download() as download_info:
page.click(\"text=Download\") page.click(\"text=Download\")
download = download_info.value`); download = download_info.value`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
context = await browser.new_context(accept_downloads=True)`); context = await browser.new_context(accept_downloads=True)`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Click text=Download # Click text=Download
async with page.expect_download() as download_info: async with page.expect_download() as download_info:
await page.click(\"text=Download\") await page.click(\"text=Download\")
download = await download_info.value`); download = await download_info.value`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
var context = await browser.NewContextAsync(new BrowserNewContextOptions var context = await browser.NewContextAsync(new BrowserNewContextOptions
{ {
AcceptDownloads = true, AcceptDownloads = true,
});`); });`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Click text=Download // Click text=Download
var download1 = await page.RunAndWaitForDownloadAsync(async () => var download1 = await page.RunAndWaitForDownloadAsync(async () =>
{ {
@ -311,9 +311,9 @@ test.describe('cli codegen', () => {
}); });
await page.click('text=click me'); await page.click('text=click me');
const sources = await recorder.waitForOutput('<javascript>', 'once'); const sources = await recorder.waitForOutput('JavaScript', 'once');
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Click text=click me // Click text=click me
page.once('dialog', dialog => { page.once('dialog', dialog => {
console.log(\`Dialog message: \${dialog.message()}\`); console.log(\`Dialog message: \${dialog.message()}\`);
@ -321,7 +321,7 @@ test.describe('cli codegen', () => {
}); });
await page.click('text=click me');`); await page.click('text=click me');`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Click text=click me // Click text=click me
page.onceDialog(dialog -> { page.onceDialog(dialog -> {
System.out.println(String.format("Dialog message: %s", dialog.message())); System.out.println(String.format("Dialog message: %s", dialog.message()));
@ -329,17 +329,17 @@ test.describe('cli codegen', () => {
}); });
page.click("text=click me");`); page.click("text=click me");`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Click text=click me # Click text=click me
page.once(\"dialog\", lambda dialog: dialog.dismiss()) page.once(\"dialog\", lambda dialog: dialog.dismiss())
page.click(\"text=click me\")`); page.click(\"text=click me\")`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Click text=click me # Click text=click me
page.once(\"dialog\", lambda dialog: dialog.dismiss()) page.once(\"dialog\", lambda dialog: dialog.dismiss())
await page.click(\"text=click me\")`); await page.click(\"text=click me\")`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Click text=click me // Click text=click me
void page_Dialog1_EventHandler(object sender, IDialog dialog) void page_Dialog1_EventHandler(object sender, IDialog dialog)
{ {
@ -364,7 +364,7 @@ test.describe('cli codegen', () => {
</script>`, server.PREFIX); </script>`, server.PREFIX);
for (let i = 1; i < 3; ++i) { for (let i = 1; i < 3; ++i) {
await page.evaluate('pushState()'); await page.evaluate('pushState()');
await recorder.waitForOutput('<javascript>', `await page.goto('${server.PREFIX}/#seqNum=${i}');`); await recorder.waitForOutput('JavaScript', `await page.goto('${server.PREFIX}/#seqNum=${i}');`);
} }
}); });
@ -378,23 +378,23 @@ test.describe('cli codegen', () => {
expect(selector).toBe('text=link'); expect(selector).toBe('text=link');
await page.click('a', { modifiers: [ platform === 'darwin' ? 'Meta' : 'Control'] }); await page.click('a', { modifiers: [ platform === 'darwin' ? 'Meta' : 'Control'] });
const sources = await recorder.waitForOutput('<javascript>', 'page1'); const sources = await recorder.waitForOutput('JavaScript', 'page1');
if (browserName === 'chromium') { if (browserName === 'chromium') {
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Open new page // Open new page
const page1 = await context.newPage(); const page1 = await context.newPage();
await page1.goto('about:blank?foo');`); await page1.goto('about:blank?foo');`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Open new page # Open new page
page1 = await context.new_page() page1 = await context.new_page()
await page1.goto("about:blank?foo")`); await page1.goto("about:blank?foo")`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Open new page // Open new page
var page1 = await context.NewPageAsync(); var page1 = await context.NewPageAsync();
await page1.GotoAsync("about:blank?foo");`); await page1.GotoAsync("about:blank?foo");`);
} else if (browserName === 'firefox') { } else if (browserName === 'firefox') {
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Click text=link // Click text=link
const [page1] = await Promise.all([ const [page1] = await Promise.all([
page.waitForEvent('popup'), page.waitForEvent('popup'),
@ -422,26 +422,26 @@ test.describe('cli codegen', () => {
await recorder.setPageContentAndWait(popup2, '<input id=name>'); await recorder.setPageContentAndWait(popup2, '<input id=name>');
await popup1.type('input', 'TextA'); await popup1.type('input', 'TextA');
await recorder.waitForOutput('<javascript>', 'TextA'); await recorder.waitForOutput('JavaScript', 'TextA');
await popup2.type('input', 'TextB'); await popup2.type('input', 'TextB');
await recorder.waitForOutput('<javascript>', 'TextB'); await recorder.waitForOutput('JavaScript', 'TextB');
const sources = recorder.sources(); const sources = recorder.sources();
expect(sources.get('<javascript>').text).toContain(`await page1.fill('input', 'TextA');`); expect(sources.get('JavaScript').text).toContain(`await page1.fill('input', 'TextA');`);
expect(sources.get('<javascript>').text).toContain(`await page2.fill('input', 'TextB');`); expect(sources.get('JavaScript').text).toContain(`await page2.fill('input', 'TextB');`);
expect(sources.get('<java>').text).toContain(`page1.fill("input", "TextA");`); expect(sources.get('Java').text).toContain(`page1.fill("input", "TextA");`);
expect(sources.get('<java>').text).toContain(`page2.fill("input", "TextB");`); expect(sources.get('Java').text).toContain(`page2.fill("input", "TextB");`);
expect(sources.get('<python>').text).toContain(`page1.fill(\"input\", \"TextA\")`); expect(sources.get('Python').text).toContain(`page1.fill(\"input\", \"TextA\")`);
expect(sources.get('<python>').text).toContain(`page2.fill(\"input\", \"TextB\")`); expect(sources.get('Python').text).toContain(`page2.fill(\"input\", \"TextB\")`);
expect(sources.get('<async python>').text).toContain(`await page1.fill(\"input\", \"TextA\")`); expect(sources.get('Python Async').text).toContain(`await page1.fill(\"input\", \"TextA\")`);
expect(sources.get('<async python>').text).toContain(`await page2.fill(\"input\", \"TextB\")`); expect(sources.get('Python Async').text).toContain(`await page2.fill(\"input\", \"TextB\")`);
expect(sources.get('<csharp>').text).toContain(`await page1.FillAsync(\"input\", \"TextA\");`); expect(sources.get('C#').text).toContain(`await page1.FillAsync(\"input\", \"TextA\");`);
expect(sources.get('<csharp>').text).toContain(`await page2.FillAsync(\"input\", \"TextB\");`); expect(sources.get('C#').text).toContain(`await page2.FillAsync(\"input\", \"TextB\");`);
}); });
test('click should emit events in order', async ({ page, openRecorder }) => { test('click should emit events in order', async ({ page, openRecorder }) => {
@ -463,7 +463,7 @@ test.describe('cli codegen', () => {
}); });
await Promise.all([ await Promise.all([
page.click('button'), page.click('button'),
recorder.waitForOutput('<javascript>', 'page.click') recorder.waitForOutput('JavaScript', 'page.click')
]); ]);
expect(messages).toEqual(['mousedown', 'mouseup', 'click']); expect(messages).toEqual(['mousedown', 'mouseup', 'click']);
}); });
@ -513,83 +513,83 @@ test.describe('cli codegen', () => {
const otherFrame = page.frames().find(f => f !== page.mainFrame() && !f.name()); const otherFrame = page.frames().find(f => f !== page.mainFrame() && !f.name());
let [sources] = await Promise.all([ let [sources] = await Promise.all([
recorder.waitForOutput('<javascript>', 'one'), recorder.waitForOutput('JavaScript', 'one'),
frameOne.click('div'), frameOne.click('div'),
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Click text=Hi, I'm frame // Click text=Hi, I'm frame
await page.frame({ await page.frame({
name: 'one' name: 'one'
}).click('text=Hi, I\\'m frame');`); }).click('text=Hi, I\\'m frame');`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Click text=Hi, I'm frame // Click text=Hi, I'm frame
page.frame("one").click("text=Hi, I'm frame");`); page.frame("one").click("text=Hi, I'm frame");`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Click text=Hi, I'm frame # Click text=Hi, I'm frame
page.frame(name=\"one\").click(\"text=Hi, I'm frame\")`); page.frame(name=\"one\").click(\"text=Hi, I'm frame\")`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Click text=Hi, I'm frame # Click text=Hi, I'm frame
await page.frame(name=\"one\").click(\"text=Hi, I'm frame\")`); await page.frame(name=\"one\").click(\"text=Hi, I'm frame\")`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Click text=Hi, I'm frame // Click text=Hi, I'm frame
await page.Frame(\"one\").ClickAsync(\"text=Hi, I'm frame\");`); await page.Frame(\"one\").ClickAsync(\"text=Hi, I'm frame\");`);
[sources] = await Promise.all([ [sources] = await Promise.all([
recorder.waitForOutput('<javascript>', 'two'), recorder.waitForOutput('JavaScript', 'two'),
frameTwo.click('div'), frameTwo.click('div'),
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Click text=Hi, I'm frame // Click text=Hi, I'm frame
await page.frame({ await page.frame({
name: 'two' name: 'two'
}).click('text=Hi, I\\'m frame');`); }).click('text=Hi, I\\'m frame');`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Click text=Hi, I'm frame // Click text=Hi, I'm frame
page.frame("two").click("text=Hi, I'm frame");`); page.frame("two").click("text=Hi, I'm frame");`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Click text=Hi, I'm frame # Click text=Hi, I'm frame
page.frame(name=\"two\").click(\"text=Hi, I'm frame\")`); page.frame(name=\"two\").click(\"text=Hi, I'm frame\")`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Click text=Hi, I'm frame # Click text=Hi, I'm frame
await page.frame(name=\"two\").click(\"text=Hi, I'm frame\")`); await page.frame(name=\"two\").click(\"text=Hi, I'm frame\")`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Click text=Hi, I'm frame // Click text=Hi, I'm frame
await page.Frame(\"two\").ClickAsync(\"text=Hi, I'm frame\");`); await page.Frame(\"two\").ClickAsync(\"text=Hi, I'm frame\");`);
[sources] = await Promise.all([ [sources] = await Promise.all([
recorder.waitForOutput('<javascript>', 'url: \''), recorder.waitForOutput('JavaScript', 'url: \''),
otherFrame.click('div'), otherFrame.click('div'),
]); ]);
expect(sources.get('<javascript>').text).toContain(` expect(sources.get('JavaScript').text).toContain(`
// Click text=Hi, I'm frame // Click text=Hi, I'm frame
await page.frame({ await page.frame({
url: 'http://localhost:${server.PORT}/frames/frame.html' url: 'http://localhost:${server.PORT}/frames/frame.html'
}).click('text=Hi, I\\'m frame');`); }).click('text=Hi, I\\'m frame');`);
expect(sources.get('<java>').text).toContain(` expect(sources.get('Java').text).toContain(`
// Click text=Hi, I'm frame // Click text=Hi, I'm frame
page.frameByUrl("http://localhost:${server.PORT}/frames/frame.html").click("text=Hi, I'm frame");`); page.frameByUrl("http://localhost:${server.PORT}/frames/frame.html").click("text=Hi, I'm frame");`);
expect(sources.get('<python>').text).toContain(` expect(sources.get('Python').text).toContain(`
# Click text=Hi, I'm frame # Click text=Hi, I'm frame
page.frame(url=\"http://localhost:${server.PORT}/frames/frame.html\").click(\"text=Hi, I'm frame\")`); page.frame(url=\"http://localhost:${server.PORT}/frames/frame.html\").click(\"text=Hi, I'm frame\")`);
expect(sources.get('<async python>').text).toContain(` expect(sources.get('Python Async').text).toContain(`
# Click text=Hi, I'm frame # Click text=Hi, I'm frame
await page.frame(url=\"http://localhost:${server.PORT}/frames/frame.html\").click(\"text=Hi, I'm frame\")`); await page.frame(url=\"http://localhost:${server.PORT}/frames/frame.html\").click(\"text=Hi, I'm frame\")`);
expect(sources.get('<csharp>').text).toContain(` expect(sources.get('C#').text).toContain(`
// Click text=Hi, I'm frame // Click text=Hi, I'm frame
await page.FrameByUrl(\"http://localhost:${server.PORT}/frames/frame.html\").ClickAsync(\"text=Hi, I'm frame\");`); await page.FrameByUrl(\"http://localhost:${server.PORT}/frames/frame.html\").ClickAsync(\"text=Hi, I'm frame\");`);
}); });
@ -610,7 +610,7 @@ test.describe('cli codegen', () => {
await page.evaluate('pushState()'); await page.evaluate('pushState()');
await page.goto(server.PREFIX + '/page2.html'); await page.goto(server.PREFIX + '/page2.html');
await recorder.waitForOutput('<javascript>', `await page.goto('${server.PREFIX}/page2.html');`); await recorder.waitForOutput('JavaScript', `await page.goto('${server.PREFIX}/page2.html');`);
}); });
test('should record slow navigation signal after mouse move', async ({ page, openRecorder, server }) => { test('should record slow navigation signal after mouse move', async ({ page, openRecorder, server }) => {
@ -632,9 +632,9 @@ test.describe('cli codegen', () => {
const [, sources] = await Promise.all([ const [, sources] = await Promise.all([
// This will click, finish the click, then mouse move, then navigate. // This will click, finish the click, then mouse move, then navigate.
page.click('button'), page.click('button'),
recorder.waitForOutput('<javascript>', 'waitForNavigation'), recorder.waitForOutput('JavaScript', 'waitForNavigation'),
]); ]);
expect(sources.get('<javascript>').text).toContain(`page.waitForNavigation(/*{ url: '${server.EMPTY_PAGE}' }*/)`); expect(sources.get('JavaScript').text).toContain(`page.waitForNavigation(/*{ url: '${server.EMPTY_PAGE}' }*/)`);
}); });
}); });

View file

@ -25,7 +25,7 @@ const launchOptions = (channel: string) => {
}; };
test('should print the correct imports and context options', async ({ browserName, channel, runCLI }) => { test('should print the correct imports and context options', async ({ browserName, channel, runCLI }) => {
const cli = runCLI([emptyHTML]); const cli = runCLI(['--target=javascript', emptyHTML]);
const expectedResult = `const { ${browserName} } = require('playwright'); const expectedResult = `const { ${browserName} } = require('playwright');
(async () => { (async () => {
@ -38,7 +38,7 @@ test('should print the correct imports and context options', async ({ browserNam
}); });
test('should print the correct context options for custom settings', async ({ browserName, channel, runCLI }) => { test('should print the correct context options for custom settings', async ({ browserName, channel, runCLI }) => {
const cli = runCLI(['--color-scheme=light', emptyHTML]); const cli = runCLI(['--color-scheme=light', '--target=javascript', emptyHTML]);
const expectedResult = `const { ${browserName} } = require('playwright'); const expectedResult = `const { ${browserName} } = require('playwright');
(async () => { (async () => {
@ -56,7 +56,7 @@ test('should print the correct context options for custom settings', async ({ br
test('should print the correct context options when using a device', async ({ browserName, channel, runCLI }) => { test('should print the correct context options when using a device', async ({ browserName, channel, runCLI }) => {
test.skip(browserName !== 'chromium'); test.skip(browserName !== 'chromium');
const cli = runCLI(['--device=Pixel 2', emptyHTML]); const cli = runCLI(['--device=Pixel 2', '--target=javascript', emptyHTML]);
const expectedResult = `const { chromium, devices } = require('playwright'); const expectedResult = `const { chromium, devices } = require('playwright');
(async () => { (async () => {
@ -73,7 +73,7 @@ test('should print the correct context options when using a device', async ({ br
test('should print the correct context options when using a device and additional options', async ({ browserName, channel, runCLI }) => { test('should print the correct context options when using a device and additional options', async ({ browserName, channel, runCLI }) => {
test.skip(browserName !== 'webkit'); test.skip(browserName !== 'webkit');
const cli = runCLI(['--color-scheme=light', '--device=iPhone 11', emptyHTML]); const cli = runCLI(['--color-scheme=light', '--device=iPhone 11', '--target=javascript', emptyHTML]);
const expectedResult = `const { webkit, devices } = require('playwright'); const expectedResult = `const { webkit, devices } = require('playwright');
(async () => { (async () => {
@ -90,7 +90,7 @@ test('should print the correct context options when using a device and additiona
test('should save the codegen output to a file if specified', async ({ browserName, channel, runCLI }, testInfo) => { test('should save the codegen output to a file if specified', async ({ browserName, channel, runCLI }, testInfo) => {
const tmpFile = testInfo.outputPath('script.js'); const tmpFile = testInfo.outputPath('script.js');
const cli = runCLI(['--output', tmpFile, emptyHTML]); const cli = runCLI(['--output', tmpFile, '--target=javascript', emptyHTML]);
await cli.exited; await cli.exited;
const content = fs.readFileSync(tmpFile); const content = fs.readFileSync(tmpFile);
expect(content.toString()).toBe(`const { ${browserName} } = require('playwright'); expect(content.toString()).toBe(`const { ${browserName} } = require('playwright');
@ -120,7 +120,7 @@ test('should print load/save storageState', async ({ browserName, channel, runCL
const loadFileName = testInfo.outputPath('load.json'); const loadFileName = testInfo.outputPath('load.json');
const saveFileName = testInfo.outputPath('save.json'); const saveFileName = testInfo.outputPath('save.json');
await fs.promises.writeFile(loadFileName, JSON.stringify({ cookies: [], origins: [] }), 'utf8'); await fs.promises.writeFile(loadFileName, JSON.stringify({ cookies: [], origins: [] }), 'utf8');
const cli = runCLI([`--load-storage=${loadFileName}`, `--save-storage=${saveFileName}`, emptyHTML]); const cli = runCLI([`--load-storage=${loadFileName}`, `--save-storage=${saveFileName}`, '--target=javascript', emptyHTML]);
const expectedResult1 = `const { ${browserName} } = require('playwright'); const expectedResult1 = `const { ${browserName} } = require('playwright');
(async () => { (async () => {

View file

@ -0,0 +1,93 @@
/**
* 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 } from './inspectorTest';
const emptyHTML = new URL('file://' + path.join(__dirname, '..', 'assets', 'empty.html')).toString();
test('should print the correct imports and context options', async ({ runCLI }) => {
const cli = runCLI([emptyHTML]);
const expectedResult = `const { test, expect } = require('@playwright/test');
test('test', async ({ page }) => {
});`;
await cli.waitFor(expectedResult);
expect(cli.text()).toContain(expectedResult);
});
test('should print the correct context options for custom settings', async ({ browserName, channel, runCLI }) => {
const cli = runCLI(['--color-scheme=light', emptyHTML]);
const expectedResult = `const { test, expect } = require('@playwright/test');
test.use({
colorScheme: 'light'
});
test('test', async ({ page }) => {`;
await cli.waitFor(expectedResult);
expect(cli.text()).toContain(expectedResult);
});
test('should print the correct context options when using a device', async ({ browserName, channel, runCLI }) => {
test.skip(browserName !== 'chromium');
const cli = runCLI(['--device=Pixel 2', emptyHTML]);
const expectedResult = `const { test, expect, devices } = require('@playwright/test');
test.use({
...devices['Pixel 2'],
});
test('test', async ({ page }) => {`;
await cli.waitFor(expectedResult);
expect(cli.text()).toContain(expectedResult);
});
test('should print the correct context options when using a device and additional options', async ({ browserName, channel, runCLI }) => {
test.skip(browserName !== 'webkit');
const cli = runCLI(['--color-scheme=light', '--device=iPhone 11', emptyHTML]);
const expectedResult = `const { test, expect, devices } = require('@playwright/test');
test.use({
...devices['iPhone 11'],
colorScheme: 'light'
});
test('test', async ({ page }) => {`;
await cli.waitFor(expectedResult);
expect(cli.text()).toContain(expectedResult);
});
test('should print load storageState', async ({ browserName, channel, runCLI }, testInfo) => {
const loadFileName = testInfo.outputPath('load.json');
const saveFileName = testInfo.outputPath('save.json');
await fs.promises.writeFile(loadFileName, JSON.stringify({ cookies: [], origins: [] }), 'utf8');
const cli = runCLI([`--load-storage=${loadFileName}`, emptyHTML]);
const expectedResult = `const { test, expect } = require('@playwright/test');
test.use({
storageState: '${loadFileName}'
});
test('test', async ({ page }) => {`;
await cli.waitFor(expectedResult);
});