public void execute_logs_any_error_raised_by_the_inner_action() { var waitHandle = new ManualResetEventSlim(); var logger = new LoggerMock(MockBehavior.Loose); var loggerService = new LoggerServiceMock(MockBehavior.Loose); var action = new ActionMock(MockBehavior.Loose); logger .When(x => x.Log(LogLevel.Error, It.IsAny<string>())) .Do(waitHandle.Set); loggerService .When(x => x.GetLogger(It.IsAny<Type>())) .Return(logger); action .When(x => x.Execute(It.IsAny<ExecutionContext>())) .Return(Observable.Throw<Unit>(new InvalidOperationException("Something bad happened"))); var sut = new DoNotAwaitActionBuilder() .WithLoggerService(loggerService) .WithInnerAction(action) .Build(); sut.Execute(new ExecutionContext()); Assert.True(waitHandle.Wait(TimeSpan.FromSeconds(3))); }
public void duration_is_calculated_as_the_sum_of_child_durations() { var action1 = new ActionMock(); var action2 = new ActionMock(); var action3 = new ActionMock(); action1 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(10)); action2 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(1)); action3 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(7)); var sut = new SequenceActionBuilder() .WithChild(action1) .WithChild(action2) .WithChild(action3) .Build(); Assert.Equal(TimeSpan.FromSeconds(18), sut.Duration); }
public void duration_is_the_maximum_duration_from_all_children() { var action1 = new ActionMock(); var action2 = new ActionMock(); var action3 = new ActionMock(); var action4 = new ActionMock(); action1 .When(x => x.Duration) .Return(TimeSpan.FromMilliseconds(150)); action2 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(3)); action3 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(5)); action4 .When(x => x.Duration) .Return(TimeSpan.FromMilliseconds(550)); var sut = new ParallelActionBuilder() .AddChild(action1) .AddChild(action2) .AddChild(action3) .AddChild(action4) .Build(); Assert.Equal(TimeSpan.FromSeconds(5), sut.Duration); }
public void execute_executes_each_child_action() { var action1 = new ActionMock(MockBehavior.Loose); var action2 = new ActionMock(MockBehavior.Loose); var action3 = new ActionMock(MockBehavior.Loose); var action4 = new ActionMock(MockBehavior.Loose); action1 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(1)); action2 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(2)); action3 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(3)); action4 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(4)); var sut = new ParallelActionBuilder() .WithChild(action1) .WithChild(action2) .WithChild(action3) .WithChild(action4) .Build(); using (var context = new ExecutionContext()) { sut.Execute(context); action1 .Verify(x => x.Execute(It.IsAny<ExecutionContext>())) .WasCalledExactlyOnce(); action2 .Verify(x => x.Execute(It.IsAny<ExecutionContext>())) .WasCalledExactlyOnce(); action3 .Verify(x => x.Execute(It.IsAny<ExecutionContext>())) .WasCalledExactlyOnce(); action4 .Verify(x => x.Execute(It.IsAny<ExecutionContext>())) .WasCalledExactlyOnce(); } }
public void duration_always_returns_zero_regardless_of_inner_action_duration() { var action = new ActionMock(); action .When(x => x.Duration) .Return(TimeSpan.FromSeconds(3)); var sut = new DoNotAwaitActionBuilder() .WithInnerAction(action) .Build(); Assert.Equal(TimeSpan.Zero, sut.Duration); }
public void duration_returns_duration_in_model(int durationInMs) { var action = new ActionMock(MockBehavior.Loose); action .When(x => x.Duration) .Return(TimeSpan.FromMilliseconds(durationInMs)); var sut = new ExerciseViewModelBuilder() .WithModel(new ExerciseBuilder() .WithBeforeExerciseAction(action)) .Build(); Assert.Equal(TimeSpan.FromMilliseconds(durationInMs), sut.Duration); }
public void duration_returns_sum_of_action_durations() { var action1 = new ActionMock(); var action2 = new ActionMock(); var action3 = new ActionMock(); action1 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(10)); action2 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(3)); action3 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(1)); var eventMatcher1 = new EventMatcherMock(); var eventMatcher2 = new EventMatcherMock(); var eventMatcher3 = new EventMatcherMock(); eventMatcher1 .When(x => x.Matches(It.IsAny<IEvent>())) .Return((IEvent @event) => @event is BeforeExerciseEvent); eventMatcher2 .When(x => x.Matches(It.IsAny<IEvent>())) .Return((IEvent @event) => @event is DuringRepetitionEvent); eventMatcher3 .When(x => x.Matches(It.IsAny<IEvent>())) .Return((IEvent @event) => @event is AfterSetEvent); var sut = new ExerciseBuilder() .WithSetCount(2) .WithRepetitionCount(3) .WithMatcherWithAction(new MatcherWithAction(eventMatcher1, action1)) .WithMatcherWithAction(new MatcherWithAction(eventMatcher2, action2)) .WithMatcherWithAction(new MatcherWithAction(eventMatcher3, action3)) .Build(); Assert.Equal(TimeSpan.FromSeconds(30), sut.Duration); }
public void execute_async_does_not_wait_for_inner_actions_execution_to_complete_before_itself_completing() { var action = new ActionMock(); action .When(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .Return(Observable.Never<Unit>()); var sut = new DoNotAwaitActionBuilder() .WithInnerAction(action) .Build(); var completed = false; sut .ExecuteAsync(new ExecutionContext()) .Subscribe(_ => completed = true); Assert.True(completed); }
public void duration_is_the_sum_of_all_exercise_durations() { var action1 = new ActionMock(); var action2 = new ActionMock(); action1 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(1)); action2 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(10)); var sut = new ExerciseProgramBuilder() .WithExercise(new ExerciseBuilder() .WithBeforeExerciseAction(action1)) .WithExercise(new ExerciseBuilder() .WithBeforeExerciseAction(action2)) .WithExercise(new ExerciseBuilder() .WithBeforeExerciseAction(action1)) .Build(); Assert.Equal(TimeSpan.FromSeconds(12), sut.Duration); }
public void skip_backwards_command_is_disabled_if_on_first_exercise() { var scheduler = new TestScheduler(); var action = new ActionMock(MockBehavior.Loose); action .When(x => x.Execute(It.IsAny<ExecutionContext>())) .Return<ExecutionContext>( ec => { ec.IsPaused = true; return ec.WaitWhilePaused(); }); var sut = new ExerciseProgramViewModelBuilder() .WithModel(new ExerciseProgramBuilder() .WithExercise(new ExerciseBuilder() .WithBeforeExerciseAction(action))) .WithScheduler(scheduler) .Build(); sut.StartCommand.ExecuteAsync(); scheduler.AdvanceMinimal(); Assert.False(sut.SkipBackwardsCommand.CanExecute.FirstAsync().Wait()); }
public void progress_is_updated_throughout_execution() { var scheduler = new TestScheduler(); var action = new ActionMock(MockBehavior.Loose); action .When(x => x.Duration) .Return(TimeSpan.FromMinutes(1)); action .When(x => x.Execute(It.IsAny<ExecutionContext>())) .Return<ExecutionContext>( ec => { ec.AddProgress(TimeSpan.FromSeconds(15)); ec.AddProgress(TimeSpan.FromSeconds(30)); ec.IsPaused = true; return ec.WaitWhilePaused(); }); var sut = new ExerciseProgramViewModelBuilder() .WithModel(new ExerciseProgramBuilder() .WithExercise(new ExerciseBuilder() .WithBeforeExerciseAction(action))) .WithScheduler(scheduler) .Build(); var progress = sut .WhenAnyValue(x => x.Progress) .CreateCollection(); sut.StartCommand.ExecuteAsync(); scheduler.AdvanceMinimal(); Assert.Equal(3, progress.Count); Assert.Equal(0, progress[0]); Assert.Equal(0.25, progress[1]); Assert.Equal(0.75, progress[2]); }
public void is_pause_visible_cycles_correctly_if_start_command_is_executed() { var scheduler = new TestScheduler(); var action = new ActionMock(MockBehavior.Loose); action .When(x => x.Duration) .Return(TimeSpan.FromMinutes(1)); action .When(x => x.Execute(It.IsAny<ExecutionContext>())) .Return<ExecutionContext>( ec => Observable .Return(Unit.Default) .Do(_ => { }) .Delay(TimeSpan.FromMinutes(1), scheduler) .Do(_ => ec.AddProgress(TimeSpan.FromMinutes(1)))); var sut = new ExerciseProgramViewModelBuilder() .WithModel( new ExerciseProgramBuilder() .WithExercise( new ExerciseBuilder() .WithBeforeExerciseAction(action))) .WithScheduler(scheduler) .Build(); Assert.False(sut.IsPauseVisible); sut.StartCommand.ExecuteAsync(); scheduler.AdvanceMinimal(); Assert.True(sut.IsPauseVisible); scheduler.AdvanceBy(TimeSpan.FromMinutes(10)); Assert.False(sut.IsPauseVisible); }
public void progress_time_span_is_updated_throughout_execution() { var scheduler = new TestSchedulerService(); var action = new ActionMock(MockBehavior.Loose); action .When(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .Return<ExecutionContext>( ec => { ec.AddProgress(TimeSpan.FromSeconds(1)); ec.AddProgress(TimeSpan.FromSeconds(3)); ec.IsPaused = true; return ec.WaitWhilePausedAsync(); }); var sut = new ExerciseProgramViewModelBuilder() .WithModel(new ExerciseProgramBuilder() .AddExercise(new ExerciseBuilder() .WithBeforeExerciseAction(action))) .WithSchedulerService(scheduler) .Build(); var progressTimeSpan = sut .WhenAnyValue(x => x.ProgressTimeSpan) .CreateCollection(); sut.StartCommand.Execute(null); scheduler.AdvanceMinimal(); Assert.Equal(3, progressTimeSpan.Count); Assert.Equal(TimeSpan.Zero, progressTimeSpan[0]); Assert.Equal(TimeSpan.FromSeconds(1), progressTimeSpan[1]); Assert.Equal(TimeSpan.FromSeconds(4), progressTimeSpan[2]); }
public void execute_executes_each_child_action_in_order() { var childCount = 10; var childExecutionOrder = new int[childCount]; var executionOrder = 0; var childActions = Enumerable .Range(0, childCount) .Select( (i, _) => { var childAction = new ActionMock(MockBehavior.Loose); childAction .When(x => x.Execute(It.IsAny<ExecutionContext>())) .Do(() => childExecutionOrder[i] = Interlocked.Increment(ref executionOrder)) .Return(Observable.Return(Unit.Default)); return childAction; }) .ToList(); var sut = new SequenceActionBuilder() .WithChildren(childActions) .Build(); using (var context = new ExecutionContext()) { sut.Execute(context).Subscribe(); for (var i = 0; i < childExecutionOrder.Length; ++i) { Assert.Equal(i + 1, childExecutionOrder[i]); } } }
public void execute_async_ensures_progress_of_child_actions_does_not_compound_when_skipping() { var action1 = new ActionMock(); var action2 = new ActionMock(); var action3 = new ActionMock(); var action4 = new ActionMock(); action1 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(3)); action2 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(8)); action3 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(10)); action4 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(4)); action1 .When(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .Do<ExecutionContext>(ec => ec.AddProgress(action1.Duration)) .Return(Observable.Return(Unit.Default)); action2 .When(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .Do<ExecutionContext>(ec => ec.AddProgress(action2.Duration)) .Return(Observable.Return(Unit.Default)); action3 .When(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .Do<ExecutionContext>(ec => ec.AddProgress(action3.Duration)) .Return(Observable.Return(Unit.Default)); action4 .When(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .Do<ExecutionContext>(ec => ec.AddProgress(action4.Duration)) .Return(Observable.Return(Unit.Default)); var sut = new ParallelActionBuilder() .AddChild(action1) .AddChild(action2) .AddChild(action3) .AddChild(action4) .Build(); using (var context = new ExecutionContext(TimeSpan.FromSeconds(5))) { sut.ExecuteAsync(context); Assert.Equal(TimeSpan.FromSeconds(10), context.Progress); action1 .Verify(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .WasNotCalled(); action4 .Verify(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .WasNotCalled(); } }
public void skip_backwards_command_restarts_the_execution_context_from_the_start_of_the_previous_exercise_if_the_current_exercise_if_only_recently_started() { var scheduler = new TestScheduler(); var action = new ActionMock(); action .When(x => x.Duration) .Return(TimeSpan.FromSeconds(10)); action .When(x => x.Execute(It.IsAny<ExecutionContext>())) .Return<ExecutionContext>( ec => { ec.AddProgress(TimeSpan.FromSeconds(0.5)); ec.IsPaused = true; return ec.WaitWhilePaused(); }); var exercise1 = new ExerciseBuilder() .WithName("Exercise 1") .WithBeforeExerciseAction(action) .Build(); var exercise2 = new ExerciseBuilder() .WithName("Exercise 2") .WithBeforeExerciseAction(action) .Build(); var sut = new ExerciseProgramViewModelBuilder() .WithModel(new ExerciseProgramBuilder() .WithExercise(exercise1) .WithExercise(exercise2)) .WithScheduler(scheduler) .Build(); var progress = sut .WhenAnyValue(x => x.ProgressTimeSpan) .CreateCollection(); // start from the second exercise sut.StartCommand.ExecuteAsync(exercise1.Duration); scheduler.AdvanceMinimal(); sut.SkipBackwardsCommand.ExecuteAsync(); scheduler.AdvanceMinimal(); Assert.Equal(5, progress.Count); Assert.Equal(TimeSpan.Zero, progress[0]); Assert.Equal(TimeSpan.FromSeconds(10), progress[1]); Assert.Equal(TimeSpan.FromSeconds(10.5), progress[2]); Assert.Equal(TimeSpan.Zero, progress[3]); Assert.Equal(TimeSpan.FromSeconds(10), progress[4]); }
public void execute_async_skips_actions_that_are_shorter_than_the_skip_ahead_even_if_the_context_is_paused() { var action1 = new ActionMock(MockBehavior.Loose); var action2 = new ActionMock(MockBehavior.Loose); var action3 = new ActionMock(MockBehavior.Loose); var eventMatcher1 = new EventMatcherMock(); var eventMatcher2 = new EventMatcherMock(); var eventMatcher3 = new EventMatcherMock(); action1 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(10)); action2 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(3)); action3 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(1)); action1 .When(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .Throw(); action2 .When(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .Throw(); eventMatcher1 .When(x => x.Matches(It.IsAny<IEvent>())) .Return((IEvent @event) => @event is BeforeExerciseEvent); eventMatcher2 .When(x => x.Matches(It.IsAny<IEvent>())) .Return((IEvent @event) => @event is BeforeExerciseEvent); eventMatcher3 .When(x => x.Matches(It.IsAny<IEvent>())) .Return((IEvent @event) => @event is BeforeExerciseEvent); var sut = new ExerciseBuilder() .AddMatcherWithAction(new MatcherWithAction(eventMatcher1, action1)) .AddMatcherWithAction(new MatcherWithAction(eventMatcher2, action2)) .AddMatcherWithAction(new MatcherWithAction(eventMatcher3, action3)) .Build(); using (var executionContext = new ExecutionContext(TimeSpan.FromSeconds(13))) { executionContext.IsPaused = true; sut.ExecuteAsync(executionContext); action3 .Verify(x => x.ExecuteAsync(executionContext)) .WasCalledExactlyOnce(); } }
public void execute_async_skips_child_actions_that_are_shorter_than_the_skip_ahead() { var action1 = new ActionMock(); var action2 = new ActionMock(); var action3 = new ActionMock(MockBehavior.Loose); action1 .When(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .Throw(); action2 .When(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .Throw(); action1 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(3)); action2 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(8)); action3 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(2)); var sut = new SequenceActionBuilder() .AddChild(action1) .AddChild(action2) .AddChild(action3) .Build(); using (var context = new ExecutionContext(TimeSpan.FromSeconds(11))) { sut.ExecuteAsync(context); action3 .Verify(x => x.ExecuteAsync(context)) .WasCalledExactlyOnce(); } }
public void skip_forwards_command_skips_to_the_next_exercise() { var scheduler = new TestScheduler(); var action = new ActionMock(); action .When(x => x.Duration) .Return(TimeSpan.FromSeconds(10)); action .When(x => x.Execute(It.IsAny<ExecutionContext>())) .Return<ExecutionContext>( ec => { ec.IsPaused = true; return ec.WaitWhilePaused(); }); var exercise1 = new ExerciseBuilder() .WithName("Exercise 1") .WithBeforeExerciseAction(action) .Build(); var exercise2 = new ExerciseBuilder() .WithName("Exercise 2") .WithBeforeExerciseAction(action) .Build(); var sut = new ExerciseProgramViewModelBuilder() .WithModel(new ExerciseProgramBuilder() .WithExercise(exercise1) .WithExercise(exercise2)) .WithScheduler(scheduler) .Build(); var progress = sut .WhenAnyValue(x => x.ProgressTimeSpan) .CreateCollection(); sut.StartCommand.ExecuteAsync(); scheduler.AdvanceMinimal(); sut.SkipForwardsCommand.ExecuteAsync(); scheduler.AdvanceMinimal(); Assert.Equal(2, progress.Count); Assert.Equal(TimeSpan.Zero, progress[0]); Assert.Equal(TimeSpan.FromSeconds(10), progress[1]); }
public void progress_is_calculated_based_on_duration_and_progress_time_span(int durationInMs, int progressInMs, double expectedProgress) { var scheduler = new TestSchedulerService(); var action = new ActionMock(MockBehavior.Loose); action .When(x => x.Duration) .Return(TimeSpan.FromMilliseconds(durationInMs)); var model = new ExerciseBuilder() .WithBeforeExerciseAction(action) .Build(); var executionContext = new ExecutionContext(); var sut = new ExerciseViewModelBuilder() .WithSchedulerService(scheduler) .WithExecutionContext(executionContext) .WithModel(model) .Build(); executionContext.SetCurrentExercise(model); executionContext.AddProgress(TimeSpan.FromMilliseconds(progressInMs)); scheduler.AdvanceMinimal(); Assert.Equal(expectedProgress, sut.Progress); }
public void execute_async_context_can_be_paused_by_child_action_that_is_not_the_longest() { var action1 = new ActionMock(MockBehavior.Loose); var action2 = new ActionMock(MockBehavior.Loose); action1 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(8)); action2 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(13)); action1 .When(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .Do<ExecutionContext>(ec => ec.IsPaused = true) .Return(Observable.Return(Unit.Default)); var sut = new ParallelActionBuilder() .AddChild(action1) .AddChild(action2) .Build(); using (var context = new ExecutionContext()) { sut.ExecuteAsync(context); // can't assume certain actions did not execute because actions run in parallel, but we can check the context is paused Assert.True(context.IsPaused); } }
public void execute_async_skips_actions_that_are_shorter_than_the_skip_ahead_even_if_the_execution_context_is_paused() { var action1 = new ActionMock(MockBehavior.Loose); var action2 = new ActionMock(MockBehavior.Loose); var action3 = new ActionMock(MockBehavior.Loose); action1 .When(x => x.Duration) .Return(TimeSpan.FromMinutes(1)); action2 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(10)); action3 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(71)); var sut = new ParallelActionBuilder() .AddChild(action1) .AddChild(action2) .AddChild(action3) .Build(); using (var context = new ExecutionContext(TimeSpan.FromSeconds(70))) { context.IsPaused = true; sut.ExecuteAsync(context); action1 .Verify(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .WasNotCalled(); action2 .Verify(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .WasNotCalled(); action3 .Verify(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .WasCalledExactlyOnce(); } }
public void skip_backwards_command_is_enabled_if_sufficient_progress_has_been_made_through_first_exercise() { var scheduler = new TestScheduler(); var action = new ActionMock(MockBehavior.Loose); action .When(x => x.Execute(It.IsAny<ExecutionContext>())) .Return<ExecutionContext>( ec => { ec.AddProgress(TimeSpan.FromSeconds(1)); ec.IsPaused = true; return ec.WaitWhilePaused(); }); var sut = new ExerciseProgramViewModelBuilder() .WithModel(new ExerciseProgramBuilder() .WithExercise(new ExerciseBuilder() .WithBeforeExerciseAction(action))) .WithScheduler(scheduler) .Build(); // TODO: technically, I should just check CanExecute(null) at the end, but without this subscription the RxCommand does not update CanExecute correctly // try changing this once I'm using new RxCommand var canExecute = sut .SkipBackwardsCommand .CanExecute .CreateCollection(); sut.StartCommand.ExecuteAsync(); scheduler.AdvanceMinimal(); Assert.Equal(2, canExecute.Count); Assert.False(canExecute[0]); Assert.True(canExecute[1]); }
public void execute_skips_child_actions_that_are_shorter_than_the_skip_ahead_even_if_the_context_is_paused() { var action1 = new ActionMock(); var action2 = new ActionMock(); var action3 = new ActionMock(MockBehavior.Loose); action1 .When(x => x.Execute(It.IsAny<ExecutionContext>())) .Throw(); action2 .When(x => x.Execute(It.IsAny<ExecutionContext>())) .Throw(); action1 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(3)); action2 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(8)); action3 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(2)); var sut = new SequenceActionBuilder() .WithChild(action1) .WithChild(action2) .WithChild(action3) .Build(); using (var context = new ExecutionContext(TimeSpan.FromSeconds(11))) { context.IsPaused = true; sut.Execute(context).Subscribe(); action3 .Verify(x => x.Execute(context)) .WasCalledExactlyOnce(); } }
public void skip_backwards_command_restarts_the_execution_context_from_the_start_of_the_current_exercise_if_sufficient_progress_has_been_made() { var scheduler = new TestScheduler(); var action = new ActionMock(MockBehavior.Loose); action .When(x => x.Execute(It.IsAny<ExecutionContext>())) .Return<ExecutionContext>( ec => { ec.AddProgress(TimeSpan.FromSeconds(4)); ec.IsPaused = true; return ec.WaitWhilePaused(); }); var sut = new ExerciseProgramViewModelBuilder() .WithModel(new ExerciseProgramBuilder() .WithExercise(new ExerciseBuilder() .WithBeforeExerciseAction(action))) .WithScheduler(scheduler) .Build(); var progress = sut .WhenAnyValue(x => x.ProgressTimeSpan) .CreateCollection(); sut.StartCommand.ExecuteAsync(); scheduler.AdvanceMinimal(); sut.SkipBackwardsCommand.ExecuteAsync(); scheduler.AdvanceMinimal(); Assert.Equal(3, progress.Count); Assert.Equal(TimeSpan.Zero, progress[0]); Assert.Equal(TimeSpan.FromSeconds(4), progress[1]); Assert.Equal(TimeSpan.Zero, progress[2]); }
public void execute_async_stops_executing_if_the_context_is_cancelled() { var action1 = new ActionMock(MockBehavior.Loose); var action2 = new ActionMock(MockBehavior.Loose); var action3 = new ActionMock(MockBehavior.Loose); var sut = new SequenceActionBuilder() .AddChild(action1) .AddChild(action2) .AddChild(action3) .Build(); using (var context = new ExecutionContext()) { action2 .When(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .Do(() => context.Cancel()) .Return(Observable.Return(Unit.Default)); Assert.ThrowsAsync<OperationCanceledException>(async () => await sut.ExecuteAsync(context)); action1 .Verify(x => x.ExecuteAsync(context)) .WasCalledExactlyOnce(); action2 .Verify(x => x.ExecuteAsync(context)) .WasCalledExactlyOnce(); action3 .Verify(x => x.ExecuteAsync(context)) .WasNotCalled(); } }
public void skip_forwards_command_is_disabled_if_on_last_exercise() { var scheduler = new TestScheduler(); var action = new ActionMock(); action .When(x => x.Duration) .Return(TimeSpan.FromSeconds(10)); action .When(x => x.Execute(It.IsAny<ExecutionContext>())) .Return<ExecutionContext>( ec => { ec.IsPaused = true; return ec.WaitWhilePaused(); }); var exercise1 = new ExerciseBuilder() .WithName("Exercise 1") .WithBeforeExerciseAction(action) .Build(); var exercise2 = new ExerciseBuilder() .WithName("Exercise 2") .WithBeforeExerciseAction(action) .Build(); var sut = new ExerciseProgramViewModelBuilder() .WithModel(new ExerciseProgramBuilder() .WithExercise(exercise1) .WithExercise(exercise2)) .WithScheduler(scheduler) .Build(); var canExecute = sut .SkipForwardsCommand .CanExecute .CreateCollection(); sut.StartCommand.ExecuteAsync(); scheduler.AdvanceMinimal(); sut.SkipForwardsCommand.ExecuteAsync(); scheduler.AdvanceMinimal(); Assert.Equal(5, canExecute.Count); Assert.False(canExecute[0]); Assert.True(canExecute[1]); Assert.False(canExecute[2]); Assert.True(canExecute[3]); Assert.False(canExecute[4]); }
public void execute_async_correctly_handles_a_skip_ahead_value_that_exceeds_even_the_longest_child_actions_duration() { var action1 = new ActionMock(MockBehavior.Loose); var action2 = new ActionMock(MockBehavior.Loose); var action3 = new ActionMock(MockBehavior.Loose); action1 .When(x => x.Duration) .Return(TimeSpan.FromMinutes(1)); action2 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(10)); action3 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(71)); var sut = new ParallelActionBuilder() .AddChild(action1) .AddChild(action2) .AddChild(action3) .Build(); using (var context = new ExecutionContext(TimeSpan.FromMinutes(3))) { sut.ExecuteAsync(context); action1 .Verify(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .WasNotCalled(); action2 .Verify(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .WasNotCalled(); action3 .Verify(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .WasNotCalled(); Assert.Equal(TimeSpan.FromSeconds(71), context.Progress); } }
public void current_exercise_reflects_that_in_the_execution_context() { var scheduler = new TestScheduler(); var action = new ActionMock(); action .When(x => x.Duration) .Return(TimeSpan.FromSeconds(10)); action .When(x => x.Execute(It.IsAny<ExecutionContext>())) .Return<ExecutionContext>( ec => { ec.IsPaused = true; return ec.WaitWhilePaused(); }); var exercise1 = new ExerciseBuilder() .WithName("Exercise 1") .WithBeforeExerciseAction(action) .Build(); var exercise2 = new ExerciseBuilder() .WithName("Exercise 2") .WithBeforeExerciseAction(action) .Build(); var exercise3 = new ExerciseBuilder() .WithName("Exercise 3") .WithBeforeExerciseAction(action) .Build(); var sut = new ExerciseProgramViewModelBuilder() .WithModel(new ExerciseProgramBuilder() .WithExercise(exercise1) .WithExercise(exercise2) .WithExercise(exercise3)) .WithScheduler(scheduler) .Build(); sut.StartCommand.ExecuteAsync(); scheduler.AdvanceMinimal(); Assert.Equal("Exercise 1", sut.CurrentExercise?.Name); sut.SkipForwardsCommand.ExecuteAsync(); scheduler.AdvanceMinimal(); Assert.Equal("Exercise 2", sut.CurrentExercise?.Name); sut.SkipForwardsCommand.ExecuteAsync(); scheduler.AdvanceMinimal(); Assert.Equal("Exercise 3", sut.CurrentExercise?.Name); sut.SkipBackwardsCommand.ExecuteAsync(); scheduler.AdvanceMinimal(); Assert.Equal("Exercise 2", sut.CurrentExercise?.Name); }
public void execute_async_skips_exercises_that_are_shorter_than_the_skip_ahead() { var action1 = new ActionMock(MockBehavior.Loose); var action2 = new ActionMock(MockBehavior.Loose); var action3 = new ActionMock(MockBehavior.Loose); action1 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(13)); action2 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(10)); action3 .When(x => x.Duration) .Return(TimeSpan.FromSeconds(5)); action1 .When(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .Throw(); action2 .When(x => x.ExecuteAsync(It.IsAny<ExecutionContext>())) .Throw(); var sut = new ExerciseProgramBuilder() .AddExercise(new ExerciseBuilder() .WithBeforeExerciseAction(action1)) .AddExercise(new ExerciseBuilder() .WithBeforeExerciseAction(action2)) .AddExercise(new ExerciseBuilder() .WithBeforeExerciseAction(action3)) .Build(); using (var executionContext = new ExecutionContext(TimeSpan.FromSeconds(23))) { sut.ExecuteAsync(executionContext); action3 .Verify(x => x.ExecuteAsync(executionContext)) .WasCalledExactlyOnce(); } }