public async Task Extended_interface_contract_changes_can_be_detected() { var ct = CancellationToken.None; IStackNavigator navigator = new BlindStackNavigator(); // If the extension methods available in the abstraction package change their signatures, we get compilation errors here. TestVM vmAfterNavigate = await navigator.Navigate(ct, () => new TestVM(), suppressTransition : false); TestVM vmAfterNavigateAndClear = await navigator.NavigateAndClear(ct, () => new TestVM(), suppressTransition : false); INavigableViewModel vm = navigator.GetActiveViewModel(); bool canGoBack = navigator.CanNavigateBack(); // Navigate twice so that RemovePrevious works. await navigator.Navigate(ct, () => new TestVM(), suppressTransition : false); await navigator.Navigate(ct, () => new TestVM(), suppressTransition : false); await navigator.RemovePrevious(ct); bool didNavigateBack = await navigator.TryNavigateBackTo <TestVM>(ct); await navigator.ProcessRequest(ct, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(), false, false)); IObservable <EventPattern <StackNavigatorEventArgs> > ob1 = navigator.ObserveStateChanged(); IObservable <StackNavigatorState> ob2 = navigator.ObserveCurrentState(); }
public void It_has_a_default_state() { var sut = new BlindStackNavigator(); Assert.NotNull(sut.State); Assert.Empty(sut.State.Stack); }
public async Task It_produces_failed_notifications_for_RemoveEntry() { var sut = new BlindStackNavigator(); await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(throwOnDispose: true))); await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM())); var events = new List <StackNavigatorEventArgs>(); sut.StateChanged += Sut_StateChanged; void Sut_StateChanged(object sender, StackNavigatorEventArgs args) { events.Add(args); } await Assert.ThrowsAsync <InvalidOperationException>(async() => await sut.RemoveEntries(CancellationToken.None, new int[] { 0 })); sut.StateChanged -= Sut_StateChanged; // There must be 2 notifications: 1 Processing when the remove starts and 1 FailedToProcess when it ends. Assert.Equal(2, events.Count); Assert.Equal(NavigatorRequestState.Processing, events[0].CurrentState.LastRequestState); Assert.Equal(NavigatorRequestState.FailedToProcess, events[1].CurrentState.LastRequestState); }
public async Task It_produces_2_notifications_for_Back() { var sut = new BlindStackNavigator(); // Add 2 items to be able to perform a back operation. await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM())); await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM())); var events = new List <StackNavigatorEventArgs>(); sut.StateChanged += Sut_StateChanged; void Sut_StateChanged(object sender, StackNavigatorEventArgs args) { events.Add(args); } await sut.NavigateBack(CancellationToken.None); sut.StateChanged -= Sut_StateChanged; // There must be 2 notifications: 1 Processing when the back starts and 1 Processed when it ends. Assert.Equal(2, events.Count); Assert.Equal(NavigatorRequestState.Processing, events[0].CurrentState.LastRequestState); Assert.Equal(NavigatorRequestState.Processed, events[1].CurrentState.LastRequestState); }
public async Task It_removes_multiple_entries_and_navigate_back_correctly() { var sut = new BlindStackNavigator(); // Add 6 items to the stack. await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(0))); await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(1))); await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(2))); await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(3))); await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(4))); await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(5))); var indexes = Enumerable.Range(2, 3); // Remove the third, fourth and fifth items await sut.RemoveEntries(CancellationToken.None, indexes); // There must be 3 items left Assert.Equal(3, sut.State.Stack.Count); // Navigates back await sut.NavigateBack(CancellationToken.None); // The viewmodel count should be 2 and the current viewmodel id should be 1 Assert.Equal(2, sut.State.Stack.Count); Assert.Equal(1, ((TestVM)sut.State.Stack.Last().ViewModel).Id); }
public async Task It_adds_entries_to_stack_when_it_navigates_forward() { var sut = new BlindStackNavigator(); var vm = await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM())); Assert.NotNull(vm); Assert.Single(sut.State.Stack); }
public async Task It_removes_all_stack_entries_when_it_clears() { var sut = new BlindStackNavigator(); // Add an item to the stack. await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM())); // Clear the stack. await sut.Clear(CancellationToken.None); // Stack must be empty. Assert.Empty(sut.State.Stack); }
public async Task It_disposes_VM_when_navigating_back() { var sut = new BlindStackNavigator(); // Add 2 items to the stack. await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(0))); var vm = (TestVM)await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(1))); // Navigate back to remove the last item. await sut.NavigateBack(CancellationToken.None); // The removed entry must be disposed. Assert.True(vm.IsDisposed); }
public async Task It_disposes_VM_when_removing_entries() { var sut = new BlindStackNavigator(); // Add 2 items to the stack. var vm = (TestVM)await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(0))); await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(1))); // Remove the first item. await sut.RemoveEntries(CancellationToken.None, new int[] { 0 }); // The removed entry must be disposed. Assert.True(vm.IsDisposed); }
public async Task It_disposes_VMs_when_clearing() { var sut = new BlindStackNavigator(); // Add 2 items to the stack. var vm0 = (TestVM)await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(0))); var vm1 = (TestVM)await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(1))); // Clear to remove all items. await sut.Clear(CancellationToken.None); // All entries must be disposed. Assert.True(vm0.IsDisposed); Assert.True(vm1.IsDisposed); }
public async Task It_removes_entries_correctly() { var sut = new BlindStackNavigator(); // Add 2 items to the stack. await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(0))); await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(1))); // Remove the first item await sut.RemoveEntries(CancellationToken.None, new int[] { 0 }); // There must be only 1 item left in the stack because we just removed one. Assert.Single(sut.State.Stack); // The remaining item must be the second navigation. Assert.Equal(1, ((TestVM)sut.State.Stack.Last().ViewModel).Id); }
public async Task Interface_contract_changes_can_be_detected() { var ct = CancellationToken.None; IStackNavigator navigator = new BlindStackNavigator(); // If the core contract changes, we get compilation errors here. INavigableViewModel vmAfterNavigate = await navigator.Navigate(ct, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(), false, false)); INavigableViewModel vmAfterBack = await navigator.NavigateBack(ct); await navigator.Clear(ct); // Navigate twice so that RemoveEntries works. await navigator.Navigate(ct, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(), false, false)); await navigator.Navigate(ct, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(), false, false)); await navigator.RemoveEntries(ct, new int[] { 0 }.AsEnumerable()); }
public async Task It_fails_to_navigate_back_when_there_arent_enough_entries() { var sut = new BlindStackNavigator(); // Add 1 item to the stack. await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM())); var stackBeforeNavigateBack = sut.State.Stack; // Navigating back must 'fail' if there is only 1 entry. // There is no exception, but the result vm must be null. var vm = await sut.NavigateBack(CancellationToken.None); Assert.Null(vm); var stackAfterNavigateBack = sut.State.Stack; // Because the back didn't do anything, the stack must not change. Assert.Equal(stackAfterNavigateBack, stackBeforeNavigateBack); }
public async Task It_navigates_back() { var sut = new BlindStackNavigator(); // Add 2 items to the stack. await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(0))); await sut.Navigate(CancellationToken.None, StackNavigatorRequest.GetNavigateRequest(() => new TestVM(1))); // The last entry must match the last navigation. Assert.Equal(1, ((TestVM)sut.State.Stack.Last().ViewModel).Id); var vmFromNavigation = await sut.NavigateBack(CancellationToken.None); var vmFromStack = (TestVM)sut.State.Stack.Last().ViewModel; // The ViewModels from the navigation and stack must be the same. Assert.Equal(vmFromStack, vmFromNavigation); // The final ViewModel must be the first one we navigated to. Assert.Equal(0, vmFromStack.Id); }