Skip to content
This repository has been archived by the owner on Sep 8, 2022. It is now read-only.

create a GaleniumExtension for JUnit5 #79

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package io.wcm.qa.glnm.junit;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.openqa.selenium.chrome.ChromeDriver;

import io.github.bonigarcia.seljup.Arguments;
import io.github.bonigarcia.seljup.SeleniumExtension;
import io.wcm.qa.glnm.context.GaleniumContext;

/**
* Galenium extension for Jupiter (JUnit 5) tests.
* Will initialize Galenium with a ChromeDriver
*/
public class GaleniumExtension extends SeleniumExtension implements BeforeEachCallback, AfterEachCallback {

@BeforeEach
void initBrowser(@Arguments("--headless") ChromeDriver driver) {
GaleniumContext.getContext().setDriver(driver);
}

@Override
public void beforeEach(ExtensionContext extensionContext) throws Exception {
new MethodExecuter().executeMethod(this, extensionContext, org.junit.jupiter.api.BeforeEach.class);
}

@Override
public void afterEach(ExtensionContext extensionContext) {
super.afterEach(extensionContext);
GaleniumContext.getContext().setDriver(null);
}

}
103 changes: 103 additions & 0 deletions modules/icing/src/main/java/io/wcm/qa/glnm/junit/MethodExecuter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package io.wcm.qa.glnm.junit;

import static org.junit.platform.commons.util.ReflectionUtils.isInnerClass;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolver;
import org.junit.platform.commons.util.AnnotationUtils;
import org.junit.platform.commons.util.Preconditions;

/** Will execute a method in a junitExtension class. useb by GaleniumExtension */
class MethodExecuter {

public void executeMethod(ParameterResolver junitExtension, ExtensionContext extensionContext, Class<? extends Annotation> annotatedBy) {
Arrays.stream(junitExtension.getClass().getDeclaredMethods())
.filter(method -> method.isAnnotationPresent(annotatedBy)).findFirst()
.ifPresent(method -> executeMethod(junitExtension, extensionContext, method));
}

private void executeMethod(ParameterResolver junitExtension, ExtensionContext extensionContext, Method method) {
try {
Parameter parameter = method.getParameters()[0];
DefaultParameterContext parameterContext = new DefaultParameterContext(parameter, 0, Optional.empty());
Object args = junitExtension.resolveParameter(parameterContext, extensionContext);
method.invoke(junitExtension, args);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException("could not invoke method", e);
}
}

private class DefaultParameterContext implements ParameterContext {

private final Parameter parameter;
private final int index;
private final Optional<Object> target;

DefaultParameterContext(Parameter parameter, int index, Optional<Object> target) {
Preconditions.condition(index >= 0, "index must be greater than or equal to zero");
this.parameter = Preconditions.notNull(parameter, "parameter must not be null");
this.index = index;
this.target = Preconditions.notNull(target, "target must not be null");
}

@Override
public Parameter getParameter() {
return this.parameter;
}

@Override
public int getIndex() {
return this.index;
}

@Override
public Optional<Object> getTarget() {
return this.target;
}

@Override
public boolean isAnnotated(Class<? extends Annotation> annotationType) {
return AnnotationUtils.isAnnotated(getEffectiveAnnotatedParameter(), annotationType);
}

@Override
public <A extends Annotation> Optional<A> findAnnotation(Class<A> annotationType) {
return AnnotationUtils.findAnnotation(getEffectiveAnnotatedParameter(), annotationType);
}

@Override
public <A extends Annotation> List<A> findRepeatableAnnotations(Class<A> annotationType) {
return AnnotationUtils.findRepeatableAnnotations(getEffectiveAnnotatedParameter(), annotationType);
}

private AnnotatedElement getEffectiveAnnotatedParameter() {
Executable executable = getDeclaringExecutable();

if (executable instanceof Constructor && isInnerClass(executable.getDeclaringClass())
&& executable.getParameterAnnotations().length == executable.getParameterCount() - 1) {

Preconditions.condition(this.index != 0,
"A ParameterContext should never be created for parameter index 0 in an inner class constructor");

return executable.getParameters()[this.index - 1];
}

return this.parameter;
}

}

}