sharee.bike-App/TestShareeLib/ViewModel/Bikes/Bike/BluetoothLock/TestCloseLockActionViewModel.cs
2023-09-22 11:38:42 +02:00

212 lines
7.6 KiB
C#

using System.Threading.Tasks;
using NSubstitute;
using NUnit.Framework;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Connector;
using TINK.Model.State;
using TINK.Services.BluetoothLock;
using TINK.View;
using TINK.ViewModel;
using TINK.ViewModel.Bikes;
using TINK.ViewModel.Bikes.Bike.BluetoothLock;
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
using static TINK.Model.Bikes.BikeInfoNS.BluetoothLock.Command.CloseCommand;
namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock
{
[TestFixture]
public class TestCloseLockActionViewModel
{
/// <summary>
/// Use case: Close lock.
/// Final state: Occupied closed, End rental requested
/// </summary>
[Test]
public async Task TestCloseLockAndRequestEndRental()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var command = Substitute.For<ICommand>();
var locks = Substitute.For<ILocksService>();
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
var viewService = Substitute.For<IViewService>();
var bikesViewModel = Substitute.For<IBikesViewModel>();
var listener = Substitute.For<ICloseCommandListener>();
var closeLockActionViewModel = new CloseLockActionViewModel<BookedOpen>(
bike,
() => pollingManager,
viewService,
bikesViewModel);
bike.Id.Returns("0");
bike.CloseLockAsync(Arg.Any<ICloseCommandListener>(), Arg.Any<Task>()).Returns(x =>
{
// Add calls to ReportStep which IBikeInfoMutable implementation would do.
closeLockActionViewModel.ReportStep(Step.StartStopingPolling);
closeLockActionViewModel.ReportStep(Step.StartingQueryingLocation);
closeLockActionViewModel.ReportStep(Step.ClosingLock);
closeLockActionViewModel.ReportStep(Step.WaitStopPollingQueryLocation);
closeLockActionViewModel.ReportStep(Step.QueryLocationTerminated);
closeLockActionViewModel.ReportStep(Step.UpdateLockingState);
return Task.CompletedTask;
});
bike.State.Value.Returns(InUseStateEnum.Booked); // Request handler factory queries state to create appropriate request handler object.
bike.LockInfo.State.Returns(LockingState.Closed); // Request handler factory queries lock state to create appropriate request handler object.
await closeLockActionViewModel.CloseLockAsync();
// 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.StartRentalProcess(Arg.Is<IRentalProcessViewModel>(
x => x.BikeId == "0"
&& x.State == CurrentRentalProcess.CloseLock
&& x.StepIndex == 1
&& x.Result == CurrentStepStatus.None));
//Step.StartingQueryingLocation
bikesViewModel.ActionText = "Start query location...";
//Step.ClosingLock
bikesViewModel.ActionText = "The lock bolt moves through the spokes of the rear wheel.";
//Step.WaitStopPollingQueryLocation
bikesViewModel.ActionText = "Query location...";
//Step.UpdateLockingState
bikesViewModel.ActionText = "Updating lock state...";
bikesViewModel.ActionText = "One moment please...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.RentalProcess.Result = CurrentStepStatus.Succeeded;
bikesViewModel.RentalProcess.StepIndex = 2;
bikesViewModel.RentalProcess.Result = CurrentStepStatus.None;
//Ask whether park bike or end rental
viewService.DisplayAlert(
"Please choose",
"Do you want to park the bike to continue riding later or return the bike now and end the rental?",
"End rental",
"Park bike"
);
closeLockActionViewModel.IsEndRentalRequested = true;
bikesViewModel.RentalProcess.Result = CurrentStepStatus.Succeeded;
bikesViewModel.RentalProcess.State = CurrentRentalProcess.None;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
return;
});
}
/// <summary>
/// Use case: Close lock.
/// Final state: Occupied closed, Park bike requested
/// </summary>
[Test]
public async Task TestCloseLockAndRequestParkBike()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var command = Substitute.For<ICommand>();
var locks = Substitute.For<ILocksService>();
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
var viewService = Substitute.For<IViewService>();
var bikesViewModel = Substitute.For<IBikesViewModel>();
var listener = Substitute.For<ICloseCommandListener>();
var closeLockActionViewModel = new CloseLockActionViewModel<BookedOpen>(
bike,
() => pollingManager,
viewService,
bikesViewModel);
bike.Id.Returns("0");
bike.CloseLockAsync(Arg.Any<ICloseCommandListener>(), Arg.Any<Task>()).Returns(x =>
{
// Add calls to ReportStep which IBikeInfoMutable implementation would do.
closeLockActionViewModel.ReportStep(Step.StartStopingPolling);
closeLockActionViewModel.ReportStep(Step.StartingQueryingLocation);
closeLockActionViewModel.ReportStep(Step.ClosingLock);
closeLockActionViewModel.ReportStep(Step.WaitStopPollingQueryLocation);
closeLockActionViewModel.ReportStep(Step.QueryLocationTerminated);
closeLockActionViewModel.ReportStep(Step.UpdateLockingState);
return Task.CompletedTask;
});
bike.State.Value.Returns(InUseStateEnum.Booked); // Request handler factory queries state to create appropriate request handler object.
bike.LockInfo.State.Returns(LockingState.Closed); // Request handler factory queries lock state to create appropriate request handler object.
await closeLockActionViewModel.CloseLockAsync();
// 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.StartRentalProcess(Arg.Is<IRentalProcessViewModel>(
x => x.BikeId == "0"
&& x.State == CurrentRentalProcess.CloseLock
&& x.StepIndex == 1
&& x.Result == CurrentStepStatus.None));
//Step.StartingQueryingLocation
bikesViewModel.ActionText = "Start query location...";
//Step.ClosingLock
bikesViewModel.ActionText = "The lock bolt moves through the spokes of the rear wheel.";
//Step.WaitStopPollingQueryLocation
bikesViewModel.ActionText = "Query location...";
//Step.UpdateLockingState
bikesViewModel.ActionText = "Updating lock state...";
bikesViewModel.ActionText = "One moment please...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.RentalProcess.Result = CurrentStepStatus.Succeeded;
bikesViewModel.RentalProcess.StepIndex = 2;
bikesViewModel.RentalProcess.Result = CurrentStepStatus.None;
//Ask whether park bike or end rental
viewService.DisplayAlert(
"Please choose",
"Do you want to park the bike to continue riding later or return the bike now and end the rental?",
"End rental",
"Park bike"
);
closeLockActionViewModel.IsEndRentalRequested = false;
bikesViewModel.RentalProcess.Result = CurrentStepStatus.Succeeded;
//Show confirmation
viewService.DisplayAlert(
"Lock is closed",
"Bike is parked. Your chargeable rental continues!",
"OK"
);
bikesViewModel.RentalProcess.State = CurrentRentalProcess.None;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
return;
});
}
}
}