package cucumber.runtime;
import cucumber.api.Scenario;
import cucumber.runtime.io.ResourceLoader;
import gherkin.formatter.Reporter;
import gherkin.formatter.model.Tag;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.Matchers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import static java.util.Arrays.asList;
import static org.mockito.Matchers.anyListOf;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class HookOrderTest {
private Runtime runtime;
private Glue glue;
@Before
public void buildMockWorld() {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
RuntimeOptions runtimeOptions = new RuntimeOptions("");
runtime = new Runtime(mock(ResourceLoader.class), classLoader, asList(mock(Backend.class)), runtimeOptions);
runtime.buildBackendWorlds(null, Collections.<Tag>emptySet(), mock(gherkin.formatter.model.Scenario.class));
glue = runtime.getGlue();
}
@Test
public void before_hooks_execute_in_order() throws Throwable {
List<HookDefinition> hooks = mockHooks(3, Integer.MAX_VALUE, 1, -1, 0, 10000, Integer.MIN_VALUE);
for (HookDefinition hook : hooks) {
glue.addBeforeHook(hook);
}
runtime.runBeforeHooks(mock(Reporter.class), new HashSet<Tag>());
InOrder inOrder = inOrder(hooks.toArray());
inOrder.verify(hooks.get(6)).execute(Matchers.<Scenario>any());
inOrder.verify(hooks.get(3)).execute(Matchers.<Scenario>any());
inOrder.verify(hooks.get(4)).execute(Matchers.<Scenario>any());
inOrder.verify(hooks.get(2)).execute(Matchers.<Scenario>any());
inOrder.verify(hooks.get(0)).execute(Matchers.<Scenario>any());
inOrder.verify(hooks.get(5)).execute(Matchers.<Scenario>any());
inOrder.verify(hooks.get(1)).execute(Matchers.<Scenario>any());
}
@Test
public void after_hooks_execute_in_reverse_order() throws Throwable {
List<HookDefinition> hooks = mockHooks(Integer.MIN_VALUE, 2, Integer.MAX_VALUE, 4, -1, 0, 10000);
for (HookDefinition hook : hooks) {
glue.addAfterHook(hook);
}
runtime.runAfterHooks(mock(Reporter.class), new HashSet<Tag>());
InOrder inOrder = inOrder(hooks.toArray());
inOrder.verify(hooks.get(2)).execute(Matchers.<Scenario>any());
inOrder.verify(hooks.get(6)).execute(Matchers.<Scenario>any());
inOrder.verify(hooks.get(3)).execute(Matchers.<Scenario>any());
inOrder.verify(hooks.get(1)).execute(Matchers.<Scenario>any());
inOrder.verify(hooks.get(5)).execute(Matchers.<Scenario>any());
inOrder.verify(hooks.get(4)).execute(Matchers.<Scenario>any());
inOrder.verify(hooks.get(0)).execute(Matchers.<Scenario>any());
}
@Test
public void hooks_order_across_many_backends() throws Throwable {
List<HookDefinition> backend1Hooks = mockHooks(3, Integer.MAX_VALUE, 1);
for (HookDefinition hook : backend1Hooks) {
glue.addBeforeHook(hook);
}
List<HookDefinition> backend2Hooks = mockHooks(2, Integer.MAX_VALUE, 4);
for (HookDefinition hook : backend2Hooks) {
glue.addBeforeHook(hook);
}
runtime.runBeforeHooks(mock(Reporter.class), new HashSet<Tag>());
List<HookDefinition> allHooks = new ArrayList<HookDefinition>();
allHooks.addAll(backend1Hooks);
allHooks.addAll(backend2Hooks);
InOrder inOrder = inOrder(allHooks.toArray());
inOrder.verify(backend1Hooks.get(2)).execute(Matchers.<Scenario>any());
inOrder.verify(backend2Hooks.get(0)).execute(Matchers.<Scenario>any());
inOrder.verify(backend1Hooks.get(0)).execute(Matchers.<Scenario>any());
inOrder.verify(backend2Hooks.get(2)).execute(Matchers.<Scenario>any());
verify(backend2Hooks.get(1)).execute(Matchers.<Scenario>any());
verify(backend1Hooks.get(1)).execute(Matchers.<Scenario>any());
}
private List<HookDefinition> mockHooks(int... ordering) {
List<HookDefinition> hooks = new ArrayList<HookDefinition>();
for (int order : ordering) {
HookDefinition hook = mock(HookDefinition.class, "Mock number " + order);
when(hook.getOrder()).thenReturn(order);
when(hook.matches(anyListOf(Tag.class))).thenReturn(true);
hooks.add(hook);
}
return hooks;
}
}