Version 3.0.381

This commit is contained in:
Anja 2024-04-09 12:53:23 +02:00
parent f963c0a219
commit 3a363acf3a
1525 changed files with 60589 additions and 125098 deletions

View file

@ -0,0 +1,221 @@
using System;
using NSubstitute;
using NUnit.Framework;
using ShareeBike.Model.Bikes.BikeInfoNS.CopriLock;
using ShareeBike.Model.Connector;
using ShareeBike.Model.Device;
using ShareeBike.Model.User;
using ShareeBike.Repository.Exception;
using ShareeBike.View;
using ShareeBike.ViewModel;
using ShareeBike.ViewModel.Bikes;
using ShareeBike.ViewModel.Bikes.Bike.CopriLock.RequestHandler;
namespace SharedBusinessLogic.Tests.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
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Booked); // State remains booked because opening failed.
var subsequent = handler.HandleRequestOption2().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Lock is opening. Please wait until it is completely open.";
connector.Command.OpenLockAsync(bike); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Connection to booking system not possible.",
"A stable Internet connection is required. Connect to WIFI or to mobile network and activate mobile data. Try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
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
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Booked); // State remains booked because opening failed.
var subsequent = handler.HandleRequestOption2().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Lock is opening. Please wait until it is completely open.";
connector.Command.OpenLockAsync(bike); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Lock could not be opened!",
"Some error",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
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
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Booked); // After Booking and opening, state is booked.
var subsequent = handler.HandleRequestOption2().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Lock is opening. Please wait until it is completely open.";
connector.Command.OpenLockAsync(bike); // Booking must be performed
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
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);
}
}
}

View file

@ -0,0 +1,222 @@
using System;
using NSubstitute;
using NUnit.Framework;
using ShareeBike.Model.Bikes.BikeInfoNS.CopriLock;
using ShareeBike.Model.Connector;
using ShareeBike.Model.Device;
using ShareeBike.Model.User;
using ShareeBike.Repository.Exception;
using ShareeBike.View;
using ShareeBike.ViewModel;
using ShareeBike.ViewModel.Bikes;
using ShareeBike.ViewModel.Bikes.Bike.CopriLock.RequestHandler;
namespace SharedBusinessLogic.Tests.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
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Booked); // State remains booked because opening failed.
var subsequent = handler.HandleRequestOption2().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Lock is opening. Please wait until it is completely open.";
connector.Command.OpenLockAsync(bike); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Connection to booking system not possible.",
"A stable Internet connection is required. Connect to WIFI or to mobile network and activate mobile data. Try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
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
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Booked); // State remains booked because opening failed.
var subsequent = handler.HandleRequestOption2().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Lock is opening. Please wait until it is completely open.";
connector.Command.OpenLockAsync(bike); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Lock could not be opened!",
"Some error",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
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
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Booked); // After Booking and opening, state is booked.
var subsequent = handler.HandleRequestOption2().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Lock is opening. Please wait until it is completely open.";
connector.Command.OpenLockAsync(bike); // Booking must be performed
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
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);
}
}
}

View file

