package cucumber.runtime.java;
import cucumber.api.Scenario;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.runtime.CucumberException;
import cucumber.runtime.Glue;
import cucumber.runtime.HookDefinition;
import cucumber.runtime.RuntimeGlue;
import cucumber.runtime.UndefinedStepsTracker;
import cucumber.runtime.xstream.LocalizedXStreams;
import gherkin.formatter.model.Tag;
import org.junit.Test;
import java.lang.reflect.Method;
import java.util.Collections;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
public class JavaHookTest {
private static final Method BEFORE;
private static final Method AFTER;
private static final Method BAD_AFTER;
static {
try {
BEFORE = HasHooks.class.getMethod("before");
AFTER = HasHooks.class.getMethod("after");
BAD_AFTER = BadHook.class.getMethod("after", String.class);
} catch (NoSuchMethodException e) {
throw new InternalError("dang");
}
}
private final SingletonFactory objectFactory = new SingletonFactory();
private final JavaBackend backend = new JavaBackend(objectFactory);
private final LocalizedXStreams localizedXStreams = new LocalizedXStreams(Thread.currentThread().getContextClassLoader());
private final Glue glue = new RuntimeGlue(new UndefinedStepsTracker(), localizedXStreams);
@org.junit.Before
public void loadNoGlue() {
backend.loadGlue(glue, Collections.<String>emptyList());
}
@Test
public void before_hooks_get_registered() throws Exception {
objectFactory.setInstance(new HasHooks());
backend.buildWorld();
backend.addHook(BEFORE.getAnnotation(Before.class), BEFORE);
JavaHookDefinition hookDef = (JavaHookDefinition) glue.getBeforeHooks().get(0);
assertEquals(0, glue.getAfterHooks().size());
assertEquals(BEFORE, hookDef.getMethod());
}
@Test
public void after_hooks_get_registered() throws Exception {
objectFactory.setInstance(new HasHooks());
backend.buildWorld();
backend.addHook(AFTER.getAnnotation(After.class), AFTER);
JavaHookDefinition hookDef = (JavaHookDefinition) glue.getAfterHooks().get(0);
assertEquals(0, glue.getBeforeHooks().size());
assertEquals(AFTER, hookDef.getMethod());
}
@Test
public void hook_order_gets_registered() {
objectFactory.setInstance(new HasHooks());
backend.buildWorld();
backend.addHook(AFTER.getAnnotation(After.class), AFTER);
HookDefinition hookDef = glue.getAfterHooks().get(0);
assertEquals(1, hookDef.getOrder());
}
@Test
public void hook_with_no_order_is_last() {
objectFactory.setInstance(new HasHooks());
backend.buildWorld();
backend.addHook(BEFORE.getAnnotation(Before.class), BEFORE);
HookDefinition hookDef = glue.getBeforeHooks().get(0);
assertEquals(10000, hookDef.getOrder());
}
@Test
public void matches_matching_tags() {
objectFactory.setInstance(new HasHooks());
backend.buildWorld();
backend.addHook(BEFORE.getAnnotation(Before.class), BEFORE);
HookDefinition before = glue.getBeforeHooks().get(0);
assertTrue(before.matches(asList(new Tag("@bar", 0), new Tag("@zap", 0))));
}
@Test
public void does_not_match_non_matching_tags() {
objectFactory.setInstance(new HasHooks());
backend.buildWorld();
backend.addHook(BEFORE.getAnnotation(Before.class), BEFORE);
HookDefinition before = glue.getBeforeHooks().get(0);
assertFalse(before.matches(asList(new Tag("@bar", 0))));
}
@Test
public void fails_if_hook_argument_is_not_scenario_result() throws Throwable {
objectFactory.setInstance(new BadHook());
backend.buildWorld();
backend.addHook(BAD_AFTER.getAnnotation(After.class), BAD_AFTER);
HookDefinition bad = glue.getAfterHooks().get(0);
try {
bad.execute(mock(Scenario.class));
fail();
} catch (CucumberException expected) {
assertEquals("When a hook declares an argument it must be of type cucumber.api.Scenario. public void cucumber.runtime.java.JavaHookTest$BadHook.after(java.lang.String)", expected.getMessage());
}
}
public static class HasHooks {
@Before({"@foo,@bar", "@zap"})
public void before() {
}
@After(order = 1)
public void after() {
}
}
public static class BadHook {
@After
public void after(String badType) {
}
}
}