Skip to content

Commit

Permalink
feat(junit-playwright) (#1412)
Browse files Browse the repository at this point in the history
  • Loading branch information
uchagani authored Dec 5, 2023
1 parent d73f953 commit f28ca44
Show file tree
Hide file tree
Showing 12 changed files with 534 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

import static com.microsoft.playwright.impl.Serialization.toJsonArray;

class Utils {
public class Utils {
static <F, T> T convertType(F f, Class<T> t) {
if (f == null) {
return null;
Expand Down Expand Up @@ -80,7 +80,7 @@ static <F, T> T convertType(F f, Class<T> t) {
}
}

static <T> T clone(T f) {
public static <T> T clone(T f) {
if (f == null) {
return f;
}
Expand Down
112 changes: 112 additions & 0 deletions playwright/src/main/java/com/microsoft/playwright/junit/Options.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package com.microsoft.playwright.junit;

import com.microsoft.playwright.APIRequest;
import com.microsoft.playwright.Browser;
import com.microsoft.playwright.BrowserType;
import com.microsoft.playwright.Playwright;
import com.microsoft.playwright.options.ViewportSize;

import java.nio.file.Path;

public class Options {
public String baseUrl;
public Path storageStatePath;
public ViewportSize viewportSize;
public String channel;
public Boolean headless;
public String browserName = "chromium";
public BrowserType.LaunchOptions launchOptions;
public Browser.NewContextOptions contextOption;
public APIRequest.NewContextOptions apiRequestOptions;
public Playwright.CreateOptions playwrightCreateOptions;

public Playwright.CreateOptions getPlaywrightCreateOptions() {
return playwrightCreateOptions;
}

public Options setPlaywrightCreateOptions(Playwright.CreateOptions playwrightCreateOptions) {
this.playwrightCreateOptions = playwrightCreateOptions;
return this;
}

public BrowserType.LaunchOptions getLaunchOptions() {
return launchOptions;
}

public Options setLaunchOptions(BrowserType.LaunchOptions launchOptions) {
this.launchOptions = launchOptions;
return this;
}

public Browser.NewContextOptions getContextOption() {
return contextOption;
}

public Options setContextOption(Browser.NewContextOptions contextOption) {
this.contextOption = contextOption;
return this;
}

public APIRequest.NewContextOptions getApiRequestOptions() {
return apiRequestOptions;
}

public Options setApiRequestOptions(APIRequest.NewContextOptions apiRequestOptions) {
this.apiRequestOptions = apiRequestOptions;
return this;
}

public String getBaseUrl() {
return baseUrl;
}

public Options setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
return this;
}

public Path getStorageStatePath() {
return storageStatePath;
}

public Options setStorageStatePath(Path storageStatePath) {
this.storageStatePath = storageStatePath;
return this;
}

public String getBrowserName() {
return browserName;
}

public Options setBrowserName(String browserName) {
this.browserName = browserName;
return this;
}

public String getChannel() {
return channel;
}

public Options setChannel(String channel) {
this.channel = channel;
return this;
}

public Boolean isHeadless() {
return headless;
}

public Options setHeadless(Boolean headless) {
this.headless = headless;
return this;
}

public ViewportSize getViewportSize() {
return viewportSize;
}

public Options setViewportSize(ViewportSize viewportSize) {
this.viewportSize = viewportSize;
return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.microsoft.playwright.junit;

import com.microsoft.playwright.junit.impl.*;
import org.junit.jupiter.api.extension.ExtendWith;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@ExtendWith({OptionsExtension.class, PlaywrightExtension.class, BrowserExtension.class, BrowserContextExtension.class,
PageExtension.class, APIRequestContextExtension.class})
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface UsePlaywright {
Class<? extends Options> options() default Options.class;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.microsoft.playwright.junit.impl;

import com.microsoft.playwright.APIRequestContext;
import com.microsoft.playwright.Playwright;
import com.microsoft.playwright.junit.Options;
import org.junit.jupiter.api.extension.*;

import static com.microsoft.playwright.junit.impl.ExtensionUtils.isParameterSupported;

public class APIRequestContextExtension implements ParameterResolver, BeforeEachCallback, AfterAllCallback {
private static final ThreadLocal<APIRequestContext> threadLocalAPIRequestContext = new ThreadLocal<>();

@Override
public void beforeEach(ExtensionContext extensionContext) {
threadLocalAPIRequestContext.remove();
}

@Override
public void afterAll(ExtensionContext extensionContext) {
threadLocalAPIRequestContext.remove();
}

@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
return isParameterSupported(parameterContext, extensionContext, APIRequestContext.class);
}

@Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
return getOrCreateAPIRequestContext(extensionContext);
}

static APIRequestContext getOrCreateAPIRequestContext(ExtensionContext extensionContext) {
APIRequestContext apiRequestContext = threadLocalAPIRequestContext.get();
if (apiRequestContext != null) {
return apiRequestContext;
}

Options options = OptionsExtension.getOptions(extensionContext);
Playwright playwright = PlaywrightExtension.getOrCreatePlaywright(extensionContext);
apiRequestContext = playwright.request().newContext(options.getApiRequestOptions());
threadLocalAPIRequestContext.set(apiRequestContext);
return apiRequestContext;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.microsoft.playwright.junit.impl;

import com.microsoft.playwright.Browser;
import com.microsoft.playwright.BrowserContext;
import com.microsoft.playwright.impl.Utils;
import com.microsoft.playwright.junit.Options;
import org.junit.jupiter.api.extension.*;

import static com.microsoft.playwright.junit.impl.ExtensionUtils.isClassHook;
import static com.microsoft.playwright.junit.impl.ExtensionUtils.isParameterSupported;

public class BrowserContextExtension implements ParameterResolver, AfterEachCallback {
private static final ThreadLocal<BrowserContext> threadLocalBrowserContext = new ThreadLocal<>();

@Override
public void afterEach(ExtensionContext extensionContext) {
BrowserContext browserContext = threadLocalBrowserContext.get();
threadLocalBrowserContext.remove();
if (browserContext != null) {
browserContext.close();
}
}

@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
return !isClassHook(extensionContext) && isParameterSupported(parameterContext, extensionContext, BrowserContext.class);
}

@Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
return getOrCreateBrowserContext(extensionContext);
}

static BrowserContext getOrCreateBrowserContext(ExtensionContext extensionContext) {
BrowserContext browserContext = threadLocalBrowserContext.get();
if (browserContext != null) {
return browserContext;
}

Options options = OptionsExtension.getOptions(extensionContext);
Browser browser = BrowserExtension.getOrCreateBrowser(extensionContext);
Browser.NewContextOptions contextOptions = getContextOptions(options);
browserContext = browser.newContext(contextOptions);
threadLocalBrowserContext.set(browserContext);
return browserContext;
}

private static Browser.NewContextOptions getContextOptions(Options options) {
Browser.NewContextOptions contextOptions = Utils.clone(options.getContextOption());
if (contextOptions == null) {
contextOptions = new Browser.NewContextOptions();
}

if (options.getBaseUrl() != null) {
contextOptions.setBaseURL(options.getBaseUrl());
}

if (options.getStorageStatePath() != null) {
contextOptions.setStorageStatePath(options.getStorageStatePath());
}

if (options.getViewportSize() != null) {
contextOptions.setViewportSize(options.getViewportSize());
}

return contextOptions;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
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.impl.Utils;
import com.microsoft.playwright.junit.Options;
import org.junit.jupiter.api.extension.*;

import static com.microsoft.playwright.junit.impl.ExtensionUtils.isParameterSupported;

public class BrowserExtension implements ParameterResolver, AfterAllCallback {
private static final ThreadLocal<Browser> threadLocalBrowser = new ThreadLocal<>();

@Override
public void afterAll(ExtensionContext extensionContext) {
Browser browser = threadLocalBrowser.get();
threadLocalBrowser.remove();
if (browser != null) {
browser.close();
}
}

@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
return isParameterSupported(parameterContext, extensionContext, Browser.class);
}

@Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
return getOrCreateBrowser(extensionContext);
}

static Browser getOrCreateBrowser(ExtensionContext extensionContext) {
Browser browser = threadLocalBrowser.get();
if (browser != null) {
return browser;
}

Options options = OptionsExtension.getOptions(extensionContext);
Playwright playwright = PlaywrightExtension.getOrCreatePlaywright(extensionContext);
BrowserType.LaunchOptions launchOptions = getLaunchOptions(options);

switch (options.getBrowserName()) {
case "webkit":
browser = playwright.webkit().launch(launchOptions);
break;
case "firefox":
browser = playwright.firefox().launch(launchOptions);
break;
case "chromium":
browser = playwright.chromium().launch(launchOptions);
break;
default:
throw new PlaywrightException("Invalid browser name.");
}

threadLocalBrowser.set(browser);
return browser;
}

private static BrowserType.LaunchOptions getLaunchOptions(Options options) {
BrowserType.LaunchOptions launchOptions = Utils.clone(options.getLaunchOptions());
if (launchOptions == null) {
launchOptions = new BrowserType.LaunchOptions();
}

if (options.isHeadless() != null) {
launchOptions.setHeadless(options.isHeadless());
}

if (options.getChannel() != null) {
options.setChannel(options.getChannel());
}

return launchOptions;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.microsoft.playwright.junit.impl;

import com.microsoft.playwright.junit.UsePlaywright;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.platform.commons.support.AnnotationSupport;

import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation;

class ExtensionUtils {
static boolean hasUsePlaywrightAnnotation(ExtensionContext extensionContext) {
return AnnotationSupport.isAnnotated(extensionContext.getTestClass(), UsePlaywright.class);
}

static UsePlaywright getUsePlaywrightAnnotation(ExtensionContext extensionContext) {
return findAnnotation(extensionContext.getTestClass(), UsePlaywright.class).get();
}

static boolean isClassHook(ExtensionContext extensionContext) {
return !extensionContext.getTestMethod().isPresent();
}

static boolean isParameterSupported(ParameterContext parameterContext, ExtensionContext extensionContext, Class<?> subject) {
if (!hasUsePlaywrightAnnotation(extensionContext)) {
return false;
}
Class<?> clazz = parameterContext.getParameter().getType();
return subject.equals(clazz);
}
}
Loading

0 comments on commit f28ca44

Please sign in to comment.