@ -0,0 +1,664 @@
using System;
using System.Threading.Tasks;
using NSubstitute;
using NUnit.Framework;
using ShareeBike.Model.Bikes.BikeInfoNS.CopriLock;
using ShareeBike.Model.Connector;
using ShareeBike.Model.Device;
using ShareeBike.Model.User;
using ShareeBike.Repository.Exception;
using ShareeBike.View;
using ShareeBike.ViewModel;
using ShareeBike.ViewModel.Bikes;
using ShareeBike.ViewModel.Bikes.Bike.CopriLock.RequestHandler;
namespace SharedBusinessLogic.Tests.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
(isConnected) => 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 behavior
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("Start rental & Open lock"));
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
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Disposable); // State remains available because booking request failed.
var subsequent = handler.HandleRequestOption1().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Renting bike...";
connector.Command.BookAndOpenAync(bike); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Connection to booking system not possible.",
"A stable Internet connection is required. Connect to WIFI or to mobile network and activate mobile data. Try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state after action
Assert.That(
subsequent.ButtonText,
Is.EqualTo("Start rental & Open lock"));
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
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Disposable); // State remains available because booking request failed.
var subsequent = handler.HandleRequestOption1().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Renting bike...";
connector.Command.BookAndOpenAync(bike); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Bike could not be rented!",
"Some error",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state after action
Assert.That(
subsequent.ButtonText,
Is.EqualTo("Start rental & Open lock"));
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
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Booked); // After Booking and opening, state is booked.
var subsequent = handler.HandleRequestOption1().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Renting bike...";
connector.Command.BookAndOpenAync(bike); // Booking must be performed
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
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>();
bike.TariffDescription.MaxReservationTimeSpan.Returns(TimeSpan.FromMinutes(15));
var handler = new DisposableClosed(
bike,
() => true, // isConnectedDelegate
(isConnected) => 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 behavior
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("Start rental & Open lock"));
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>();
bike.TariffDescription.MaxReservationTimeSpan.Returns(TimeSpan.FromMinutes(15));
var handler = new DisposableClosed(
bike,
() => true, // isConnectedDelegate
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Disposable); // State remains available because booking request failed.
var subsequent = handler.HandleRequestOption2().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Reserving bike...";
connector.Command.DoReserve(bike); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
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.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state after action
Assert.That(
subsequent.ButtonText,
Is.EqualTo("Start rental & Open lock"));
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>();
bike.TariffDescription.MaxReservationTimeSpan.Returns(TimeSpan.FromMinutes(15));
var handler = new DisposableClosed(
bike,
() => true, // isConnectedDelegate
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Disposable); // State remains available because booking request failed.
var subsequent = handler.HandleRequestOption2().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Reserving bike...";
connector.Command.DoReserve(bike); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Connection to booking system not possible.",
"A stable Internet connection is required. Connect to WIFI or to mobile network and activate mobile data. Try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state after action
Assert.That(
subsequent.ButtonText,
Is.EqualTo("Start rental & Open lock"));
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>();
bike.TariffDescription.MaxReservationTimeSpan.Returns(TimeSpan.FromMinutes(15));
var handler = new DisposableClosed(
bike,
() => true, // isConnectedDelegate
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Disposable); // State remains available because booking request failed.
var subsequent = handler.HandleRequestOption2().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Reserving bike...";
connector.Command.DoReserve(bike); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Bike could not be reserved!",
"Some error",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state after action
Assert.That(
subsequent.ButtonText,
Is.EqualTo("Start rental & Open lock"));
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>();
bike.TariffDescription.MaxReservationTimeSpan.Returns(TimeSpan.FromMinutes(15));
var handler = new DisposableClosed(
bike,
() => true, // isConnectedDelegate
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Booked); // After Booking and opening, lock state is open.
var subsequent = handler.HandleRequestOption2().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Reserving bike...";
connector.Command.DoReserve(bike); // Booking must be performed
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
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);
}
}
}

View file

@ -0,0 +1,204 @@
using System;
using NSubstitute;
using NUnit.Framework;
using ShareeBike;
using ShareeBike.Model.Bikes.BikeInfoNS.CopriLock;
using ShareeBike.Model.Bikes.BikeInfoNS.DriveNS.BatteryNS;
using ShareeBike.Model.Connector;
using ShareeBike.Model.Device;
using ShareeBike.Model.User;
using ShareeBike.View;
using ShareeBike.ViewModel;
using ShareeBike.ViewModel.Bikes;
using ShareeBike.ViewModel.Bikes.Bike.CopriLock.RequestHandler;
namespace SharedBusinessLogic.Tests.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
(isConnected) => connector,
() => pollingManager,
Substitute.For<ISmartDevice>(),
viewService,
bikesViewModel,
activeUser);
connector.Command.DoSubmitFeedback(
Arg.Any<ShareeBike.Model.Connector.IUserFeedback>(),
Arg.Any<Uri>()).Returns(x => throw new Exception("Context info", new Exception("Tst")));
var subsequent = handler.HandleRequestOption2().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
viewService.DisplayUserFeedbackPopup(Arg.Any<IBatteryMutable>());
bikesViewModel.ActionText = "Submitting feedback...";
connector.Command.DoSubmitFeedback(Arg.Any<ShareeBike.Model.Connector.IUserFeedback>(), Arg.Any<Uri>()); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Submitting feedback failed!",
"A stable Internet connection is required. Connect to WIFI or to mobile network and activate mobile data. Try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
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
(isConnected) => connector,
() => pollingManager,
Substitute.For<ISmartDevice>(),
viewService,
bikesViewModel,
activeUser);
var subsequent = handler.HandleRequestOption2().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
viewService.DisplayUserFeedbackPopup(Arg.Any<IBatteryMutable>());
bikesViewModel.ActionText = "Submitting feedback...";
connector.Command.DoSubmitFeedback(Arg.Any<ShareeBike.Model.Connector.IUserFeedback>(), Arg.Any<Uri>()); // Booking must be performed
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
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
(isConnected) => connector,
() => pollingManager,
Substitute.For<ISmartDevice>(),
viewService,
bikesViewModel,
activeUser);
bike.BookingFinishedModel.MiniSurvey.Questions.Count.Returns(1);
var subsequent = handler.HandleRequestOption2().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
viewService.DisplayUserFeedbackPopup(Arg.Any<IBatteryMutable>());
bikesViewModel.ActionText = "Submitting feedback...";
connector.Command.DoSubmitFeedback(Arg.Any<ShareeBike.Model.Connector.IUserFeedback>(), Arg.Any<Uri>()); // Booking must be performed
viewService.PushModalAsync(ViewTypes.MiniSurvey);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
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);
}
}
}

