mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2025-06-21 21:46:27 +02:00
Version 3.0.337
This commit is contained in:
parent
fd0e63cf10
commit
573fe77e12
2336 changed files with 33688 additions and 86082 deletions
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,461 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.State;
|
||||
using TINK.Model.User;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using TINK.Services.BluetoothLock.Exception;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
using TINK.Services.Geolocation;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
|
||||
|
||||
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.UnknownFromHardwareError);
|
||||
|
||||
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("Error when connecting with lock!", "Internet must be reachable to connect to lock of rented bike.\r\nContext info\r\nIs WIFI available/ mobile networt available and mobile data activated / ... ?", "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.UnknownFromHardwareError);
|
||||
|
||||
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("Error when connecting with lock!", "Communication error during lock search.\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(
|
||||
"Error when connecting with lock!",
|
||||
"Lock can only be found when rented bike is nearby.",
|
||||
"Retry",
|
||||
"Cancel");
|
||||
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(
|
||||
"Error when connecting with lock!",
|
||||
"Lock of rented bike cannot be be connected right now.",
|
||||
"",
|
||||
"Retry",
|
||||
"Cancel");
|
||||
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("Error when connecting with lock!", "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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,28 +1,27 @@
|
|||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using NSubstitute;
|
||||
using TINK.Model.Bikes.Bike.BluetoothLock;
|
||||
using NUnit.Framework;
|
||||
using TINK.Model;
|
||||
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.State;
|
||||
using TINK.Model.User;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Repository.Request;
|
||||
using TINK.Repository.Response;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using TINK.Services.BluetoothLock.Exception;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
using TINK.Services.Geolocation;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.State;
|
||||
using Xamarin.Essentials;
|
||||
using TINK.Services.BluetoothLock.Exception;
|
||||
using TINK.Repository.Exception;
|
||||
using System;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
using TINK.Model.Bike.BluetoothLock;
|
||||
using TINK.Model.User;
|
||||
using TINK.Repository.Request;
|
||||
using Newtonsoft.Json;
|
||||
using TINK.Repository.Response;
|
||||
using TINK.Model.Device;
|
||||
using System.Threading;
|
||||
using TINK.Model;
|
||||
|
||||
namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||
{
|
||||
|
@ -159,7 +158,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
|||
locks.Received()[0].CloseAsync(); // Lock must be closed
|
||||
bikesViewModel.ActionText = "Query location...";
|
||||
bikesViewModel.ActionText = "Returning bike...";
|
||||
connector.Command.DoReturn(bike, Arg.Is<LocationDto>(x => x.Latitude == 1 && x.Longitude ==2), Arg.Any<ISmartDevice>()); // Booking must be performed
|
||||
connector.Command.DoReturn(bike, Arg.Is<LocationDto>(x => x.Latitude == 1 && x.Longitude == 2), Arg.Any<ISmartDevice>()); // Booking must be performed
|
||||
bikesViewModel.ActionText = "Disconnecting lock...";
|
||||
locks.DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
|
@ -209,7 +208,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
|||
viewService.DisplayAlert(string.Empty, "Close lock and return bike Nr. 0?", "Yes", "No").Returns(Task.FromResult(true));
|
||||
|
||||
locks[0].CloseAsync()
|
||||
.Returns< LockitLockingState?>(x => throw new OutOfReachException());
|
||||
.Returns<LockitLockingState?>(x => throw new OutOfReachException());
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked); // Booking state remains unchanged if closing fails.
|
||||
|
||||
|
@ -485,7 +484,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
|||
viewService.DisplayAlert(string.Empty, "Close lock and return bike Nr. 0?", "Yes", "No").Returns(Task.FromResult(true));
|
||||
|
||||
locks[0].CloseAsync()
|
||||
.Returns<LockitLockingState?>(x => throw new CouldntCloseMovingException());
|
||||
.Returns<LockitLockingState?>(x => throw new CouldntCloseMovingException());
|
||||
|
||||
//bike.LockInfo.State.Returns(LockingState.Open); // If locking fails bike remains open.
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked); // Booking state remains unchanged if closing fails.
|
||||
|
@ -560,7 +559,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
|||
viewService.DisplayAlert(string.Empty, "Close lock and return bike Nr. 0?", "Yes", "No").Returns(Task.FromResult(true));
|
||||
|
||||
locks[0].CloseAsync()
|
||||
.Returns(LockitLockingState.Open);
|
||||
.Returns(LockitLockingState.Open);
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked); // Booking state remains unchanged if closing fails.
|
||||
|
||||
|
@ -1011,7 +1010,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
|||
bike.State.Value.Returns(InUseStateEnum.Booked); // Booking state remains unchanged if closing fails.
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
|
||||
locks.DidNotReceive().DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
|
||||
|
||||
// Verify behaviour
|
||||
|
@ -1075,7 +1074,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
|||
locks[0].CloseAsync()
|
||||
.Returns(Task.FromResult((LockitLockingState?)LockitLockingState.Closed)); // Return lock state indicating success
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
||||
|
@ -1132,9 +1131,9 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
|||
activeUser);
|
||||
|
||||
locks[0].CloseAsync()
|
||||
.Returns<Task<LockitLockingState?>>(x => throw new OutOfReachException());
|
||||
.Returns<Task<LockitLockingState?>>(x => throw new OutOfReachException());
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
bike.LockInfo.State.Returns(LockingState.Open);
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
@ -1192,9 +1191,9 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
|||
activeUser);
|
||||
|
||||
locks[0].CloseAsync()
|
||||
.Returns<Task< LockitLockingState?>>(x => throw new Exception("Exception message."));
|
||||
.Returns<Task<LockitLockingState?>>(x => throw new Exception("Exception message."));
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
bike.LockInfo.State.Returns(LockingState.Open);
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
@ -1256,7 +1255,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
|||
|
||||
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()).Returns(x => throw new WebConnectFailureException("Context info", new System.Exception("hoppla")));
|
||||
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
||||
|
|
|
@ -1,25 +1,24 @@
|
|||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike.BluetoothLock;
|
||||
using TINK.Model.Bikes.Bike.BluetoothLock;
|
||||
using Newtonsoft.Json;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.State;
|
||||
using TINK.Model.User;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Repository.Request;
|
||||
using TINK.Repository.Response;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using TINK.Services.BluetoothLock.Exception;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
using TINK.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.Repository.Request;
|
||||
using TINK.Repository.Response;
|
||||
using Newtonsoft.Json;
|
||||
using TINK.Model.Device;
|
||||
|
||||
namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||
{
|
||||
|
|
|
@ -0,0 +1,589 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.State;
|
||||
using TINK.Model.User;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using TINK.Services.BluetoothLock.Exception;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
using TINK.Services.Geolocation;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
|
||||
|
||||
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("Connection error when reserving the bike!", "Context info.\r\nIs WIFI available/ mobile networt available and mobile data activated / ... ?", "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("Error when reserving the bike!", "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.UnknownDisconnected); // 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 = "Lock out of reach";
|
||||
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.UnknownDisconnected); // 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 = "Lock not found";
|
||||
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.UnknownFromHardwareError); // 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,441 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.State;
|
||||
using TINK.Model.User;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using TINK.Services.BluetoothLock.Exception;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
using TINK.Services.Geolocation;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
|
||||
|
||||
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.", "Is WIFI available/ mobile networt available and mobile data activated / ... ?"),
|
||||
"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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,25 +1,24 @@
|
|||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
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.Bikes.BikeInfoNS.BluetoothLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.State;
|
||||
using TINK.Model.User;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Repository.Request;
|
||||
using TINK.Repository.Response;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using TINK.Services.BluetoothLock.Exception;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
using TINK.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.Repository.Request;
|
||||
using TINK.Model.Device;
|
||||
|
||||
namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||
{
|
||||
|
@ -224,7 +223,10 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
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");
|
||||
viewService.DisplayAlert(
|
||||
"Error when canceling the reservation!",
|
||||
"Can not login user mustermann@server.de. Mail address unknown or password invalid.",
|
||||
"OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
|
@ -289,7 +291,10 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
bikesViewModel.ActionText = "Canceling reservation...";
|
||||
connector.Command.DoCancelReservation(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Verbingungsfehler beim Aufheben der Reservierung!", "Context info.\r\nIs WIFI available/ mobile networt available and mobile data activated / ... ?", "OK");
|
||||
viewService.DisplayAlert(
|
||||
"Connection error when canceling the reservation!",
|
||||
"Context info.\r\nIs WIFI available/ mobile networt available and mobile data activated / ... ?",
|
||||
"OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
|
@ -354,7 +359,10 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
bikesViewModel.ActionText = "Canceling reservation...";
|
||||
connector.Command.DoCancelReservation(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert("Fehler beim Aufheben der Reservierung!", "Exception message.", "OK");
|
||||
viewService.DisplayAlert(
|
||||
"Error when canceling the reservation!",
|
||||
"Exception message.",
|
||||
"OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
|
@ -542,6 +550,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
"OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
|
@ -610,6 +619,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
"OK");
|
||||
bikesViewModel.ActionText = "Updating...";
|
||||
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||
bikesViewModel.ActionText = "";
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
|
@ -856,7 +866,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
.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.
|
||||
|
||||
|
||||
locks[0].GetBatteryPercentageAsync().Returns<Task<double>>(x => throw new OutOfReachException());
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
|
|
@ -0,0 +1,760 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.State;
|
||||
using TINK.Model.User;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Repository.Response;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using TINK.Services.BluetoothLock.Exception;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
using TINK.Services.Geolocation;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
|
||||
|
||||
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.UnknownDisconnected); // 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.UnknownDisconnected); // 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(
|
||||
"Error when canceling the reservation!",
|
||||
"Can not login user mustermann@server.de. Mail address unknown or password invalid.",
|
||||
"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.UnknownDisconnected); // 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(
|
||||
"Connection error when canceling the reservation!",
|
||||
"Context info\r\nIs WIFI available/ mobile networt available and mobile data activated / ... ?",
|
||||
"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.UnknownDisconnected); // 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(
|
||||
"Error when canceling the reservation!",
|
||||
"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.UnknownFromHardwareError);
|
||||
|
||||
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("Error when connecting to lock!", "Internet must be reachable to connect to lock of reserved bike.\r\nContext info.\r\nIs WIFI available/ mobile networt available and mobile data activated / ... ?", "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.UnknownFromHardwareError);
|
||||
|
||||
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("Error when connecting to lock!", "Communication error during lock search.\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(
|
||||
"Error when connecting to lock!",
|
||||
"Lock can only be found when reserved bike is nearby.",
|
||||
"Retry",
|
||||
"Cancel");
|
||||
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(
|
||||
"Error when connecting to lock!",
|
||||
"Lock of reserved bike can not be found.",
|
||||
"",
|
||||
"Retry",
|
||||
"Cancel");
|
||||
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("Error when connecting to lock!", "Lock status of the reserved bike could not be determined.", "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,679 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.State;
|
||||
using TINK.Model.User;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Repository.Response;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using TINK.Services.BluetoothLock.Exception;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
using TINK.Services.Geolocation;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
|
||||
|
||||
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.", "Is WIFI available/ mobile networt available and mobile data activated / ... ?"),
|
||||
"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(
|
||||
"Error when canceling the reservation!",
|
||||
"Can not login user mustermann@server.de. Mail address unknown or password invalid.",
|
||||
"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(
|
||||
"Connection error when canceling the reservation!",
|
||||
"Context info\r\nIs WIFI available/ mobile networt available and mobile data activated / ... ?",
|
||||
"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(
|
||||
"Error when canceling the reservation!",
|
||||
"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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,25 +1,24 @@
|
|||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike.BluetoothLock;
|
||||
using TINK.Model.Bikes.Bike.BluetoothLock;
|
||||
using Newtonsoft.Json;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.State;
|
||||
using TINK.Model.User;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Repository.Request;
|
||||
using TINK.Repository.Response;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using TINK.Services.BluetoothLock.Exception;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
using TINK.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.Repository.Request;
|
||||
using TINK.Repository.Response;
|
||||
using Newtonsoft.Json;
|
||||
using TINK.Model.Device;
|
||||
|
||||
namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||
{
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
using System;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using TINK.Model.Bikes.BikeInfoNS.CopriLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.User;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Bikes.Bike.CopriLock.RequestHandler;
|
||||
|
||||
namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestBookedClosed
|
||||
{
|
||||
/// <summary>
|
||||
/// Use case: Try to open lock.
|
||||
/// Final state: Bike remains locked and stays booked.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestOpenLockOpenLockAsyncFailsWebConnectFailureException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new BookedClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
bike.LockInfo.State.Returns(LockingState.Closed); // Locking state does not change.
|
||||
|
||||
connector.Command.OpenLockAsync(bike).Returns(x => throw new WebConnectFailureException("Context info", new Exception("Tst")));
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Booked); // State remains booked because opening failed.
|
||||
|
||||
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 = "Opening lock...";
|
||||
connector.Command.OpenLockAsync(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAdvancedAlert(
|
||||
"Connection error when opening the lock!",
|
||||
"Is WIFI available/ mobile networt available and mobile data activated / ... ?",
|
||||
"Context info",
|
||||
"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.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("BookedClosed"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.False);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Open lock"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Try to open lock.
|
||||
/// Final state: Bike remains locked and stays booked.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestOpenLockOpenLockAsyncFailsException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new BookedClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
bike.LockInfo.State.Returns(LockingState.Closed); // Locking state does not change.
|
||||
|
||||
connector.Command.OpenLockAsync(bike).Returns(x => throw new Exception("Some error", new Exception("Inner exception")));
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Booked); // State remains booked because opening failed.
|
||||
|
||||
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 = "Opening lock...";
|
||||
connector.Command.OpenLockAsync(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert(
|
||||
"Error while opening lock!",
|
||||
"Some error",
|
||||
"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.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("BookedClosed"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.False);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Open lock"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Open lock.
|
||||
/// Final state: Lock is opened and bike remains booked.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestOpenLock()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new BookedClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
bike.LockInfo.State.Returns(LockingState.Open); // After opening, lock state is open.
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Booked); // After Booking and opening, state is 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 = "Opening lock...";
|
||||
connector.Command.OpenLockAsync(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
|
||||
Assert.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("BookedOpen"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.False);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Open lock"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,221 @@
|
|||
using System;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using TINK.Model.Bikes.BikeInfoNS.CopriLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.User;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Bikes.Bike.CopriLock.RequestHandler;
|
||||
|
||||
namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestBookedOpen
|
||||
{
|
||||
/// <summary>
|
||||
/// Use case: Try to open lock.
|
||||
/// Final state: Bike remains locked and stays booked.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestOpenLockOpenLockAsyncFailsWebConnectFailureException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new BookedOpen(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
bike.LockInfo.State.Returns(LockingState.Closed); // Locking state does not change.
|
||||
|
||||
connector.Command.OpenLockAsync(bike).Returns(x => throw new WebConnectFailureException("Context info", new Exception("Tst")));
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Booked); // State remains booked because opening failed.
|
||||
|
||||
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 = "Opening lock...";
|
||||
connector.Command.OpenLockAsync(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAdvancedAlert(
|
||||
"Connection error when opening the lock!",
|
||||
"Is WIFI available/ mobile networt available and mobile data activated / ... ?",
|
||||
"Context info",
|
||||
"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.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("BookedClosed"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.False);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Open lock"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Try to open lock.
|
||||
/// Final state: Bike remains locked and stays booked.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestOpenLockOpenLockAsyncFailsException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new BookedOpen(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
bike.LockInfo.State.Returns(LockingState.Closed); // Locking state does not change.
|
||||
|
||||
connector.Command.OpenLockAsync(bike).Returns(x => throw new Exception("Some error", new Exception("Inner exception")));
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Booked); // State remains booked because opening failed.
|
||||
|
||||
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 = "Opening lock...";
|
||||
connector.Command.OpenLockAsync(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert(
|
||||
"Error while opening lock!",
|
||||
"Some error",
|
||||
"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.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("BookedClosed"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.False);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Open lock"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Open lock.
|
||||
/// Final state: Lock is opened and bike remains booked.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestOpenLock()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new BookedOpen(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
bike.LockInfo.State.Returns(LockingState.Open); // After opening, lock state is open.
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Booked); // After Booking and opening, state is 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 = "Opening lock...";
|
||||
connector.Command.OpenLockAsync(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
|
||||
Assert.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("BookedOpen"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.False);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Open lock"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,656 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using TINK.Model.Bikes.BikeInfoNS.CopriLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.User;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Bikes.Bike.CopriLock.RequestHandler;
|
||||
|
||||
namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
|
||||
{
|
||||
public class TestDisposableClosed
|
||||
{
|
||||
/// <summary>
|
||||
/// Use case: Start booking and cancel.
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestBookAndReleaseCancel()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(
|
||||
string.Empty,
|
||||
"Rent bike Nr. 0 and open lock?",
|
||||
"Yes",
|
||||
"No").Returns(Task.FromResult(false)); // User chooes "No"
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
viewService.DisplayAlert(
|
||||
string.Empty,
|
||||
"Rent bike Nr. 0 and open lock?",
|
||||
"Yes",
|
||||
"No");
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("Open lock & rent bike"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.True);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Reserve bike"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Try book bike and release from station.
|
||||
/// Final state: Bike is disposable.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestBookAndReleaseBookAndOpenAyncFailsWebConnectFailureException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(
|
||||
string.Empty,
|
||||
string.Format("Rent bike {0} and open lock?", "Nr. 0"),
|
||||
"Yes",
|
||||
"No").Returns(Task.FromResult(true));
|
||||
|
||||
bike.LockInfo.State.Returns(LockingState.Closed); // Locking state does not change.
|
||||
|
||||
connector.Command.BookAndOpenAync(bike).Returns(x => throw new WebConnectFailureException("Context info", new Exception("Tst")));
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Disposable); // State remains available because booking request failed.
|
||||
|
||||
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 = "Renting bike...";
|
||||
connector.Command.BookAndOpenAync(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAdvancedAlert(
|
||||
"Connection error when renting the bike!",
|
||||
"Is WIFI available/ mobile networt available and mobile data activated / ... ?",
|
||||
"Context info",
|
||||
"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.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("Open lock & rent bike"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.True);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Reserve bike"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Try book bike and release from station.
|
||||
/// Final state: Bike is disposable.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestBookAndReleaseBookAndOpenAyncFailsException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(
|
||||
string.Empty,
|
||||
string.Format("Rent bike {0} and open lock?", "Nr. 0"),
|
||||
"Yes",
|
||||
"No").Returns(Task.FromResult(true));
|
||||
|
||||
bike.LockInfo.State.Returns(LockingState.Closed); // Locking state does not change.
|
||||
|
||||
connector.Command.BookAndOpenAync(bike).Returns(x => throw new Exception("Some error", new Exception("Inner exception")));
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Disposable); // State remains available because booking request failed.
|
||||
|
||||
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 = "Renting bike...";
|
||||
connector.Command.BookAndOpenAync(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert(
|
||||
"Error when renting the bike!",
|
||||
"Some error",
|
||||
"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.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("Open lock & rent bike"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.True);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Reserve bike"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Book bike and release from station.
|
||||
/// Final state: Bike is booked and released from station.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestBookAndRelease()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(
|
||||
string.Empty,
|
||||
string.Format("Rent bike {0} and open lock?", "Nr. 0"),
|
||||
"Yes",
|
||||
"No").Returns(Task.FromResult(true));
|
||||
|
||||
bike.LockInfo.State.Returns(LockingState.Open); // After Booking and opening, lock state is open.
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Booked); // After Booking and opening, state is 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 = "Renting bike...";
|
||||
connector.Command.BookAndOpenAync(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
|
||||
Assert.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("BookedOpen"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.False);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Open lock"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Cancel reserving.
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestReserveCancel()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => 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)); // User chooes "No"
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().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.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("Open lock & rent bike"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.True);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Reserve bike"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Try book reserve bike.
|
||||
/// Final state: Bike is disposable.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestReserveDoReserveFailsBookingDeclinedException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => 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));
|
||||
|
||||
bike.LockInfo.State.Returns(LockingState.Closed); // Locking state does not change.
|
||||
|
||||
connector.Command.DoReserve(bike).Returns(x => throw new BookingDeclinedException(4));
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Disposable); // State remains available because booking request failed.
|
||||
|
||||
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 = "Reserving bike...";
|
||||
connector.Command.DoReserve(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert(
|
||||
"Hint",
|
||||
"A reservation of bike Nr. 0 was rejected because the maximum allowed number of 4 reservations/ rentals had already been made.",
|
||||
"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.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("Open lock & rent bike"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.True);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Reserve bike"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Try book reserve bike.
|
||||
/// Final state: Bike is disposable.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestReserveDoReserveFailsWebConnectFailureException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => 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));
|
||||
|
||||
bike.LockInfo.State.Returns(LockingState.Closed); // Locking state does not change.
|
||||
|
||||
connector.Command.DoReserve(bike).Returns(x => throw new WebConnectFailureException("Context info", new Exception("Tst")));
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Disposable); // State remains available because booking request failed.
|
||||
|
||||
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 = "Reserving bike...";
|
||||
connector.Command.DoReserve(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAdvancedAlert(
|
||||
"Connection error when reserving the bike!",
|
||||
"Is WIFI available/ mobile networt available and mobile data activated / ... ?",
|
||||
"Context info",
|
||||
"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.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("Open lock & rent bike"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.True);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Reserve bike"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Try book reserve bike.
|
||||
/// Final state: Bike is disposable.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestReserveDoReserveFailsException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => 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));
|
||||
|
||||
bike.LockInfo.State.Returns(LockingState.Closed); // Locking state does not change.
|
||||
|
||||
connector.Command.DoReserve(bike).Returns(x => throw new Exception("Some error", new Exception("Inner exception")));
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Disposable); // State remains available because booking request failed.
|
||||
|
||||
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 = "Reserving bike...";
|
||||
connector.Command.DoReserve(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert(
|
||||
"Error when reserving the bike!",
|
||||
"Some error",
|
||||
"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.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("Open lock & rent bike"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.True);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Reserve bike"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Reserve bike.
|
||||
/// Final state: Bike is booked and released from station.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestReserve()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new DisposableClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => 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));
|
||||
|
||||
bike.LockInfo.State.Returns(LockingState.Open); // After Booking and opening, lock state is open.
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Booked); // After Booking and opening, lock state is open.
|
||||
|
||||
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 = "Reserving bike...";
|
||||
connector.Command.DoReserve(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
|
||||
Assert.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("BookedOpen"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.False);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Open lock"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,204 @@
|
|||
using System;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using TINK;
|
||||
using TINK.Model.Bikes.BikeInfoNS.CopriLock;
|
||||
using TINK.Model.Bikes.BikeInfoNS.DriveNS.BatteryNS;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.User;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Bikes.Bike.CopriLock.RequestHandler;
|
||||
|
||||
namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestFeedbackPending
|
||||
{
|
||||
/// <summary>
|
||||
/// Use case: Give feedback but submission fails.
|
||||
/// Final state: Feedback is pending.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestGiveFeedbackDoSubmitFeedbackFailsException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new FeedbackPending(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
connector.Command.DoSubmitFeedback(
|
||||
Arg.Any<TINK.Model.Connector.IUserFeedback>(),
|
||||
Arg.Any<Uri>()).Returns(x => throw new Exception("Context info", new Exception("Tst")));
|
||||
|
||||
|
||||
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
|
||||
viewService.DisplayUserFeedbackPopup(Arg.Any<IBattery>(), Arg.Any<string>());
|
||||
bikesViewModel.ActionText = "Submitting feedback...";
|
||||
connector.Command.DoSubmitFeedback(Arg.Any<TINK.Model.Connector.IUserFeedback>(), Arg.Any<Uri>()); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert(
|
||||
"Submitting feedback failed!",
|
||||
"Your feedback could not be send to server successfully.",
|
||||
"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.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("FeedbackPending"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.False);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Give Feedback"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Give feedback.
|
||||
/// Final state: Feedback is pending.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestGiveFeedback()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new FeedbackPending(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
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
|
||||
viewService.DisplayUserFeedbackPopup(Arg.Any<IBattery>(), Arg.Any<string>());
|
||||
bikesViewModel.ActionText = "Submitting feedback...";
|
||||
connector.Command.DoSubmitFeedback(Arg.Any<TINK.Model.Connector.IUserFeedback>(), Arg.Any<Uri>()); // 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.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("FeedbackPending"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.False);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Give Feedback"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Give feedback.
|
||||
/// Final state: Feedback is pending.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestGiveFeedbackAndQuerry()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new FeedbackPending(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.BookingFinishedModel.MiniSurvey.Questions.Count.Returns(1);
|
||||
|
||||
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
|
||||
viewService.DisplayUserFeedbackPopup(Arg.Any<IBattery>(), Arg.Any<string>());
|
||||
bikesViewModel.ActionText = "Submitting feedback...";
|
||||
connector.Command.DoSubmitFeedback(Arg.Any<TINK.Model.Connector.IUserFeedback>(), Arg.Any<Uri>()); // Booking must be performed
|
||||
viewService.PushModalAsync(ViewTypes.MiniSurvey);
|
||||
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.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("FeedbackPending"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.False);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Give Feedback"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,641 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using TINK.Model.Bikes.BikeInfoNS.CopriLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.User;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Repository.Response;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Bikes.Bike.CopriLock.RequestHandler;
|
||||
|
||||
namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestReservedClosed
|
||||
{
|
||||
/// <summary>
|
||||
/// Use case: Cancel reservation.
|
||||
/// 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 pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(
|
||||
string.Empty,
|
||||
"Cancel reservation for bike Nr. 0?",
|
||||
"Yes",
|
||||
"No").Returns(Task.FromResult(false)); // User chooes "No"
|
||||
|
||||
var subsequent = handler.HandleRequestOption1().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
viewService.DisplayAlert(
|
||||
string.Empty,
|
||||
"Cancel reservation for bike Nr. 0?",
|
||||
"Yes",
|
||||
"No");
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("Cancel bike reservation"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.True);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Open lock & rent bike"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCancelReservationDoCancelReservationInvalidAuthorizationResponseException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(
|
||||
string.Empty,
|
||||
"Cancel reservation for bike Nr. 0?",
|
||||
"Yes",
|
||||
"No").Returns(Task.FromResult(true));
|
||||
|
||||
connector.Command.DoCancelReservation(bike).Returns(x => throw new InvalidAuthorizationResponseException(
|
||||
"otto@mustermann.de", JsonConvert.DeserializeObject<ResponseBase>(@"{}")));
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Reserved); // Locking state does not change.
|
||||
|
||||
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(
|
||||
"Error when canceling the reservation!",
|
||||
"Can not login user otto@mustermann.de. Mail address unknown or password invalid.",
|
||||
"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.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("Cancel bike reservation"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.True);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Open lock & rent bike"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCancelReservationDoCancelReservationFailsWebConnectFailureException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(
|
||||
string.Empty,
|
||||
"Cancel reservation for bike Nr. 0?",
|
||||
"Yes",
|
||||
"No").Returns(Task.FromResult(true));
|
||||
|
||||
connector.Command.DoCancelReservation(bike).Returns(x => throw new WebConnectFailureException("Context info", new Exception("Tst")));
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Reserved); // Locking state does not change.
|
||||
|
||||
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.DisplayAdvancedAlert(
|
||||
"Connection error when canceling the reservation!",
|
||||
"Is WIFI available/ mobile networt available and mobile data activated / ... ?",
|
||||
"Context info",
|
||||
"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.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("Cancel bike reservation"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.True);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Open lock & rent bike"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Try cancel reservation.
|
||||
/// Final state: Bike remains reserved.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCancelReservationDoCancelReservationFailsException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(
|
||||
string.Empty,
|
||||
"Cancel reservation for bike Nr. 0?",
|
||||
"Yes",
|
||||
"No").Returns(Task.FromResult(true));
|
||||
|
||||
connector.Command.DoCancelReservation(bike).Returns(x => throw new Exception("Some error", new Exception("Inner exception")));
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Reserved); // Locking state does not change.
|
||||
|
||||
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); // Cancel reservation must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAlert(
|
||||
"Error when canceling the reservation!",
|
||||
"Some error",
|
||||
"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.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("Cancel bike reservation"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.True);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Open lock & rent bike"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Cancel reservation.
|
||||
/// Final state: Bike is available again.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCancelReservation()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(
|
||||
string.Empty,
|
||||
"Cancel reservation for bike Nr. 0?",
|
||||
"Yes",
|
||||
"No").Returns(Task.FromResult(true));
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Disposable); // Reservation gets canceled.
|
||||
|
||||
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); // Cancel reservation 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
|
||||
Assert.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("Open lock & rent bike"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.True);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Reserve bike"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Cancel booking.
|
||||
/// Final state: Same as initial state.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestBookAndReleaseCancel()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(
|
||||
string.Empty,
|
||||
"Rent bike Nr. 0 and open lock?",
|
||||
"Yes",
|
||||
"No").Returns(Task.FromResult(false)); // User chooes "No"
|
||||
|
||||
var subsequent = handler.HandleRequestOption2().Result;
|
||||
|
||||
// Verify behaviour
|
||||
Received.InOrder(() =>
|
||||
{
|
||||
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||
viewService.DisplayAlert(
|
||||
string.Empty,
|
||||
"Rent bike Nr. 0 and open lock?",
|
||||
"Yes",
|
||||
"No");
|
||||
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||
});
|
||||
|
||||
// Verify state after action
|
||||
Assert.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("Cancel bike reservation"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.True);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Open lock & rent bike"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Try book bike and release from station.
|
||||
/// Final state: Bike is disposable.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestBookAndReleaseBookAndOpenAyncFailsWebConnectFailureException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(
|
||||
string.Empty,
|
||||
string.Format("Rent bike {0} and open lock?", "Nr. 0"),
|
||||
"Yes",
|
||||
"No").Returns(Task.FromResult(true));
|
||||
|
||||
connector.Command.BookAndOpenAync(bike).Returns(x => throw new WebConnectFailureException("Context info", new Exception("Tst")));
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Reserved); // State remains reserved because booking request failed.
|
||||
|
||||
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 = "Renting bike...";
|
||||
connector.Command.BookAndOpenAync(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAdvancedAlert(
|
||||
"Connection error when renting the bike!",
|
||||
"Is WIFI available/ mobile networt available and mobile data activated / ... ?",
|
||||
"Context info",
|
||||
"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.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("Cancel bike reservation"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.True);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Open lock & rent bike"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Try book bike and release from station.
|
||||
/// Final state: Bike is disposable.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestBookAndReleaseBookAndOpenAyncFailsException()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(
|
||||
string.Empty,
|
||||
string.Format("Rent bike {0} and open lock?", "Nr. 0"),
|
||||
"Yes",
|
||||
"No").Returns(Task.FromResult(true));
|
||||
|
||||
connector.Command.BookAndOpenAync(bike).Returns(x => throw new Exception("Some error", new Exception("Inner exception")));
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Reserved); // State remains reserved because booking request failed.
|
||||
|
||||
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 = "Renting bike...";
|
||||
connector.Command.BookAndOpenAync(bike); // Booking must be performed
|
||||
bikesViewModel.ActionText = "";
|
||||
viewService.DisplayAdvancedAlert(
|
||||
"Error when renting the bike!",
|
||||
"Some error",
|
||||
String.Empty,
|
||||
"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.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("Cancel bike reservation"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.True);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Open lock & rent bike"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use case: Book bike and release from station.
|
||||
/// Final state: Bike is booked and released from station.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestBookAndRelease()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
var handler = new ReservedClosed(
|
||||
bike,
|
||||
() => true, // isConnectedDelegate
|
||||
(isConnexted) => connector,
|
||||
() => pollingManager,
|
||||
Substitute.For<ISmartDevice>(),
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
bike.Id.Returns("0");
|
||||
|
||||
viewService.DisplayAlert(
|
||||
string.Empty,
|
||||
string.Format("Rent bike {0} and open lock?", "Nr. 0"),
|
||||
"Yes",
|
||||
"No").Returns(Task.FromResult(true));
|
||||
|
||||
bike.LockInfo.State.Returns(LockingState.Open); // After Booking and opening, lock state is open.
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Booked); // After Booking and opening, state is 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 = "Renting bike...";
|
||||
connector.Command.BookAndOpenAync(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
|
||||
Assert.That(
|
||||
subsequent.ButtonText,
|
||||
Is.EqualTo("BookedOpen"));
|
||||
Assert.That(
|
||||
subsequent.IsButtonVisible,
|
||||
Is.False);
|
||||
Assert.That(
|
||||
subsequent.LockitButtonText,
|
||||
Is.EqualTo("Open lock"));
|
||||
Assert.That(
|
||||
subsequent.IsLockitButtonVisible,
|
||||
Is.True);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
using System;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using TINK.Model.Bikes.BikeInfoNS.CopriLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.User;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Bikes.Bike.CopriLock;
|
||||
using TINK.ViewModel.Bikes.Bike.CopriLock.RequestHandler;
|
||||
|
||||
namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestReqeustHandlerFactory
|
||||
{
|
||||
[Test]
|
||||
public void TestCreateDisposable()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var smartDevice = Substitute.For<ISmartDevice>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Disposable);
|
||||
|
||||
var requestHandler = RequestHandlerFactory.Create(
|
||||
bike,
|
||||
() => true /*isConnectedDelegate*/,
|
||||
(isconnected) => connector,
|
||||
() => pollingManager,
|
||||
smartDevice,
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
Assert.That(
|
||||
requestHandler.GetType(),
|
||||
Is.EqualTo(typeof(DisposableClosed)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCreateReserved()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var smartDevice = Substitute.For<ISmartDevice>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Reserved);
|
||||
|
||||
var requestHandler = RequestHandlerFactory.Create(
|
||||
bike,
|
||||
() => true /*isConnectedDelegate*/,
|
||||
(isconnected) => connector,
|
||||
() => pollingManager,
|
||||
smartDevice,
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
Assert.That(
|
||||
requestHandler.GetType(),
|
||||
Is.EqualTo(typeof(ReservedClosed)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCreateBooked()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var smartDevice = Substitute.For<ISmartDevice>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.Booked);
|
||||
|
||||
foreach (LockingState state in Enum.GetValues(typeof(LockingState)))
|
||||
{
|
||||
bike.LockInfo.State.Returns(state);
|
||||
|
||||
var requestHandler = RequestHandlerFactory.Create(
|
||||
bike,
|
||||
() => true /*isConnectedDelegate*/,
|
||||
(isconnected) => connector,
|
||||
() => pollingManager,
|
||||
smartDevice,
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
Assert.That(
|
||||
requestHandler.GetType(),
|
||||
Is.EqualTo(state == LockingState.Closed
|
||||
? typeof(BookedClosed)
|
||||
: typeof(BookedOpen)));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCreateFeedbackPending()
|
||||
{
|
||||
var bike = Substitute.For<IBikeInfoMutable>();
|
||||
var connector = Substitute.For<IConnector>();
|
||||
var command = Substitute.For<ICommand>();
|
||||
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||
var smartDevice = Substitute.For<ISmartDevice>();
|
||||
var viewService = Substitute.For<IViewService>();
|
||||
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||
var activeUser = Substitute.For<IUser>();
|
||||
|
||||
bike.State.Value.Returns(TINK.Model.State.InUseStateEnum.FeedbackPending);
|
||||
|
||||
foreach (LockingState state in Enum.GetValues(typeof(LockingState)))
|
||||
{
|
||||
bike.LockInfo.State.Returns(state);
|
||||
|
||||
var requestHandler = RequestHandlerFactory.Create(
|
||||
bike,
|
||||
() => true /*isConnectedDelegate*/,
|
||||
(isconnected) => connector,
|
||||
() => pollingManager,
|
||||
smartDevice,
|
||||
viewService,
|
||||
bikesViewModel,
|
||||
activeUser);
|
||||
|
||||
Assert.That(
|
||||
requestHandler.GetType(),
|
||||
Is.EqualTo(typeof(FeedbackPending)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
using NUnit.Framework;
|
||||
using TINK.Model.Bikes.Bike;
|
||||
using TINK.Model.Bikes.BikeInfoNS;
|
||||
using TINK.ViewModel.Bikes.Bike;
|
||||
|
||||
namespace TestShareeLib.ViewModel.Bikes.Bike
|
||||
|
@ -31,7 +31,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike
|
|||
Assert.That(
|
||||
viewModel.Name,
|
||||
Is.EqualTo("Fancy Tarif"));
|
||||
|
||||
|
||||
Assert.That(
|
||||
viewModel.TariffEntries.Count,
|
||||
Is.EqualTo(2));
|
||||
|
@ -39,11 +39,11 @@ namespace TestShareeLib.ViewModel.Bikes.Bike
|
|||
Assert.That(
|
||||
viewModel.InfoEntries.Count,
|
||||
Is.EqualTo(1));
|
||||
|
||||
|
||||
Assert.That(
|
||||
viewModel.OperatorAgb,
|
||||
Is.EqualTo("Mit der Mietrad Anmietung wird folgender Betreiber <a href='$varenv->{wwwhost}/site/agb.html' target='_blank'>AGB</a> zugestimmt"));
|
||||
|
||||
|
||||
Assert.That(
|
||||
viewModel.TarifEntry1.Value,
|
||||
Is.EqualTo("Max Gebühr"));
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
using NSubstitute;
|
||||
using NSubstitute.ExceptionExtensions;
|
||||
using NUnit.Framework;
|
||||
using Plugin.BLE.Abstractions.Contracts;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using NSubstitute;
|
||||
using NSubstitute.ExceptionExtensions;
|
||||
using NUnit.Framework;
|
||||
using Plugin.BLE.Abstractions.Contracts;
|
||||
using TestFramework.Model.Device;
|
||||
using TestFramework.Model.Services.Geolocation;
|
||||
using TestFramework.Model.User.Account;
|
||||
|
@ -15,12 +15,12 @@ using TINK.Model;
|
|||
using TINK.Model.Connector;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.Services.CopriApi;
|
||||
using TINK.Services.Geolocation;
|
||||
using TINK.Repository;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Services;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
using TINK.Services.Geolocation;
|
||||
using TINK.Services.Permissions;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel.BikesAtStation;
|
||||
|
@ -55,7 +55,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
activeGeolocationService: typeof(GeolocationMock).FullName),
|
||||
new StoreMock(new TINK.Model.User.Account.Account("", null, false, null, new List<string>())),
|
||||
isConnectedFunc: () => true,
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), sessionCookie, mail, new CopriCallsMemory001(sessionCookie)),
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, new CopriCallsMemory001(sessionCookie)),
|
||||
merchantId: "MyMerchId",
|
||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||
locationPermissionsService: null,
|
||||
|
@ -64,6 +64,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
device: new DeviceMock(), // Permissions
|
||||
specialFolder: new SpecialFolderMock(),
|
||||
cipher: null,
|
||||
theme: null,
|
||||
postAction: (d, obj) => d(obj),
|
||||
currentVersion: new Version(3, 2, 0, 115), // Current app version
|
||||
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
|
||||
|
@ -126,6 +127,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
var permissions = Substitute.For<ILocationPermission>();
|
||||
var bluetooth = Substitute.For<IBluetoothLE>();
|
||||
|
||||
const string MERCH_ID = "MyMerchId";
|
||||
|
||||
var tinkApp = new TinkApp(
|
||||
new TINK.Model.Settings.Settings(
|
||||
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.Off } }),
|
||||
|
@ -137,7 +140,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
activeGeolocationService: typeof(GeolocationMock).FullName),
|
||||
new StoreMock(new TINK.Model.User.Account.Account("a@b", "123456789", false, "5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", new List<string> { "300001", "300029" })),
|
||||
isConnectedFunc: () => true,
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), sessionCookie, mail, new CopriCallsMemory(SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, new CopriCallsMemory(MERCH_ID, SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
|
||||
merchantId: "MyMerchId",
|
||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||
locationPermissionsService: null,
|
||||
|
@ -146,6 +149,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
device: new DeviceMock(), // Permissions,
|
||||
specialFolder: new SpecialFolderMock(),
|
||||
cipher: null,
|
||||
theme: null,
|
||||
postAction: (d, obj) => d(obj),
|
||||
currentVersion: new Version(3, 2, 0, 115), // Current app version
|
||||
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
|
||||
|
@ -205,6 +209,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
}
|
||||
);
|
||||
|
||||
const string MERCH_ID = "MyMerchId";
|
||||
|
||||
var tinkApp = new TinkApp(
|
||||
new TINK.Model.Settings.Settings(
|
||||
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.Off } }),
|
||||
|
@ -216,8 +222,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
activeGeolocationService: typeof(GeolocationMock).FullName),
|
||||
new StoreMock(new TINK.Model.User.Account.Account("a@b", "123456789", false, "5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", new List<string> { "300001", "300029" })),
|
||||
isConnectedFunc: () => true,
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), sessionCookie, mail, new CopriCallsMemory(SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
|
||||
merchantId: "MyMerchId", // Instance geolocation mocks both parts
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo(MERCH_ID, "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, new CopriCallsMemory(MERCH_ID, SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
|
||||
merchantId: MERCH_ID, // Instance geolocation mocks both parts
|
||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||
locationPermissionsService: null,
|
||||
locationServicesContainer: geolocation,
|
||||
|
@ -225,6 +231,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
device: new DeviceMock(), // Permissions,
|
||||
specialFolder: new SpecialFolderMock(),
|
||||
cipher: null,
|
||||
theme: null,
|
||||
postAction: (d, obj) => d(obj),
|
||||
currentVersion: new Version(3, 2, 0, 115), // Current app version
|
||||
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
|
||||
|
@ -326,6 +333,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
|
||||
bluetooth.State.Returns(BluetoothState.On);
|
||||
|
||||
const string MERCH_ID = "MyMerchId";
|
||||
|
||||
var tinkApp = new TinkApp(
|
||||
new TINK.Model.Settings.Settings(
|
||||
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.Off } }),
|
||||
|
@ -337,8 +346,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
activeGeolocationService: typeof(GeolocationMock).FullName),
|
||||
new StoreMock(new TINK.Model.User.Account.Account("a@b", "123456789", false, "5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", new List<string> { "300001", "300029" })),
|
||||
isConnectedFunc: () => true,
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), sessionCookie, mail, new CopriCallsMemory(SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
|
||||
merchantId: "MyMerchId",
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo(MERCH_ID, "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, new CopriCallsMemory(MERCH_ID, SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
|
||||
merchantId: MERCH_ID,
|
||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||
locationPermissionsService: null,
|
||||
locationServicesContainer: geolocation,
|
||||
|
@ -346,6 +355,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
device: new DeviceMock(), // Permissions,
|
||||
specialFolder: new SpecialFolderMock(),
|
||||
cipher: null,
|
||||
theme: null,
|
||||
postAction: (d, obj) => d(obj),
|
||||
currentVersion: new Version(3, 2, 0, 115), // Current app version
|
||||
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
|
||||
|
@ -450,6 +460,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
{ new LockInfoTdo.Builder { Id = 2200537, State = LockitLockingState.Closed }.Build() }
|
||||
}
|
||||
);
|
||||
const string MERCH_ID = "MyMerchId";
|
||||
|
||||
var tinkApp = new TinkApp(
|
||||
new TINK.Model.Settings.Settings(
|
||||
|
@ -462,8 +473,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
activeGeolocationService: typeof(GeolocationMock).FullName),
|
||||
new StoreMock(new TINK.Model.User.Account.Account("a@b", "123456789", false, "5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", new List<string> { "300001", "300029" })),
|
||||
isConnectedFunc: () => true,
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), sessionCookie, mail, new CopriCallsMemory(SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
|
||||
merchantId: "MyMerchId",
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo(MERCH_ID, "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, new CopriCallsMemory(MERCH_ID, SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
|
||||
merchantId: MERCH_ID,
|
||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||
locationPermissionsService: null,
|
||||
locationServicesContainer: geolocation,
|
||||
|
@ -471,6 +482,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
device: new DeviceMock(), // Permissions,
|
||||
specialFolder: new SpecialFolderMock(),
|
||||
cipher: null,
|
||||
theme: null,
|
||||
postAction: (d, obj) => d(obj),
|
||||
currentVersion: new Version(3, 2, 0, 115), // Current app version
|
||||
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
|
||||
|
@ -572,6 +584,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
{ new LockInfoTdo.Builder { Id = 2200537, State = LockitLockingState.Closed }.Build() }
|
||||
}
|
||||
);
|
||||
const string MERCH_ID = "MyMerchId";
|
||||
|
||||
var tinkApp = new TinkApp(
|
||||
new TINK.Model.Settings.Settings(
|
||||
|
@ -584,8 +597,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
activeGeolocationService: typeof(GeolocationMock).FullName),
|
||||
new StoreMock(new TINK.Model.User.Account.Account("a@b", "123456789", false, "5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", new List<string> { "300001", "300029" })),
|
||||
isConnectedFunc: () => true,
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), sessionCookie, mail, new CopriCallsMemory(SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
|
||||
merchantId: "MyMerchId",
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo(MERCH_ID, "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, new CopriCallsMemory(MERCH_ID, SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
|
||||
merchantId: MERCH_ID,
|
||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||
locationPermissionsService: null,
|
||||
locationServicesContainer: geolocation,
|
||||
|
@ -593,6 +606,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
device: new DeviceMock(), // Permissions,
|
||||
specialFolder: new SpecialFolderMock(),
|
||||
cipher: null,
|
||||
theme: null,
|
||||
postAction: (d, obj) => d(obj),
|
||||
currentVersion: new Version(3, 2, 0, 115), // Current app version
|
||||
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
|
||||
|
@ -692,6 +706,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
{ new LockInfoTdo.Builder { Id = 2200537, State = LockitLockingState.Closed }.Build() }
|
||||
}
|
||||
);
|
||||
const string MERCH_ID = "MyMerchId";
|
||||
|
||||
var tinkApp = new TinkApp(
|
||||
new TINK.Model.Settings.Settings(
|
||||
|
@ -704,8 +719,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
activeGeolocationService: typeof(GeolocationMock).FullName),
|
||||
new StoreMock(new TINK.Model.User.Account.Account("a@b", "123456789", false, "5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", new List<string> { "300001", "300029" })),
|
||||
isConnectedFunc: () => true,
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), sessionCookie, mail, new CopriCallsMemory(SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
|
||||
merchantId: "MyMerchId",
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo(MERCH_ID, "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, new CopriCallsMemory(MERCH_ID, SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
|
||||
merchantId: MERCH_ID,
|
||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||
locationPermissionsService: null,
|
||||
locationServicesContainer: geolocation,
|
||||
|
@ -713,6 +728,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
device: new DeviceMock(), // Permissions,
|
||||
specialFolder: new SpecialFolderMock(),
|
||||
cipher: null,
|
||||
theme: null,
|
||||
postAction: (d, obj) => d(obj),
|
||||
currentVersion: new Version(3, 2, 0, 115), // Current app version
|
||||
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
|
||||
|
@ -805,6 +821,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
locksService.TimeOut.Returns(timeOut);
|
||||
timeOut.MultiConnect.Returns(new TimeSpan(0));
|
||||
|
||||
const string MERCH_ID = "MyMerchId";
|
||||
|
||||
var tinkApp = new TinkApp(
|
||||
new TINK.Model.Settings.Settings(
|
||||
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.Off } }),
|
||||
|
@ -816,8 +834,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
activeGeolocationService: typeof(GeolocationMock).FullName),
|
||||
new StoreMock(),
|
||||
isConnectedFunc: () => true,
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), sessionCookie, mail, new CopriCallsMemory001(sessionCookie)),
|
||||
merchantId: "MyMerchId",
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo(MERCH_ID, "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, new CopriCallsMemory001(sessionCookie)),
|
||||
merchantId: MERCH_ID,
|
||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||
locationPermissionsService: Substitute.For<ILocationPermission>(),
|
||||
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocation>>(),
|
||||
|
@ -825,6 +843,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
device: new DeviceMock(),
|
||||
specialFolder: new SpecialFolderMock(),
|
||||
cipher: null,
|
||||
theme: null,
|
||||
postAction: (d, obj) => d(obj),
|
||||
currentVersion: new Version(3, 2, 0, 115), // Current app version
|
||||
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
|
||||
|
@ -880,6 +899,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
locksService.TimeOut.Returns(timeOut);
|
||||
timeOut.MultiConnect.Returns(new TimeSpan(0));
|
||||
|
||||
const string MERCH_ID = "MyMerchId";
|
||||
|
||||
var tinkApp = new TinkApp(
|
||||
new TINK.Model.Settings.Settings(
|
||||
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.Off }, { FilterHelper.CITYBIKE, FilterState.On } }),
|
||||
|
@ -891,7 +912,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
activeGeolocationService: typeof(GeolocationMock).FullName),
|
||||
new StoreMock(),
|
||||
isConnectedFunc: () => true,
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), sessionCookie, mail, new CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)),
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, new CopriCallsMemory(MERCH_ID, SampleSets.Set2, 1, sessionCookie)),
|
||||
merchantId: "MyMerchId",
|
||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||
locationPermissionsService: Substitute.For<ILocationPermission>(),
|
||||
|
@ -900,6 +921,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
device: new DeviceMock(),
|
||||
specialFolder: new SpecialFolderMock(),
|
||||
cipher: null,
|
||||
theme: null,
|
||||
postAction: (d, obj) => d(obj),
|
||||
currentVersion: new Version(3, 2, 0, 115), // Current app version
|
||||
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
|
||||
|
@ -966,7 +988,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
"6103_112e96b36ba33de245943c5ffaf369cd_", // Was 4da3044c8657a04ba60e2eaa753bc51a before switching from data provider CopriCallsMemory(SampleSets.Set2, 1, ...)
|
||||
new List<string> { FilterHelper.CARGOBIKE })),
|
||||
isConnectedFunc: () => true,
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), sessionCookie, mail, new CopriCallsMemory001(sessionCookie)),
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, new CopriCallsMemory001(sessionCookie)),
|
||||
merchantId: "MyMerchId",
|
||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||
locationPermissionsService: Substitute.For<ILocationPermission>(),
|
||||
|
@ -975,6 +997,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
device: new DeviceMock(),
|
||||
specialFolder: new SpecialFolderMock(),
|
||||
cipher: null,
|
||||
theme: null,
|
||||
postAction: (d, obj) => d(obj),
|
||||
currentVersion: new Version(3, 2, 0, 115), // Current app version
|
||||
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
|
||||
|
@ -1007,7 +1030,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
|
||||
Assert.AreEqual("Available.", bikesAtStation.FirstOrDefault(x => x.Id == "FR9999").StateText);
|
||||
Assert.AreEqual("Available.", bikesAtStation.FirstOrDefault(x => x.Id == "FR9999").StateText);
|
||||
Assert.AreEqual("Max. reservation time of 15 minutes expired.", bikesAtStation.FirstOrDefault(x => x.Id == "FR1004").StateText);
|
||||
Assert.AreEqual("Max. reservation time of 15 min. expired.", bikesAtStation.FirstOrDefault(x => x.Id == "FR1004").StateText);
|
||||
Assert.AreEqual($"Rented since {DateTime.Parse("2021-11-06 18:57:25.445447+01"):dd. MMMM HH:mm}.", bikesAtStation.FirstOrDefault(x => x.Id == "FR1544").StateText); // Was 7
|
||||
|
||||
// Login hint/ no bikes frame
|
||||
|
@ -1041,7 +1064,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
activeGeolocationService: typeof(GeolocationMock).FullName),
|
||||
new StoreMock(),
|
||||
isConnectedFunc: () => false,
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), sessionCookie, mail, new CopriCallsMemory001(sessionCookie)),
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, new CopriCallsMemory001(sessionCookie)),
|
||||
merchantId: "MyMerchId",
|
||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||
locationPermissionsService: Substitute.For<ILocationPermission>(),
|
||||
|
@ -1050,6 +1073,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
device: new DeviceMock(),
|
||||
specialFolder: new SpecialFolderMock(),
|
||||
cipher: null, // Not connected.
|
||||
theme: null,
|
||||
postAction: (d, obj) => d(obj),
|
||||
currentVersion: new Version(3, 2, 0, 115), // Current app version
|
||||
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
|
||||
|
@ -1115,17 +1139,19 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
|
|||
new StoreMock(),
|
||||
isConnectedFunc: () => false,
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new TINK.Model.Connector.Connector(
|
||||
uri,
|
||||
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
|
||||
sessionCookie,
|
||||
mail,
|
||||
server: new CopriProviderHttps(
|
||||
uri,
|
||||
TinkApp.MerchantId,
|
||||
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
|
||||
sessionCookie: sessionCookie,
|
||||
cacheServer: new CopriCallsCacheMemory001(sessionCookie: sessionCookie),
|
||||
httpsServer: new ExceptionServer((msg) => new WebConnectFailureException(msg, new Exception("Source expection."))))),
|
||||
uri,
|
||||
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
|
||||
null /*UI language */,
|
||||
sessionCookie,
|
||||
mail,
|
||||
server: new CopriProviderHttps(
|
||||
uri,
|
||||
TinkApp.MerchantId,
|
||||
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
|
||||
null /*UI language */,
|
||||
sessionCookie: sessionCookie,
|
||||
cacheServer: new CopriCallsCacheMemory001(sessionCookie: sessionCookie),
|
||||
httpsServer: new ExceptionServer((msg) => new WebConnectFailureException(msg, new Exception("Source expection."))))),
|
||||
merchantId: "MyMerchId",
|
||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||
locationPermissionsService: Substitute.For<ILocationPermission>(),
|
||||
|
@ -1134,6 +1160,7 @@ httpsServer: new ExceptionServer((msg) => new WebConnectFailureException(msg, ne
|
|||
device: new DeviceMock(),
|
||||
specialFolder: new SpecialFolderMock(),
|
||||
cipher: null, // Not connected.
|
||||
theme: null,
|
||||
postAction: (d, obj) => d(obj),
|
||||
currentVersion: new Version(3, 2, 0, 115), // Current app version
|
||||
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
|
||||
|
@ -1203,17 +1230,19 @@ httpsServer: new ExceptionServer((msg) => new WebConnectFailureException(msg, ne
|
|||
new StoreMock(),
|
||||
isConnectedFunc: () => false,
|
||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new TINK.Model.Connector.Connector(
|
||||
uri,
|
||||
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
|
||||
sessionCookie,
|
||||
mail,
|
||||
server: new CopriProviderHttps(
|
||||
uri,
|
||||
TinkApp.MerchantId,
|
||||
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
|
||||
sessionCookie: sessionCookie,
|
||||
cacheServer: new CopriCallsCacheMemory001(sessionCookie: sessionCookie),
|
||||
httpsServer: new ExceptionServer((msg) => new Exception(msg)))),
|
||||
uri,
|
||||
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
|
||||
null /*UI language */,
|
||||
sessionCookie,
|
||||
mail,
|
||||
server: new CopriProviderHttps(
|
||||
uri,
|
||||
TinkApp.MerchantId,
|
||||
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
|
||||
null /*UI language */,
|
||||
sessionCookie: sessionCookie,
|
||||
cacheServer: new CopriCallsCacheMemory001(sessionCookie: sessionCookie),
|
||||
httpsServer: new ExceptionServer((msg) => new Exception(msg)))),
|
||||
merchantId: "MyMerchId",
|
||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||
locationPermissionsService: Substitute.For<ILocationPermission>(),
|
||||
|
@ -1222,6 +1251,7 @@ httpsServer: new ExceptionServer((msg) => new WebConnectFailureException(msg, ne
|
|||
device: new DeviceMock(),
|
||||
specialFolder: new SpecialFolderMock(),
|
||||
cipher: null, // Not connected.
|
||||
theme: null,
|
||||
postAction: (d, obj) => d(obj),
|
||||
currentVersion: new Version(3, 2, 0, 115), // Current app version
|
||||
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
using NUnit.Framework;
|
||||
using TINK.ViewModel.Login;
|
||||
|
||||
namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.CopriWebView
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestManageAccountViewModel
|
||||
{
|
||||
[Test]
|
||||
public void TestUrl()
|
||||
{
|
||||
var viewModel = new ManageAccountViewModel("Keks", "Merchant", "de", "Hosti");
|
||||
Assert.AreEqual("https://Hosti?sessionid=KeksMerchant&lang=de", viewModel.Uri);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
using NUnit.Framework;
|
||||
using TINK.ViewModel.CopriWebView;
|
||||
|
||||
namespace TestShareeLib.ViewModel.CopriWebView
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestPasswordForgottonViewModel
|
||||
{
|
||||
[Test]
|
||||
public void TestUri()
|
||||
=> Assert.That(
|
||||
new PasswordForgottonViewModel("merch", "de", "host").Uri,
|
||||
Is.EqualTo("https://host/app/Account?sessionid=merch&lang=de"));
|
||||
|
||||
[Test]
|
||||
public void TestUrl()
|
||||
{
|
||||
var viewModel = new PasswordForgottonViewModel("Merchant", null /* lang */, "Hosti");
|
||||
Assert.AreEqual("https://Hosti/app/Account?sessionid=Merchant", viewModel.Uri);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUrl_TINKLive()
|
||||
{
|
||||
var viewModel = new PasswordForgottonViewModel("Merchant", "us", "app.tink-konstanz.de");
|
||||
Assert.AreEqual("https://app.tink-konstanz.de/app/Account?sessionid=Merchant&lang=us", viewModel.Uri);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUrl_TINK()
|
||||
{
|
||||
var viewModel = new PasswordForgottonViewModel("Merchant", "de", "tinkwwp.copri-bike.de");
|
||||
Assert.AreEqual("https://tinkwwp.copri-bike.de/app/Account?sessionid=Merchant&lang=de", viewModel.Uri);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
using NUnit.Framework;
|
||||
using TINK.ViewModel.CopriWebView;
|
||||
|
||||
namespace TestShareeLib.ViewModel.CopriWebView
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestRegisterPageViewModel
|
||||
{
|
||||
[Test]
|
||||
public void TestUri()
|
||||
=> Assert.That(
|
||||
new RegisterPageViewModel("merch", "us", "host").Uri,
|
||||
Is.EqualTo("https://host/app/Account/1.%20Kundendaten?sessionid=merch&lang=us"));
|
||||
}
|
||||
}
|
15
TestShareeLib/ViewModel/Login/TestManageAccountViewModel.cs
Normal file
15
TestShareeLib/ViewModel/Login/TestManageAccountViewModel.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
using NUnit.Framework;
|
||||
using TINK.ViewModel.Login;
|
||||
|
||||
namespace TestShareeLib.ViewModel.Login
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestManageAccountViewModel
|
||||
{
|
||||
[Test]
|
||||
public void TestUri()
|
||||
=> Assert.That(
|
||||
new ManageAccountViewModel("keks", "merch", "de", "host").Uri,
|
||||
Is.EqualTo("https://host?sessionid=keksmerch&lang=de"));
|
||||
}
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using TINK.ViewModel.MiniSurvey.Question;
|
||||
|
||||
namespace TestShareeLib.ViewModel.MiniSurvey.Question
|
||||
|
@ -14,7 +12,7 @@ namespace TestShareeLib.ViewModel.MiniSurvey.Question
|
|||
{
|
||||
var vm = new CheckOneViewModel(
|
||||
new KeyValuePair<string, string>("q5", "wie ist das Wetter heute"),
|
||||
new Dictionary<string, string> { { "opt1", "regnerisch"}, { "opt2", "bewölkt" }, { "opt3", "sonnig" } });
|
||||
new Dictionary<string, string> { { "opt1", "regnerisch" }, { "opt2", "bewölkt" }, { "opt3", "sonnig" } });
|
||||
|
||||
Assert.That(
|
||||
vm.Question.Key,
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using TINK.ViewModel.MiniSurvey.Question;
|
||||
|
||||
namespace TestShareeLib.ViewModel.MiniSurvey.Question
|
||||
|
@ -43,7 +41,7 @@ namespace TestShareeLib.ViewModel.MiniSurvey.Question
|
|||
new KeyValuePair<string, string>("q9", "War das essen heute gut?"));
|
||||
|
||||
vm.AnswerText = "Sehr wohlschmeckend!"; // Member is called if user enters text.
|
||||
|
||||
|
||||
Assert.That(
|
||||
vm.Answer.Key,
|
||||
Is.EqualTo("Sehr wohlschmeckend!"),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using NUnit.Framework;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace TINK.ViewModel.Settings
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using NUnit.Framework;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.ViewModel;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using TINK.Settings;
|
||||
using TINK.ViewModel;
|
||||
|
||||
namespace UITest.Fixtures.ObjectTests
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using NUnit.Framework;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using TINK.ViewModel;
|
||||
|
||||
namespace TestTINKLib.Fixtures.ObjectTests
|
||||
|
@ -23,7 +23,7 @@ namespace TestTINKLib.Fixtures.ObjectTests
|
|||
{
|
||||
int index = 0;
|
||||
var task = new PollingUpdateTask(() => index++, new System.TimeSpan(10));
|
||||
|
||||
|
||||
System.Threading.SpinWait.SpinUntil(() => index > 2);
|
||||
|
||||
await task.Terminate();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using NSubstitute;
|
||||
using System;
|
||||
using NSubstitute;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using TINK.Model.Bikes.Bike.BC;
|
||||
using TINK.Model.Bikes.BikeInfoNS.BC;
|
||||
using TINK.ViewModel;
|
||||
|
||||
namespace TestShareeLib.ViewModel
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue