From 51b061d8054ce281e42e9cca9229bf2c5c307a1e Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Tue, 3 Oct 2023 12:59:12 -0700 Subject: [PATCH 1/2] feat: config fixture --- .../microsoft/playwright/junit/Config.java | 95 +++++++++++++++++++ .../playwright/junit/ConfigFactory.java | 5 + .../junit/DefaultConfigFactory.java | 8 ++ .../playwright/junit/UsePlaywright.java | 2 + .../junit/impl/BrowserContextExtension.java | 37 +++++++- .../junit/impl/BrowserExtension.java | 27 +++++- .../junit/impl/ConfigExtension.java | 48 ++++++++++ .../junit/impl/PlaywrightExtension.java | 10 +- .../TestFixturesWithCustomConfig.java | 32 +++++++ 9 files changed, 255 insertions(+), 9 deletions(-) create mode 100644 playwright/src/main/java/com/microsoft/playwright/junit/Config.java create mode 100644 playwright/src/main/java/com/microsoft/playwright/junit/ConfigFactory.java create mode 100644 playwright/src/main/java/com/microsoft/playwright/junit/DefaultConfigFactory.java create mode 100644 playwright/src/main/java/com/microsoft/playwright/junit/impl/ConfigExtension.java create mode 100644 playwright/src/test/java/com/microsoft/playwright/TestFixturesWithCustomConfig.java diff --git a/playwright/src/main/java/com/microsoft/playwright/junit/Config.java b/playwright/src/main/java/com/microsoft/playwright/junit/Config.java new file mode 100644 index 000000000..b3d3187a4 --- /dev/null +++ b/playwright/src/main/java/com/microsoft/playwright/junit/Config.java @@ -0,0 +1,95 @@ +package com.microsoft.playwright.junit; + +import com.microsoft.playwright.APIRequest; +import com.microsoft.playwright.Browser; +import com.microsoft.playwright.BrowserType; + +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; + +public class Config { + private BrowserType.LaunchOptions launchOptions = new BrowserType.LaunchOptions(); + private Browser.NewContextOptions contextOption = new Browser.NewContextOptions(); + private APIRequest.NewContextOptions apiRequestOptions = new APIRequest.NewContextOptions(); + private Map clientValues = new HashMap<>(); + + private boolean trace; + private boolean video; + private boolean screenshot; + private String browserName = "chromium"; + private Path outputDir; + + public boolean trace() { + return trace; + } + + public void setTrace(boolean enabled) { + trace = enabled; + } + + public boolean screenshot() { + return screenshot; + } + + public void setScreenshot(boolean screenshot) { + this.screenshot = screenshot; + } + + public boolean video() { + return video; + } + + public void setVideo(boolean video) { + this.video = video; + } + + public void setOutputDir(Path dir) { + outputDir = dir; + } + + public Path outputDir() { + return outputDir; + } + + public String browserName() { + return browserName; + } + + public void setBrowserName(String browserName) { + this.browserName = browserName; + } + + public void setHeadless(boolean headless) { + launchOptions.setHeadless(headless); + } + + public void setBaseURL(String url) { + contextOption.setBaseURL(url); + } + + public void setStorageStatePath(Path path) { + contextOption.setStorageStatePath(path); + } + + public BrowserType.LaunchOptions launchOptions() { + return launchOptions; + } + + public Browser.NewContextOptions contextOptions() { + return contextOption; + } + + public APIRequest.NewContextOptions apiRequestOptions() { + return apiRequestOptions; + } + + public void setClientValue(String name, T value) { + clientValues.put(name, value); + } + + public T getClientValue(String name) { + return (T) clientValues.get(name); + } + +} diff --git a/playwright/src/main/java/com/microsoft/playwright/junit/ConfigFactory.java b/playwright/src/main/java/com/microsoft/playwright/junit/ConfigFactory.java new file mode 100644 index 000000000..e20980444 --- /dev/null +++ b/playwright/src/main/java/com/microsoft/playwright/junit/ConfigFactory.java @@ -0,0 +1,5 @@ +package com.microsoft.playwright.junit; + +public interface ConfigFactory { + Config newConfig(); +} diff --git a/playwright/src/main/java/com/microsoft/playwright/junit/DefaultConfigFactory.java b/playwright/src/main/java/com/microsoft/playwright/junit/DefaultConfigFactory.java new file mode 100644 index 000000000..ff4a4d66f --- /dev/null +++ b/playwright/src/main/java/com/microsoft/playwright/junit/DefaultConfigFactory.java @@ -0,0 +1,8 @@ +package com.microsoft.playwright.junit; + +public class DefaultConfigFactory implements ConfigFactory { + @Override + public Config newConfig() { + return new Config(); + } +} diff --git a/playwright/src/main/java/com/microsoft/playwright/junit/UsePlaywright.java b/playwright/src/main/java/com/microsoft/playwright/junit/UsePlaywright.java index 7200dd527..8dd99bb0a 100644 --- a/playwright/src/main/java/com/microsoft/playwright/junit/UsePlaywright.java +++ b/playwright/src/main/java/com/microsoft/playwright/junit/UsePlaywright.java @@ -20,4 +20,6 @@ Class browserFactory() default DefaultBrowserFactory.class; Class browserContextFactory() default DefaultBrowserContextFactory.class; + + Class configFactory() default DefaultConfigFactory.class; } diff --git a/playwright/src/main/java/com/microsoft/playwright/junit/impl/BrowserContextExtension.java b/playwright/src/main/java/com/microsoft/playwright/junit/impl/BrowserContextExtension.java index d96151cee..b9d86b21d 100644 --- a/playwright/src/main/java/com/microsoft/playwright/junit/impl/BrowserContextExtension.java +++ b/playwright/src/main/java/com/microsoft/playwright/junit/impl/BrowserContextExtension.java @@ -3,10 +3,16 @@ import com.microsoft.playwright.Browser; import com.microsoft.playwright.BrowserContext; import com.microsoft.playwright.PlaywrightException; +import com.microsoft.playwright.Tracing; import com.microsoft.playwright.junit.BrowserContextFactory; +import com.microsoft.playwright.junit.Config; import com.microsoft.playwright.junit.UsePlaywright; import org.junit.jupiter.api.extension.*; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + import static com.microsoft.playwright.junit.impl.ExtensionUtils.*; public class BrowserContextExtension implements ParameterResolver, AfterEachCallback, AfterAllCallback { @@ -20,7 +26,7 @@ public class BrowserContextExtension implements ParameterResolver, AfterEachCall @Override public void afterEach(ExtensionContext extensionContext) { - cleanupBrowserContext(); + cleanupBrowserContext(extensionContext); } @Override @@ -49,8 +55,21 @@ static BrowserContext getOrCreateBrowserContext(ExtensionContext extensionContex } Browser browser = BrowserExtension.getOrCreateBrowser(extensionContext); - BrowserContextFactory browserContextFactory = getBrowserContextFactoryInstance(extensionContext); - browserContext = browserContextFactory.newBrowserContext(browser); + + Config config = ConfigExtension.getConfig(extensionContext); + if (config == null) { + BrowserContextFactory browserContextFactory = getBrowserContextFactoryInstance(extensionContext); + browserContext = browserContextFactory.newBrowserContext(browser); + } else { + Browser.NewContextOptions options = config.contextOptions(); + browserContext = browser.newContext(options); + + if (config.trace()) { + // TODO: setSources + browserContext.tracing().start(new Tracing.StartOptions().setSnapshots(true).setScreenshots(true)); + } + } + threadLocalBrowserContext.set(browserContext); return browserContext; } @@ -71,10 +90,20 @@ private static BrowserContextFactory getBrowserContextFactoryInstance(ExtensionC } } - private void cleanupBrowserContext() { + private void cleanupBrowserContext(ExtensionContext extensionContext) { try { BrowserContext browserContext = threadLocalBrowserContext.get(); if (browserContext != null) { + Config config = ConfigExtension.getConfig(extensionContext); + if (config != null) { + Path dir = ConfigExtension.outputDirForTest(config, extensionContext); + try { + Files.createDirectories(dir); + } catch (IOException e) { + throw new PlaywrightException("Failed to create ouptut dir", e); + } + browserContext.tracing().stop(new Tracing.StopOptions().setPath(dir.resolve("trace.zip"))); + } browserContext.close(); } } finally { diff --git a/playwright/src/main/java/com/microsoft/playwright/junit/impl/BrowserExtension.java b/playwright/src/main/java/com/microsoft/playwright/junit/impl/BrowserExtension.java index 0d079bba9..4db38ea20 100644 --- a/playwright/src/main/java/com/microsoft/playwright/junit/impl/BrowserExtension.java +++ b/playwright/src/main/java/com/microsoft/playwright/junit/impl/BrowserExtension.java @@ -1,10 +1,10 @@ package com.microsoft.playwright.junit.impl; import com.microsoft.playwright.Browser; +import com.microsoft.playwright.BrowserType; import com.microsoft.playwright.Playwright; import com.microsoft.playwright.PlaywrightException; -import com.microsoft.playwright.junit.BrowserFactory; -import com.microsoft.playwright.junit.UsePlaywright; +import com.microsoft.playwright.junit.*; import org.junit.jupiter.api.extension.*; import static com.microsoft.playwright.junit.impl.ExtensionUtils.getUsePlaywrightAnnotation; @@ -54,11 +54,32 @@ static Browser getOrCreateBrowser(ExtensionContext extensionContext) { Playwright playwright = PlaywrightExtension.getOrCreatePlaywright(extensionContext); BrowserFactory browserFactory = getBrowserFactoryInstance(extensionContext); - browser = browserFactory.newBrowser(playwright); + + Config config = ConfigExtension.getConfig(extensionContext); + if (config == null) { + browser = browserFactory.newBrowser(playwright); + } else { + browser = newBrowser(playwright, config); + } threadLocalBrowser.set(browser); return browser; } + private static Browser newBrowser(Playwright playwright, Config config) { + BrowserType.LaunchOptions launchOptions = config.launchOptions(); + switch (config.browserName()) { + case "webkit": + return playwright.webkit().launch(launchOptions); + case "firefox": + return playwright.firefox().launch(launchOptions); + case "chromium": + return playwright.chromium().launch(launchOptions); + default: + throw new PlaywrightException("Invalid value set for browserName. Must be one of: chromium, firefox, webkit"); + } + } + + private static BrowserFactory getBrowserFactoryInstance(ExtensionContext extensionContext) { if (threadLocalBrowserFactory.get() != null) { return threadLocalBrowserFactory.get(); diff --git a/playwright/src/main/java/com/microsoft/playwright/junit/impl/ConfigExtension.java b/playwright/src/main/java/com/microsoft/playwright/junit/impl/ConfigExtension.java new file mode 100644 index 000000000..dfd416241 --- /dev/null +++ b/playwright/src/main/java/com/microsoft/playwright/junit/impl/ConfigExtension.java @@ -0,0 +1,48 @@ +package com.microsoft.playwright.junit.impl; + +import com.microsoft.playwright.*; +import com.microsoft.playwright.junit.*; +import org.junit.jupiter.api.extension.*; + +import java.nio.file.FileSystems; +import java.nio.file.Path; + +import static com.microsoft.playwright.junit.impl.ExtensionUtils.getUsePlaywrightAnnotation; + +public class ConfigExtension implements AfterAllCallback { + private static final ThreadLocal threadLocalConfig = new ThreadLocal<>(); + + @Override + public void afterAll(ExtensionContext extensionContext) { + threadLocalConfig.remove(); + } + + static Config getConfig(ExtensionContext extensionContext) { + Config config = threadLocalConfig.get(); + if (config != null) { + return config; + } + UsePlaywright usePlaywrightAnnotation = getUsePlaywrightAnnotation(extensionContext); + if (!DefaultConfigFactory.class.equals(usePlaywrightAnnotation.configFactory())) { + try { + ConfigFactory configFactory = usePlaywrightAnnotation.configFactory().newInstance(); + config = configFactory.newConfig(); + threadLocalConfig.set(config); + } catch (InstantiationException | IllegalAccessException e) { + throw new PlaywrightException("Failed to create config", e); + } + } + return config; + } + + static Path outputDirForTest(Config config, ExtensionContext extensionContext) { + Path dir = config.outputDir(); + if (dir == null) { + // CWD + dir = FileSystems.getDefault().getPath(""); + } + // String className = extensionContext.getTestClass().get().getName(); + String methodName = extensionContext.getTestMethod().get().getName(); + return dir.resolve(methodName); + } +} diff --git a/playwright/src/main/java/com/microsoft/playwright/junit/impl/PlaywrightExtension.java b/playwright/src/main/java/com/microsoft/playwright/junit/impl/PlaywrightExtension.java index 84671fc40..014cdd0c0 100644 --- a/playwright/src/main/java/com/microsoft/playwright/junit/impl/PlaywrightExtension.java +++ b/playwright/src/main/java/com/microsoft/playwright/junit/impl/PlaywrightExtension.java @@ -2,6 +2,7 @@ import com.microsoft.playwright.Playwright; import com.microsoft.playwright.PlaywrightException; +import com.microsoft.playwright.junit.Config; import com.microsoft.playwright.junit.PlaywrightFactory; import com.microsoft.playwright.junit.UsePlaywright; import org.junit.jupiter.api.extension.*; @@ -43,8 +44,13 @@ static Playwright getOrCreatePlaywright(ExtensionContext extensionContext) { return playwright; } - PlaywrightFactory playwrightFactory = getPlaywrightFactoryInstance(extensionContext); - playwright = playwrightFactory.newPlaywright(); + Config config = ConfigExtension.getConfig(extensionContext); + if (config == null) { + PlaywrightFactory playwrightFactory = getPlaywrightFactoryInstance(extensionContext); + playwright = playwrightFactory.newPlaywright(); + } else { + playwright = Playwright.create(); + } threadLocalPlaywright.set(playwright); return playwright; } diff --git a/playwright/src/test/java/com/microsoft/playwright/TestFixturesWithCustomConfig.java b/playwright/src/test/java/com/microsoft/playwright/TestFixturesWithCustomConfig.java new file mode 100644 index 000000000..8dc17bf1b --- /dev/null +++ b/playwright/src/test/java/com/microsoft/playwright/TestFixturesWithCustomConfig.java @@ -0,0 +1,32 @@ +package com.microsoft.playwright; + +import com.microsoft.playwright.junit.Config; +import com.microsoft.playwright.junit.ConfigFactory; +import com.microsoft.playwright.junit.UsePlaywright; +import org.junit.jupiter.api.*; + +import java.nio.file.Paths; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + + +@UsePlaywright(configFactory = TestFixturesWithCustomConfig.CustomConfigFactory.class) +public class TestFixturesWithCustomConfig { + public static class CustomConfigFactory implements ConfigFactory { + @Override + public Config newConfig() { + Config config = new Config(); + config.setOutputDir(Paths.get("/tmp/tracing")); + config.setBrowserName("webkit"); + config.setTrace(true); + config.contextOptions().setViewportSize(1280, 960); + return config; + } + } + + @Test + void recordTraceInWebKit(Page page) { + page.navigate("https://playwright.dev"); + } +} From 18287ba3a76b712fc431194971989e30b9d09ef1 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Tue, 3 Oct 2023 16:19:39 -0700 Subject: [PATCH 2/2] Revert options that depend on reporter integration --- .../microsoft/playwright/junit/Config.java | 36 ------------------- .../junit/impl/BrowserContextExtension.java | 15 -------- .../junit/impl/ConfigExtension.java | 11 ------ .../TestFixturesWithCustomConfig.java | 2 -- 4 files changed, 64 deletions(-) diff --git a/playwright/src/main/java/com/microsoft/playwright/junit/Config.java b/playwright/src/main/java/com/microsoft/playwright/junit/Config.java index b3d3187a4..ecf991c25 100644 --- a/playwright/src/main/java/com/microsoft/playwright/junit/Config.java +++ b/playwright/src/main/java/com/microsoft/playwright/junit/Config.java @@ -14,43 +14,7 @@ public class Config { private APIRequest.NewContextOptions apiRequestOptions = new APIRequest.NewContextOptions(); private Map clientValues = new HashMap<>(); - private boolean trace; - private boolean video; - private boolean screenshot; private String browserName = "chromium"; - private Path outputDir; - - public boolean trace() { - return trace; - } - - public void setTrace(boolean enabled) { - trace = enabled; - } - - public boolean screenshot() { - return screenshot; - } - - public void setScreenshot(boolean screenshot) { - this.screenshot = screenshot; - } - - public boolean video() { - return video; - } - - public void setVideo(boolean video) { - this.video = video; - } - - public void setOutputDir(Path dir) { - outputDir = dir; - } - - public Path outputDir() { - return outputDir; - } public String browserName() { return browserName; diff --git a/playwright/src/main/java/com/microsoft/playwright/junit/impl/BrowserContextExtension.java b/playwright/src/main/java/com/microsoft/playwright/junit/impl/BrowserContextExtension.java index b9d86b21d..a75650e7c 100644 --- a/playwright/src/main/java/com/microsoft/playwright/junit/impl/BrowserContextExtension.java +++ b/playwright/src/main/java/com/microsoft/playwright/junit/impl/BrowserContextExtension.java @@ -63,11 +63,6 @@ static BrowserContext getOrCreateBrowserContext(ExtensionContext extensionContex } else { Browser.NewContextOptions options = config.contextOptions(); browserContext = browser.newContext(options); - - if (config.trace()) { - // TODO: setSources - browserContext.tracing().start(new Tracing.StartOptions().setSnapshots(true).setScreenshots(true)); - } } threadLocalBrowserContext.set(browserContext); @@ -94,16 +89,6 @@ private void cleanupBrowserContext(ExtensionContext extensionContext) { try { BrowserContext browserContext = threadLocalBrowserContext.get(); if (browserContext != null) { - Config config = ConfigExtension.getConfig(extensionContext); - if (config != null) { - Path dir = ConfigExtension.outputDirForTest(config, extensionContext); - try { - Files.createDirectories(dir); - } catch (IOException e) { - throw new PlaywrightException("Failed to create ouptut dir", e); - } - browserContext.tracing().stop(new Tracing.StopOptions().setPath(dir.resolve("trace.zip"))); - } browserContext.close(); } } finally { diff --git a/playwright/src/main/java/com/microsoft/playwright/junit/impl/ConfigExtension.java b/playwright/src/main/java/com/microsoft/playwright/junit/impl/ConfigExtension.java index dfd416241..8f05787b2 100644 --- a/playwright/src/main/java/com/microsoft/playwright/junit/impl/ConfigExtension.java +++ b/playwright/src/main/java/com/microsoft/playwright/junit/impl/ConfigExtension.java @@ -34,15 +34,4 @@ static Config getConfig(ExtensionContext extensionContext) { } return config; } - - static Path outputDirForTest(Config config, ExtensionContext extensionContext) { - Path dir = config.outputDir(); - if (dir == null) { - // CWD - dir = FileSystems.getDefault().getPath(""); - } - // String className = extensionContext.getTestClass().get().getName(); - String methodName = extensionContext.getTestMethod().get().getName(); - return dir.resolve(methodName); - } } diff --git a/playwright/src/test/java/com/microsoft/playwright/TestFixturesWithCustomConfig.java b/playwright/src/test/java/com/microsoft/playwright/TestFixturesWithCustomConfig.java index 8dc17bf1b..cd9b742d6 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestFixturesWithCustomConfig.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestFixturesWithCustomConfig.java @@ -17,9 +17,7 @@ public static class CustomConfigFactory implements ConfigFactory { @Override public Config newConfig() { Config config = new Config(); - config.setOutputDir(Paths.get("/tmp/tracing")); config.setBrowserName("webkit"); - config.setTrace(true); config.contextOptions().setViewportSize(1280, 960); return config; }