View file

@ -0,0 +1,639 @@
using System;
using System.Threading.Tasks;
using Newtonsoft.Json;
using NSubstitute;
using NUnit.Framework;
using ShareeBike.Model.Bikes.BikeInfoNS.CopriLock;
using ShareeBike.Model.Connector;
using ShareeBike.Model.Device;
using ShareeBike.Model.User;
using ShareeBike.Repository.Exception;
using ShareeBike.Repository.Response;
using ShareeBike.View;
using ShareeBike.ViewModel;
using ShareeBike.ViewModel.Bikes;
using ShareeBike.ViewModel.Bikes.Bike.CopriLock.RequestHandler;
namespace SharedBusinessLogic.Tests.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
(isConnected) => 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 behavior
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 reservation"));
Assert.That(
subsequent.IsButtonVisible,
Is.True);
Assert.That(
subsequent.LockitButtonText,
Is.EqualTo("Start rental & Open lock"));
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
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Reserved); // Locking state does not change.
var subsequent = handler.HandleRequestOption1().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Canceling reservation...";
connector.Command.DoCancelReservation(bike); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Reservation could not be canceled!",
"Your session has expired. Please login new and try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state after action
Assert.That(
subsequent.ButtonText,
Is.EqualTo("Cancel reservation"));
Assert.That(
subsequent.IsButtonVisible,
Is.True);
Assert.That(
subsequent.LockitButtonText,
Is.EqualTo("Start rental & Open lock"));
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
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Reserved); // Locking state does not change.
var subsequent = handler.HandleRequestOption1().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Canceling reservation...";
connector.Command.DoCancelReservation(bike); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Reservation could not be canceled!",
"A stable Internet connection is required. Connect to WIFI or to mobile network and activate mobile data. Try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state after action
Assert.That(
subsequent.ButtonText,
Is.EqualTo("Cancel reservation"));
Assert.That(
subsequent.IsButtonVisible,
Is.True);
Assert.That(
subsequent.LockitButtonText,
Is.EqualTo("Start rental & Open lock"));
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
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Reserved); // Locking state does not change.
var subsequent = handler.HandleRequestOption1().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Canceling reservation...";
connector.Command.DoCancelReservation(bike); // Cancel reservation must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Reservation could not be canceled!",
"Some error",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state after action
Assert.That(
subsequent.ButtonText,
Is.EqualTo("Cancel reservation"));
Assert.That(
subsequent.IsButtonVisible,
Is.True);
Assert.That(
subsequent.LockitButtonText,
Is.EqualTo("Start rental & Open lock"));
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
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Disposable); // Reservation gets canceled.
var subsequent = handler.HandleRequestOption1().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Canceling reservation...";
connector.Command.DoCancelReservation(bike); // Cancel reservation must be performed
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state
Assert.That(
subsequent.ButtonText,
Is.EqualTo("Start rental & Open lock"));
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
(isConnected) => 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 behavior
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 reservation"));
Assert.That(
subsequent.IsButtonVisible,
Is.True);
Assert.That(
subsequent.LockitButtonText,
Is.EqualTo("Start rental & Open lock"));
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
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Reserved); // State remains reserved because booking request failed.
var subsequent = handler.HandleRequestOption2().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Renting bike...";
connector.Command.BookAndOpenAync(bike); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Connection to booking system not possible.",
"A stable Internet connection is required. Connect to WIFI or to mobile network and activate mobile data. Try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state after action
Assert.That(
subsequent.ButtonText,
Is.EqualTo("Cancel reservation"));
Assert.That(
subsequent.IsButtonVisible,
Is.True);
Assert.That(
subsequent.LockitButtonText,
Is.EqualTo("Start rental & Open lock"));
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
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Reserved); // State remains reserved because booking request failed.
var subsequent = handler.HandleRequestOption2().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Renting bike...";
connector.Command.BookAndOpenAync(bike); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAdvancedAlert(
"Bike could not be rented!",
"Some error",
String.Empty,
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state after action
Assert.That(
subsequent.ButtonText,
Is.EqualTo("Cancel reservation"));
Assert.That(
subsequent.IsButtonVisible,
Is.True);
Assert.That(
subsequent.LockitButtonText,
Is.EqualTo("Start rental & Open lock"));
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
(isConnected) => 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(ShareeBike.Model.State.InUseStateEnum.Booked); // After Booking and opening, state is booked.
var subsequent = handler.HandleRequestOption2().Result;
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Renting bike...";
connector.Command.BookAndOpenAync(bike); // Booking must be performed
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
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);
}
}
}