using System.Threading.Tasks; using NSubstitute; using NUnit.Framework; using ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock; using ShareeBike.View; using ShareeBike.ViewModel; using ShareeBike.ViewModel.Bikes; using ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler; using CancelReservationCommand = ShareeBike.Model.Bikes.BikeInfoNS.BikeNS.Command.CancelReservationCommand; using DisconnectCommand = ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock.Command.DisconnectCommand; using ShareeBike.ViewModel.Bikes.Bike; using ShareeBike.Model.State; using NSubstitute.Core.Arguments; using ShareeBike.Model.Bikes.BikeInfoNS.BikeNS.Command; namespace SharedBusinessLogic.Tests.ViewModel.Bikes.Bike { [TestFixture] public class TestCancelReservationActionViewModel { [Test] public async Task TestCancelReservation() { var bike = Substitute.For(); var pollingManager = Substitute.For(); var viewService = Substitute.For(); var bikesViewModel = Substitute.For(); var listener = Substitute.For(); var cancelReservationActionViewModel = new CancelReservationActionViewModel( bike, () => pollingManager, viewService, bikesViewModel); bike.Id.Returns("0"); bike.State.Value.Returns(InUseStateEnum.Reserved); bike.CancelReservationAsync(Arg.Any()).Returns(x => { cancelReservationActionViewModel.ReportStep(CancelReservationCommand.Step.CancelReservation); return Task.CompletedTask; }); bike.LockInfo.State.Returns(LockingState.Closed); bike.DisconnectAsync(Arg.Any()).Returns(x => { cancelReservationActionViewModel.ReportStep(DisconnectCommand.Step.DisconnectLock); return Task.CompletedTask; }); await cancelReservationActionViewModel.CancelReservationAsync(); bike.State.Value.Returns(InUseStateEnum.Disposable); bike.LockInfo.State.Returns(LockingState.UnknownDisconnected); // Verify behavior Received.InOrder(() => { bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.ActionText = "One moment please..."; pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action bikesViewModel.ActionText = "Canceling reservation..."; bikesViewModel.ActionText = "Disconnecting lock..."; bikesViewModel.ActionText = "One moment please..."; pollingManager.StartAsync(); // polling must be restarted again bikesViewModel.ActionText = string.Empty; bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked }); } [Test] public async Task TestCancelReservationException() { var bike = Substitute.For(); var pollingManager = Substitute.For(); var viewService = Substitute.For(); var bikesViewModel = Substitute.For(); var listener = Substitute.For(); var cancelReservationActionViewModel = new CancelReservationActionViewModel( bike, () => pollingManager, viewService, bikesViewModel); bike.Id.Returns("0"); bike.State.Value.Returns(InUseStateEnum.Reserved); bike.CancelReservationAsync(Arg.Any()).Returns(x => { cancelReservationActionViewModel.ReportStep(CancelReservationCommand.Step.CancelReservation); cancelReservationActionViewModel.ReportStateAsync(CancelReservationCommand.State.GeneralCancelReservationError, "details").Wait(); return Task.CompletedTask; }); await cancelReservationActionViewModel.CancelReservationAsync(); bike.State.Value.Returns(InUseStateEnum.Reserved); // Verify behavior Received.InOrder(() => { bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.ActionText = "One moment please..."; pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action bikesViewModel.ActionText = "Canceling reservation..."; bikesViewModel.ActionText = string.Empty; viewService.DisplayAdvancedAlert( "Reservation could not be canceled!", "details", "Please try again.", "OK"); bikesViewModel.ActionText = "One moment please..."; pollingManager.StartAsync(); // polling must be restarted again bikesViewModel.ActionText = string.Empty; bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked }); } [Test] public async Task TestCancelReservationNoWebException() { var bike = Substitute.For(); var pollingManager = Substitute.For(); var viewService = Substitute.For(); var bikesViewModel = Substitute.For(); var listener = Substitute.For(); var cancelReservationActionViewModel = new CancelReservationActionViewModel( bike, () => pollingManager, viewService, bikesViewModel); bike.Id.Returns("0"); bike.State.Value.Returns(InUseStateEnum.Reserved); bike.CancelReservationAsync(Arg.Any()).Returns(x => { cancelReservationActionViewModel.ReportStep(CancelReservationCommand.Step.CancelReservation); cancelReservationActionViewModel.ReportStateAsync(CancelReservationCommand.State.WebConnectFailed, "details").Wait(); return Task.CompletedTask; }); await cancelReservationActionViewModel.CancelReservationAsync(); bike.State.Value.Returns(InUseStateEnum.Reserved); // Verify behavior Received.InOrder(() => { bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.ActionText = "One moment please..."; pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action bikesViewModel.ActionText = "Canceling reservation..."; bikesViewModel.ActionText = string.Empty; viewService.DisplayAlert( "Connection to booking system not possible.", "A stable Internet connection is required. Connect to WIFI or to mobile network and activate mobile data. Try again.", "OK" ); bikesViewModel.ActionText = "One moment please..."; pollingManager.StartAsync(); // polling must be restarted again bikesViewModel.ActionText = string.Empty; bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked }); } [Test] public async Task TestCancelReservationInvalidResponseException() { var bike = Substitute.For(); var pollingManager = Substitute.For(); var viewService = Substitute.For(); var bikesViewModel = Substitute.For(); var listener = Substitute.For(); var cancelReservationActionViewModel = new CancelReservationActionViewModel( bike, () => pollingManager, viewService, bikesViewModel); bike.Id.Returns("0"); bike.State.Value.Returns(InUseStateEnum.Reserved); bike.CancelReservationAsync(Arg.Any()).Returns(x => { cancelReservationActionViewModel.ReportStep(CancelReservationCommand.Step.CancelReservation); cancelReservationActionViewModel.ReportStateAsync(CancelReservationCommand.State.InvalidResponse, "details").Wait(); return Task.CompletedTask; }); await cancelReservationActionViewModel.CancelReservationAsync(); bike.State.Value.Returns(InUseStateEnum.Reserved); // Verify behavior Received.InOrder(() => { bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.ActionText = "One moment please..."; pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action bikesViewModel.ActionText = "Canceling reservation..."; bikesViewModel.ActionText = string.Empty; viewService.DisplayAlert( "Reservation could not be canceled!", "Your session has expired. Please login new and try again.", "OK" ); bikesViewModel.ActionText = "One moment please..."; pollingManager.StartAsync(); // polling must be restarted again bikesViewModel.ActionText = string.Empty; bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked }); } } }