package cucumber.runtime.rhino; import cucumber.runtime.HookDefinition; import cucumber.runtime.RuntimeGlue; import cucumber.runtime.io.MultiLoader; import cucumber.runtime.io.ResourceLoader; import gherkin.formatter.model.Tag; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.mozilla.javascript.WrappedException; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.instanceOf; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.doNothing; @RunWith(MockitoJUnitRunner.class) public class RhinoHooksTest { private static final String[] NO_TAG = {}; private static final String[] TAG = {"@bellies"}; private static final String[] TAGS = {"@tag1", "@tag2"}; private static final int DEFAULT_ORDER = 1000; private static final int DEFAULT_TIMEOUT = 0; private final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); private final ResourceLoader resourceLoader = new MultiLoader(classLoader); @Mock private RuntimeGlue glue; private ArgumentCaptor<HookDefinition> beforeHookCaptor; private ArgumentCaptor<HookDefinition> afterHookCaptor; @Before public void startCapturingHooksArguments() { // given beforeHookCaptor = ArgumentCaptor.forClass(HookDefinition.class); afterHookCaptor = ArgumentCaptor.forClass(HookDefinition.class); doNothing().when(glue).addBeforeHook(beforeHookCaptor.capture()); doNothing().when(glue).addAfterHook(afterHookCaptor.capture()); } @Test public void shouldCallAddBeforeAndAfterHook() throws IOException { // when RhinoBackend jsBackend = new RhinoBackend(resourceLoader); jsBackend.loadGlue(glue, Collections.singletonList("classpath:cucumber/runtime/rhinotest/rhino_hooks")); List<HookDefinition> beforeHooks = beforeHookCaptor.getAllValues(); List<HookDefinition> afterHooks = afterHookCaptor.getAllValues(); // then assertHooks(beforeHooks.get(0), afterHooks.get(0), NO_TAG, DEFAULT_ORDER, DEFAULT_TIMEOUT); assertHooks(beforeHooks.get(1), afterHooks.get(1), TAG, DEFAULT_ORDER, DEFAULT_TIMEOUT); assertHooks(beforeHooks.get(2), afterHooks.get(2), TAGS, DEFAULT_ORDER, DEFAULT_TIMEOUT); assertHooks(beforeHooks.get(3), afterHooks.get(3), TAGS, DEFAULT_ORDER, 300); assertHooks(beforeHooks.get(4), afterHooks.get(4), TAGS, 10, DEFAULT_TIMEOUT); assertHooks(beforeHooks.get(5), afterHooks.get(5), TAGS, 20, 600); } @Test(expected = InterruptedException.class) public void shouldFailWithTimeout() throws Throwable { // when RhinoBackend jsBackend = new RhinoBackend(resourceLoader); jsBackend.loadGlue(glue, Collections.singletonList("classpath:cucumber/runtime/rhino_hooks_timeout")); List<HookDefinition> beforeHooks = beforeHookCaptor.getAllValues(); try { beforeHooks.get(0).execute(null); fail(); } catch (WrappedException expected) { throw expected.getWrappedException(); } } private void assertHooks(HookDefinition beforeHook, HookDefinition afterHook, String[] tags, int order, long timeoutMillis) { assertHook(beforeHook, tags, order, timeoutMillis); assertHook(afterHook, tags, order, timeoutMillis); } private void assertHook(HookDefinition hookDefinition, String[] tagExprs, int order, long timeoutMillis) { assertThat(hookDefinition, instanceOf(RhinoHookDefinition.class)); RhinoHookDefinition rhinoHook = (RhinoHookDefinition) hookDefinition; List<Tag> tags = new ArrayList<Tag>(); for (String tagExpr : tagExprs) { tags.add(new Tag(tagExpr, null)); } assertTrue(rhinoHook.getTagExpression().evaluate(tags)); assertThat(rhinoHook.getOrder(), equalTo(order)); assertThat(rhinoHook.getTimeout(), equalTo(timeoutMillis)); } }