/** * Creates a handler for events or exceptions of the specified type. * <p> * Internally, a default use case ("Handles events") is created in the model. * </p> * * @param eventOrExceptionClass the specified event / exception class * @param <T> the type of events/exceptions * @return a part of the builder used to create the event handler (the "system reaction") */ public <T> FlowlessUserPart<T> on(Class<T> eventOrExceptionClass) { FlowlessUserPart<T> on = useCase(HANDLES_EVENTS).on(eventOrExceptionClass); return on; }
@Test public void twoFlowlessStepsReactToEventsOfDifferentTypeInDifferentUseCases() { Model model = modelBuilder .useCase(USE_CASE) .on(EntersText.class).system(displaysEnteredText()) .useCase(USE_CASE_2) .on(EntersNumber.class).system(displaysEnteredNumber()) .build(); modelRunner.run(model); Optional<Step> latestStepRun = modelRunner.reactTo(entersNumber()); assertEquals(EntersNumber.class, latestStepRun.get().getEventClass()); latestStepRun = modelRunner.reactTo(entersText()); assertEquals(EntersText.class, latestStepRun.get().getEventClass()); }
@Test public void twoFlowlessStepsReactWhenConditionIsTrueInSecondStepWithoutEvent() { Model model = modelBuilder.useCase(USE_CASE) .on(EntersText.class).system(displaysEnteredText()) .condition(() -> modelRunner.getLatestStep().isPresent() && modelRunner.getLatestStep().get().getEventClass().equals(EntersText.class)).system(displaysConstantText()) .build(); modelRunner.run(model).reactTo(entersText()); assertEquals(ModelRunner.class, modelRunner.getLatestStep().get().getEventClass()); }
@Test public void recordsEventWithUnhandledEventHandler() { Model model = modelBuilder.useCase(USE_CASE).on(EntersText.class).system(displaysEnteredText()).build(); modelRunner.handleUnhandledWith(this::eventRecordingEventHandler); modelRunner.run(model); modelRunner.reactTo(entersNumber()); Object event = optionalEvent.get(); assertTrue(event instanceof EntersNumber); }
@Test public void oneFlowlessStepReacts() { Model model = modelBuilder.useCase(USE_CASE) .on(EntersText.class).system(displaysEnteredText()) .build(); modelRunner.run(model); Optional<Step> latestStepRun = modelRunner.reactTo(entersText()); assertEquals(EntersText.class, latestStepRun.get().getEventClass()); }
@Test public void createsSingleStepThatHandlesUserCommandWithUseCaseButWithoutFlow() { UseCasePart useCasePart = modelBuilder.useCase(USE_CASE); Model model = useCasePart .on(EntersText.class).system(displaysEnteredText()) .build(); UseCase useCase = useCasePart.getUseCase(); Collection<Step> steps = useCase.getSteps(); assertEquals(1, steps.size()); Step step = steps.iterator().next(); assertEquals("S1", step.getName()); assertEquals(USE_CASE, step.getUseCase().getName()); assertEquals(model.getSystemActor(), step.getActors()[0]); }
@Test public void twoFlowlessStepsReactToEventsOfDifferentTypeInWrongOrder() { Model model = modelBuilder.useCase(USE_CASE) .on(EntersText.class).system(displaysEnteredText()) .on(EntersNumber.class).system(displaysEnteredNumber()) .build(); modelRunner.run(model); Optional<Step> latestStepRun = modelRunner.reactTo(entersNumber()); assertEquals(EntersNumber.class, latestStepRun.get().getEventClass()); latestStepRun = modelRunner.reactTo(entersText()); assertEquals(EntersText.class, latestStepRun.get().getEventClass()); }
@Test public void twoFlowlessStepsReactToEventsOfDifferentTypeInRightOrder() { Model model = modelBuilder.useCase(USE_CASE) .on(EntersText.class).system(displaysEnteredText()) .on(EntersNumber.class).system(displaysEnteredNumber()) .build(); modelRunner.run(model); Optional<Step> latestStepRun = modelRunner.reactTo(entersText()); assertEquals(EntersText.class, latestStepRun.get().getEventClass()); latestStepRun = modelRunner.reactTo(entersNumber()); assertEquals(EntersNumber.class, latestStepRun.get().getEventClass()); }
@Test public void createsTwoStepsWithoutFlow() { UseCasePart useCasePart = modelBuilder.useCase(USE_CASE); useCasePart .on(EntersText.class).system(displaysEnteredText()) .on(EntersNumber.class).system(displaysEnteredNumber()) .build(); Collection<Step> steps = useCasePart.getUseCase().getSteps(); assertEquals(2, steps.size()); Iterator<Step> stepIt = steps.iterator(); Step step = stepIt.next(); assertEquals("S1", step.getName()); assertEquals(USE_CASE, step.getUseCase().getName()); step = stepIt.next(); assertEquals("S2", step.getName()); assertEquals(USE_CASE, step.getUseCase().getName()); }
@Test public void twoFlowlessStepsDontReactWhenConditionIsFalseInSecondStep() { Model model = modelBuilder.useCase(USE_CASE) .on(EntersText.class).system(displaysEnteredText()) .condition(() -> false).on(EntersNumber.class).system(displaysEnteredNumber()) .build(); modelRunner.run(model); Optional<Step> latestStepRun = modelRunner.reactTo(entersText()); assertEquals(EntersText.class, latestStepRun.get().getEventClass()); latestStepRun = modelRunner.reactTo(entersNumber()); assertEquals(EntersText.class, latestStepRun.get().getEventClass()); }
@Test public void twoFlowlessStepsReactWhenConditionIsTrueInSecondStepWithEvent() { Model model = modelBuilder.useCase(USE_CASE) .on(EntersText.class).system(displaysEnteredText()) .condition(() -> true).on(EntersNumber.class).system(displaysEnteredNumber()) .build(); modelRunner.run(model); Optional<Step> latestStepRun = modelRunner.reactTo(entersText()); assertEquals(EntersText.class, latestStepRun.get().getEventClass()); latestStepRun = modelRunner.reactTo(entersNumber()); assertEquals(EntersNumber.class, latestStepRun.get().getEventClass()); }
@Test public void recordIsEmptyForFreshlyRunModel() { Model model = modelBuilder.useCase(USE_CASE) .on(EntersText.class).system(displaysEnteredText()) .build(); modelRunner.run(model); assertEquals(0, modelRunner.getRecordedEvents().length); assertEquals(0, modelRunner.getRecordedStepNames().length); }
@Test public void recordIsEmptyIfRecordingWasStoppedBeforeBeingStarted() { Model model = modelBuilder.useCase(USE_CASE) .on(EntersText.class).system(displaysEnteredText()) .build(); modelRunner.run(model).stopRecording(); assertEquals(0, modelRunner.getRecordedEvents().length); assertEquals(0, modelRunner.getRecordedStepNames().length); }
@Test public void recordSingleEvent() { Model model = modelBuilder.useCase(USE_CASE) .on(EntersText.class).system(displaysEnteredText()) .build(); modelRunner.run(model).startRecording(); modelRunner.reactTo(entersText()); assertEquals(1, modelRunner.getRecordedEvents().length); assertEquals(EntersText.class, modelRunner.getRecordedEvents()[0].getClass()); assertEquals(1, modelRunner.getRecordedStepNames().length); assertEquals("S1", modelRunner.getRecordedStepNames()[0]); }
@Test public void recordMultipleEvents_startRecordingBeforeRunning() { Model model = modelBuilder.useCase(USE_CASE) .on(EntersText.class).system(displaysEnteredText()) .on(EntersNumber.class).system(displaysEnteredNumber()) .build(); modelRunner.startRecording().run(model); modelRunner.reactTo(entersText(), entersNumber()); assertEquals(2, modelRunner.getRecordedEvents().length); assertEquals(EntersText.class, modelRunner.getRecordedEvents()[0].getClass()); assertEquals(EntersNumber.class, modelRunner.getRecordedEvents()[1].getClass()); assertEquals(2, modelRunner.getRecordedStepNames().length); assertEquals("S1", modelRunner.getRecordedStepNames()[0]); assertEquals("S2", modelRunner.getRecordedStepNames()[1]); }
@Test public void recordMultipleEvents_startRecordingAfterRunning() { Model model = modelBuilder.useCase(USE_CASE) .on(EntersText.class).system(displaysEnteredText()) .on(EntersNumber.class).system(displaysEnteredNumber()) .build(); modelRunner.run(model).startRecording(); modelRunner.reactTo(entersText(), entersNumber()); assertEquals(2, modelRunner.getRecordedEvents().length); assertEquals(EntersText.class, modelRunner.getRecordedEvents()[0].getClass()); assertEquals(EntersNumber.class, modelRunner.getRecordedEvents()[1].getClass()); assertEquals(2, modelRunner.getRecordedStepNames().length); assertEquals("S1", modelRunner.getRecordedStepNames()[0]); assertEquals("S2", modelRunner.getRecordedStepNames()[1]); }
@Test public void continueRecordingAfterRestart() { Model model = modelBuilder.useCase(USE_CASE) .on(EntersText.class).system(displaysEnteredText()) .on(EntersNumber.class).system(displaysEnteredNumber()) .build(); modelRunner.run(model).startRecording(); modelRunner.reactTo(entersText()); modelRunner.restart(); modelRunner.reactTo(entersNumber()); assertEquals(2, modelRunner.getRecordedEvents().length); assertEquals(EntersText.class, modelRunner.getRecordedEvents()[0].getClass()); assertEquals(EntersNumber.class, modelRunner.getRecordedEvents()[1].getClass()); assertEquals(2, modelRunner.getRecordedStepNames().length); assertEquals("S1", modelRunner.getRecordedStepNames()[0]); assertEquals("S2", modelRunner.getRecordedStepNames()[1]); } }
@Test public void noMoreRecordingAfterRecordingIsStopped() { Model model = modelBuilder.useCase(USE_CASE) .on(EntersText.class).system(displaysEnteredText()) .on(EntersNumber.class).system(displaysEnteredNumber()) .build(); modelRunner.run(model).startRecording(); modelRunner.reactTo(entersText()); modelRunner.stopRecording(); modelRunner.reactTo(entersNumber()); assertEquals(1, modelRunner.getRecordedEvents().length); assertEquals(EntersText.class, modelRunner.getRecordedEvents()[0].getClass()); assertEquals(1, modelRunner.getRecordedStepNames().length); assertEquals("S1", modelRunner.getRecordedStepNames()[0]); }