mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2025-04-19 03:27:29 +02:00
Legacy testing lib added..
This commit is contained in:
parent
0167fc321f
commit
47ed05837e
118 changed files with 17505 additions and 0 deletions
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,462 @@
|
|||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike.BluetoothLock;
|
||||
using TINK.Model.Bikes.Bike.BluetoothLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using TINK.Services.BluetoothLock.Exception;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
using TINK.Model.Services.Geolocation;
|
||||
using TINK.Model.State;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
|
||||
using TINK.Model.User;
|
||||
using TINK.Model.Device;
|
||||
|
||||
namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestBookedDisconnected
|
||||
{
|
||||
/// <summary>
|
||||
/// Test construction of object.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Testctor()
|
||||
{
|
||||
var handler = new BookedDisconnected(
|
||||
Substitute.For<IBikeInfoMutable>(),
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => Substitute.For<IConnector>(),
|
||||
Substitute.For<IGeolocation>(),
|
||||
Substitute.For<ILocksService>(),
|
||||
() => Substitute.For<IPollingUpdateTaskManager>(),
|
||||
Substitute.For<ISmartDevice>(),
|
||||
Substitute.For<IViewService>(),
|
||||
Substitute.For<IBikesViewModel>(),
|
||||
Substitute.For<IUser>());
|
||||
|
||||
// Verify prerequisites.
|
||||
Assert.AreEqual("BookedDisconnected", handler.ButtonText);
|
||||
Assert.IsFalse(handler.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", handler.LockitButtonText);
|
||||
Assert.IsTrue(handler.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNotSupported()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new BookedDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify that nothing happened because request is not supported.
|
||||
Assert.AreEqual("BookedDisconnected", subsequent.ButtonText);
|
||||
Assert.IsFalse(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
|
||||
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Search.
|
||||
/// Final state: Booked open
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSearch()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
var timeOuts = Substitute.For<ITimeOutProvider>();
|
||||
|
||||
var handler = new BookedDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>())
|
||||
.Returns(Task.FromResult(new LockInfoTdo.Builder { State = LockitLockingState.Open }.Build()));
|
||||
locks.TimeOut.Returns(timeOuts);
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Request server...";
|
||||
connector.Command.CalculateAuthKeys(bike);
|
||||
bikesViewModel.ActionText = "Searching lock...";
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>());
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Close lock & return bike", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
|
||||
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Search.
|
||||
/// Final state: Booked unknown
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSearchCalculateAuthKeysFailsWebConnectFailureException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new BookedDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
connector.Command.CalculateAuthKeys(bike).Returns(x => throw new WebConnectFailureException("Context info", new Exception("Tst")));
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
bike.LockInfo.State.Returns(LockingState.Unknown);
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Request server...";
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Fehler bei Verbinden mit Schloss!", "Internet muss erreichbar sein um Verbindung mit Schloss für gemietetes Rad herzustellen.\r\nContext info\r\nIst WLAN verfügbar/ Mobilfunknetz vefügbar und mobile Daten aktiviert / ... ?", "OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("BookedDisconnected", handler.ButtonText);
|
||||
Assert.IsFalse(handler.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", handler.LockitButtonText);
|
||||
Assert.IsTrue(handler.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Search.
|
||||
/// Final state: Booked unknown
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSearchCalculateAuthKeysFailsException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new BookedDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
connector.Command.CalculateAuthKeys(bike).Returns(x => throw new Exception("Exception message."));
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
bike.LockInfo.State.Returns(LockingState.Unknown);
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Request server...";
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Fehler bei Verbinden mit Schloss!", "Kommunikationsfehler bei Schlosssuche.\r\nException message.", "OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("BookedDisconnected", handler.ButtonText);
|
||||
Assert.IsFalse(handler.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", handler.LockitButtonText);
|
||||
Assert.IsTrue(handler.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Search.
|
||||
/// Final state: Booked unknown
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSearchConnectFailsOutOfReachException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
var timeOuts = Substitute.For<ITimeOutProvider>();
|
||||
|
||||
var handler = new BookedDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>())
|
||||
.Returns<Task<LockInfoTdo>>(x => { throw new OutOfReachException(); });
|
||||
locks.TimeOut.Returns(timeOuts);
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Request server...";
|
||||
connector.Command.CalculateAuthKeys(bike);
|
||||
bikesViewModel.ActionText = "Searching lock...";
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>());
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert(
|
||||
"Fehler bei Verbinden mit Schloss!",
|
||||
"Schloss kann erst gefunden werden, wenn gemietetes Rad in der Nähe ist.",
|
||||
"Wiederholen",
|
||||
"Abbrechen");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("BookedDisconnected", handler.ButtonText);
|
||||
Assert.IsFalse(handler.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", handler.LockitButtonText);
|
||||
Assert.IsTrue(handler.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Search.
|
||||
/// Final state: Booked unknown
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSearchConnectFailsException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
var timeOuts = Substitute.For<ITimeOutProvider>();
|
||||
|
||||
var handler = new BookedDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>())
|
||||
.Returns<Task<LockInfoTdo>>(x => throw new Exception("Exception message.") );
|
||||
locks.TimeOut.Returns(timeOuts);
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Request server...";
|
||||
connector.Command.CalculateAuthKeys(bike);
|
||||
bikesViewModel.ActionText = "Searching lock...";
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>());
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAdvancedAlert(
|
||||
"Fehler bei Verbinden mit Schloss!",
|
||||
"Lock of rented bike can not be found.",
|
||||
"Exception message.",
|
||||
"Wiederholen",
|
||||
"Abbrechen");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("BookedDisconnected", handler.ButtonText);
|
||||
Assert.IsFalse(handler.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", handler.LockitButtonText);
|
||||
Assert.IsTrue(handler.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Search.
|
||||
/// Final state: Booked unknown
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSearchConnectNotOpen()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
var timeOuts = Substitute.For<ITimeOutProvider>();
|
||||
|
||||
var handler = new BookedDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>())
|
||||
.Returns(new LockInfoTdo.Builder { State = null }.Build());
|
||||
locks.TimeOut.Returns(timeOuts);
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Request server...";
|
||||
connector.Command.CalculateAuthKeys(bike);
|
||||
bikesViewModel.ActionText = "Searching lock...";
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>());
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Fehler bei Verbinden mit Schloss!", "Schlossstatus des gemieteten Rads konnte nicht ermittelt werden.", "OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("BookedDisconnected", handler.ButtonText);
|
||||
Assert.IsFalse(handler.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", handler.LockitButtonText);
|
||||
Assert.IsTrue(handler.IsLockitButtonVisible);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,590 @@
|
|||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike.BluetoothLock;
|
||||
using TINK.Model.Bikes.Bike.BluetoothLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using TINK.Services.BluetoothLock.Exception;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
using TINK.Model.Services.Geolocation;
|
||||
using TINK.Model.State;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
|
||||
using TINK.Model.User;
|
||||
using TINK.Model.Device;
|
||||
|
||||
namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestDisposableDisconnected
|
||||
{
|
||||
/// <summary>
|
||||
/// Test construction of object.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Testctor()
|
||||
{
|
||||
var handler = new DisposableDisconnected(
|
||||
Substitute.For<IBikeInfoMutable>(),
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => Substitute.For<IConnector>(),
|
||||
Substitute.For<IGeolocation>(),
|
||||
Substitute.For<ILocksService>(),
|
||||
() => Substitute.For<IPollingUpdateTaskManager>(),
|
||||
Substitute.For<ISmartDevice>(),
|
||||
Substitute.For<IViewService>(),
|
||||
Substitute.For<IBikesViewModel>(),
|
||||
Substitute.For<IUser>());
|
||||
|
||||
// Verify prerequisites.
|
||||
Assert.AreEqual("Reserve bike", handler.ButtonText);
|
||||
Assert.IsTrue(handler.IsButtonVisible);
|
||||
Assert.AreEqual("DisposableDisconnected", handler.LockitButtonText);
|
||||
Assert.IsFalse(handler.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Cancel reservation.
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestReserveAndConnectCancel()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Reserve bike Nr. 0 free of charge for 15 min?", "Yes", "No").Returns(Task.FromResult(false));
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
viewService.DisplayAlert(string.Empty, "Reserve bike Nr. 0 free of charge for 15 min?", "Yes", "No");
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Reserve bike", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("DisposableDisconnected", subsequent.LockitButtonText);
|
||||
Assert.IsFalse(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Reserve bike.
|
||||
/// Final state: Reserved closed.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestReserveAndConnect()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
var timeOuts = Substitute.For<ITimeOutProvider>();
|
||||
|
||||
var handler = new DisposableDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Reserve bike Nr. 0 free of charge for 15 min?", "Yes", "No").Returns(Task.FromResult(true));
|
||||
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(),Arg.Any<TimeSpan>())
|
||||
.Returns(Task.FromResult(new LockInfoTdo.Builder { State = LockitLockingState.Closed }.Build())); // Return lock state indicating success
|
||||
|
||||
locks.TimeOut.Returns(timeOuts);
|
||||
|
||||
viewService.DisplayAlert(string.Empty, string.Format("Rent bike {0} and open lock?", "Nr. 0"), "Yes", "No").Returns(Task.FromResult(true));
|
||||
|
||||
locks[0].OpenAsync()
|
||||
.Returns(Task.FromResult((LockitLockingState?)LockitLockingState.Open)); // Return lock state indicating success
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked); // Booking call leads to setting of state to booked.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Reserving bike...";
|
||||
connector.Command.DoReserve(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "Searching lock...";
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>());
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.ActionText = "Renting bike...";
|
||||
connector.Command.DoBook(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "Opening lock...";
|
||||
locks.Received()[0].OpenAsync(); // Lock must be opened
|
||||
bikesViewModel.ActionText = "Reading charging level...";
|
||||
locks[0].GetBatteryPercentageAsync();
|
||||
bikesViewModel.ActionText = "Updating lock state...";
|
||||
connector.Command.UpdateLockingStateAsync(bike, null);
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Close lock & return bike", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
|
||||
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Reserve bike.
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestReserveAndConnectReserveFailsBookingDeclinedException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Reserve bike Nr. 0 free of charge for 15 min?", "Yes", "No").Returns(Task.FromResult(true));
|
||||
|
||||
connector.Command.DoReserve(bike).Returns(x => throw new BookingDeclinedException(7)); // Booking must be performed
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
bike.LockInfo.State.Returns(LockingState.Closed); // Requsthandler factory queries lock state to create appropriate request handler object.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Reserving bike...";
|
||||
connector.Command.DoReserve(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Hint", string.Format("A reservation of bike {0} was rejected because the maximum allowed number of {1} reservations/ rentals had already been made.", 0, 7), "OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Reserve bike", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("DisposableDisconnected", subsequent.LockitButtonText);
|
||||
Assert.IsFalse(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Reserve bike.
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestReserveAndConnectReserveFailsWebConnectFailureException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Reserve bike Nr. 0 free of charge for 15 min?", "Yes", "No").Returns(Task.FromResult(true));
|
||||
|
||||
connector.Command.DoReserve(bike).Returns<Task>(x => throw new WebConnectFailureException("Context info.", new Exception("chub")));
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
bike.LockInfo.State.Returns(LockingState.Closed); // Requsthandler factory queries lock state to create appropriate request handler object.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Reserving bike...";
|
||||
connector.Command.DoReserve(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Verbingungsfehler beim Reservieren des Rads!", "Context info.\r\nIst WLAN verfügbar/ Mobilfunknetz vefügbar und mobile Daten aktiviert / ... ?", "OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Reserve bike", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("DisposableDisconnected", subsequent.LockitButtonText);
|
||||
Assert.IsFalse(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Reserve bike.
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestReserveAndConnectReserveFailsException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Reserve bike Nr. 0 free of charge for 15 min?", "Yes", "No").Returns(Task.FromResult(true));
|
||||
|
||||
connector.Command.DoReserve(bike).Returns<Task>(x => throw new Exception("Exception message."));
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
bike.LockInfo.State.Returns(LockingState.Closed); // Requsthandler factory queries lock state to create appropriate request handler object.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Reserving bike...";
|
||||
connector.Command.DoReserve(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Fehler beim Reservieren des Rads!", "Exception message.", "OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Reserve bike", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("DisposableDisconnected", subsequent.LockitButtonText);
|
||||
Assert.IsFalse(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Reserve bike.
|
||||
/// Final state: Reserved unknown.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestReserveAndConnectConnectOutOfReachException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
var timeOuts = Substitute.For<ITimeOutProvider>();
|
||||
|
||||
var handler = new DisposableDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Reserve bike Nr. 0 free of charge for 15 min?", "Yes", "No").Returns(Task.FromResult(true));
|
||||
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>()).Returns<LockInfoTdo>(x => throw new OutOfReachException());
|
||||
locks.TimeOut.Returns(timeOuts);
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
bike.LockInfo.State.Returns(LockingState.Disconnected); // Requsthandler factory queries lock state to create appropriate request handler object.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Reserving bike...";
|
||||
connector.Command.DoReserve(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "Searching lock...";
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>());
|
||||
bikesViewModel.ActionText = "Schloss außerhalb Reichweite";
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Cancel bike reservation", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
|
||||
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Reserve bike.
|
||||
/// Final state: Reserved unknown.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestReserveAndConnectConnectException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
var timeOuts = Substitute.For<ITimeOutProvider>();
|
||||
|
||||
var handler = new DisposableDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Reserve bike Nr. 0 free of charge for 15 min?", "Yes", "No").Returns(Task.FromResult(true));
|
||||
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>()).Returns<LockInfoTdo>(x => throw new Exception("Exception message."));
|
||||
locks.TimeOut.Returns(timeOuts);
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
bike.LockInfo.State.Returns(LockingState.Disconnected); // Requsthandler factory queries lock state to create appropriate request handler object.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Reserving bike...";
|
||||
connector.Command.DoReserve(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "Searching lock...";
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>());
|
||||
bikesViewModel.ActionText = "Schloss nicht gefunden";
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Cancel bike reservation", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
|
||||
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Reserve bike.
|
||||
/// Final state: Reserved unknown.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestReserveAndConnectConnectStateUnknown()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
var timeOuts = Substitute.For<ITimeOutProvider>();
|
||||
|
||||
var handler = new DisposableDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Reserve bike Nr. 0 free of charge for 15 min?", "Yes", "No").Returns(Task.FromResult(true));
|
||||
|
||||
locks.TimeOut.Returns(timeOuts);
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
bike.LockInfo.State.Returns(LockingState.Unknown); // Connect did not throw an exception but lock state is still unknown.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Reserving bike...";
|
||||
connector.Command.DoReserve(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "Searching lock...";
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>());
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Cancel bike reservation", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
|
||||
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNotsupported()
|
||||
{
|
||||
var handler = new DisposableDisconnected(
|
||||
Substitute.For<IBikeInfoMutable>(),
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => Substitute.For<IConnector>(),
|
||||
Substitute.For<IGeolocation>(),
|
||||
Substitute.For<ILocksService>(),
|
||||
() => Substitute.For<IPollingUpdateTaskManager>(),
|
||||
Substitute.For<ISmartDevice>(),
|
||||
Substitute.For<IViewService>(),
|
||||
Substitute.For<IBikesViewModel>(),
|
||||
Substitute.For<IUser>());
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Reserve bike", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("DisposableDisconnected", subsequent.LockitButtonText);
|
||||
Assert.IsFalse(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,442 @@
|
|||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike.BluetoothLock;
|
||||
using TINK.Model.Bikes.Bike.BluetoothLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using TINK.Services.BluetoothLock.Exception;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
using TINK.Model.Services.Geolocation;
|
||||
using TINK.Model.State;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
|
||||
using TINK.Model.User;
|
||||
using TINK.Model.Device;
|
||||
|
||||
namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestDisposableOpen
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Test construction of object.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Testctor()
|
||||
{
|
||||
var handler = new DisposableOpen (
|
||||
Substitute.For<IBikeInfoMutable>(),
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => Substitute.For<IConnector>(),
|
||||
Substitute.For<IGeolocation>(),
|
||||
Substitute.For<ILocksService>(),
|
||||
() => Substitute.For<IPollingUpdateTaskManager>(),
|
||||
Substitute.For<ISmartDevice>(),
|
||||
Substitute.For<IViewService>(),
|
||||
Substitute.For<IBikesViewModel>(),
|
||||
Substitute.For<IUser>());
|
||||
|
||||
// Verify prerequisites.
|
||||
Assert.AreEqual("Rent bike or close lock", handler.ButtonText);
|
||||
Assert.IsTrue(handler.IsButtonVisible);
|
||||
Assert.AreEqual(nameof(DisposableOpen), handler.LockitButtonText);
|
||||
Assert.IsFalse(handler.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Lock bike.
|
||||
/// Final state: Disposable Closed.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCloseLock()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableOpen(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Fahrrad Nr. 0 mieten oder Schloss schließen?", "Mieten", "Schloss schließen").Returns(Task.FromResult(false));
|
||||
|
||||
locks[0].CloseAsync().Returns(Task.FromResult((LockitLockingState?)LockitLockingState.Closed));
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Disposable); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Closing lock...";
|
||||
locks[0].CloseAsync();
|
||||
bikesViewModel.ActionText = "Disconnecting lock...";
|
||||
locks.DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Reserve bike", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("DisposableDisconnected", subsequent.LockitButtonText);
|
||||
Assert.IsFalse(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Lock bike.
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCloseLockCloseFailsOutOfReachExcption()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableOpen(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Fahrrad Nr. 0 mieten oder Schloss schließen?", "Mieten", "Schloss schließen").Returns(Task.FromResult(false));
|
||||
|
||||
locks[0].CloseAsync().Returns<Task<LockitLockingState?>>(x => throw new OutOfReachException());
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Disposable); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
bike.LockInfo.State.Returns(LockingState.Open);
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
locks.DidNotReceive().DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Closing lock...";
|
||||
locks[0].CloseAsync();
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Lock can not be closed!", "Lock cannot be closed until bike is near.", "OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Reserve bike", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual(nameof(DisposableDisconnected), subsequent.LockitButtonText);
|
||||
Assert.IsFalse(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Lock bike.
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCloseLockCloseFailsExcption()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableOpen(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Fahrrad Nr. 0 mieten oder Schloss schließen?", "Mieten", "Schloss schließen").Returns(Task.FromResult(false));
|
||||
|
||||
locks[0].CloseAsync().Returns<Task<LockitLockingState?>>(x => throw new Exception("Exception message."));
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Disposable); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
bike.LockInfo.State.Returns(LockingState.Open);
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
locks.DidNotReceive().DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Closing lock...";
|
||||
locks[0].CloseAsync();
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Lock can not be closed!", "Exception message.", "OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Reserve bike", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual(nameof(DisposableDisconnected), subsequent.LockitButtonText);
|
||||
Assert.IsFalse(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Lock bike.
|
||||
/// Final state: Booked Open.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestDoBook()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableOpen(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Fahrrad Nr. 0 mieten oder Schloss schließen?", "Mieten", "Schloss schließen").Returns(Task.FromResult(true));
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
bike.LockInfo.State.Returns(LockingState.Open);
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Reading charging level...";
|
||||
locks[0].GetBatteryPercentageAsync();
|
||||
bikesViewModel.ActionText = "Renting bike...";
|
||||
connector.Command.DoBook(bike);
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Close lock & return bike", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
|
||||
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Lock bike.
|
||||
/// Final state: Disposabled Closed.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestDoBookDoBookFailsWebConnectFailureException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableOpen(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Fahrrad Nr. 0 mieten oder Schloss schließen?", "Mieten", "Schloss schließen").Returns(Task.FromResult(true));
|
||||
|
||||
connector.Command.DoBook(bike).Returns(x => throw new WebConnectFailureException("Context info.", new Exception("chub")));
|
||||
|
||||
locks[0].CloseAsync().Returns(Task.FromResult((LockitLockingState?)LockitLockingState.Closed));
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Disposable);
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Reading charging level...";
|
||||
locks[0].GetBatteryPercentageAsync();
|
||||
bikesViewModel.ActionText = "Renting bike...";
|
||||
connector.Command.DoBook(bike);
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert(
|
||||
"Connection error when renting the bike!",
|
||||
string.Format("Attention: Lock is closed!\r\n{0}\r\n{1}", "Context info.", "Ist WLAN verfügbar/ Mobilfunknetz vefügbar und mobile Daten aktiviert / ... ?"),
|
||||
"OK");
|
||||
bikesViewModel.ActionText = "Verschließe Schloss...";
|
||||
locks[0].CloseAsync();
|
||||
bikesViewModel.ActionText = "Disconnecting lock...";
|
||||
locks.DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Reserve bike", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("DisposableDisconnected", subsequent.LockitButtonText);
|
||||
Assert.IsFalse(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Lock bike.
|
||||
/// Final state: Disposabled Closed.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestDoBookDoBookFailsException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableOpen(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Fahrrad Nr. 0 mieten oder Schloss schließen?", "Mieten", "Schloss schließen").Returns(Task.FromResult(true));
|
||||
|
||||
connector.Command.DoBook(bike).Returns(x => throw new Exception("Exception message."));
|
||||
|
||||
locks[0].CloseAsync().Returns(Task.FromResult((LockitLockingState?)LockitLockingState.Closed));
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Disposable);
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Reading charging level...";
|
||||
locks[0].GetBatteryPercentageAsync();
|
||||
bikesViewModel.ActionText = "Renting bike...";
|
||||
connector.Command.DoBook(bike);
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Error when renting the bike!", "Attention: Lock is closed!\r\nException message.", "OK");
|
||||
bikesViewModel.ActionText = "Verschließe Schloss...";
|
||||
locks[0].CloseAsync();
|
||||
bikesViewModel.ActionText = "Disconnecting lock...";
|
||||
locks.DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Reserve bike", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("DisposableDisconnected", subsequent.LockitButtonText);
|
||||
Assert.IsFalse(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,752 @@
|
|||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike.BluetoothLock;
|
||||
using TINK.Model.Bikes.Bike.BluetoothLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using TINK.Services.BluetoothLock.Exception;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
using TINK.Model.Services.Geolocation;
|
||||
using TINK.Model.State;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
|
||||
using Newtonsoft.Json;
|
||||
using TINK.Repository.Response;
|
||||
using TINK.Model.User;
|
||||
using TINK.Model.Device;
|
||||
|
||||
namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||
{
|
||||
public class TestReservedDisconnected
|
||||
{
|
||||
/// <summary>
|
||||
/// Test construction of object.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Testctor()
|
||||
{
|
||||
var handler = new ReservedDisconnected(
|
||||
Substitute.For<IBikeInfoMutable>(),
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => Substitute.For<IConnector>(),
|
||||
Substitute.For<IGeolocation>(),
|
||||
Substitute.For<ILocksService>(),
|
||||
() => Substitute.For<IPollingUpdateTaskManager>(),
|
||||
Substitute.For<ISmartDevice>(),
|
||||
Substitute.For<IViewService>(),
|
||||
Substitute.For<IBikesViewModel>(),
|
||||
Substitute.For<IUser>());
|
||||
|
||||
// Verify prerequisites.
|
||||
Assert.AreEqual("Cancel bike reservation", handler.ButtonText);
|
||||
Assert.IsTrue(handler.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", handler.LockitButtonText);
|
||||
Assert.IsTrue(handler.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Cancel reservation.
|
||||
/// Comment: User deceide to abort cancelling (user is ased whether to really cancel)
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCancelReservationCancel()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, string.Format("Cancel reservation for bike {0}?", "Nr. 0"), "Yes", "No").Returns(Task.FromResult(false));
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
viewService.DisplayAlert(string.Empty, string.Format("Cancel reservation for bike {0}?", "Nr. 0"), "Yes", "No");
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Cancel bike reservation", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
|
||||
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Cancel reservation.
|
||||
/// Final state: Disposable.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCancelReservation()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, string.Format("Cancel reservation for bike {0}?", "Nr. 0"), "Yes", "No").Returns(Task.FromResult(true));
|
||||
bike.State.Value.Returns(InUseStateEnum.Disposable); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
bike.LockInfo.State.Returns(LockingState.Disconnected); // Requsthandler factory queries lock state to create appropriate request handler object.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Canceling reservation...";
|
||||
connector.Command.DoCancelReservation(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Reserve bike", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("DisposableDisconnected", subsequent.LockitButtonText);
|
||||
Assert.IsFalse(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Cancel reservation.
|
||||
/// Comment: Exception is thrown.
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCancelReservationDoCancelReservationInvalidAuthorizationResponseException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, string.Format("Cancel reservation for bike {0}?", "Nr. 0"), "Yes", "No").Returns(Task.FromResult(true));
|
||||
|
||||
var l_oResponse = JsonConvert.DeserializeObject<AuthorizationResponse>(@"
|
||||
{
|
||||
""response"" : ""authorization"",
|
||||
""authcookie"" : ""4da3044c8657a04ba60e2eaa753bc51a"",
|
||||
""user_group"" : [ ""TINK"", ""Konrad"" ],
|
||||
""response_state"" : ""OK"",
|
||||
""apiserver"" : ""https://tinkwwp.copri-bike.de""
|
||||
}");
|
||||
|
||||
connector.Command.DoCancelReservation(bike).Returns(x => throw new InvalidAuthorizationResponseException("mustermann@server.de", l_oResponse));
|
||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
bike.LockInfo.State.Returns(LockingState.Disconnected); // Requsthandler factory queries lock state to create appropriate request handler object.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Canceling reservation...";
|
||||
connector.Command.DoCancelReservation(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Fehler beim Aufheben der Reservierung!", "Kann Benutzer mustermann@server.de nicht anmelden. Mailadresse unbekannt oder Passwort ungültig.", "OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Cancel bike reservation", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
|
||||
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Cancel reservation.
|
||||
/// Comment: Canceling reservation fails.
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCancelReservationDoCancelReservationWebConnectFailureException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, string.Format("Cancel reservation for bike {0}?", "Nr. 0"), "Yes", "No").Returns(Task.FromResult(true));
|
||||
|
||||
connector.Command.DoCancelReservation(bike).Returns(x => throw new WebConnectFailureException("Context info", new Exception("chub")));
|
||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
bike.LockInfo.State.Returns(LockingState.Disconnected); // Requsthandler factory queries lock state to create appropriate request handler object.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Canceling reservation...";
|
||||
connector.Command.DoCancelReservation(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Verbingungsfehler beim Aufheben der Reservierung!", "Context info\r\nIst WLAN verfügbar/ Mobilfunknetz vefügbar und mobile Daten aktiviert / ... ?", "OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Cancel bike reservation", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
|
||||
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Cancel reservation.
|
||||
/// Comment: Canceling reservation fails.
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCancelReservationDoCancelReservationException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, string.Format("Cancel reservation for bike {0}?", "Nr. 0"), "Yes", "No").Returns(Task.FromResult(true));
|
||||
|
||||
connector.Command.DoCancelReservation(bike).Returns(x => throw new Exception("Exception message."));
|
||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
bike.LockInfo.State.Returns(LockingState.Disconnected); // Requsthandler factory queries lock state to create appropriate request handler object.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Canceling reservation...";
|
||||
connector.Command.DoCancelReservation(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Fehler beim Aufheben der Reservierung!", "Exception message.", "OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Cancel bike reservation", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
|
||||
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Search.
|
||||
/// Final state: reserved closed
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSearch()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
var timeOuts = Substitute.For<ITimeOutProvider>();
|
||||
|
||||
var handler = new ReservedDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>())
|
||||
.Returns(Task.FromResult(new LockInfoTdo.Builder { State = LockitLockingState.Closed }.Build()));
|
||||
|
||||
locks.TimeOut.Returns(timeOuts);
|
||||
|
||||
viewService.DisplayAlert(string.Empty, string.Format("Rent bike {0} and open lock?", "Nr. 0"), "Yes", "No").Returns(Task.FromResult(true));
|
||||
|
||||
locks[0].OpenAsync()
|
||||
.Returns(Task.FromResult((LockitLockingState?)LockitLockingState.Open)); // Return lock state indicating success
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked); // Booking call leads to setting of state to booked.
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Request server...";
|
||||
connector.Command.CalculateAuthKeys(bike);
|
||||
bikesViewModel.ActionText = "Searching lock...";
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>());
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.ActionText = "Renting bike...";
|
||||
connector.Command.DoBook(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "Opening lock...";
|
||||
locks.Received()[0].OpenAsync(); // Lock must be opened
|
||||
bikesViewModel.ActionText = "Reading charging level...";
|
||||
locks[0].GetBatteryPercentageAsync();
|
||||
bikesViewModel.ActionText = "Updating lock state...";
|
||||
connector.Command.UpdateLockingStateAsync(bike, null);
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Close lock & return bike", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
|
||||
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Search.
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSearchCalculateAuthKeysFailsWebConnectFailureException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
connector.Command.CalculateAuthKeys(bike).Returns(x => throw new WebConnectFailureException("Context info.", new Exception("Tst")));
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
bike.LockInfo.State.Returns(LockingState.Unknown);
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Request server...";
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Fehler bei Verbinden mit Schloss!", "Internet muss erreichbar sein um Verbindung mit Schloss für reserviertes Rad herzustellen.\r\nContext info.\r\nIst WLAN verfügbar/ Mobilfunknetz vefügbar und mobile Daten aktiviert / ... ?", "OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Cancel bike reservation", handler.ButtonText);
|
||||
Assert.IsTrue(handler.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", handler.LockitButtonText);
|
||||
Assert.IsTrue(handler.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Search.
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSearchCalculateAuthKeysFailsException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
connector.Command.CalculateAuthKeys(bike).Returns(x => throw new Exception("Exception message."));
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
bike.LockInfo.State.Returns(LockingState.Unknown);
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Request server...";
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Fehler bei Verbinden mit Schloss!", "Kommunikationsfehler bei Schlosssuche.\r\nException message.", "OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Cancel bike reservation", handler.ButtonText);
|
||||
Assert.IsTrue(handler.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", handler.LockitButtonText);
|
||||
Assert.IsTrue(handler.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Search.
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSearchConnectFailsOutOfReachException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
var timeOuts = Substitute.For<ITimeOutProvider>();
|
||||
|
||||
var handler = new ReservedDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>())
|
||||
.Returns<Task<LockInfoTdo>>(x => { throw new OutOfReachException(); });
|
||||
locks.TimeOut.Returns(timeOuts);
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Request server...";
|
||||
connector.Command.CalculateAuthKeys(bike);
|
||||
bikesViewModel.ActionText = "Searching lock...";
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>());
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert(
|
||||
"Fehler bei Verbinden mit Schloss!",
|
||||
"Schloss kann erst gefunden werden, wenn reserviertes Rad in der Nähe ist.",
|
||||
"Wiederholen",
|
||||
"Abbrechen");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Cancel bike reservation", handler.ButtonText);
|
||||
Assert.IsTrue(handler.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", handler.LockitButtonText);
|
||||
Assert.IsTrue(handler.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Search.
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSearchConnectFailsException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
var timeOuts = Substitute.For<ITimeOutProvider>();
|
||||
|
||||
var handler = new ReservedDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>())
|
||||
.Returns<Task<LockInfoTdo>>(x => throw new Exception("Execption message."));
|
||||
locks.TimeOut.Returns(timeOuts);
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Request server...";
|
||||
connector.Command.CalculateAuthKeys(bike);
|
||||
bikesViewModel.ActionText = "Searching lock...";
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>());
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAdvancedAlert(
|
||||
"Fehler bei Verbinden mit Schloss!",
|
||||
"Lock of reserved bike can not be found.",
|
||||
"Execption message.",
|
||||
"Wiederholen",
|
||||
"Abbrechen");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Cancel bike reservation", handler.ButtonText);
|
||||
Assert.IsTrue(handler.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", handler.LockitButtonText);
|
||||
Assert.IsTrue(handler.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Search.
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSearchConnectNotOpen()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
var timeOuts = Substitute.For<ITimeOutProvider>();
|
||||
|
||||
var handler = new ReservedDisconnected(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>())
|
||||
.Returns(new LockInfoTdo.Builder { State = null }.Build());
|
||||
locks.TimeOut.Returns(timeOuts);
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Request server...";
|
||||
connector.Command.CalculateAuthKeys(bike);
|
||||
bikesViewModel.ActionText = "Searching lock...";
|
||||
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>());
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Fehler bei Verbinden mit Schloss!", "Schlossstatus des reservierten Rads konnte nicht ermittelt werden.", "OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Cancel bike reservation", handler.ButtonText);
|
||||
Assert.IsTrue(handler.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", handler.LockitButtonText);
|
||||
Assert.IsTrue(handler.IsLockitButtonVisible);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,671 @@
|
|||
using Newtonsoft.Json;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike.BluetoothLock;
|
||||
using TINK.Model.Bikes.Bike.BluetoothLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Repository.Response;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using TINK.Services.BluetoothLock.Exception;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
using TINK.Model.Services.Geolocation;
|
||||
using TINK.Model.State;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
|
||||
using TINK.Model.User;
|
||||
using TINK.Model.Device;
|
||||
|
||||
namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestReservedOpen
|
||||
{
|
||||
/// <summary>
|
||||
/// Test construction of object.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Testctor()
|
||||
{
|
||||
var handler = new ReservedOpen(
|
||||
Substitute.For<IBikeInfoMutable>(),
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => Substitute.For<IConnector>(),
|
||||
Substitute.For<IGeolocation>(),
|
||||
Substitute.For<ILocksService>(),
|
||||
() => Substitute.For<IPollingUpdateTaskManager>(),
|
||||
Substitute.For<ISmartDevice>(),
|
||||
Substitute.For<IViewService>(),
|
||||
Substitute.For<IBikesViewModel>(),
|
||||
Substitute.For<IUser>());
|
||||
|
||||
// Verify prerequisites.
|
||||
Assert.AreEqual("Rad zurückgeben oder mieten", handler.ButtonText);
|
||||
Assert.IsTrue(handler.IsButtonVisible);
|
||||
Assert.AreEqual("Alarm/ Sounds verwalten", handler.LockitButtonText);
|
||||
Assert.IsFalse(handler.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: User books bike.
|
||||
/// Final state: Booked.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestBook()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedOpen(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Rad Nr. 0 abschließen und zurückgeben oder Rad mieten?", "Zurückgeben", "Mieten").Returns(Task.FromResult(false));
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
bike.LockInfo.State.Returns(LockingState.Open); // Requsthandler factory queries lock state to create appropriate request handler object.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Reading charging level...";
|
||||
locks[0].GetBatteryPercentageAsync();
|
||||
bikesViewModel.ActionText = "Renting bike...";
|
||||
connector.Command.DoBook(bike);
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Close lock & return bike", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
|
||||
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: User books bike.
|
||||
/// Final state: Reserved closed.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestBookBookFailsWebConnectFailureException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedOpen(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Rad Nr. 0 abschließen und zurückgeben oder Rad mieten?", "Zurückgeben", "Mieten").Returns(Task.FromResult(false));
|
||||
|
||||
connector.Command.DoBook(bike).Returns(x => throw new WebConnectFailureException("Context info.", new Exception("Tst")));
|
||||
|
||||
locks[0].CloseAsync().Returns(LockitLockingState.Closed);
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Reading charging level...";
|
||||
locks[0].GetBatteryPercentageAsync();
|
||||
bikesViewModel.ActionText = "Renting bike...";
|
||||
connector.Command.DoBook(bike);
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert(
|
||||
"Connection error when renting the bike!",
|
||||
string.Format("Attention: Lock is closed!\r\n{0}\r\n{1}", "Context info.", "Ist WLAN verfügbar/ Mobilfunknetz vefügbar und mobile Daten aktiviert / ... ?"),
|
||||
"OK");
|
||||
bikesViewModel.ActionText = "Wiederverschließe Schloss...";
|
||||
locks[0].CloseAsync();
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Cancel bike reservation", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("Open lock & rent bike", subsequent.LockitButtonText);
|
||||
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: User books bike.
|
||||
/// Final state: Reserved closed.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestBookBookFailsException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedOpen(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Rad Nr. 0 abschließen und zurückgeben oder Rad mieten?", "Zurückgeben", "Mieten").Returns(Task.FromResult(false));
|
||||
|
||||
connector.Command.DoBook(bike).Returns(x => throw new Exception("Exception message."));
|
||||
|
||||
locks[0].CloseAsync().Returns(LockitLockingState.Closed);
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Reading charging level...";
|
||||
locks[0].GetBatteryPercentageAsync();
|
||||
bikesViewModel.ActionText = "Renting bike...";
|
||||
connector.Command.DoBook(bike);
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Error when renting the bike!", "Attention: Lock is closed!\r\nException message.", "OK");
|
||||
bikesViewModel.ActionText = "Wiederverschließe Schloss...";
|
||||
locks[0].CloseAsync();
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Cancel bike reservation", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("Open lock & rent bike", subsequent.LockitButtonText);
|
||||
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Close lock and cancel reservation.
|
||||
/// Final state: Booked.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCloseLockAndCancelReservation()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedOpen(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Rad Nr. 0 abschließen und zurückgeben oder Rad mieten?", "Zurückgeben", "Mieten").Returns(Task.FromResult(true));
|
||||
|
||||
locks[0].CloseAsync().Returns(LockitLockingState.Closed);
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Disposable); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Closing lock...";
|
||||
locks[0].CloseAsync();
|
||||
bikesViewModel.ActionText = "Canceling reservation...";
|
||||
connector.Command.DoCancelReservation(bike);
|
||||
bikesViewModel.ActionText = "Disconnecting lock...";
|
||||
locks.DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Reserve bike", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("DisposableDisconnected", subsequent.LockitButtonText);
|
||||
Assert.IsFalse(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Close lock and cancel reservation.
|
||||
/// Final state: Reserved open.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCloseLockAndCancelReservationCloseFailsOutOfReachException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedOpen(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(
|
||||
string.Empty,
|
||||
"Rad Nr. 0 abschließen und zurückgeben oder Rad mieten?",
|
||||
"Zurückgeben",
|
||||
"Mieten").Returns(Task.FromResult(true));
|
||||
|
||||
locks[0].CloseAsync()
|
||||
.Returns<Task<LockitLockingState?>>(x => { throw new OutOfReachException(); });
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
bike.LockInfo.State.Returns(LockingState.Open);
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
locks.DidNotReceive().DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Closing lock...";
|
||||
locks[0].CloseAsync();
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert(
|
||||
"Lock can not be closed!",
|
||||
"Lock cannot be closed until bike is near.\r\nPlease try again to close bike or report bike to support!",
|
||||
"OK");
|
||||
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Cancel bike reservation", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
|
||||
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Close lock and cancel reservation.
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCloseLockAndCancelReservationCloseFailsException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedOpen(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(
|
||||
string.Empty,
|
||||
"Rad Nr. 0 abschließen und zurückgeben oder Rad mieten?",
|
||||
"Zurückgeben",
|
||||
"Mieten").Returns(Task.FromResult(true));
|
||||
|
||||
locks[0].CloseAsync()
|
||||
.Returns<Task<LockitLockingState?>>(x => { throw new Exception("Exception message."); });
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
bike.LockInfo.State.Returns(LockingState.Open);
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
locks.DidNotReceive().DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Closing lock...";
|
||||
locks[0].CloseAsync();
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert(
|
||||
"Lock can not be closed!",
|
||||
"Please try to lock again or report bike to support!\r\nException message.",
|
||||
"OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("Cancel bike reservation", subsequent.ButtonText);
|
||||
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
|
||||
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Close lock and cancel reservation.
|
||||
/// Final state: Reserved closed.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCloseLockAndCancelReservationCancelReservationInvalidAuthorizationResponseException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedOpen(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
var response = JsonConvert.DeserializeObject<AuthorizationResponse>(@"
|
||||
{
|
||||
""response"" : ""authorization"",
|
||||
""authcookie"" : ""4da3044c8657a04ba60e2eaa753bc51a"",
|
||||
""user_group"" : [ ""TINK"", ""Konrad"" ],
|
||||
""response_state"" : ""OK"",
|
||||
""apiserver"" : ""https://tinkwwp.copri-bike.de""
|
||||
}");
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Rad Nr. 0 abschließen und zurückgeben oder Rad mieten?", "Zurückgeben", "Mieten").Returns(Task.FromResult(true));
|
||||
|
||||
locks[0].CloseAsync().Returns(LockitLockingState.Closed);
|
||||
|
||||
connector.Command.DoCancelReservation(bike).Returns(x => throw new InvalidAuthorizationResponseException("mustermann@server.de", response));
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Disposable); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
|
||||
locks.DidNotReceive().DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Closing lock...";
|
||||
locks[0].CloseAsync();
|
||||
bikesViewModel.ActionText = "Canceling reservation...";
|
||||
connector.Command.DoCancelReservation(bike);
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Fehler beim Aufheben der Reservierung!", "Kann Benutzer mustermann@server.de nicht anmelden. Mailadresse unbekannt oder Passwort ungültig.", "OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("InvalidState", subsequent.ButtonText);
|
||||
Assert.IsFalse(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("InvalidState", subsequent.LockitButtonText);
|
||||
Assert.IsFalse(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Close lock and cancel reservation.
|
||||
/// Final state: Reserved closed.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCloseLockAndCancelReservationCancelReservationWebConnectFailureException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedOpen(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Rad Nr. 0 abschließen und zurückgeben oder Rad mieten?", "Zurückgeben", "Mieten").Returns(Task.FromResult(true));
|
||||
|
||||
locks[0].CloseAsync().Returns(LockitLockingState.Closed);
|
||||
|
||||
connector.Command.DoCancelReservation(bike).Returns(x => throw new WebConnectFailureException("Context info", new Exception("chub")));
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Disposable); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
locks.DidNotReceive().DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Closing lock...";
|
||||
locks[0].CloseAsync();
|
||||
bikesViewModel.ActionText = "Canceling reservation...";
|
||||
connector.Command.DoCancelReservation(bike);
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Verbingungsfehler beim Aufheben der Reservierung!", "Context info\r\nIst WLAN verfügbar/ Mobilfunknetz vefügbar und mobile Daten aktiviert / ... ?", "OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("InvalidState", subsequent.ButtonText);
|
||||
Assert.IsFalse(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("InvalidState", subsequent.LockitButtonText);
|
||||
Assert.IsFalse(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Close lock and cancel reservation.
|
||||
/// Final state: Reserved closed.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCloseLockAndCancelReservationCancelReservationException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var geolocation = Substitute.For<IGeolocation>();
|
||||
var locks = Substitute.For<ILocksService>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedOpen(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
geolocation,
|
||||
locks,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(string.Empty, "Rad Nr. 0 abschließen und zurückgeben oder Rad mieten?", "Zurückgeben", "Mieten").Returns(Task.FromResult(true));
|
||||
|
||||
locks[0].CloseAsync().Returns(LockitLockingState.Closed);
|
||||
|
||||
connector.Command.DoCancelReservation(bike).Returns(x => throw new Exception("Exception message.", new Exception("chub")));
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Disposable); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
locks.DidNotReceive().DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
bikesViewModel.ActionText = "One moment please...";
|
||||
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||
bikesViewModel.ActionText = "Closing lock...";
|
||||
locks[0].CloseAsync();
|
||||
bikesViewModel.ActionText = "Canceling reservation...";
|
||||
connector.Command.DoCancelReservation(bike);
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Fehler beim Aufheben der Reservierung!", "Exception message.", "OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.AreEqual("InvalidState", subsequent.ButtonText);
|
||||
Assert.IsFalse(subsequent.IsButtonVisible);
|
||||
Assert.AreEqual("InvalidState", subsequent.LockitButtonText);
|
||||
Assert.IsFalse(subsequent.IsLockitButtonVisible);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
using NUnit.Framework;
|
||||
using Rhino.Mocks;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TestTINKLib.Mocks.Services;
|
||||
using TINK.Model.Bike.BluetoothLock;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.State;
|
||||
using TINK.Model.User;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Bikes.Bike.BluetoothLock;
|
||||
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
|
||||
|
||||
namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
|
||||
{
|
||||
/// <summary>
|
||||
/// Moved to TestShareeLib (.Net Core)
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class TestRequestHandlerFactory
|
||||
{
|
||||
[Test]
|
||||
public void TestCreate()
|
||||
{
|
||||
// Verify handler for disposable bike.
|
||||
var bike = new BikeInfoMutable(new BikeInfo("22", 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "12"));
|
||||
Assert.AreEqual(InUseStateEnum.Disposable, bike.State.Value);
|
||||
Assert.AreEqual(LockingState.Disconnected, bike.LockInfo.State);
|
||||
Assert.AreEqual(
|
||||
typeof(DisposableDisconnected),
|
||||
RequestHandlerFactory.Create(
|
||||
bike,
|
||||
() => false, // isConnectedDelegate
|
||||
(connected) => null, // connectorFactory
|
||||
new GeolocationMock(), // geolocation
|
||||
new LocksServiceMock(), // LockService
|
||||
null, // viewUpdateManager
|
||||
NSubstitute.Substitute.For<ISmartDevice>(),
|
||||
null /* viewService */ ,
|
||||
MockRepository.GenerateStub<IBikesViewModel>(),
|
||||
MockRepository.GenerateStub<IUser>()).GetType());
|
||||
|
||||
// Verify handler for requested bike with state unknown.
|
||||
bike = new BikeInfoMutable(new BikeInfo("22", 0 /* lock Id */, new Guid(), /*K User*/ null, /*K Admin*/ null, /*K Seed*/ null, new DateTime(2020, 1, 1), "a@b.com", "12", null, null, () => new DateTime(2020, 1, 1), false, new List<string>(), TINK.Model.Bike.WheelType.Mono, TINK.Model.Bike.TypeOfBike.Allround));
|
||||
Assert.AreEqual(
|
||||
typeof(ReservedDisconnected),
|
||||
RequestHandlerFactory.Create(
|
||||
bike,
|
||||
() => false, // isConnectedDelegate
|
||||
(connected) => null, // connectorFactory
|
||||
new GeolocationMock(), // geolocation
|
||||
new LocksServiceMock(), // LockService
|
||||
null, // viewUpdateManager
|
||||
NSubstitute.Substitute.For<ISmartDevice>(),
|
||||
null /* viewService */,
|
||||
MockRepository.GenerateStub<IBikesViewModel>(),
|
||||
MockRepository.GenerateStub<IUser>()).GetType());
|
||||
|
||||
// Verify handler for requested bike with state closed.
|
||||
bike = new BikeInfoMutable(new BikeInfo("22", 0 /* lock Id*/, new Guid(), null, null, null, new System.DateTime(2020, 1, 1), "a@b.com", "12", null, null, () => new DateTime(2020, 1, 1), false, new List<string>(), TINK.Model.Bike.WheelType.Mono, TINK.Model.Bike.TypeOfBike.Allround));
|
||||
bike.LockInfo.State = LockingState.Closed;
|
||||
Assert.AreEqual(
|
||||
typeof(ReservedClosed),
|
||||
RequestHandlerFactory.Create(
|
||||
bike,
|
||||
() => false, // isConnectedDelegate
|
||||
(connected) => null, // connectorFactory
|
||||
new GeolocationMock(), // geolocation
|
||||
new LocksServiceMock(), // LockService
|
||||
null, // viewUpdateManager
|
||||
NSubstitute.Substitute.For<ISmartDevice>(),
|
||||
null /* viewService */,
|
||||
MockRepository.GenerateStub<IBikesViewModel>(),
|
||||
MockRepository.GenerateStub<IUser>()).GetType());
|
||||
|
||||
// Verify handler for requested bike with state open.
|
||||
bike = new BikeInfoMutable(new BikeInfo("22", 0 /* lock Id*/, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b.com", "12", null, null, () => new DateTime(2020, 1, 1), false, new List<string>(), TINK.Model.Bike.WheelType.Mono, TINK.Model.Bike.TypeOfBike.Allround));
|
||||
bike.LockInfo.State = LockingState.Open;
|
||||
Assert.AreEqual(
|
||||
typeof(ReservedOpen),
|
||||
RequestHandlerFactory.Create(
|
||||
bike,
|
||||
() => false, // isConnectedDelegate
|
||||
(connected) => null, // connectorFactory
|
||||
new GeolocationMock(), // geolocation
|
||||
new LocksServiceMock(), // LockService
|
||||
null, // viewUpdateManager
|
||||
NSubstitute.Substitute.For<ISmartDevice>(),
|
||||
null /* viewService */,
|
||||
MockRepository.GenerateStub<IBikesViewModel>(),
|
||||
MockRepository.GenerateStub<IUser>()).GetType());
|
||||
|
||||
// Verify handler for booked bike with state closed.
|
||||
bike = new BikeInfoMutable(new BikeInfo("22", 0 /* lock Id*/, new Guid(), null, null, null, new System.DateTime(2020, 1, 1), "a@b.com", "12", null /*operator uri*/, null, false, new List<string>(), TINK.Model.Bike.WheelType.Mono, TINK.Model.Bike.TypeOfBike.Allround));
|
||||
bike.LockInfo.State = LockingState.Closed;
|
||||
Assert.AreEqual(
|
||||
typeof(BookedClosed),
|
||||
RequestHandlerFactory.Create(
|
||||
bike,
|
||||
() => false, // isConnectedDelegate
|
||||
(connected) => null, // connectorFactory
|
||||
new GeolocationMock(), // geolocation
|
||||
new LocksServiceMock(), // LockService
|
||||
null, // viewUpdateManager
|
||||
NSubstitute.Substitute.For<ISmartDevice>(),
|
||||
null /* viewService */,
|
||||
MockRepository.GenerateStub<IBikesViewModel>(),
|
||||
MockRepository.GenerateStub<IUser>()).GetType());
|
||||
|
||||
// Verify handler for booked bike with state open.
|
||||
bike = new BikeInfoMutable(new BikeInfo("22", 0 /* lock Id*/, new Guid(), null, null, null, new System.DateTime(2020, 1, 1), "a@b.com", "12", null /*operator uri*/, null, false, new List<string>(), TINK.Model.Bike.WheelType.Mono, TINK.Model.Bike.TypeOfBike.Allround));
|
||||
bike.LockInfo.State = LockingState.Open;
|
||||
Assert.AreEqual(
|
||||
typeof(BookedOpen),
|
||||
RequestHandlerFactory.Create(
|
||||
bike,
|
||||
() => false, // isConnectedDelegate
|
||||
(connected) => null, // connectorFactory
|
||||
new GeolocationMock(), // geolocation
|
||||
new LocksServiceMock(), // LockService
|
||||
null, // viewUpdateManager
|
||||
NSubstitute.Substitute.For<ISmartDevice>(),
|
||||
null /* viewService */,
|
||||
MockRepository.GenerateStub<IBikesViewModel>(),
|
||||
MockRepository.GenerateStub<IUser>()).GetType());
|
||||
|
||||
// Verify handler for booked bike with state unknown.
|
||||
bike = new BikeInfoMutable(new BikeInfo("22", 0 /* lock Id*/, new Guid(), null, null, null, new System.DateTime(2020, 1, 1), "a@b.com", "12", null /*operator uri*/, null, false, new List<string>(), TINK.Model.Bike.WheelType.Mono, TINK.Model.Bike.TypeOfBike.Allround));
|
||||
|
||||
Assert.AreEqual(
|
||||
typeof(BookedDisconnected),
|
||||
RequestHandlerFactory.Create(
|
||||
bike,
|
||||
()=> false, // isConnectedDelegate
|
||||
(connected) => null, // connectorFactory
|
||||
new GeolocationMock(), // geolocation
|
||||
new LocksServiceMock(), // LockService
|
||||
null, // viewUpdateManager
|
||||
NSubstitute.Substitute.For<ISmartDevice>(),
|
||||
null /* viewService */,
|
||||
MockRepository.GenerateStub<IBikesViewModel>(),
|
||||
MockRepository.GenerateStub<IUser>()).GetType());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue