From 6494bb30a03ec7d21df3512d612a45874815c3e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Greffier?= Date: Tue, 20 Feb 2024 20:08:53 +0100 Subject: [PATCH] JUnit codegen (#29424) Codegen for JUnit Fixes https://github.com/microsoft/playwright-java/issues/1039 Following JUnit5 integration https://github.com/microsoft/playwright-java/issues/1369 --- packages/playwright-core/src/cli/program.ts | 2 +- .../playwright-core/src/server/recorder.ts | 3 +- .../src/server/recorder/java.ts | 45 +++++++++++++++++-- .../inspector/cli-codegen-java.spec.ts | 30 +++++++++++++ tests/library/inspector/inspectorTest.ts | 1 + 5 files changed, 76 insertions(+), 5 deletions(-) diff --git a/packages/playwright-core/src/cli/program.ts b/packages/playwright-core/src/cli/program.ts index 5f2767d3f3..c38683a832 100644 --- a/packages/playwright-core/src/cli/program.ts +++ b/packages/playwright-core/src/cli/program.ts @@ -65,7 +65,7 @@ Examples: commandWithOpenOptions('codegen [url]', 'open page and generate code for user actions', [ ['-o, --output ', 'saves the generated script to a file'], - ['--target ', `language to generate, one of javascript, playwright-test, python, python-async, python-pytest, csharp, csharp-mstest, csharp-nunit, java`, codegenId()], + ['--target ', `language to generate, one of javascript, playwright-test, python, python-async, python-pytest, csharp, csharp-mstest, csharp-nunit, java, java-junit`, codegenId()], ['--save-trace ', 'record a trace for the session and save it to a file'], ['--test-id-attribute ', 'use the specified attribute to generate data test ID selectors'], ]).action(function(url, options) { diff --git a/packages/playwright-core/src/server/recorder.ts b/packages/playwright-core/src/server/recorder.ts index d288726fcd..997e1244d2 100644 --- a/packages/playwright-core/src/server/recorder.ts +++ b/packages/playwright-core/src/server/recorder.ts @@ -433,7 +433,8 @@ class ContextRecorder extends EventEmitter { setOutput(codegenId: string, outputFile?: string) { const languages = new Set([ - new JavaLanguageGenerator(), + new JavaLanguageGenerator('junit'), + new JavaLanguageGenerator('library'), new JavaScriptLanguageGenerator(/* isPlaywrightTest */false), new JavaScriptLanguageGenerator(/* isPlaywrightTest */true), new PythonLanguageGenerator(/* isAsync */false, /* isPytest */true), diff --git a/packages/playwright-core/src/server/recorder/java.ts b/packages/playwright-core/src/server/recorder/java.ts index 742b4db93a..d4ebfdeea4 100644 --- a/packages/playwright-core/src/server/recorder/java.ts +++ b/packages/playwright-core/src/server/recorder/java.ts @@ -26,16 +26,36 @@ import { JavaScriptFormatter } from './javascript'; import { escapeWithQuotes } from '../../utils/isomorphic/stringUtils'; import { asLocator } from '../../utils/isomorphic/locatorGenerators'; +type JavaLanguageMode = 'library' | 'junit'; + export class JavaLanguageGenerator implements LanguageGenerator { - id = 'java'; + id: string; groupName = 'Java'; - name = 'Library'; + name: string; highlighter = 'java' as Language; + _mode: JavaLanguageMode; + + constructor(mode: JavaLanguageMode) { + if (mode === 'library') { + this.name = 'Library'; + this.id = 'java'; + } else if (mode === 'junit') { + this.name = 'JUnit'; + this.id = 'java-junit'; + } else { + throw new Error(`Unknown Java language mode: ${mode}`); + } + this._mode = mode; + } generateAction(actionInContext: ActionInContext): string { const action = actionInContext.action; const pageAlias = actionInContext.frame.pageAlias; - const formatter = new JavaScriptFormatter(6); + const offset = this._mode === 'junit' ? 4 : 6; + const formatter = new JavaScriptFormatter(offset); + + if (this._mode !== 'library' && (action.name === 'openPage' || action.name === 'closePage')) + return ''; if (action.name === 'openPage') { formatter.add(`Page ${pageAlias} = context.newPage();`); @@ -141,6 +161,21 @@ export class JavaLanguageGenerator implements LanguageGenerator { generateHeader(options: LanguageGeneratorOptions): string { const formatter = new JavaScriptFormatter(); + if (this._mode === 'junit') { + formatter.add(` + import com.microsoft.playwright.junit.UsePlaywright; + import com.microsoft.playwright.Page; + import com.microsoft.playwright.options.*; + + import org.junit.jupiter.api.*; + import static com.microsoft.playwright.assertions.PlaywrightAssertions.*; + + @UsePlaywright + public class TestExample { + @Test + void test(Page page) {`); + return formatter.format(); + } formatter.add(` import com.microsoft.playwright.*; import com.microsoft.playwright.options.*; @@ -157,6 +192,10 @@ export class JavaLanguageGenerator implements LanguageGenerator { generateFooter(saveStorage: string | undefined): string { const storageStateLine = saveStorage ? `\n context.storageState(new BrowserContext.StorageStateOptions().setPath(${quote(saveStorage)}));\n` : ''; + if (this._mode === 'junit') { + return `${storageStateLine} } +}`; + } return `${storageStateLine} } } }`; diff --git a/tests/library/inspector/cli-codegen-java.spec.ts b/tests/library/inspector/cli-codegen-java.spec.ts index 738ec37cf9..6b22a1a4cb 100644 --- a/tests/library/inspector/cli-codegen-java.spec.ts +++ b/tests/library/inspector/cli-codegen-java.spec.ts @@ -103,3 +103,33 @@ test('should work with --save-har', async ({ runCLI }, testInfo) => { const json = JSON.parse(fs.readFileSync(harFileName, 'utf-8')); expect(json.log.creator.name).toBe('Playwright'); }); + +test('should print the correct imports in junit', async ({ runCLI, channel, browserName }) => { + const cli = runCLI(['--target=java-junit', emptyHTML]); + const expectedImportResult = `import com.microsoft.playwright.junit.UsePlaywright; +import com.microsoft.playwright.Page; +import com.microsoft.playwright.options.*; + +import org.junit.jupiter.api.*; +import static com.microsoft.playwright.assertions.PlaywrightAssertions.*;`; + await cli.waitFor(expectedImportResult); +}); + +test('should print a valid basic program in junit', async ({ runCLI, channel, browserName }) => { + const cli = runCLI(['--target=java-junit', emptyHTML]); + const expectedResult = `import com.microsoft.playwright.junit.UsePlaywright; +import com.microsoft.playwright.Page; +import com.microsoft.playwright.options.*; + +import org.junit.jupiter.api.*; +import static com.microsoft.playwright.assertions.PlaywrightAssertions.*; + +@UsePlaywright +public class TestExample { + @Test + void test(Page page) { + page.navigate("${emptyHTML}"); + } +}`; + await cli.waitFor(expectedResult); +}); diff --git a/tests/library/inspector/inspectorTest.ts b/tests/library/inspector/inspectorTest.ts index 8485c9f219..7f759f13aa 100644 --- a/tests/library/inspector/inspectorTest.ts +++ b/tests/library/inspector/inspectorTest.ts @@ -35,6 +35,7 @@ const codegenLang2Id: Map = new Map([ ['JSON', 'jsonl'], ['JavaScript', 'javascript'], ['Java', 'java'], + ['Java JUnit', 'java-junit'], ['Python', 'python'], ['Python Async', 'python-async'], ['Pytest', 'python-pytest'],