public void retrieved_data_is_used_to_populate_the_initial_values() { new TestScheduler().With(scheduler => { var dinosaur = new Dinosaur("Barney", 13, new byte[] { 1, 2, 3 }); var api = new ApiMock(); api .When(x => x.GetDinosaur(42)) .Return(Observable.Return(dinosaur)); var sut = new DinosaurDetailsViewModel( 42, new BitmapLoaderMock(), api); sut .Activator .Activate(); scheduler.AdvanceByMs(1); Assert.Equal("Barney", sut.Name); Assert.Equal("13", sut.Weight); Assert.Equal(13, sut.ValidatedWeight.Value); Assert.NotNull(sut.Image); }); }
public void errors_retrieving_data_are_surfaced() { CurrentThreadScheduler.Instance.With(scheduler => { var api = new ApiMock(); api .When(x => x.GetDinosaur(It.IsAny <int>())) .Return(Observable.Throw <Dinosaur>(new InvalidOperationException("foo"))); var sut = new DinosaurDetailsViewModel( 42, new BitmapLoaderMock(), api); sut .Activator .Activate(); Assert.NotNull(sut.Error); Assert.Equal("foo", sut.Error.Exception.Message); api .When(x => x.GetDinosaur(It.IsAny <int>())) .Return(Observable.Return(default(Dinosaur))); sut .Error .RetryCommand .Execute(null); Assert.Null(sut.Error); }); }
public void errors_saving_data_are_surfaced() { new TestScheduler().With(scheduler => { var api = new ApiMock(); api .When(x => x.SaveDinosaur(It.IsAny <Dinosaur>())) .Return(Observable.Throw <Unit>(new InvalidOperationException("foo"))); var sut = new DinosaurDetailsViewModel( 42, new BitmapLoaderMock(), api); sut .Activator .Activate(); sut.Name = "Barney"; sut.Weight = "42"; scheduler.AdvanceByMs(2001); Assert.NotNull(sut.Error); Assert.Equal("foo", sut.Error.Exception.Message); api .When(x => x.SaveDinosaur(It.IsAny <Dinosaur>())) .Return(Observable.Return(Unit.Default)); sut .Error .RetryCommand .Execute(null); scheduler.AdvanceByMs(1); Assert.Null(sut.Error); }); }
public void busy_flag_remains_true_whilst_saving_data() { new TestScheduler().With(scheduler => { var api = new ApiMock(); var saveDinosaur = new Subject <Unit>(); api .When(x => x.SaveDinosaur(It.IsAny <Dinosaur>())) .Return(saveDinosaur); var sut = new DinosaurDetailsViewModel( 42, new BitmapLoaderMock(), api); sut .Activator .Activate(); sut.Name = "Barney"; sut.Weight = "42"; scheduler.AdvanceByMs(2001); Assert.True(sut.IsBusy); saveDinosaur.OnCompleted(); scheduler.AdvanceByMs(1); Assert.False(sut.IsBusy); }); }
public void busy_flag_remains_true_whilst_deleting_data() { CurrentThreadScheduler.Instance.With(scheduler => { var api = new ApiMock(); var deleteDinosaur = new Subject <Unit>(); api .When(x => x.DeleteDinosaur(It.IsAny <int>())) .Return(deleteDinosaur); var sut = new DinosaurDetailsViewModel( 42, new BitmapLoaderMock(), api); sut .Activator .Activate(); using (sut.ConfirmDeleteInteraction.RegisterHandler(context => context.SetOutput(true))) { sut .DeleteCommand .Execute() .Subscribe(); Assert.True(sut.IsBusy); } deleteDinosaur.OnCompleted(); Assert.False(sut.IsBusy); }); }
public void data_cannot_be_deleted_if_the_auditing_system_is_unavailable() { var api = new ApiMock(); var isAuditingAvailable = new BehaviorSubject <bool>(true); api .When(x => x.IsAuditingAvailable) .Return(isAuditingAvailable); var sut = new DinosaurDetailsViewModel( 42, new BitmapLoaderMock(), api); sut .Activator .Activate(); Assert.True(sut.DeleteCommand.CanExecute.FirstAsync().Wait()); isAuditingAvailable.OnNext(false); Assert.False(sut.DeleteCommand.CanExecute.FirstAsync().Wait()); isAuditingAvailable.OnNext(true); Assert.True(sut.DeleteCommand.CanExecute.FirstAsync().Wait()); }
public void saves_are_throttled_to_two_seconds() { new TestScheduler().With(scheduler => { var api = new ApiMock(); var sut = new DinosaurDetailsViewModel( 42, new BitmapLoaderMock(), api); sut .Activator .Activate(); scheduler.AdvanceByMs(2000); sut.Name = "Barney"; scheduler.AdvanceByMs(500); sut.Name = "Barney the Dinosaur"; scheduler.AdvanceByMs(500); sut.Weight = "42"; scheduler.AdvanceByMs(1999); api .Verify(x => x.SaveDinosaur(It.IsAny <Dinosaur>())) .WasNotCalled(); scheduler.AdvanceByMs(1); api .Verify(x => x.SaveDinosaur(It.IsAny <Dinosaur>())) .WasCalledExactlyOnce(); }); }
public void data_is_saved_immediately_upon_deactivation_even_if_two_seconds_has_not_elapsed_since_last_change() { new TestScheduler().With(scheduler => { var api = new ApiMock(); var sut = new DinosaurDetailsViewModel( 42, new BitmapLoaderMock(), api); sut .Activator .Activate(); sut.Name = "Barney"; scheduler.AdvanceByMs(1); api .Verify(x => x.SaveDinosaur(It.IsAny <Dinosaur>())) .WasNotCalled(); sut .Activator .Deactivate(); scheduler.AdvanceByMs(1); api .Verify(x => x.SaveDinosaur(It.IsAny <Dinosaur>())) .WasCalledExactlyOnce(); }); }
public void data_is_saved_two_seconds_after_image_data_is_modified() { new TestScheduler().With(scheduler => { var api = new ApiMock(); var sut = new DinosaurDetailsViewModel( 42, new BitmapLoaderMock(), api); sut .Activator .Activate(); scheduler.AdvanceByMs(2000); sut.Weight = "42"; sut.ImageData = new byte[] { 1, 2, 3 }; scheduler.AdvanceByMs(1999); api .Verify(x => x.SaveDinosaur(It.IsAny <Dinosaur>())) .WasNotCalled(); scheduler.AdvanceByMs(1); api .Verify(x => x.SaveDinosaur(It.IsAny <Dinosaur>())) .WasCalledExactlyOnce(); }); }
public void data_is_not_retrieved_upon_construction() { var api = new ApiMock(); var sut = new DinosaurDetailsViewModel( 42, new BitmapLoaderMock(), api); api .Verify(x => x.GetDinosaur(It.IsAny <int>())) .WasNotCalled(); }
public void data_is_retrieved_upon_activation() { var api = new ApiMock(); var sut = new DinosaurDetailsViewModel( 42, new BitmapLoaderMock(), api); sut .Activator .Activate(); api .Verify(x => x.GetDinosaur(42)) .WasCalledExactlyOnce(); }
public void data_is_not_saved_if_it_is_invalid() { var api = new ApiMock(); var sut = new DinosaurDetailsViewModel( 42, new BitmapLoaderMock(), api); sut .Activator .Activate(); sut.Weight = "42a"; api .Verify(x => x.SaveDinosaur(It.IsAny <Dinosaur>())) .WasNotCalled(); }
public void data_is_deleted_if_user_confirms() { var api = new ApiMock(); var sut = new DinosaurDetailsViewModel( 42, new BitmapLoaderMock(), api); using (sut.ConfirmDeleteInteraction.RegisterHandler(context => context.SetOutput(true))) { sut .DeleteCommand .Execute() .Subscribe(); } api .Verify(x => x.DeleteDinosaur(It.IsAny <int>())) .WasCalledExactlyOnce(); }
public void memory_is_reclaimed_after_deactivation() { // // IMPORTANT: if you're observing failures in this test, try running it in release mode without a debugger attached. // CurrentThreadScheduler.Instance.With(scheduler => { // The SUT will subscribe to this subject, so we hold a reference to it so that it can't be GC'd. var isAuditingAvailable = new Subject <bool>(); var api = new ApiMock(); api .When(x => x.IsAuditingAvailable) .Return(isAuditingAvailable); var sut = new DinosaurDetailsViewModel( 42, new BitmapLoaderMock(), api); sut .Activator .Activate(); var weakSut = new WeakReference(sut); sut = null; GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); Assert.True(weakSut.IsAlive); // Deactivation is when the SUT should detach subscriptions and therefore become eligible for collection. ((DinosaurDetailsViewModel)weakSut.Target) .Activator .Deactivate(); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); Assert.False(weakSut.IsAlive); }); }
public void errors_deleting_data_are_surfaced() { CurrentThreadScheduler.Instance.With(scheduler => { var api = new ApiMock(); api .When(x => x.DeleteDinosaur(It.IsAny <int>())) .Return(Observable.Throw <Unit>(new InvalidOperationException("foo"))); var sut = new DinosaurDetailsViewModel( 42, new BitmapLoaderMock(), api); sut .Activator .Activate(); using (sut.ConfirmDeleteInteraction.RegisterHandler(context => context.SetOutput(true))) { sut .DeleteCommand .Execute() .Subscribe( _ => { }, _ => { }); Assert.NotNull(sut.Error); Assert.Equal("foo", sut.Error.Exception.Message); api .When(x => x.DeleteDinosaur(It.IsAny <int>())) .Return(Observable.Return(Unit.Default)); sut .Error .RetryCommand .Execute(null); Assert.Null(sut.Error); } }); }
public void busy_flag_remains_true_whilst_retrieving_data() { CurrentThreadScheduler.Instance.With(scheduler => { var api = new ApiMock(); var getDinosaur = new Subject <Dinosaur>(); api .When(x => x.GetDinosaur(It.IsAny <int>())) .Return(getDinosaur); var sut = new DinosaurDetailsViewModel( 42, new BitmapLoaderMock(), api); sut .Activator .Activate(); Assert.True(sut.IsBusy); getDinosaur.OnCompleted(); Assert.False(sut.IsBusy); }); }