Skip to content

Commit

Permalink
fix: fix the cli tests, generate snake python (#5003)
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelfeldman authored Jan 13, 2021
1 parent decf373 commit 9a9ac60
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 78 deletions.
2 changes: 1 addition & 1 deletion src/cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ async function codegen(options: Options, url: string | undefined, target: string
if (process.env.PWTRACE)
contextOptions.recordVideo = { dir: path.join(process.cwd(), '.trace') };

const outputs: CodeGeneratorOutput[] = [new TerminalOutput(process.stdout, languageGenerator.highligherType())];
const outputs: CodeGeneratorOutput[] = [TerminalOutput.create(process.stdout, languageGenerator.highlighterType())];
if (outputFile)
outputs.push(new FileOutput(outputFile));
const output = new OutputMultiplexer(outputs);
Expand Down
4 changes: 2 additions & 2 deletions src/cli/codegen/languages/csharp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { MouseClickOptions, toModifiers } from '../utils';

export class CSharpLanguageGenerator implements LanguageGenerator {

highligherType(): HighlighterType {
highlighterType(): HighlighterType {
return 'csharp';
}

Expand Down Expand Up @@ -155,7 +155,7 @@ export class CSharpLanguageGenerator implements LanguageGenerator {
}

generateFooter(saveStorage: string | undefined): string {
const storageStateLine = saveStorage ? `\nawait context.StorageStateAsync(path: "${saveStorage}")` : '';
const storageStateLine = saveStorage ? `\nawait context.StorageStateAsync(path: "${saveStorage}");` : '';
return `// ---------------------${storageStateLine}`;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/cli/codegen/languages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface LanguageGenerator {
generateHeader(browserName: string, launchOptions: LaunchOptions, contextOptions: BrowserContextOptions, deviceName?: string): string;
generateAction(actionInContext: ActionInContext, performingAction: boolean): string;
generateFooter(saveStorage: string | undefined): string;
highligherType(): HighlighterType;
highlighterType(): HighlighterType;
}

export { JavaScriptLanguageGenerator } from './javascript';
4 changes: 2 additions & 2 deletions src/cli/codegen/languages/javascript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { MouseClickOptions, toModifiers } from '../utils';

export class JavaScriptLanguageGenerator implements LanguageGenerator {

highligherType(): HighlighterType {
highlighterType(): HighlighterType {
return 'javascript';
}

Expand Down Expand Up @@ -157,7 +157,7 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator {
}

generateFooter(saveStorage: string | undefined): string {
const storageStateLine = saveStorage ? `\n await context.storageState({ path: '${saveStorage}' })` : '';
const storageStateLine = saveStorage ? `\n await context.storageState({ path: '${saveStorage}' });` : '';
return ` // ---------------------${storageStateLine}
await context.close();
await browser.close();
Expand Down
19 changes: 12 additions & 7 deletions src/cli/codegen/languages/python.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class PythonLanguageGenerator implements LanguageGenerator {
this._asyncPrefix = isAsync ? 'async ' : '';
}

highligherType(): HighlighterType {
highlighterType(): HighlighterType {
return 'python';
}

Expand All @@ -43,7 +43,7 @@ export class PythonLanguageGenerator implements LanguageGenerator {
formatter.add('# ' + actionTitle(action));

if (action.name === 'openPage') {
formatter.add(`${pageAlias} = ${this._awaitPrefix}context.newPage()`);
formatter.add(`${pageAlias} = ${this._awaitPrefix}context.new_page()`);
if (action.url && action.url !== 'about:blank' && action.url !== 'chrome://newtab/')
formatter.add(`${pageAlias}.goto('${action.url}')`);
return formatter.format();
Expand Down Expand Up @@ -155,21 +155,21 @@ from playwright.async_api import async_playwright
async def run(playwright) {
browser = await playwright.${browserName}.launch(${formatOptions(launchOptions, false)})
context = await browser.newContext(${formatContextOptions(contextOptions, deviceName)})`);
context = await browser.new_context(${formatContextOptions(contextOptions, deviceName)})`);
} else {
formatter.add(`
from playwright.sync_api import sync_playwright
def run(playwright) {
browser = playwright.${browserName}.launch(${formatOptions(launchOptions, false)})
context = browser.newContext(${formatContextOptions(contextOptions, deviceName)})`);
context = browser.new_context(${formatContextOptions(contextOptions, deviceName)})`);
}
return formatter.format();
}

generateFooter(saveStorage: string | undefined): string {
if (this._isAsync) {
const storageStateLine = saveStorage ? `\n await context.storageState(path="${saveStorage}")` : '';
const storageStateLine = saveStorage ? `\n await context.storage_state(path="${saveStorage}")` : '';
return ` # ---------------------${storageStateLine}
await context.close()
await browser.close()
Expand All @@ -179,7 +179,7 @@ async def main():
await run(playwright)
asyncio.run(main())`;
} else {
const storageStateLine = saveStorage ? `\n context.storageState(path="${saveStorage}")` : '';
const storageStateLine = saveStorage ? `\n context.storage_state(path="${saveStorage}")` : '';
return ` # ---------------------${storageStateLine}
context.close()
browser.close()
Expand All @@ -204,11 +204,16 @@ function formatValue(value: any): string {
return String(value);
}

function toSnakeCase(name: string): string {
const toSnakeCaseRegex = /((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z]))/g;
return name.replace(toSnakeCaseRegex, `_$1`).toLowerCase();
}

function formatOptions(value: any, hasArguments: boolean): string {
const keys = Object.keys(value);
if (!keys.length)
return '';
return (hasArguments ? ', ' : '') + keys.map(key => `${key}=${formatValue(value[key])}`).join(', ');
return (hasArguments ? ', ' : '') + keys.map(key => `${toSnakeCase(key)}=${formatValue(value[key])}`).join(', ');
}

function formatContextOptions(options: BrowserContextOptions, deviceName: string | undefined): string {
Expand Down
54 changes: 44 additions & 10 deletions src/cli/codegen/outputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,31 +42,45 @@ export class OutputMultiplexer implements CodeGeneratorOutput {
}
}

export class FileOutput implements CodeGeneratorOutput {
private _fileName: string;
private _lines: string[];
constructor(fileName: string) {
this._fileName = fileName;
this._lines = [];
}
export class BufferOutput {
lines: string[] = [];

printLn(text: string) {
this._lines.push(...text.trimEnd().split('\n'));
this.lines.push(...text.trimEnd().split('\n'));
}

popLn(text: string) {
this._lines.length -= text.trimEnd().split('\n').length;
this.lines.length -= text.trimEnd().split('\n').length;
}

buffer(): string {
return this.lines.join('\n');
}
}

export class FileOutput extends BufferOutput implements CodeGeneratorOutput {
private _fileName: string;

constructor(fileName: string) {
super();
this._fileName = fileName;
}

flush() {
fs.writeFileSync(this._fileName, this._lines.join('\n'));
fs.writeFileSync(this._fileName, this.buffer());
}
}

export class TerminalOutput implements CodeGeneratorOutput {
private _output: Writable
private _language: string;

static create(output: Writable, language: string) {
if (process.stdout.columns)
return new TerminalOutput(output, language);
return new FlushingTerminalOutput(output);
}

constructor(output: Writable, language: string) {
this._output = output;
this._language = language;
Expand Down Expand Up @@ -112,3 +126,23 @@ export class TerminalOutput implements CodeGeneratorOutput {

flush() {}
}

export class FlushingTerminalOutput extends BufferOutput implements CodeGeneratorOutput {
private _output: Writable

constructor(output: Writable) {
super();
this._output = output;
}

printLn(text: string) {
super.printLn(text);
this._output.write('-------------8<-------------\n');
this._output.write(this.buffer() + '\n');
this._output.write('-------------8<-------------\n');
}

flush() {
this._output.write(this.buffer() + '\n');
}
}
2 changes: 1 addition & 1 deletion test/cli/cli-codegen-csharp.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ it('should print load/save storageState', async ({ runCLI, testInfo }) => {
const cli = runCLI([`--load-storage=${loadFileName}`, `--save-storage=${saveFileName}`, 'codegen', '--target=csharp', emptyHTML]);
const expectedResult = `await Playwright.InstallAsync();
using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync();
await using var browser = await playwright.Chromium.LaunchAsync(headless: false);
var context = await browser.NewContextAsync(storageState: "${loadFileName}");
// Open new page
Expand Down
4 changes: 2 additions & 2 deletions test/cli/cli-codegen-javascript.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ it('should save the codegen output to a file if specified', async ({ runCLI, tes
const tmpFile = testInfo.outputPath('script.js');
const cli = runCLI(['codegen', '--output', tmpFile, emptyHTML]);
await cli.exited;
const content = await fs.readFileSync(tmpFile);
const content = fs.readFileSync(tmpFile);
expect(content.toString()).toBe(`const { chromium } = require('playwright');
(async () => {
Expand Down Expand Up @@ -115,7 +115,7 @@ it('should print load/save storageState', async ({ runCLI, testInfo }) => {
const saveFileName = testInfo.outputPath('save.json');
await fs.promises.writeFile(loadFileName, JSON.stringify({ cookies: [], origins: [] }), 'utf8');
const cli = runCLI([`--load-storage=${loadFileName}`, `--save-storage=${saveFileName}`, 'codegen', emptyHTML]);
const expectedResult = `const { chromium, devices } = require('playwright');
const expectedResult = `const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({
Expand Down
42 changes: 21 additions & 21 deletions test/cli/cli-codegen-python-async.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ from playwright.async_api import async_playwright
async def run(playwright):
browser = await playwright.chromium.launch(headless=False)
context = await browser.newContext()`;
context = await browser.new_context()`;
await cli.waitFor(expectedResult);
expect(cli.text()).toContain(expectedResult);
});
Expand All @@ -41,7 +41,7 @@ from playwright.async_api import async_playwright
async def run(playwright):
browser = await playwright.chromium.launch(headless=False)
context = await browser.newContext(colorScheme="light")`;
context = await browser.new_context(color_scheme="light")`;
await cli.waitFor(expectedResult);
expect(cli.text()).toContain(expectedResult);
});
Expand All @@ -53,7 +53,7 @@ from playwright.async_api import async_playwright
async def run(playwright):
browser = await playwright.chromium.launch(headless=False)
context = await browser.newContext(**playwright.devices["Pixel 2"])`;
context = await browser.new_context(**playwright.devices["Pixel 2"])`;
await cli.waitFor(expectedResult);
expect(cli.text()).toContain(expectedResult);
});
Expand All @@ -65,7 +65,7 @@ from playwright.async_api import async_playwright
async def run(playwright):
browser = await playwright.chromium.launch(headless=False)
context = await browser.newContext(**playwright.devices["Pixel 2"], colorScheme="light")`;
context = await browser.new_context(**playwright.devices["Pixel 2"], color_scheme="light")`;
await cli.waitFor(expectedResult);
expect(cli.text()).toContain(expectedResult);
});
Expand All @@ -80,10 +80,10 @@ from playwright.async_api import async_playwright
async def run(playwright):
browser = await playwright.chromium.launch(headless=False)
context = await browser.newContext()
context = await browser.new_context()
# Open new page
page = await context.newPage()
page = await context.new_page()
# Go to ${emptyHTML}
await page.goto("${emptyHTML}")
Expand All @@ -101,29 +101,29 @@ async def main():
asyncio.run(main())`);
});

it('should print load/save storageState', async ({ runCLI, testInfo }) => {
it('should print load/save storage_state', async ({ 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}`, `--save-storage=${saveFileName}`, 'codegen', '--target=python-async', emptyHTML]);
const expectedResult = `import asyncio
from playwright.async_api import async_playwright
from playwright.async_api import async_playwright
async def run(playwright):
browser = await playwright.chromium.launch(headless=False)
context = await browser.newContext(storageState="${loadFileName}")
async def run(playwright):
browser = await playwright.chromium.launch(headless=False)
context = await browser.new_context(storage_state="${loadFileName}")
# Open new page
page = await context.newPage()
# Open new page
page = await context.new_page()
# ---------------------
await context.storageState(path="${saveFileName}")
await context.close()
await browser.close()
# ---------------------
await context.storage_state(path="${saveFileName}")
await context.close()
await browser.close()
async def main():
async with async_playwright() as playwright:
await run(playwright)
asyncio.run(main())`;
async def main():
async with async_playwright() as playwright:
await run(playwright)
asyncio.run(main())`;
await cli.waitFor(expectedResult);
});
Loading

0 comments on commit 9a9ac60

Please sign in to comment.