Version 3.0.370

This commit is contained in:
Anja 2023-08-31 12:20:06 +02:00
parent f5cf9bb22f
commit bdb2dec1c1
233 changed files with 10252 additions and 6779 deletions

View file

@ -0,0 +1,491 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using NSubstitute;
using NUnit.Framework;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Connector;
using TINK.Model.State;
using TINK.Repository.Request;
using TINK.Services.BluetoothLock;
using TINK.Services.BluetoothLock.Tdo;
using TINK.Services.Geolocation;
using Geolocation = TINK.Services.Geolocation.Geolocation;
using static TINK.Model.Bikes.BikeInfoNS.BluetoothLock.Command.CloseCommand;
using NSubstitute.ExceptionExtensions;
using TINK.Services.BluetoothLock.Exception;
using TINK.Repository.Exception;
using Newtonsoft.Json;
using TINK.Repository.Response;
using TINK.ViewModel;
namespace TestShareeLib.Model.Bikes.BikeInfoNS.BluetoothLock.Command
{
[TestFixture]
public class TestCloseCommand
{
[Test]
public async Task TestCloseGeolocationServiceGetAsyncFails()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
var listener = Substitute.For<ICloseCommandListener>();
var viewUpdateManager = Substitute.For<IPollingUpdateTaskManager>();
var startOfTest = DateTime.Now;
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>()).Throws(new Exception("Ups no location..."));
locks[0].CloseAsync()
.Returns(Task.FromResult((LockitLockingState?)LockitLockingState.Closed)); // Return lock state indicating success
bike.State.Value.Returns(InUseStateEnum.Booked);
await InvokeAsync<TestCloseCommand>(
bike,
geolocation,
locks,
() => true, // isConnectedDelegate
(isConnexted) => connector,
listener, null);
// Verify that location is kept because bike might be returned later.
Assert.That(
bike.LockInfo.Location,
Is.Null);
// Verify behavior
Received.InOrder(async () =>
{
listener.Received().ReportStep(Step.StartingQueryingLocation);
await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
await listener.Received().ReportStateAsync(State.StartGeolocationException, "Ups no location...");
listener.Received().ReportStep(Step.ClosingLock);
await locks.Received()[0].CloseAsync(); // Lock must be closed
await connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
});
}
/// <summary>
/// Use case: Close lock
/// </summary>
[Test]
public async Task TestClose()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
var listener = Substitute.For<ICloseCommandListener>();
var viewUpdateManager = Substitute.For<IPollingUpdateTaskManager>();
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>()).Returns(new Geolocation.Builder { Latitude = 47.99, Longitude = 7.78 }.Build());
locks[0].CloseAsync()
.Returns(Task.FromResult((LockitLockingState?)LockitLockingState.Closed)); // Return lock state indicating success
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.State.Returns(LockingState.Open);
await InvokeAsync<TestCloseCommand>(
bike,
geolocation,
locks,
() => true, // isConnectedDelegate
(isConnexted) => connector,
listener, null);
// Verify that location is kept because bike might be returned later.
Assert.That(
bike.LockInfo.Location.Latitude,
Is.EqualTo(47.99).Within(0.001));
Assert.That(
bike.LockInfo.Location.Longitude,
Is.EqualTo(7.78).Within(0.001));
Assert.That(
bike.LockInfo.State,
Is.EqualTo(LockingState.Closed));
// Verify behavior
Received.InOrder(async () =>
{
listener.Received().ReportStep(Step.StartingQueryingLocation);
await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
listener.Received().ReportStep(Step.ClosingLock);
await locks.Received()[0].CloseAsync(); // Lock must be closed
listener.Received().ReportStep(Step.WaitStopPollingQueryLocation);
listener.Received().ReportStep(Step.QueryLocationTerminated);
await connector.Command.UpdateLockingStateAsync(bike, Arg.Is<LocationDto>(x => x.Latitude == 47.99 && x.Longitude == 7.78));
});
}
[Test]
public void TestCloseCloseFailsOutOfReachException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
var listener = Substitute.For<ICloseCommandListener>();
var viewUpdateManager = Substitute.For<IPollingUpdateTaskManager>();
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>()).Returns(new Geolocation.Builder { Latitude = 47.99, Longitude = 7.78 }.Build());
locks[0].CloseAsync()
.Returns<Task<LockitLockingState?>>(x => throw new OutOfReachException());
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.State.Returns(LockingState.Open);
Assert.That(
async () => await InvokeAsync<TestCloseCommand>(
bike,
geolocation,
locks,
() => true, // isConnectedDelegate
(isConnexted) => connector,
listener, null),
Throws.InstanceOf<OutOfReachException>());
// Verify behavior
Received.InOrder(async () =>
{
listener.Received().ReportStep(Step.StartingQueryingLocation);
await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
listener.Received().ReportStep(Step.ClosingLock);
await locks.Received()[0].CloseAsync(); // Lock must be closed
await listener.Received().ReportStateAsync(State.OutOfReachError, "Exception of type 'TINK.Services.BluetoothLock.Exception.OutOfReachException' was thrown.");
});
Assert.That(
bike.LockInfo.State,
Is.EqualTo(LockingState.UnknownDisconnected));
}
[Test]
public void TestCloseCloseFailsCouldntCloseMovingException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
var listener = Substitute.For<ICloseCommandListener>();
var viewUpdateManager = Substitute.For<IPollingUpdateTaskManager>();
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>()).Returns(new Geolocation.Builder { Latitude = 47.99, Longitude = 7.78 }.Build());
locks[0].CloseAsync()
.Returns<Task<LockitLockingState?>>(x => throw new CouldntCloseMovingException());
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.State.Returns(LockingState.Open);
Assert.That(
async () => await InvokeAsync<TestCloseCommand>(
bike, geolocation, locks, () => true, (isConnexted) => connector, listener, null),
Throws.InstanceOf<CouldntCloseMovingException>());
// Verify behavior
Received.InOrder(async () =>
{
listener.Received().ReportStep(Step.StartingQueryingLocation);
await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
listener.Received().ReportStep(Step.ClosingLock);
await locks.Received()[0].CloseAsync(); // Lock must be closed
await listener.Received().ReportStateAsync(State.CouldntCloseMovingError, "The process is motion sensitive. Step close to the lock, do not move, and try again.");
await connector.Command.UpdateLockingStateAsync(bike, Arg.Is<LocationDto>(x => x.Latitude == 47.99 && x.Longitude == 7.78));
});
Assert.That(
bike.LockInfo.State,
Is.EqualTo(LockingState.Open));
}
[Test]
public void TestCloseCloseFailsCouldntCloseBoltBlockedException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
var listener = Substitute.For<ICloseCommandListener>();
var viewUpdateManager = Substitute.For<IPollingUpdateTaskManager>();
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>()).Returns(new Geolocation.Builder { Latitude = 47.99, Longitude = 7.78 }.Build());
locks[0].CloseAsync()
.Returns<Task<LockitLockingState?>>(x => throw new CouldntCloseBoltBlockedException());
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.State.Returns(LockingState.Open);
Assert.That(
async () => await InvokeAsync<TestCloseCommand>(bike, geolocation, locks, () => true, (isConnexted) => connector, listener, null),
Throws.InstanceOf<CouldntCloseBoltBlockedException>());
// Verify behavior
Received.InOrder(async () =>
{
listener.Received().ReportStep(Step.StartingQueryingLocation);
await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
listener.Received().ReportStep(Step.ClosingLock);
await locks.Received()[0].CloseAsync(); // Lock must be closed
await listener.Received().ReportStateAsync(State.CouldntCloseBoltBlockedError, "Lock bolt is blocked. Make sure that no spoke or any other obstacle prevents the lock from closing and try again.");
await connector.Command.UpdateLockingStateAsync(bike, Arg.Is<LocationDto>(x => x.Latitude == 47.99 && x.Longitude == 7.78));
});
Assert.That(
bike.LockInfo.State,
Is.EqualTo(LockingState.UnknownFromHardwareError));
}
[Test]
public void TestCloseCloseFailsCouldntCloseBoltBlockedExceptionOpen()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
var listener = Substitute.For<ICloseCommandListener>();
var viewUpdateManager = Substitute.For<IPollingUpdateTaskManager>();
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>()).Returns(new Geolocation.Builder { Latitude = 47.99, Longitude = 7.78 }.Build());
locks[0].CloseAsync()
.Returns<Task<LockitLockingState?>>(x => throw new CouldntCloseBoltBlockedException(LockingState.Open));
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.State.Returns(LockingState.Open);
Assert.That(
async () => await InvokeAsync<TestCloseCommand>(bike, geolocation, locks, () => true, (isConnexted) => connector, listener, null),
Throws.InstanceOf<CouldntCloseBoltBlockedException>());
// Verify behavior
Received.InOrder(async () =>
{
listener.Received().ReportStep(Step.StartingQueryingLocation);
await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
listener.Received().ReportStep(Step.ClosingLock);
await locks.Received()[0].CloseAsync(); // Lock must be closed
await listener.Received().ReportStateAsync(State.CouldntCloseBoltBlockedError, "Lock bolt is blocked. Make sure that no spoke or any other obstacle prevents the lock from closing and try again.");
await connector.Command.UpdateLockingStateAsync(bike, Arg.Is<LocationDto>(x => x.Latitude == 47.99 && x.Longitude == 7.78));
});
Assert.That(
bike.LockInfo.State,
Is.EqualTo(LockingState.Open));
}
[Test]
public void TestCloseCloseFailsCouldntCloseInconsistentState()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
var listener = Substitute.For<ICloseCommandListener>();
var viewUpdateManager = Substitute.For<IPollingUpdateTaskManager>();
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>()).Returns(new Geolocation.Builder { Latitude = 47.99, Longitude = 7.78 }.Build());
locks[0].CloseAsync()
.Returns<Task<LockitLockingState?>>(x => throw new CouldntCloseInconsistentStateExecption(LockitLockingState.Unknown.GetLockingState()));
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.State.Returns(LockingState.Open);
Assert.That(
async () => await InvokeAsync<TestCloseCommand>(bike, geolocation, locks, () => true, (isConnexted) => connector, listener, null),
Throws.InstanceOf<CouldntCloseInconsistentStateExecption>());
// Verify behavior
Received.InOrder(async () =>
{
listener.Received().ReportStep(Step.StartingQueryingLocation);
await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
listener.Received().ReportStep(Step.ClosingLock);
await locks.Received()[0].CloseAsync(); // Lock must be closed
await listener.Received().ReportStateAsync(State.GeneralCloseError, "Lock reports unknown bold position. Lock could be closed or open. Please try again or contact customer support.");
await connector.Command.UpdateLockingStateAsync(bike, Arg.Is<LocationDto>(x => x.Latitude == 47.99 && x.Longitude == 7.78));
});
Assert.That(
bike.LockInfo.State,
Is.EqualTo(LockingState.UnknownFromHardwareError));
}
[Test]
public void TestCloseCloseFailsException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var command = Substitute.For<ICommand>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
var listener = Substitute.For<ICloseCommandListener>();
var viewUpdateManager = Substitute.For<IPollingUpdateTaskManager>();
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>()).Returns(new Geolocation.Builder { Latitude = 47.99, Longitude = 7.78 }.Build());
locks[0].CloseAsync()
.Returns<Task<LockitLockingState?>>(x => throw new Exception("Exception message."));
bike.State.Value.Returns(InUseStateEnum.Booked);
Assert.That(
async () => await InvokeAsync<TestCloseCommand>(bike, geolocation, locks, () => true, (isConnexted) => connector, listener, null),
Throws.InstanceOf<Exception>());
// Verify behavior
Received.InOrder(async () =>
{
listener.Received().ReportStep(Step.StartingQueryingLocation);
await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
listener.Received().ReportStep(Step.ClosingLock);
await locks.Received()[0].CloseAsync(); // Lock must be closed
await listener.ReportStateAsync(State.GeneralCloseError, "Exception message.");
await connector.Command.UpdateLockingStateAsync(bike, Arg.Is<LocationDto>(x => x.Latitude == 47.99 && x.Longitude == 7.78));
});
Assert.That(
bike.LockInfo.State,
Is.EqualTo(LockingState.UnknownDisconnected));
}
[Test]
public async Task TestCloseWaitGeolocationServiceGetAsyncFails()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var command = Substitute.For<ICommand>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
var listener = Substitute.For<ICloseCommandListener>();
var viewUpdateManager = Substitute.For<IPollingUpdateTaskManager>();
locks[0].CloseAsync()
.Returns(LockitLockingState.Closed); // Return lock state indicating success
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>()).Returns(Task.FromException<IGeolocation>(new Exception("Ups, some error...")));
bike.State.Value.Returns(InUseStateEnum.Booked);
await InvokeAsync<TestCloseCommand>(bike, geolocation, locks, () => true, (isConnexted) => connector, listener, null);
// Verify behavior
Received.InOrder(async () =>
{
listener.Received().ReportStep(Step.StartingQueryingLocation);
await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
listener.Received().ReportStep(Step.ClosingLock);
await locks.Received()[0].CloseAsync(); // Lock must be closed
listener.Received().ReportStep(Step.WaitStopPollingQueryLocation);
await listener.Received().ReportStateAsync(State.WaitGeolocationException, "Ups, some error...");
listener.Received().ReportStep(Step.QueryLocationTerminated);
await connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
});
}
[Test]
public async Task TestCloseUpdateLockingStateFailsWebConnectFailureException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var command = Substitute.For<ICommand>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
var listener = Substitute.For<ICloseCommandListener>();
var viewUpdateManager = Substitute.For<IPollingUpdateTaskManager>();
locks[0].CloseAsync()
.Returns(LockitLockingState.Closed); // Return lock state indicating success
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()).Returns(x => throw new WebConnectFailureException("Context info.", new System.Exception("hoppla")));
bike.State.Value.Returns(InUseStateEnum.Booked);
await InvokeAsync<TestCloseCommand>(bike, geolocation, locks, () => true, (isConnexted) => connector, listener, null);
// Verify behavior
Received.InOrder(async () =>
{
listener.Received().ReportStep(Step.StartingQueryingLocation);
await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
listener.Received().ReportStep(Step.ClosingLock);
await locks.Received()[0].CloseAsync(); // Lock must be closed
await connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
await listener.ReportStateAsync(State.WebConnectFailed, "Context info.");
});
}
[Test]
public async Task TestCloseUpdateLockingStateFailsResponseException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var command = Substitute.For<ICommand>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
var listener = Substitute.For<ICloseCommandListener>();
var viewUpdateManager = Substitute.For<IPollingUpdateTaskManager>();
locks[0].CloseAsync()
.Returns(LockitLockingState.Closed); // Return lock state indicating success
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()).Returns(x =>
throw new ReturnBikeException(JsonConvert.DeserializeObject<DoReturnResponse>(@"{ ""response_text"" : ""Some invalid data received!""}"), "Outer message."));
bike.State.Value.Returns(InUseStateEnum.Booked);
await InvokeAsync<TestCloseCommand>(bike, geolocation, locks, () => true, (isConnexted) => connector, listener, null);
// Verify behavior
Received.InOrder(async () =>
{
listener.Received().ReportStep(Step.StartingQueryingLocation);
await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
listener.Received().ReportStep(Step.ClosingLock);
await locks.Received()[0].CloseAsync(); // Lock must be closed
await connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
await listener.ReportStateAsync(State.ResponseIsInvalid, "Outer message.");
});
}
[Test]
public async Task TestCloseUpdateLockingStateFailsException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var command = Substitute.For<ICommand>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
var listener = Substitute.For<ICloseCommandListener>();
var viewUpdateManager = Substitute.For<IPollingUpdateTaskManager>();
locks[0].CloseAsync()
.Returns(LockitLockingState.Closed); // Return lock state indicating success
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()).Returns(x => throw new Exception("Exception message."));
bike.State.Value.Returns(InUseStateEnum.Booked);
await InvokeAsync<TestCloseCommand>(bike, geolocation, locks, () => true, (isConnexted) => connector, listener, null);
// Verify behavior
Received.InOrder(async () =>
{
listener.Received().ReportStep(Step.StartingQueryingLocation);
await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
listener.Received().ReportStep(Step.ClosingLock);
await locks.Received()[0].CloseAsync(); // Lock must be closed
await connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
await listener.ReportStateAsync(State.BackendUpdateFailed, "Exception message.");
});
}
}
}

View file

@ -0,0 +1,203 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using NSubstitute;
using NSubstitute.ExceptionExtensions;
using NUnit.Framework;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock.Command;
using TINK.Model.Connector;
using TINK.Model.Device;
using TINK.Model.State;
using TINK.Model.User;
using TINK.Services.BluetoothLock;
using TINK.Services.Geolocation;
using static TINK.Model.Bikes.BikeInfoNS.BluetoothLock.Command.GetLockedLocationCommand;
namespace TestShareeLib.Model.Bikes.BikeInfoNS.BluetoothLock.Command
{
public class TestGetBikeLocationCommand
{
/// <summary>
/// Use case: End rental.
/// Final state: Booked, lock state unknown.
/// </summary>
/// <remarks> Replaces test TestReturnOutOfReach which was removed for sharee.bike version ~3.0.362. </remarks>
[Test]
public void TestReturnLastGeolocatonNullLockOutOfReach()
{
var bike = Substitute.For<IBikeInfoMutable>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
var listener = Substitute.For<IGetLockedLocationCommandListener>();
bike.Id.Returns("0");
bike.LockInfo.Location.Returns((IGeolocation)null); // When locking bike geolocation was not available.
locks[0].GetDeviceState().Returns(DeviceState.Disconnected); // Simulate bike out of reach.
locks.DisconnectAsync(0, Arg.Any<Guid>()).Returns(LockingState.UnknownDisconnected); // Simulate disconnecting.
bike.State.Value.Returns(InUseStateEnum.Booked);
Assert.That(
async () => await InvokeAsync<TestGetBikeLocationCommand>(
bike,
geolocation,
locks,
listener: listener),
Throws.TypeOf<Exception>());
// Verify behavior
Received.InOrder(() =>
{
listener.ReportStep(Step.StartingQueryLocation);
var location = bike.LockInfo.Location;
locks[0].GetDeviceState();
listener.ReportStateAsync(State.DisconnetedNoLocationError, "");
listener.ReportStep(Step.DisconnectingLockOnDisconnectedNoLocationError);
locks.DisconnectAsync(0, Arg.Any<Guid>());
listener.ReportStateAsync(State.QueryLocationSucceeded, "");
});
Assert.That(
bike.LockInfo.State,
Is.EqualTo(LockingState.UnknownDisconnected));
}
/// <summary>
/// Use case: End rental.
/// Final state: Booked, lock state unknown.
/// </summary>
/// <remarks>Replaces test TestReturnLockInReachNoGeolocation which was removed for sharee.bike older ~ 3.0.362.</remarks>
[Test]
public void TestReturnStartGetGeolocationException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
var listener = Substitute.For<IGetLockedLocationCommandListener>();
bike.Id.Returns("0");
bike.LockInfo.Location.Returns((IGeolocation)null); // When locking bike geolocation was not available.
locks[0].GetDeviceState().Returns(DeviceState.Connected); // Simulate bike in reach.
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>()).Throws(new Exception("Ups...")); // Simulate error when starting query for geolocation.
bike.State.Value.Returns(InUseStateEnum.Booked); // Booking state does not change.
bike.LockInfo.State.Returns(LockingState.Closed); // Locking state does not change.
var subsequent = InvokeAsync<TestGetBikeLocationCommand>(
bike,
geolocation,
locks,
listener: listener);
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.StartingQueryLocation);
locks[0].GetDeviceState();
await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
await listener.ReportStateAsync(State.QueryLocationFailed, "Ups...");
});
}
/// <summary>
/// Use case: End rental.
/// Final state: Booked, lock state unknown.
/// </summary>
[Test]
public void TestReturnGetGeolocationException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
var listener = Substitute.For<IGetLockedLocationCommandListener>();
bike.Id.Returns("0");
bike.LockInfo.Location.Returns((IGeolocation)null); // When locking bike geolocation was not available.
locks[0].GetDeviceState().Returns(DeviceState.Connected); // Simulate bike in reach.
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>())
.Returns(Task.FromException<IGeolocation>(new Exception("Ups..."))); // Simulate error starting query for geolocation.
bike.State.Value.Returns(InUseStateEnum.Booked); // Booking state does not change.
bike.LockInfo.State.Returns(LockingState.Closed); // Locking state does not change.
Assert.That(
async () => await InvokeAsync<TestGetBikeLocationCommand>(
bike,
geolocation,
locks,
listener: listener),
Throws.TypeOf<Exception>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.StartingQueryLocation);
locks[0].GetDeviceState();
await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
await listener.ReportStateAsync(State.QueryLocationFailed, "Ups...");
});
}
/// <summary>
/// Use case: End rental.
/// Final state: Disposable closed
/// </summary>
[Test]
public async Task TestReturnLockInReach()
{
var bike = Substitute.For<IBikeInfoMutable>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
var listener = Substitute.For<IGetLockedLocationCommandListener>();
bike.LockInfo.Location.Returns((IGeolocation)null);
bike.Id.Returns("0");
locks[0].GetDeviceState().Returns(DeviceState.Connected); // Simulate bike in reach. If bike is out of reach bluetooth state changes to unknown.
var location = Substitute.For<IGeolocation>();
location.Latitude.Returns(7);
location.Longitude.Returns(9);
location.Timestamp.Returns(DateTimeOffset.MinValue);
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime>()).Returns(Task.FromResult(
location
)); ;
var lockingLocation = await InvokeAsync<TestGetBikeLocationCommand>(
bike,
geolocation,
locks,
() => DateTime.MinValue,
listener);
Assert.That(lockingLocation.Latitude, Is.EqualTo(7));
Assert.That(lockingLocation.Longitude, Is.EqualTo(9));
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.StartingQueryLocation);
var dummyLoc = bike.LockInfo.Location; // Check if location was available when closing lock.
locks[0].GetDeviceState(); // Check if bike is connected.
await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime>()); // Query current location.
await listener.ReportStateAsync(State.QueryLocationSucceeded, string.Empty);
});
}
}
}

View file

@ -1,7 +1,12 @@
using System;
using NSubstitute;
using NUnit.Framework;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Bikes.BikeInfoNS.DriveNS;
using TINK.Model.Connector;
using TINK.Services.BluetoothLock;
using TINK.Services.Geolocation;
using TINK.ViewModel;
namespace TestShareeLib.Model.Bike.BluetoothLock
{
@ -13,6 +18,11 @@ namespace TestShareeLib.Model.Bike.BluetoothLock
{
Assert.That(
new BikeInfoMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>(),
new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(
new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike(
"MyBikeId",
@ -31,6 +41,11 @@ namespace TestShareeLib.Model.Bike.BluetoothLock
{
Assert.That(
new BikeInfoMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>(),
new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(
new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike(
"MyBikeId",
@ -50,7 +65,14 @@ namespace TestShareeLib.Model.Bike.BluetoothLock
public void TestCtorBikeNull()
{
Assert.That(
() => new BikeInfoMutable(null, "My Station Name"),
() => new BikeInfoMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>(),
null,
"My Station Name"),
Throws.ArgumentNullException);
}
}

View file

@ -95,7 +95,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
lockInfo.Location = new Geolocation.Builder { Latitude = 47.99, Longitude = 7.78}.Build();
// Veryfy that location is kept because bike might be returned later.
// Verify that location is kept because bike might be returned later.
Assert.That(
lockInfo.Location.Latitude,
Is.EqualTo(47.99).Within(0.001));
@ -113,7 +113,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
lockInfo.State = LockingState.Closed;
// Veryfy that location is kept because bike might be returned later.
// Verify that location is kept because bike might be returned later.
Assert.That(
lockInfo.Location,
Is.Null);

View file

@ -1,15 +1,20 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using NSubstitute;
using NUnit.Framework;
using TINK.Model.Bikes;
using TINK.Model.Bikes.BikeInfoNS;
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.Model.Bikes.BikeInfoNS.DriveNS;
using TINK.Model.Connector;
using TINK.Model.Connector.Updater;
using TINK.Model.State;
using TINK.Model.Stations;
using TINK.Model.Stations.StationNS;
using TINK.Services.BluetoothLock;
using TINK.Services.Geolocation;
using TINK.ViewModel;
using BikeInfo = TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo;
namespace TestTINKLib
@ -54,7 +59,12 @@ namespace TestTINKLib
[Test]
public void TestAdd()
{
var l_oColl = new BikeCollectionMutable();
var l_oColl = new BikeCollectionMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>());
l_oColl.Add(new BikeInfoMutable("57", LockModel.ILockIt, false, new List<string> { "TINK" }, WheelType.Two, TypeOfBike.Allround));
@ -67,7 +77,12 @@ namespace TestTINKLib
var l_oBikeRequested = new BikeInfoMutable("20", LockModel.ILockIt, false, new List<string> { "TINK" }, WheelType.Trike, TypeOfBike.Allround);
l_oBikeRequested.State.Load(new StateInfo(() => DateTime.Now, DateTime.Now, TimeSpan.FromMinutes(15), "john@long", "1234"));
var l_oBikeColl = new BikeCollectionMutable
var l_oBikeColl = new BikeCollectionMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>())
{
new BikeInfoMutable("63", LockModel.ILockIt, false, new List<string> { "TINK" }, WheelType.Two, TypeOfBike.Allround),
new BikeInfoMutable("57", LockModel.ILockIt, false, new List<string> { "TINK" }, WheelType.Trike, TypeOfBike.Cargo),
@ -95,7 +110,12 @@ namespace TestTINKLib
var bikeRequested = new BikeInfoMutable("20", LockModel.ILockIt, false, new List<string> { "TINK" }, WheelType.Trike, TypeOfBike.Allround);
bikeRequested.State.Load(new StateInfo(() => DateTime.Now, DateTime.Now, TimeSpan.FromMinutes(15), "john@long", "1234"));
var bikeColl = new BikeCollectionMutable
var bikeColl = new BikeCollectionMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>())
{
new BikeInfoMutable("63", LockModel.ILockIt, false, new List<string> { "TINK" }, WheelType.Two, TypeOfBike.Allround),
new BikeInfoMutable("57", LockModel.ILockIt, false, new List<string> { "TINK" }, WheelType.Trike, TypeOfBike.Cargo),
@ -152,7 +172,12 @@ namespace TestTINKLib
[Test]
public void TestUpdate_StationName_NewBike()
{
var bikeColl = new BikeCollectionMutable();
var bikeColl = new BikeCollectionMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>());
// Verify initial state
Assert.That(bikeColl.GetById("57"), Is.Null);
@ -184,7 +209,12 @@ namespace TestTINKLib
public void TestUpdate_StationName_UpdateExistingBike()
{
var bikeColl = new BikeCollectionMutable
var bikeColl = new BikeCollectionMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>())
{
new BikeInfoMutable("57", LockModel.ILockIt, false, new List<string> { "TINK" }, WheelType.Trike, TypeOfBike.Cargo),
};
@ -229,7 +259,12 @@ namespace TestTINKLib
public void TestUpdate_StationName_Nullstations()
{
var bikeColl = new BikeCollectionMutable();
var bikeColl = new BikeCollectionMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>());
var bikeResponse = new List<BikeInfo>
@ -265,7 +300,13 @@ namespace TestTINKLib
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri);
Assert.That(
BikeCollectionMutable.BikeInfoMutableFactory.Create(bikeInfo, "Stat1").GetType(),
BikeCollectionMutable.BikeInfoMutableFactory.Create(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>(),
bikeInfo, "Stat1").GetType(),
Is.EqualTo(typeof(TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable)));
}
@ -284,7 +325,13 @@ namespace TestTINKLib
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri);
Assert.That(
BikeCollectionMutable.BikeInfoMutableFactory.Create(bikeInfo, "Stat1").GetType(),
BikeCollectionMutable.BikeInfoMutableFactory.Create(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>(),
bikeInfo, "Stat1").GetType(),
Is.EqualTo(typeof(TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfoMutable)));
}
@ -304,7 +351,13 @@ namespace TestTINKLib
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri);
Assert.That(
BikeCollectionMutable.BikeInfoMutableFactory.Create(bikeInfo, "Stat1"),
BikeCollectionMutable.BikeInfoMutableFactory.Create(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>(),
bikeInfo, "Stat1"),
Is.Null);
}
}

View file

@ -1,18 +1,23 @@
using System;
using System.Linq;
using Newtonsoft.Json;
using NSubstitute;
using NUnit.Framework;
using TINK.Model;
using TINK.Model.Bikes;
using TINK.Model.Bikes.BikeInfoNS.BC;
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.Model.Bikes.BikeInfoNS.DriveNS;
using TINK.Model.Connector;
using TINK.Model.Connector.Updater;
using TINK.Model.State;
using TINK.Model.User.Account;
using TINK.Repository;
using TINK.Repository.Response;
using TINK.Repository.Response.Stations;
using TINK.Services.BluetoothLock;
using TINK.Services.Geolocation;
using TINK.ViewModel;
using Xamarin.Forms;
using static TINK.Repository.CopriCallsMemory;
@ -640,7 +645,13 @@ namespace TestShareeLib.Model.Connector.Updater
public void TestLoad_Reserved_CalculateAuthKeys()
{
// Construct requested bike.
var bike = new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(
var bike = new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>(),
new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(
new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("17", LockModel.ILockIt),
new Drive(),
DataSource.Copri,
@ -680,7 +691,13 @@ namespace TestShareeLib.Model.Connector.Updater
public void TestLoad_Booked_CalculateAuthKeys()
{
// Construct occupied bike.
var bike = new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(
var bike = new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>(),
new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(
new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("17", LockModel.ILockIt),
new Drive(),
DataSource.Copri,
@ -716,7 +733,13 @@ namespace TestShareeLib.Model.Connector.Updater
public void TestLoad_Reserved_DoBook()
{
// Construct requested bike.
var bike = new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(
var bike = new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>(),
new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(
new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("17", LockModel.ILockIt),
new Drive(),
DataSource.Copri,

View file

@ -16,8 +16,10 @@ using TINK.Model.Stations.StationNS;
using TINK.Model.User;
using TINK.Repository;
using TINK.Services;
using TINK.Services.BluetoothLock;
using TINK.Services.Geolocation;
using TINK.Services.Permissions;
using TINK.ViewModel;
using TINK.ViewModel.Settings;
using static TINK.Repository.CopriCallsMemory;
@ -36,7 +38,12 @@ namespace TestTINKLib.Fixtures.UseCases.SelectStation
IEnumerable<IStation> stations,
string selectedStationId)
{
var l_oBikesAtStation = new BikeCollectionMutable();
var l_oBikesAtStation = new BikeCollectionMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>());
var l_oBikesAvailable = (await connector.Query.GetBikesAsync()).Response;

View file

@ -51,5 +51,14 @@
<None Include="Model\Bikes\BikeInfoNS\BC\TestBikeSerializeJSON.cs" />
<None Include="Model\Bikes\BikeInfoNS\TestBikeCollectionSerializeJSON.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="Mono.Android">
<HintPath>..\..\..\..\..\..\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\ReferenceAssemblies\Microsoft\Framework\MonoAndroid\v12.0\Mono.Android.dll</HintPath>
</Reference>
<Reference Include="Xamarin.iOS">
<HintPath>..\..\..\..\..\..\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\ReferenceAssemblies\Microsoft\Framework\Xamarin.iOS\v1.0\Xamarin.iOS.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View file

@ -159,7 +159,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Account
Assert.AreEqual("Logged in as a@b.", settingsPageViewModel.LoggedInInfo);
Assert.IsTrue(settingsPageViewModel.IsBookingStateInfoVisible, "A user is logged but no bikes requested/ booked.");
Assert.AreEqual("Aktuell 2 Fahrräder reserviert/ gebucht.", settingsPageViewModel.BookingStateInfo);
Assert.AreEqual("Currently 2 bikes reserved/ booked.", settingsPageViewModel.BookingStateInfo);
}
[Test]
@ -202,7 +202,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Account
Assert.AreEqual("Logged in as a@b.", settingsPageViewModel.LoggedInInfo);
Assert.IsTrue(settingsPageViewModel.IsBookingStateInfoVisible, "A user is logged but no bikes requested/ booked.");
Assert.AreEqual("Aktuell 2 Fahrräder reserviert/ gebucht. Verbindungsstatus: Offline.", settingsPageViewModel.BookingStateInfo);
Assert.AreEqual("Currently 2 bikes reserved/ booked. Connectivity: Offline.", settingsPageViewModel.BookingStateInfo);
}
[Test]
@ -233,7 +233,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Account
null /*UI language */,
sessionCookie: sessionCookie,
cacheServer: new CopriCallsCacheMemory001(sessionCookie: sessionCookie),
httpsServer: new ExceptionServer((msg) => new WebConnectFailureException(msg, new Exception("Source expection."))))),
httpsServer: new ExceptionServer((msg) => new WebConnectFailureException(msg, new Exception("Source exception."))))),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(),
@ -258,7 +258,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Account
Assert.AreEqual("Logged in as a@b.", settingsPageViewModel.LoggedInInfo); // CopriCallsCacheMemory(SampleSets.Set2,
Assert.IsTrue(settingsPageViewModel.IsBookingStateInfoVisible, "A user is logged but no bikes requested/ booked.");
Assert.AreEqual("Aktuell 2 Fahrräder reserviert/ gebucht. Verbindungsstatus: Offline.", settingsPageViewModel.BookingStateInfo);
Assert.AreEqual("Currently 2 bikes reserved/ booked. Connectivity: Offline.", settingsPageViewModel.BookingStateInfo);
}
}
}

View file

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
@ -23,6 +22,7 @@ using TINK.View;
using TINK.ViewModel;
using TINK.ViewModel.Bikes;
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
using static TINK.Model.Bikes.BikeInfoNS.BluetoothLock.Command.GetLockedLocationCommand;
namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
@ -58,9 +58,9 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
/// Use case: End rental.
/// Final state: Booked, lock state unknown.
/// </summary>
/// <remarks> Replaces test TestReturnOutOfReach which was removed for sharee.bike verion ~3.0.362. </remarks>
/// <remarks> Replaces test TestReturnOutOfReach which was removed for sharee.bike version ~3.0.362. </remarks>
[Test]
public void TestReturnLastGeolocatonNullLockOfOfReach()
public void TestReturnLastGeolocatonNullLockOutOfReach()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
@ -86,11 +86,14 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bike.Id.Returns("0");
bike.LockInfo.Location.Returns((IGeolocation)null); // When locking bike geolocation was not available.
locks[0].GetDeviceState().Returns(DeviceState.Disconnected); // Simulate bike out of reach.
locks.DisconnectAsync(0, Arg.Any<Guid>()).Returns(LockingState.UnknownDisconnected); // Simulate disconnecting.
bike.GetLockedBikeLocationAsync(Arg.Any<IGetLockedLocationCommandListener>()).Throws((x) =>
{
handler.ReportStep(Step.StartingQueryLocation);
handler.ReportStateAsync(TINK.Model.Bikes.BikeInfoNS.BluetoothLock.Command.GetLockedLocationCommand.State.DisconnetedNoLocationError, "").Wait();
handler.ReportStep(Step.DisconnectingLockOnDisconnectedNoLocationError);
handler.ReportStateAsync(TINK.Model.Bikes.BikeInfoNS.BluetoothLock.Command.GetLockedLocationCommand.State.QueryLocationSucceeded, "").Wait();
throw new Exception();
});
bike.State.Value.Returns(InUseStateEnum.Booked);
@ -100,13 +103,11 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
locks[0].GetDeviceState();
viewService.DisplayAlert(
"Error at ending rental!",
"We could not assign the bike to any station. For this we need your location information while you are standing right next to the bike. Only then your rental can be terminated!\r\n\r\nApproach the bike, turn on Bluetooth and Location services and try again.",
"Rental could not be terminated!",
"We could not assign the bike to any station. For this we need your location information while you are standing right next to the bike. Only then your rental can be terminated!\r\n\r\nApproach the bike lock, turn on Bluetooth and Location services and try again.",
"OK");
bikesViewModel.ActionText = "Disconnecting lock...";
locks.DisconnectAsync(0, Arg.Any<Guid>());
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -150,79 +151,29 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bike.Id.Returns("0");
bike.LockInfo.Location.Returns((IGeolocation)null); // When locking bike geolocation was not available.
locks[0].GetDeviceState().Returns(DeviceState.Connected); // Simulate bike in reach.
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>()).Throws(new Exception("Ups...")); // Simulate error when starting query for geolocation.
var subsequent = handler.HandleRequestOption1().Result;
// Verify behavior
Received.InOrder(() =>
bike.GetLockedBikeLocationAsync(Arg.Any<IGetLockedLocationCommandListener>()).Throws((x) =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
locks[0].GetDeviceState();
bikesViewModel.ActionText = "Start query location...";
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
viewService.DisplayAlert(
"Error at ending rental!",
"End rental at an unknown location is not possible.\r\nStart getting geolocation failed.",
"OK");
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
handler.ReportStep(Step.StartingQueryLocation);
handler.ReportStateAsync(TINK.Model.Bikes.BikeInfoNS.BluetoothLock.Command.GetLockedLocationCommand.State.QueryLocationFailed, "Ups...").Wait();
throw new Exception();
});
// Verify state after action
Assert.AreEqual("End rental", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Open lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
}
bike.State.Value.Returns(InUseStateEnum.Booked); // Booking state does not change.
/// <summary>
/// Use case: End rental.
/// Comment: User decide to abort returning bike
/// Final state: Same as initial state.
/// </summary>
[Test]
public void TestReturnCancel()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var command = Substitute.For<ICommand>();
var geolocation = Substitute.For<IGeolocationService>();
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 BookedClosed(
bike,
() => true, // isConnectedDelegate
(isConnexted) => connector,
geolocation,
locks,
() => pollingManager,
Substitute.For<ISmartDevice>(),
viewService,
bikesViewModel,
activeUser);
bike.Id.Returns("0");
viewService.DisplayAlert(string.Empty, "End rental of bike Nr. 0?", "Yes", "No").Returns(Task.FromResult(false));
bike.LockInfo.State.Returns(LockingState.Closed); // Locking state does not change.
var subsequent = handler.HandleRequestOption1().Result;
locks.DidNotReceive().DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
viewService.DisplayAlert(string.Empty, "End rental of bike Nr. 0?", "Yes", "No");
bikesViewModel.ActionText = "Query location...";
viewService.DisplayAlert(
"Rental could not be terminated!",
"Grant Location permission, activate Location services and try again.",
"OK");
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -264,14 +215,18 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bike.Id.Returns("0");
bike.LockInfo.Location.Returns((IGeolocation)null); // When locking bike geolocation was not available.
bike.GetLockedBikeLocationAsync(Arg.Any<IGetLockedLocationCommandListener>())
.Returns((x) =>
{
handler.ReportStep(Step.StartingQueryLocation);
handler.ReportStateAsync(TINK.Model.Bikes.BikeInfoNS.BluetoothLock.Command.GetLockedLocationCommand.State.QueryLocationFailed, "Ups...").Wait();
return Task.FromException<LocationDto>(new Exception("Ups..."));
});
locks[0].GetDeviceState().Returns(DeviceState.Connected); // Simulate bike in reach.
bike.State.Value.Returns(InUseStateEnum.Booked); // Booking state does not change.
viewService.DisplayAlert(string.Empty, "End rental of bike Nr. 0?", "Yes", "No").Returns(Task.FromResult(true));
bike.LockInfo.State.Returns(LockingState.Closed); // Locking state does not change.
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>())
.Returns(Task.FromException<IGeolocation>(new Exception("Ups..."))); // Simulate error starting query for geolocation.
var subsequent = handler.HandleRequestOption1().Result;
@ -279,14 +234,11 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
locks[0].GetDeviceState();
bikesViewModel.ActionText = "Start query location...";
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
bikesViewModel.ActionText = "Query location...";
viewService.DisplayAlert(
"Location query failed",
"End rental at an unknown location is not possible.\r\nMake sure you have granted location sharing permission and your location services are enabled.\r\nTry again!",
"Rental could not be terminated!",
"Grant Location permission, activate Location services and try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -327,24 +279,19 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel,
activeUser);
bike.LockInfo.Location.Returns((IGeolocation)null);
bike.Id.Returns("0");
viewService.DisplayAlert(string.Empty, "End rental of bike Nr. 0?", "Yes", "No").Returns(Task.FromResult(true));
locks[0].GetDeviceState().Returns(DeviceState.Connected); // Simulate bike in reach. If bike is out of reach bluetooth state changes to unknown.
bike.GetLockedBikeLocationAsync(Arg.Any<IGetLockedLocationCommandListener>()).Returns((x) =>
{
handler.ReportStep(Step.StartingQueryLocation);
handler.ReportStateAsync(TINK.Model.Bikes.BikeInfoNS.BluetoothLock.Command.GetLockedLocationCommand.State.QueryLocationSucceeded, string.Empty).Wait();
return Task.FromResult(new LocationDto.Builder().Build());
});
var location = Substitute.For<IGeolocation>();
location.Latitude.Returns(7);
location.Longitude.Returns(9);
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime>()).Returns(Task.FromResult(
location
)); ;
bike.State.Value.Returns(InUseStateEnum.Disposable); // Requesthandler factory queries state to create appropriate request handler object.
bike.LockInfo.State.Returns(LockingState.Closed); // Requesthandler factory queries lock state to create appropriate request handler object.
bike.State.Value.Returns(InUseStateEnum.Disposable); // Request handler factory queries state to create appropriate request handler object.
bike.LockInfo.State.Returns(LockingState.Closed); // Request handler factory queries lock state to create appropriate request handler object.
var subsequent = handler.HandleRequestOption1().Result;
@ -352,16 +299,15 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime>());
bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Query location...";
bikesViewModel.ActionText = "Ending rental...";
bikesViewModel.ActionText = "One moment please...";
connector.Command.DoReturn(bike, Arg.Is<LocationDto>(x => x != null));
bikesViewModel.ActionText = "Disconnecting lock...";
locks.DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -424,17 +370,15 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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 = "Ending rental...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "One moment please...";
connector.Command.DoReturn(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAdvancedAlert(
"Connection error when ending rental.",
"Internet must be available when ending rental. Please establish an Internet connection!\r\nIs WIFI/mobile network available and mobile data activated?",
"Context info",
viewService.DisplayAlert(
"Rental could not be terminated!",
"A stable Internet connection is required. Connect to WIFI or to mobile network and activate mobile data. Try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -498,13 +442,12 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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 = "Ending rental...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "One moment please...";
connector.Command.DoReturn(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error at ending rental!", "End rental outside of station is not possible. Distance to station 42 is 15986 m.", "OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
viewService.DisplayAlert("Rental could not be terminated!", "End rental outside or at wrong station is not possible. Distance to next suitable station 42 is 15986 m.", "OK");
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -568,13 +511,12 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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 = "Ending rental...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "One moment please...";
connector.Command.DoReturn(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error at ending rental!", "End rental at an unknown location is not possible.\r\nRental can be ended if\r\n- location information is available when closing lock\r\n- bike is in reach and location information is available when pressing button \"End rental\"", "OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
viewService.DisplayAlert("Rental could not be terminated!", "End rental at an unknown location is not possible.\r\nRental can be ended if\r\n- location information is available when closing lock\r\n- bike is in reach and location information is available when pressing button \"End rental\"", "OK");
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -636,13 +578,12 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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 = "Ending rental...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "One moment please...";
connector.Command.DoReturn(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAdvancedAlert("Statusfehler beim Zurückgeben des Rads!", "Outer message.", "Some invalid data received!", "OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
viewService.DisplayAdvancedAlert("Rental could not be terminated!", "Outer message.", "Some invalid data received!", "OK");
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -691,8 +632,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
connector.Command.DoReturn(bike, Arg.Any<LocationDto>()).Returns<BookingFinishedModel>(x => throw new Exception("Exception message."));
bike.State.Value.Returns(InUseStateEnum.Booked); // Requesthandler factory queries state to create appropriate request handler object.
bike.LockInfo.State.Returns(LockingState.Closed); // Requesthandler factory queries lock state to create appropriate request handler object.
bike.State.Value.Returns(InUseStateEnum.Booked); // Request handler factory queries state to create appropriate request handler object.
bike.LockInfo.State.Returns(LockingState.Closed); // Request handler factory queries lock state to create appropriate request handler object.
var subsequent = handler.HandleRequestOption1().Result;
@ -703,13 +644,16 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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 = "Ending rental...";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "One moment please...";
connector.Command.DoReturn(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error at ending rental!", "Exception message.", "OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
viewService.DisplayAlert(
"Rental could not be terminated!",
"Exception message.",
"OK"
);
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -762,7 +706,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = "Reading charging level...";
@ -770,16 +714,16 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, null);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state "Booked Open" after action
Assert.AreEqual("Close lock & end rental", subsequent.ButtonText);
// Verify state after action
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -824,13 +768,13 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error while opening lock!", "Lock cannot be opened until bike is near.", "OK");
viewService.DisplayAlert("Lock could not be opened!", "Make sure you have granted Bluetooth permission to the app. Step as close as possible to the bike lock and try again.", "OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -847,7 +791,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
/// Final state: Same as initial state.
/// </summary>
[Test]
public void TestOpenOpenFailsCouldntOpenBoldBlockedException()
public void TestOpenOpenFailsCouldntOpenBoltBlockedException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
@ -884,13 +828,13 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error while opening lock!", "Ensure that no obstacle prevents lock from opening and try again.", "OK");
viewService.DisplayAlert("Lock could not be opened!", "Lock bolt is blocked. Make sure that no spoke presses against the lock bolt and try again.", "OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -945,13 +889,13 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error while opening lock!", "After try to open lock state closed is reported.", "OK");
viewService.DisplayAlert("Lock could not be opened!", "Lock reports it is still closed. Please try again!", "OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -1005,13 +949,13 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Lock can not be opened!", "The lock could not be opened correctly. Try again!\r\n\r\nAttention! Your rental has already started.\r\nIf the lock still won't open, make sure the lock is closed and end rental.\r\nImportant: Send an email to the operator (otherwise your paid rental will continue!) with: Problem description, bike number, drop-off station.", "OK");
viewService.DisplayAlert("Lock could not be opened!", "Position of lock bolt is unknown. Lock could be closed or open. Please try again!", "OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -1065,13 +1009,18 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error while opening lock!", "Exception message.", "OK");
viewService.DisplayAdvancedAlert(
"Lock could not be opened!",
"Exception message.",
"Please try again.",
"OK"
);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -1126,7 +1075,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = "Reading charging level...";
@ -1135,16 +1084,16 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, null);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state "Booked Open" after action
Assert.AreEqual("Close lock & end rental", subsequent.ButtonText);
// Verify state after action
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -1190,7 +1139,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = "Reading charging level...";
@ -1199,16 +1148,16 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, null);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state "Booked Closed" after action
Assert.AreEqual("Close lock & end rental", subsequent.ButtonText);
// Verify state after action
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -1255,7 +1204,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = "Reading charging level...";
@ -1264,16 +1213,16 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
connector.Command.UpdateLockingStateAsync(bike, null);
bikesViewModel.ActionText = "Internet must be available for updating lock status. Please establish an Internet connection!";
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state "Booked Open" after action
Assert.AreEqual("Close lock & end rental", subsequent.ButtonText);
// Verify state after action
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -1320,7 +1269,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = "Reading charging level...";
@ -1329,16 +1278,16 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = "Connection error on updating locking status.";
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state "Booked Open" after action
Assert.AreEqual("Close lock & end rental", subsequent.ButtonText);
// Verify state after action
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -1386,7 +1335,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = "Reading charging level...";
@ -1395,16 +1344,16 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = "Status error on updating lock state.";
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state "Booked Open" after action
Assert.AreEqual("Close lock & end rental", subsequent.ButtonText);
// Verify state after action
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
}
}

View file

@ -125,22 +125,22 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // 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
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.AreEqual("Close lock & end rental", subsequent.ButtonText);
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -184,12 +184,16 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Request server...";
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error when connecting with lock!", "Internet must be reachable to connect to lock of rented bike. Please establish an Internet connection!\r\nContext info\r\nIs WIFI/mobile network available and mobile data activated?", "OK");
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.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -242,12 +246,12 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Request server...";
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error when connecting with lock!", "Communication error during lock search.\r\nException message.", "OK");
viewService.DisplayAlert("Connection to the lock could not be established.", "Exception message.", "OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -302,19 +306,18 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // 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 = string.Empty;
viewService.DisplayAlert(
"Error when connecting with lock!",
"Lock can only be found when rented bike is nearby.",
"Retry",
"Cancel");
"Connection to the lock could not be established.",
"Make sure you have granted Bluetooth permission to the app. Step as close as possible to the bike lock and try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -369,20 +372,20 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // 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 = string.Empty;
viewService.DisplayAdvancedAlert(
"Error when connecting with lock!",
"Your mobile device does not connect to the bike lock. Please step as close as possible to the bike and try again.",
"Connection to the lock could not be established.",
"Please step as close as possible to the bike lock and try again.",
"",
"Retry",
"Cancel");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -438,15 +441,15 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // 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 = string.Empty;
viewService.DisplayAlert("Error when connecting with lock!", "Schlossstatus des gemieteten Rads konnte nicht ermittelt werden.", "OK");
viewService.DisplayAlert("Connection to the lock could not be established.", "Lock status could not be determined. Please contact customer support.", "OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});

View file

@ -4,6 +4,7 @@ using Newtonsoft.Json;
using NSubstitute;
using NUnit.Framework;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock.Command;
using TINK.Model.Connector;
using TINK.Model.Device;
using TINK.Model.State;
@ -19,6 +20,7 @@ using TINK.View;
using TINK.ViewModel;
using TINK.ViewModel.Bikes;
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
using static TINK.Model.Bikes.BikeInfoNS.BluetoothLock.Command.CloseCommand;
namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
@ -92,7 +94,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = "Reading charging level...";
@ -100,16 +102,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, null);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state "Booked Open" after action
Assert.AreEqual("Close lock & end rental", subsequent.ButtonText);
// Verify state after action
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -154,13 +156,13 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error while opening lock!", "Lock cannot be opened until bike is near.", "OK");
viewService.DisplayAlert("Lock could not be opened!", "Make sure you have granted Bluetooth permission to the app. Step as close as possible to the bike lock and try again.", "OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -177,7 +179,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
/// Final state: Same as initial state.
/// </summary>
[Test]
public void TestOpenOpenFailsCouldntOpenBoldBlockedException()
public void TestOpenOpenFailsCouldntOpenBoltBlockedException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
@ -214,13 +216,13 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error while opening lock!", "Ensure that no obstacle prevents lock from opening and try again.", "OK");
viewService.DisplayAlert("Lock could not be opened!", "Lock bolt is blocked. Make sure that no spoke presses against the lock bolt and try again.", "OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -274,13 +276,13 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error while opening lock!", "After try to open lock state closed is reported.", "OK");
viewService.DisplayAlert("Lock could not be opened!", "Lock reports it is still closed. Please try again!", "OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -334,13 +336,13 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = "";
viewService.DisplayAlert("Lock can not be opened!", "The lock could not be opened correctly. Try again!\r\n\r\nAttention! Your rental has already started.\r\nIf the lock still won't open, make sure the lock is closed and end rental.\r\nImportant: Send an email to the operator (otherwise your paid rental will continue!) with: Problem description, bike number, drop-off station.", "OK");
viewService.DisplayAlert("Lock could not be opened!", "Position of lock bolt is unknown. Lock could be closed or open. Please try again!", "OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -394,13 +396,17 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error while opening lock!", "Exception message.", "OK");
viewService.DisplayAdvancedAlert(
"Lock could not be opened!",
"Exception message.",
"Please try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -455,7 +461,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = "Reading charging level...";
@ -464,16 +470,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, null);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state "Booked Open" after action
Assert.AreEqual("Close lock & end rental", subsequent.ButtonText);
// Verify state after action
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
@ -520,7 +526,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = "Reading charging level...";
@ -529,16 +535,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, null);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state "Booked Open" after action
Assert.AreEqual("Close lock & end rental", subsequent.ButtonText);
// Verify state after action
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -585,7 +591,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = "Reading charging level...";
@ -594,16 +600,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
connector.Command.UpdateLockingStateAsync(bike, null);
bikesViewModel.ActionText = "Internet must be available for updating lock status. Please establish an Internet connection!";
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state "Booked Open" after action
Assert.AreEqual("Close lock & end rental", subsequent.ButtonText);
// Verify state after action
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -650,7 +656,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = "Reading charging level...";
@ -659,16 +665,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = "Connection error on updating locking status.";
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state "Booked Open" after action
Assert.AreEqual("Close lock & end rental", subsequent.ButtonText);
// Verify state after action
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -716,7 +722,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be closed
bikesViewModel.ActionText = "Reading charging level...";
@ -725,16 +731,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = "Status error on updating lock state.";
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state "Booked Open" after action
Assert.AreEqual("Close lock & end rental", subsequent.ButtonText);
// Verify state after action
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -766,10 +772,17 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel,
activeUser);
locks[0].CloseAsync()
.Returns(Task.FromResult((LockitLockingState?)LockitLockingState.Closed)); // Return lock state indicating success
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.State.Returns(LockingState.Closed); // Return lock state indicating success
bike.CloseLockAsync(Arg.Any<ICloseCommandListener>(), Arg.Any<Task>()).Returns(x =>
{
// Add calls to ReportStep which IBikeInfoMutable implementation would do.
handler.ReportStep(Step.ClosingLock);
handler.ReportStep(Step.UpdateLockingState);
return Task.CompletedTask;
}
);
var subsequent = handler.HandleRequestOption2().Result;
@ -778,13 +791,11 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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 = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
bikesViewModel.ActionText = "One moment please...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -825,11 +836,18 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel,
activeUser);
locks[0].CloseAsync()
.Returns<Task<LockitLockingState?>>(x => throw new OutOfReachException());
bike.CloseLockAsync(Arg.Any<ICloseCommandListener>(), Arg.Any<Task>())
.Returns(async x =>
{
// Add calls to ReportStep which IBikeInfoMutable implementation would do.
handler.ReportStep(Step.ClosingLock);
await handler.ReportStateAsync(CloseCommand.State.OutOfReachError, "");
throw new OutOfReachException();
}
);
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.State.Returns(LockingState.Open);
bike.LockInfo.State.Returns(LockingState.UnknownDisconnected); /// If <see cref="OutOfReachException"/> is fired lock state is set to state unknown because disconnected.
var subsequent = handler.HandleRequestOption2().Result;
@ -838,13 +856,12 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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 = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Lock can not be closed!", "Lock cannot be closed until bike is near.", "OK");
viewService.DisplayAlert("Lock could not be closed!", "Make sure you have granted Bluetooth permission to the app. Step as close as possible to the bike lock and try again.", "OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -885,11 +902,17 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel,
activeUser);
locks[0].CloseAsync()
.Returns<Task<LockitLockingState?>>(x => throw new Exception("Exception message."));
bike.CloseLockAsync(Arg.Any<ICloseCommandListener>(), Arg.Any<Task>()).Returns(async x =>
{
// Add calls to ReportStep which IBikeInfoMutable implementation would do.
handler.ReportStep(Step.ClosingLock);
await handler.ReportStateAsync(State.GeneralCloseError, "Exception message.");
throw new Exception("Exception message.");
}
);
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.State.Returns(LockingState.Open);
bike.LockInfo.State.Returns(LockingState.UnknownDisconnected); // If CloseLock fires an exception of type Exception lock state is set to unknown.
var subsequent = handler.HandleRequestOption2().Result;
@ -898,13 +921,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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 = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Lock can not be closed!", "Exception message.", "OK");
viewService.DisplayAlert(
"Lock could not be closed!",
"Exception message.",
"OK"
);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -945,12 +971,17 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel,
activeUser);
locks[0].CloseAsync()
.Returns(LockitLockingState.Closed); // Return lock state indicating success
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()).Returns(x => throw new WebConnectFailureException("Context info", new System.Exception("hoppla")));
bike.CloseLockAsync(Arg.Any<ICloseCommandListener>(), Arg.Any<Task>()).Returns(async x =>
{
// Add calls to ReportStep which IBikeInfoMutable implementation would do.
handler.ReportStep(Step.ClosingLock);
handler.ReportStep(Step.UpdateLockingState);
await handler.ReportStateAsync(CloseCommand.State.WebConnectFailed, "Context info");
}
);
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.State.Returns(LockingState.Closed);
var subsequent = handler.HandleRequestOption2().Result;
@ -959,14 +990,12 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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 = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = "Internet must be available for updating lock status. Please establish an Internet connection!";
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
bikesViewModel.ActionText = "One moment please...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -1007,12 +1036,18 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel,
activeUser);
locks[0].CloseAsync()
.Returns(LockitLockingState.Closed); // Return lock state indicating success
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()).Returns(x => throw new Exception("Exception message."));
bike.CloseLockAsync(Arg.Any<ICloseCommandListener>(), Arg.Any<Task>())
.Returns(async x =>
{
// Add calls to ReportStep which IBikeInfoMutable implementation would do.
handler.ReportStep(Step.ClosingLock);
handler.ReportStep(Step.UpdateLockingState);
await handler.ReportStateAsync(CloseCommand.State.BackendUpdateFailed, "Exception message.");
}
);
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.State.Returns(LockingState.Closed);
var subsequent = handler.HandleRequestOption2().Result;
@ -1021,14 +1056,12 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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 = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = "Connection error on updating locking status.";
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
bikesViewModel.ActionText = "One moment please...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -1069,13 +1102,18 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel,
activeUser);
locks[0].CloseAsync()
.Returns(LockitLockingState.Closed); // Return lock state indicating success
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()).Returns(x =>
throw new ReturnBikeException(JsonConvert.DeserializeObject<ReservationCancelReturnResponse>(@"{ ""response_text"" : ""Some invalid data received!""}"), "Outer message."));
bike.CloseLockAsync(Arg.Any<ICloseCommandListener>(), Arg.Any<Task>())
.Returns(async x =>
{
// Add calls to ReportStep which IBikeInfoMutable implementation would do.
handler.ReportStep(Step.ClosingLock);
handler.ReportStep(Step.UpdateLockingState);
await handler.ReportStateAsync(CloseCommand.State.ResponseIsInvalid, "Some invalid data received");
}
);
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.State.Returns(LockingState.Closed);
var subsequent = handler.HandleRequestOption2().Result;
@ -1084,14 +1122,12 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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 = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = "Status error on updating lock state.";
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
bikesViewModel.ActionText = "One moment please...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});

View file

@ -154,7 +154,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
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 = "Searching lock...";
@ -169,16 +169,16 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, null);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Close lock & end rental", subsequent.ButtonText);
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -228,13 +228,13 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
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", 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
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -293,13 +293,13 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
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 error when reserving the bike!", "Context info.\r\nIs WIFI/mobile network available and mobile data activated?", "OK");
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.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -358,13 +358,18 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
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("Error when reserving the bike!", "Exception message.", "OK");
viewService.DisplayAdvancedAlert(
"Bike could not be reserved!",
"Exception message.",
"Please try again.",
"OK"
);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -425,20 +430,20 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
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 = "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
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.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -493,20 +498,20 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
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 = "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
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.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -560,19 +565,19 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
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 = "Searching lock...";
locks.ConnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>());
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);

View file

@ -42,7 +42,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
Substitute.For<IUser>());
// Verify prerequisites.
Assert.AreEqual("Rent bike or close lock", handler.ButtonText);
Assert.AreEqual("Close lock or rent bike", handler.ButtonText);
Assert.IsTrue(handler.IsButtonVisible);
Assert.AreEqual(nameof(DisposableOpen), handler.LockitButtonText);
Assert.IsFalse(handler.IsLockitButtonVisible);
@ -77,7 +77,9 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel,
activeUser);
viewService.DisplayAlert(string.Empty, "Fahrrad Nr. 0 mieten oder Schloss schließen?", "Mieten", "Schloss schließen").Returns(Task.FromResult(false));
bike.Id.Returns("0");
viewService.DisplayAlert(string.Empty, "Close lock or rent bike Nr. 0?", "Rent bike", "Close lock").Returns(Task.FromResult(false));
locks[0].CloseAsync().Returns(Task.FromResult((LockitLockingState?)LockitLockingState.Closed));
@ -90,13 +92,13 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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 = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
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
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -137,7 +139,9 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel,
activeUser);
viewService.DisplayAlert(string.Empty, "Fahrrad Nr. 0 mieten oder Schloss schließen?", "Mieten", "Schloss schließen").Returns(Task.FromResult(false));
bike.Id.Returns("0");
viewService.DisplayAlert(string.Empty, "Close lock or rent bike Nr. 0?", "Rent bike", "Close lock").Returns(Task.FromResult(false));
locks[0].CloseAsync().Returns<Task<LockitLockingState?>>(x => throw new OutOfReachException());
@ -153,13 +157,13 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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 = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
locks[0].CloseAsync();
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Lock can not be closed!", "Lock cannot be closed until bike is near.", "OK");
viewService.DisplayAlert("Lock could not be closed!", "Make sure you have granted Bluetooth permission to the app. Step as close as possible to the bike lock and try again.", "OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -200,7 +204,9 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel,
activeUser);
viewService.DisplayAlert(string.Empty, "Fahrrad Nr. 0 mieten oder Schloss schließen?", "Mieten", "Schloss schließen").Returns(Task.FromResult(false));
bike.Id.Returns("0");
viewService.DisplayAlert(string.Empty, "Close lock or rent bike Nr. 0?", "Rent bike", "Close lock").Returns(Task.FromResult(false));
locks[0].CloseAsync().Returns<Task<LockitLockingState?>>(x => throw new Exception("Exception message."));
@ -216,13 +222,18 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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 = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
locks[0].CloseAsync();
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Lock can not be closed!", "Exception message.", "OK");
viewService.DisplayAdvancedAlert(
"Lock could not be closed!",
"Exception message.",
"Please try again.",
"OK"
);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -265,7 +276,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bike.Id.Returns("0");
viewService.DisplayAlert(string.Empty, "Fahrrad Nr. 0 mieten oder Schloss schließen?", "Mieten", "Schloss schließen").Returns(Task.FromResult(true));
viewService.DisplayAlert(string.Empty, "Close lock or rent bike Nr. 0?", "Rent bike", "Close lock").Returns(Task.FromResult(true));
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.State.Returns(LockingState.Open);
@ -277,27 +288,27 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // 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.DoBookAsync(bike);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Close lock & end rental", subsequent.ButtonText);
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
/// Use case: Lock bike.
/// Final state: Disposabled Closed.
/// Final state: Disposable Closed.
/// </summary>
[Test]
public void TestDoBookDoBookFailsWebConnectFailureException()
@ -326,7 +337,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bike.Id.Returns("0");
viewService.DisplayAlert(string.Empty, "Fahrrad Nr. 0 mieten oder Schloss schließen?", "Mieten", "Schloss schließen").Returns(Task.FromResult(true));
viewService.DisplayAlert(string.Empty, "Close lock or rent bike Nr. 0?", "Rent bike", "Close lock").Returns(Task.FromResult(true));
connector.Command.DoBookAsync(bike).Returns(x => throw new WebConnectFailureException("Context info.", new Exception("chub")));
@ -341,22 +352,22 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // 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.DoBookAsync(bike);
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Connection error when renting the bike!",
string.Format("Attention: Lock is closed!\r\n{0}\r\n{1}", "Context info.", "Is WIFI/mobile network available and mobile data activated?"),
"Bike could not be rented!",
"A stable Internet connection is required. Connect to WIFI or to mobile network and activate mobile data. Try again.",
"OK");
bikesViewModel.ActionText = "Verschließe Schloss...";
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
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
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -370,7 +381,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
/// <summary>
/// Use case: Lock bike.
/// Final state: Disposabled Closed.
/// Final state: Disposable Closed.
/// </summary>
[Test]
public void TestDoBookDoBookFailsException()
@ -399,7 +410,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bike.Id.Returns("0");
viewService.DisplayAlert(string.Empty, "Fahrrad Nr. 0 mieten oder Schloss schließen?", "Mieten", "Schloss schließen").Returns(Task.FromResult(true));
viewService.DisplayAlert(string.Empty, "Close lock or rent bike Nr. 0?", "Rent bike", "Close lock").Returns(Task.FromResult(true));
connector.Command.DoBookAsync(bike).Returns(x => throw new Exception("Exception message."));
@ -414,19 +425,19 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // 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.DoBookAsync(bike);
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error when renting the bike!", "Attention: Lock is closed!\r\nException message.", "OK");
bikesViewModel.ActionText = "Verschließe Schloss...";
viewService.DisplayAlert("Bike could not be rented!", "Exception message.", "OK");
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
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
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});

View file

@ -44,7 +44,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
Substitute.For<IUser>());
// Verify prerequisites.
Assert.AreEqual("Cancel bike reservation", handler.ButtonText);
Assert.AreEqual("Cancel reservation", handler.ButtonText);
Assert.IsTrue(handler.IsButtonVisible);
Assert.AreEqual("Open lock & rent bike", handler.LockitButtonText);
Assert.IsTrue(handler.IsLockitButtonVisible);
@ -97,7 +97,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
});
// Verify state after action
Assert.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Open lock & rent bike", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -145,13 +145,13 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
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 = "Disconnecting lock...";
locks.DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -219,22 +219,22 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
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(
"Error when canceling the reservation!",
"Can not login user mustermann@server.de. Mail address unknown or password invalid.",
"Reservation could not be canceled!",
"Your session has expired. Please login new and try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Open lock & rent bike", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -287,22 +287,22 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
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(
"Connection error when canceling the reservation!",
"Context info.\r\nIs WIFI/mobile network available and mobile data activated?",
"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.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Open lock & rent bike", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -355,22 +355,23 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
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(
"Error when canceling the reservation!",
viewService.DisplayAdvancedAlert(
"Reservation could not be canceled!",
"Exception message.",
"Please try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Open lock & rent bike", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -418,7 +419,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
});
// Verify state after action
Assert.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Open lock & rent bike", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -470,7 +471,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Renting bike...";
connector.Command.DoBookAsync(bike, LockingAction.Open); // Booking must be performed
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
@ -480,16 +481,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, null);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Close lock & end rental", subsequent.ButtonText);
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -539,23 +540,22 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Renting bike...";
connector.Command.DoBookAsync(bike, LockingAction.Open); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAdvancedAlert(
"Connection error when renting the bike!",
"Is WIFI/mobile network available and mobile data activated?",
"Context info",
viewService.DisplayAlert(
"Bike could not be rented!",
"A stable Internet connection is required. Connect to WIFI or to mobile network and activate mobile data. Try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state "reserved closed" after action
Assert.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Open lock & rent bike", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -608,23 +608,23 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Renting bike...";
connector.Command.DoBookAsync(bike, LockingAction.Open); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAdvancedAlert(
"Error when renting the bike!",
"",
"Bike could not be rented!",
"Please try again.",
"Exception message.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state "reserved closed" after action
Assert.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Open lock & rent bike", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -677,21 +677,26 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Renting bike...";
connector.Command.DoBookAsync(bike, LockingAction.Open); // Booking must be performed
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be opened
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error while opening lock!", "Lock cannot be opened until bike is near.", "OK");
viewService.DisplayAdvancedAlert(
"Lock could not be opened!",
"Make sure you have granted Bluetooth permission to the app. Step as close as possible to the bike lock and try again.",
"Attention! Your rental has already started.\r\nIf the lock still won't open, make sure the lock is closed and end rental.\r\nImportant: Send an email to customer support (otherwise your paid rental will continue!) with: Problem description, bike number, drop-off station.",
"OK"
);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -744,21 +749,26 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Renting bike...";
connector.Command.DoBookAsync(bike, LockingAction.Open); // Booking must be performed
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be opened
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error while opening lock!", "Exception message.", "OK");
viewService.DisplayAdvancedAlert(
"Lock could not be opened!",
"Please try again.",
"Exception message.",
"OK"
);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -810,19 +820,19 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Renting bike...";
connector.Command.DoBookAsync(bike, LockingAction.Open); // Booking must be performed
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
locks.Received()[0].OpenAsync(); // Lock must be opened
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -876,7 +886,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Renting bike...";
connector.Command.DoBookAsync(bike, LockingAction.Open); // Booking must be performed
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
@ -887,16 +897,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, null);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Close lock & end rental", subsequent.ButtonText);
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -947,7 +957,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Renting bike...";
connector.Command.DoBookAsync(bike, LockingAction.Open); // Booking must be performed
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
@ -958,16 +968,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, null);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Close lock & end rental", subsequent.ButtonText);
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -1018,7 +1028,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Renting bike...";
connector.Command.DoBookAsync(bike, LockingAction.Open); // Booking must be performed
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
@ -1029,16 +1039,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
connector.Command.UpdateLockingStateAsync(bike, null);
bikesViewModel.ActionText = "Internet must be available for updating lock status. Please establish an Internet connection!";
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Close lock & end rental", subsequent.ButtonText);
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -1089,7 +1099,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Renting bike...";
connector.Command.DoBookAsync(bike, LockingAction.Open); // Booking must be performed
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
@ -1100,16 +1110,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = "Connection error on updating locking status.";
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Close lock & end rental", subsequent.ButtonText);
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -1161,7 +1171,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Renting bike...";
connector.Command.DoBookAsync(bike, LockingAction.Open); // Booking must be performed
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
@ -1172,16 +1182,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = "Status error on updating lock state.";
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Close lock & end rental", subsequent.ButtonText);
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
}
}

View file

@ -42,7 +42,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
Substitute.For<IUser>());
// Verify prerequisites.
Assert.AreEqual("Cancel bike reservation", handler.ButtonText);
Assert.AreEqual("Cancel reservation", handler.ButtonText);
Assert.IsTrue(handler.IsButtonVisible);
Assert.AreEqual("Search lock", handler.LockitButtonText);
Assert.IsTrue(handler.IsLockitButtonVisible);
@ -93,7 +93,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
});
// Verify state after action
Assert.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -141,11 +141,11 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
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 = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -211,22 +211,22 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
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(
"Error when canceling the reservation!",
"Can not login user mustermann@server.de. Mail address unknown or password invalid.",
"Reservation could not be canceled!",
"Your session has expired. Please login new and try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -277,22 +277,22 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
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(
"Connection error when canceling the reservation!",
"Context info\r\nIs WIFI/mobile network available and mobile data activated?",
"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.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -343,22 +343,23 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
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(
"Error when canceling the reservation!",
viewService.DisplayAdvancedAlert(
"Reservation could not be canceled!",
"Exception message.",
"Please try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -415,7 +416,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Request server...";
connector.Command.CalculateAuthKeys(bike);
bikesViewModel.ActionText = "Searching lock...";
@ -430,16 +431,16 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, null);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Close lock & end rental", subsequent.ButtonText);
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -483,18 +484,22 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Request server...";
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error when connecting to lock!", "Internet must be reachable to connect to lock of reserved bike. Please establish an Internet connection!\r\nContext info.\r\nIs WIFI/mobile network available and mobile data activated?", "OK");
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.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", handler.ButtonText);
Assert.AreEqual("Cancel reservation", handler.ButtonText);
Assert.IsTrue(handler.IsButtonVisible);
Assert.AreEqual("Search lock", handler.LockitButtonText);
Assert.IsTrue(handler.IsLockitButtonVisible);
@ -541,18 +546,23 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Request server...";
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error when connecting to lock!", "Communication error during lock search.\r\nException message.", "OK");
viewService.DisplayAdvancedAlert(
"Connection to the lock could not be established.",
"Exception message.",
"Please step as close as possible to the bike lock and try again.",
"OK"
);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", handler.ButtonText);
Assert.AreEqual("Cancel reservation", handler.ButtonText);
Assert.IsTrue(handler.IsButtonVisible);
Assert.AreEqual("Search lock", handler.LockitButtonText);
Assert.IsTrue(handler.IsLockitButtonVisible);
@ -601,25 +611,24 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // 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 = string.Empty;
viewService.DisplayAlert(
"Error when connecting to lock!",
"Lock can only be found when reserved bike is nearby.",
"Retry",
"Cancel");
"Connection to the lock could not be established.",
"Make sure you have granted Bluetooth permission to the app. Step as close as possible to the bike lock and try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", handler.ButtonText);
Assert.AreEqual("Cancel reservation", handler.ButtonText);
Assert.IsTrue(handler.IsButtonVisible);
Assert.AreEqual("Search lock", handler.LockitButtonText);
Assert.IsTrue(handler.IsLockitButtonVisible);
@ -669,26 +678,26 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // 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 = string.Empty;
viewService.DisplayAdvancedAlert(
"Error when connecting to lock!",
"Your mobile device does not connect to the bike lock. Please step as close as possible to the bike and try again.",
"Connection to the lock could not be established.",
"Please step as close as possible to the bike lock and try again.",
"",
"Retry",
"Cancel");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", handler.ButtonText);
Assert.AreEqual("Cancel reservation", handler.ButtonText);
Assert.IsTrue(handler.IsButtonVisible);
Assert.AreEqual("Search lock", handler.LockitButtonText);
Assert.IsTrue(handler.IsLockitButtonVisible);
@ -737,21 +746,21 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // 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 = string.Empty;
viewService.DisplayAlert("Error when connecting to lock!", "Lock status of the reserved bike could not be determined.", "OK");
viewService.DisplayAlert("Connection to the lock could not be established.", "Lock status could not be determined. Please contact customer support.", "OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", handler.ButtonText);
Assert.AreEqual("Cancel reservation", handler.ButtonText);
Assert.IsTrue(handler.IsButtonVisible);
Assert.AreEqual("Search lock", handler.LockitButtonText);
Assert.IsTrue(handler.IsLockitButtonVisible);

View file

@ -43,7 +43,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
Substitute.For<IUser>());
// Verify prerequisites.
Assert.AreEqual("Rad zurückgeben oder mieten", handler.ButtonText);
Assert.AreEqual("Close lock or rent bike", handler.ButtonText);
Assert.IsTrue(handler.IsButtonVisible);
Assert.AreEqual("Alarm/ Sounds verwalten", handler.LockitButtonText);
Assert.IsFalse(handler.IsLockitButtonVisible);
@ -78,7 +78,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel,
activeUser);
viewService.DisplayAlert(string.Empty, "Rad Nr. 0 abschließen und zurückgeben oder Rad mieten?", "Zurückgeben", "Mieten").Returns(Task.FromResult(false));
viewService.DisplayAlert(string.Empty, "Close lock or rent bike Nr. 0?", "Close lock", "Rent bike").Returns(Task.FromResult(false));
bike.State.Value.Returns(InUseStateEnum.Booked); // Requesthandler factory queries state to create appropriate request handler object.
bike.LockInfo.State.Returns(LockingState.Open); // Requesthandler factory queries lock state to create appropriate request handler object.
@ -90,22 +90,22 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // 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.DoBookAsync(bike);
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Close lock & end rental", subsequent.ButtonText);
Assert.AreEqual("Close lock", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
Assert.AreEqual(string.Empty, subsequent.LockitButtonText);
Assert.That(subsequent.IsLockitButtonVisible, Is.False);
}
/// <summary>
@ -137,7 +137,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel,
activeUser);
viewService.DisplayAlert(string.Empty, "Rad Nr. 0 abschließen und zurückgeben oder Rad mieten?", "Zurückgeben", "Mieten").Returns(Task.FromResult(false));
viewService.DisplayAlert(string.Empty, "Close lock or rent bike Nr. 0?", "Close lock", "Rent bike").Returns(Task.FromResult(false));
connector.Command.DoBookAsync(bike).Returns(x => throw new WebConnectFailureException("Context info.", new Exception("Tst")));
@ -152,26 +152,26 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // 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.DoBookAsync(bike);
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Connection error when renting the bike!",
string.Format("Attention: Lock is closed!\r\n{0}\r\n{1}", "Context info.", "Is WIFI/mobile network available and mobile data activated?"),
"Bike could not be rented!",
"A stable Internet connection is required. Connect to WIFI or to mobile network and activate mobile data. Try again.",
"OK");
bikesViewModel.ActionText = "Wiederverschließe Schloss...";
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
locks[0].CloseAsync();
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Open lock & rent bike", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -206,7 +206,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel,
activeUser);
viewService.DisplayAlert(string.Empty, "Rad Nr. 0 abschließen und zurückgeben oder Rad mieten?", "Zurückgeben", "Mieten").Returns(Task.FromResult(false));
viewService.DisplayAlert(string.Empty, "Close lock or rent bike Nr. 0?", "Close lock", "Rent bike").Returns(Task.FromResult(false));
connector.Command.DoBookAsync(bike).Returns(x => throw new Exception("Exception message."));
@ -221,23 +221,27 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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
pollingManager.StopAsync(); // 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.DoBookAsync(bike);
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Error when renting the bike!", "Attention: Lock is closed!\r\nException message.", "OK");
bikesViewModel.ActionText = "Wiederverschließe Schloss...";
viewService.DisplayAdvancedAlert(
"Bike could not be rented!",
"Exception message.",
"Please try again.",
"OK");
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
locks[0].CloseAsync();
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Open lock & rent bike", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -274,7 +278,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
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));
viewService.DisplayAlert(string.Empty, "Close lock or rent bike Nr. 0?", "Close lock", "Rent bike").Returns(Task.FromResult(true));
locks[0].CloseAsync().Returns(LockitLockingState.Closed);
@ -287,15 +291,15 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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 = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
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
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -339,10 +343,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
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));
string.Empty, "Close lock or rent bike Nr. 0?", "Close lock", "Rent bike").Returns(Task.FromResult(true));
locks[0].CloseAsync()
.Returns<Task<LockitLockingState?>>(x => { throw new OutOfReachException(); });
@ -359,23 +360,23 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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 = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
locks[0].CloseAsync();
bikesViewModel.ActionText = string.Empty;
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 operator!",
"Lock could not be closed!",
"Make sure you have granted Bluetooth permission to the app. Step as close as possible to the bike lock and try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -413,10 +414,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
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));
string.Empty, "Close lock or rent bike Nr. 0?", "Close lock", "Rent bike").Returns(Task.FromResult(true));
locks[0].CloseAsync()
.Returns<Task<LockitLockingState?>>(x => { throw new Exception("Exception message."); });
@ -433,22 +431,22 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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 = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
locks[0].CloseAsync();
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Lock can not be closed!",
"Please try to lock again or report bike to operator!\r\nException message.",
"Lock could not be closed!",
"Step close to the lock and try again or report bike to operator!\r\nException message.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
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.AreEqual("Cancel bike reservation", subsequent.ButtonText);
Assert.AreEqual("Cancel reservation", subsequent.ButtonText);
Assert.IsTrue(subsequent.IsButtonVisible);
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
Assert.IsTrue(subsequent.IsLockitButtonVisible);
@ -494,7 +492,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
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));
viewService.DisplayAlert(string.Empty, "Close lock or rent bike Nr. 0?", "Close lock", "Rent bike").Returns(Task.FromResult(true));
locks[0].CloseAsync().Returns(LockitLockingState.Closed);
@ -511,18 +509,18 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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 = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
locks[0].CloseAsync();
bikesViewModel.ActionText = "Canceling reservation...";
connector.Command.DoCancelReservation(bike);
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Error when canceling the reservation!",
"Can not login user mustermann@server.de. Mail address unknown or password invalid.",
"Reservation could not be canceled!",
"Your session has expired. Please login new and try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -565,7 +563,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
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));
viewService.DisplayAlert(string.Empty, "Close lock or rent bike Nr. 0?", "Close lock", "Rent bike").Returns(Task.FromResult(true));
locks[0].CloseAsync().Returns(LockitLockingState.Closed);
@ -582,18 +580,18 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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 = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
locks[0].CloseAsync();
bikesViewModel.ActionText = "Canceling reservation...";
connector.Command.DoCancelReservation(bike);
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Connection error when canceling the reservation!",
"Context info\r\nIs WIFI/mobile network available and mobile data activated?",
"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.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -636,7 +634,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
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));
viewService.DisplayAlert(string.Empty, "Close lock or rent bike Nr. 0?", "Close lock", "Rent bike").Returns(Task.FromResult(true));
locks[0].CloseAsync().Returns(LockitLockingState.Closed);
@ -653,18 +651,19 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
{
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 = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Stay with the bike until the lock is closed.";
locks[0].CloseAsync();
bikesViewModel.ActionText = "Canceling reservation...";
connector.Command.DoCancelReservation(bike);
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Error when canceling the reservation!",
viewService.DisplayAdvancedAlert(
"Reservation could not be canceled!",
"Exception message.",
"Please try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});

View file

@ -1,14 +1,19 @@
using System;
using System.Collections.Generic;
using NSubstitute;
using NUnit.Framework;
using TestFramework.Model.Services.Geolocation;
using TestFramework.Services.BluetoothLock;
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Bikes.BikeInfoNS.DriveNS;
using TINK.Model.Connector;
using TINK.Model.Device;
using TINK.Model.State;
using TINK.Model.User;
using TINK.Services.BluetoothLock;
using TINK.Services.Geolocation;
using TINK.ViewModel;
using TINK.ViewModel.Bikes;
using TINK.ViewModel.Bikes.Bike.BluetoothLock;
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
@ -26,6 +31,11 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
{
// Verify handler for disposable bike.
var bike = new BikeInfoMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>(),
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "12"),
"My Station Name");
Assert.AreEqual(InUseStateEnum.Disposable, bike.State.Value);
@ -39,13 +49,18 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
new GeolocationMock(), // geolocation
new LocksServiceMock(), // LockService
null, // viewUpdateManager
NSubstitute.Substitute.For<ISmartDevice>(),
Substitute.For<ISmartDevice>(),
null /* viewService */ ,
NSubstitute.Substitute.For<IBikesViewModel>(),
NSubstitute.Substitute.For<IUser>()).GetType());
Substitute.For<IBikesViewModel>(),
Substitute.For<IUser>()).GetType());
// Verify handler for requested bike with state unknown.
bike = new BikeInfoMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>(),
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt, WheelType.Mono, TypeOfBike.Allround), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 0 /* lock Id */, new Guid(), /*K User*/ null, /*K Admin*/ null, /*K Seed*/ null, new DateTime(2020, 1, 1), "a@b.com", "12", null, null, () => new DateTime(2020, 1, 1), false, new List<string>()),
"My Station Name");
Assert.AreEqual(
@ -57,13 +72,18 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
new GeolocationMock(), // geolocation
new LocksServiceMock(), // LockService
null, // viewUpdateManager
NSubstitute.Substitute.For<ISmartDevice>(),
Substitute.For<ISmartDevice>(),
null /* viewService */,
NSubstitute.Substitute.For<IBikesViewModel>(),
NSubstitute.Substitute.For<IUser>()).GetType());
Substitute.For<IBikesViewModel>(),
Substitute.For<IUser>()).GetType());
// Verify handler for requested bike with state closed.
bike = new BikeInfoMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>(),
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt, WheelType.Mono, TypeOfBike.Allround), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 0 /* lock Id*/, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b.com", "12", null, null, () => new DateTime(2020, 1, 1), false, new List<string>()),
"My Station Name");
bike.LockInfo.State = LockingState.Closed;
@ -76,13 +96,18 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
new GeolocationMock(), // geolocation
new LocksServiceMock(), // LockService
null, // viewUpdateManager
NSubstitute.Substitute.For<ISmartDevice>(),
Substitute.For<ISmartDevice>(),
null /* viewService */,
NSubstitute.Substitute.For<IBikesViewModel>(),
NSubstitute.Substitute.For<IUser>()).GetType());
Substitute.For<IBikesViewModel>(),
Substitute.For<IUser>()).GetType());
// Verify handler for requested bike with state open.
bike = new BikeInfoMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>(),
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt, WheelType.Mono, TypeOfBike.Allround), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 0 /* lock Id*/, new Guid(), null /* user key */, null, null, new DateTime(2020, 1, 1), "a@b.com", "12", null, null, () => new DateTime(2020, 1, 1), false, new List<string>()),
"My Station Name");
bike.LockInfo.State = LockingState.Open;
@ -95,13 +120,18 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
new GeolocationMock(), // geolocation
new LocksServiceMock(), // LockService
null, // viewUpdateManager
NSubstitute.Substitute.For<ISmartDevice>(),
Substitute.For<ISmartDevice>(),
null /* viewService */,
NSubstitute.Substitute.For<IBikesViewModel>(),
NSubstitute.Substitute.For<IUser>()).GetType());
Substitute.For<IBikesViewModel>(),
Substitute.For<IUser>()).GetType());
// Verify handler for booked bike with state closed.
bike = new BikeInfoMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>(),
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt, WheelType.Mono, TypeOfBike.Allround), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 0 /* lock Id*/, new Guid(), null, null, null, new System.DateTime(2020, 1, 1), "a@b.com", "12", null /*operator uri*/, null, false, new List<string>()),
"My Station Name");
bike.LockInfo.State = LockingState.Closed;
@ -114,13 +144,18 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
new GeolocationMock(), // geolocation
new LocksServiceMock(), // LockService
null, // viewUpdateManager
NSubstitute.Substitute.For<ISmartDevice>(),
Substitute.For<ISmartDevice>(),
null /* viewService */,
NSubstitute.Substitute.For<IBikesViewModel>(),
NSubstitute.Substitute.For<IUser>()).GetType());
Substitute.For<IBikesViewModel>(),
Substitute.For<IUser>()).GetType());
// Verify handler for booked bike with state open.
bike = new BikeInfoMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>(),
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt, WheelType.Mono, TypeOfBike.Allround), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 0 /* lock Id*/, new Guid(), null, null, null, new System.DateTime(2020, 1, 1), "a@b.com", "12", null /*operator uri*/, null, false, new List<string>()),
"My Station Name");
bike.LockInfo.State = LockingState.Open;
@ -133,13 +168,18 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
new GeolocationMock(), // geolocation
new LocksServiceMock(), // LockService
null, // viewUpdateManager
NSubstitute.Substitute.For<ISmartDevice>(),
Substitute.For<ISmartDevice>(),
null /* viewService */,
NSubstitute.Substitute.For<IBikesViewModel>(),
NSubstitute.Substitute.For<IUser>()).GetType());
Substitute.For<IBikesViewModel>(),
Substitute.For<IUser>()).GetType());
// Verify handler for booked bike with state unknown.
bike = new BikeInfoMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>(),
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt, WheelType.Mono, TypeOfBike.Allround), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 0 /* lock Id*/, new Guid(), null, null, null, new System.DateTime(2020, 1, 1), "a@b.com", "12", null /*operator uri*/, null, false, new List<string>()),
"My Station Name");
@ -152,10 +192,10 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
new GeolocationMock(), // geolocation
new LocksServiceMock(), // LockService
null, // viewUpdateManager
NSubstitute.Substitute.For<ISmartDevice>(),
Substitute.For<ISmartDevice>(),
null /* viewService */,
NSubstitute.Substitute.For<IBikesViewModel>(),
NSubstitute.Substitute.For<IUser>()).GetType());
Substitute.For<IBikesViewModel>(),
Substitute.For<IUser>()).GetType());
}
}
}

View file

@ -0,0 +1,553 @@
using System;
using System.Threading.Tasks;
using Newtonsoft.Json;
using NSubstitute;
using NSubstitute.ExceptionExtensions;
using NUnit.Framework;
using TINK.Model;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Connector;
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.Geolocation;
using TINK.View;
using TINK.ViewModel;
using TINK.ViewModel.Bikes;
using TINK.ViewModel.Bikes.Bike.BluetoothLock;
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
using static TINK.Model.Bikes.BikeInfoNS.BluetoothLock.Command.GetLockedLocationCommand;
namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock
{
[TestFixture]
public class TestReturnBikeActionViewModel
{
/// <summary>
/// Use case: End rental.
/// Final state: Booked, lock state unknown.
/// </summary>
/// <remarks> Replaces test TestReturnOutOfReach which was removed for sharee.bike version ~3.0.362. </remarks>
[Test]
public async Task TestReturnLastGeolocatonNullLockOutOfReach()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var command = Substitute.For<ICommand>();
var geolocation = Substitute.For<IGeolocationService>();
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 returnBikeActionViewModel = new EndRentalActionViewModel<BookedClosed>(
bike,
() => true, // isConnectedDelegate
(isConnexted) => connector,
locks,
() => pollingManager,
viewService,
bikesViewModel);
bike.Id.Returns("0");
bike.GetLockedBikeLocationAsync(Arg.Any<IGetLockedLocationCommandListener>()).Throws((x) =>
{
returnBikeActionViewModel.ReportStep(Step.StartingQueryLocation);
returnBikeActionViewModel.ReportStateAsync(State.DisconnetedNoLocationError, "").Wait();
returnBikeActionViewModel.ReportStep(Step.DisconnectingLockOnDisconnectedNoLocationError);
returnBikeActionViewModel.ReportStateAsync(State.QueryLocationSucceeded, "").Wait();
throw new Exception();
});
bike.State.Value.Returns(InUseStateEnum.Booked);
await returnBikeActionViewModel.EndRentalAsync();
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
viewService.DisplayAlert(
"Rental could not be terminated!",
"We could not assign the bike to any station. For this we need your location information while you are standing right next to the bike. Only then your rental can be terminated!\r\n\r\nApproach the bike lock, turn on Bluetooth and Location services and try again.",
"OK");
bikesViewModel.ActionText = "Disconnecting lock...";
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
// Verify state after action
Assert.That(
bike.LockInfo.State,
Is.EqualTo(LockingState.UnknownDisconnected));
}
/// <summary>
/// Use case: End rental.
/// Final state: Booked, lock state unknown.
/// </summary>
/// <remarks>Replaces test TestReturnLockInReachNoGeolocation which was removed for sharee.bike older ~ 3.0.362.</remarks>
[Test]
public void TestReturnStartGetGeolocationException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var command = Substitute.For<ICommand>();
var geolocation = Substitute.For<IGeolocationService>();
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 EndRentalActionViewModel<BookedClosed>(
bike,
() => true, // isConnectedDelegate
(isConnexted) => connector,
locks,
() => pollingManager,
viewService,
bikesViewModel);
bike.Id.Returns("0");
bike.GetLockedBikeLocationAsync(Arg.Any<IGetLockedLocationCommandListener>()).Throws((x) =>
{
handler.ReportStep(Step.StartingQueryLocation);
handler.ReportStateAsync(State.QueryLocationFailed, "Ups...").Wait();
throw new Exception();
});
bike.State.Value.Returns(InUseStateEnum.Booked); // Booking state does not change.
bike.LockInfo.State.Returns(LockingState.Closed); // Locking state does not change.
var subsequent = handler.EndRentalAsync();
// Verify behavior
Received.InOrder(async () =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "Query location...";
await viewService.DisplayAlert(
"Rental could not be terminated!",
"Grant Location permission, activate Location services and try again.",
"OK");
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
}
/// <summary>
/// Use case: End rental.
/// Final state: Booked, lock state unknown.
/// </summary>
[Test]
public async Task TestReturnGetGeolocationException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var command = Substitute.For<ICommand>();
var geolocation = Substitute.For<IGeolocationService>();
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 EndRentalActionViewModel<BookedClosed>(
bike,
() => true, // isConnectedDelegate
(isConnexted) => connector,
locks,
() => pollingManager,
viewService,
bikesViewModel);
bike.Id.Returns("0");
bike.GetLockedBikeLocationAsync(Arg.Any<IGetLockedLocationCommandListener>())
.Returns((x) =>
{
handler.ReportStep(Step.StartingQueryLocation);
handler.ReportStateAsync(State.QueryLocationFailed, "Ups...").Wait();
return Task.FromException<LocationDto>(new Exception("Ups..."));
});
bike.State.Value.Returns(InUseStateEnum.Booked); // Booking state does not change.
bike.LockInfo.State.Returns(LockingState.Closed); // Locking state does not change.
await handler.EndRentalAsync();
// Verify behavior
Received.InOrder(() =>
{
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "Query location...";
viewService.DisplayAlert(
"Rental could not be terminated!",
"Grant Location permission, activate Location services and try again.",
"OK");
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
}
/// <summary>
/// Use case: End rental.
/// Final state: Disposable closed
/// </summary>
[Test]
public async Task TestReturnLockInReach()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var command = Substitute.For<ICommand>();
var locks = Substitute.For<ILocksService>();
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
var viewService = Substitute.For<IViewService>();
var bikesViewModel = Substitute.For<IBikesViewModel>();
var listener = Substitute.For<IGetLockedLocationCommandListener>();
var returnBikeActionViewModel = new EndRentalActionViewModel<BookedClosed>(
bike,
() => true, // isConnectedDelegate
(isConnexted) => connector,
locks,
() => pollingManager,
viewService,
bikesViewModel);
bike.Id.Returns("0");
viewService.DisplayAlert(string.Empty, "End rental of bike Nr. 0?", "Yes", "No").Returns(Task.FromResult(true));
bike.GetLockedBikeLocationAsync(Arg.Any<IGetLockedLocationCommandListener>()).Returns((x) =>
{
returnBikeActionViewModel.ReportStep(Step.StartingQueryLocation);
returnBikeActionViewModel.ReportStateAsync(State.QueryLocationSucceeded, string.Empty).Wait();
return Task.FromResult(new LocationDto.Builder().Build());
});
bike.State.Value.Returns(InUseStateEnum.Disposable); // Request handler factory queries state to create appropriate request handler object.
bike.LockInfo.State.Returns(LockingState.Closed); // Request handler factory queries lock state to create appropriate request handler object.
await returnBikeActionViewModel.EndRentalAsync();
// 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 = "Query location...";
bikesViewModel.ActionText = "One moment please...";
connector.Command.DoReturn(bike, Arg.Is<LocationDto>(x => x != null));
bikesViewModel.ActionText = "Disconnecting lock...";
locks.DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
bikesViewModel.ActionText = "Updating...";
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
}
/// <summary>
/// Use case: End rental.
/// Final state: Same as initial state.
/// </summary>
[Test]
public async Task TestReturnReturnFailsWebConnectFailureException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var command = Substitute.For<ICommand>();
var locks = Substitute.For<ILocksService>();
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
var viewService = Substitute.For<IViewService>();
var bikesViewModel = Substitute.For<IBikesViewModel>();
var handler = new EndRentalActionViewModel<BookedClosed>(
bike,
() => true, // isConnectedDelegate
(isConnexted) => connector,
locks,
() => pollingManager,
viewService,
bikesViewModel);
bike.Id.Returns("0");
viewService.DisplayAlert(string.Empty, "End rental of bike Nr. 0?", "Yes", "No").Returns(Task.FromResult(true));
locks[0].GetDeviceState().Returns(DeviceState.Connected); // Simulate bike in reach. If bike is out of reach bluetooth state changes to unknown.
connector.Command.DoReturn(bike, Arg.Any<LocationDto>()).Returns<BookingFinishedModel>(x => throw new WebConnectFailureException("Context info", new Exception("hoppla")));
bike.State.Value.Returns(InUseStateEnum.Booked); // Requesthandler factory queries state to create appropriate request handler object.
bike.LockInfo.State.Returns(LockingState.Closed); // Requesthandler factory queries lock state to create appropriate request handler object.
await handler.EndRentalAsync();
await locks.DidNotReceive().DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
await locks.DidNotReceive().DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
// 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 = "One moment please...";
connector.Command.DoReturn(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Rental could not be terminated!",
"A stable Internet connection is required. Connect to WIFI or to mobile network and activate mobile data. Try again.",
"OK");
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
}
/// <summary>
/// Use case: End rental.
/// Final state: Same as initial state.
/// </summary>
[Test]
public async Task TestReturnReturnFailsNotAtStationException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var command = Substitute.For<ICommand>();
var locks = Substitute.For<ILocksService>();
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
var viewService = Substitute.For<IViewService>();
var bikesViewModel = Substitute.For<IBikesViewModel>();
var handler = new EndRentalActionViewModel<BookedClosed>(
bike,
() => true, // isConnectedDelegate
(isConnexted) => connector,
locks,
() => pollingManager,
viewService,
bikesViewModel);
bike.Id.Returns("0");
viewService.DisplayAlert(string.Empty, "End rental of bike Nr. 0?", "Yes", "No").Returns(Task.FromResult(true));
locks[0].GetDeviceState().Returns(DeviceState.Connected); // Simulate bike in reach. If bike is out of reach bluetooth state changes to unknown.
NotAtStationException.IsNotAtStation("Failure 2178: bike 1545 out of GEO fencing. 15986 meter distance to next station 42. OK: bike 1545 locked confirmed", out NotAtStationException notAtStationException);
connector.Command.DoReturn(bike, Arg.Any<LocationDto>()).Returns<BookingFinishedModel>(x =>
throw notAtStationException);
bike.State.Value.Returns(InUseStateEnum.Booked); // Requesthandler factory queries state to create appropriate request handler object.
bike.LockInfo.State.Returns(LockingState.Closed); // Requesthandler factory queries lock state to create appropriate request handler object.
await handler.EndRentalAsync();
await locks.DidNotReceive().DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
// 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 = "One moment please...";
connector.Command.DoReturn(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Rental could not be terminated!", "End rental outside or at wrong station is not possible. Distance to next suitable station 42 is 15986 m.", "OK");
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
}
/// <summary>
/// Use case: End rental.
/// Final state: Same as initial state.
/// </summary>
[Test]
public async Task TestReturnReturnFailsNoGPSDataException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var command = Substitute.For<ICommand>();
var locks = Substitute.For<ILocksService>();
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
var viewService = Substitute.For<IViewService>();
var bikesViewModel = Substitute.For<IBikesViewModel>();
var handler = new EndRentalActionViewModel<BookedClosed>(
bike,
() => true, // isConnectedDelegate
(isConnexted) => connector,
locks,
() => pollingManager,
viewService,
bikesViewModel);
bike.Id.Returns("0");
viewService.DisplayAlert(string.Empty, "End rental of bike Nr. 0?", "Yes", "No").Returns(Task.FromResult(true));
locks[0].GetDeviceState().Returns(DeviceState.Connected); // Simulate bike in reach. If bike is out of reach bluetooth state changes to unknown.
NoGPSDataException.IsNoGPSData("Failure 2245: No GPS data, state change forbidden.", out NoGPSDataException noGPSDataException);
connector.Command.DoReturn(bike, Arg.Any<LocationDto>()).Returns<BookingFinishedModel>(x =>
throw noGPSDataException);
bike.State.Value.Returns(InUseStateEnum.Booked); // Requesthandler factory queries state to create appropriate request handler object.
bike.LockInfo.State.Returns(LockingState.Closed); // Requesthandler factory queries lock state to create appropriate request handler object.
await handler.EndRentalAsync();
await locks.DidNotReceive().DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
// 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 = "One moment please...";
connector.Command.DoReturn(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert("Rental could not be terminated!", "End rental at an unknown location is not possible.\r\nRental can be ended if\r\n- location information is available when closing lock\r\n- bike is in reach and location information is available when pressing button \"End rental\"", "OK");
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
}
/// <summary>
/// Use case: End rental.
/// Final state: Same as initial state.
/// </summary>
[Test]
public async Task TestReturnReturnFailsResponseException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var command = Substitute.For<ICommand>();
var locks = Substitute.For<ILocksService>();
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
var viewService = Substitute.For<IViewService>();
var bikesViewModel = Substitute.For<IBikesViewModel>();
var handler = new EndRentalActionViewModel<BookedClosed>(
bike,
() => true, // isConnectedDelegate
(isConnexted) => connector,
locks,
() => pollingManager,
viewService,
bikesViewModel);
bike.Id.Returns("0");
viewService.DisplayAlert(string.Empty, "End rental of bike Nr. 0?", "Yes", "No").Returns(Task.FromResult(true));
locks[0].GetDeviceState().Returns(DeviceState.Connected); // Simulate bike in reach. If bike is out of reach bluetooth state changes to unknown.
connector.Command.DoReturn(bike, Arg.Any<LocationDto>()).Returns<BookingFinishedModel>(x =>
throw new ReturnBikeException(JsonConvert.DeserializeObject<DoReturnResponse>(@"{ ""response_text"" : ""Some invalid data received!""}"), "Outer message."));
bike.State.Value.Returns(InUseStateEnum.Booked); // Requesthandler factory queries state to create appropriate request handler object.
bike.LockInfo.State.Returns(LockingState.Closed); // Requesthandler factory queries lock state to create appropriate request handler object.
await handler.EndRentalAsync();
await locks.DidNotReceive().DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
// 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 = "One moment please...";
connector.Command.DoReturn(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAdvancedAlert("Rental could not be terminated!", "Outer message.", "Some invalid data received!", "OK");
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
}
/// <summary>
/// Use case: End rental.
/// Final state: Same as initial state.
/// </summary>
[Test]
public async Task TestReturnReturnFailsException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var command = Substitute.For<ICommand>();
var locks = Substitute.For<ILocksService>();
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
var viewService = Substitute.For<IViewService>();
var bikesViewModel = Substitute.For<IBikesViewModel>();
var returnBikeActionViewModel = new EndRentalActionViewModel<BookedClosed>(
bike,
() => true, // isConnectedDelegate
(isConnexted) => connector,
locks,
() => pollingManager,
viewService,
bikesViewModel);
bike.Id.Returns("0");
viewService.DisplayAlert(string.Empty, "End rental of bike Nr. 0?", "Yes", "No").Returns(Task.FromResult(true));
locks[0].GetDeviceState().Returns(DeviceState.Connected); // Simulate bike in reach. If bike is out of reach bluetooth state changes to unknown.
connector.Command.DoReturn(bike, Arg.Any<LocationDto>()).Returns<BookingFinishedModel>(x => throw new Exception("Exception message."));
bike.State.Value.Returns(InUseStateEnum.Booked); // Request handler factory queries state to create appropriate request handler object.
bike.LockInfo.State.Returns(LockingState.Closed); // Request handler factory queries lock state to create appropriate request handler object.
await returnBikeActionViewModel.EndRentalAsync();
await locks.DidNotReceive().DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
// 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 = "One moment please...";
connector.Command.DoReturn(bike, Arg.Any<LocationDto>());
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Rental could not be terminated!",
"Exception message.",
"OK"
);
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
}
}
}

View file

@ -56,17 +56,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
connector.Command.OpenLockAsync(bike); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAdvancedAlert(
"Connection error when opening the lock!",
"Is WIFI/mobile network available and mobile data activated?",
"Context info",
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.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -126,16 +125,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
connector.Command.OpenLockAsync(bike); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Error while opening lock!",
"Lock could not be opened!",
"Some error",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -193,11 +192,11 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
connector.Command.OpenLockAsync(bike); // Booking must be performed
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});

View file

@ -56,17 +56,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
connector.Command.OpenLockAsync(bike); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAdvancedAlert(
"Connection error when opening the lock!",
"Is WIFI/mobile network available and mobile data activated?",
"Context info",
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.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -126,16 +125,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
connector.Command.OpenLockAsync(bike); // Booking must be performed
bikesViewModel.ActionText = string.Empty;
viewService.DisplayAlert(
"Error while opening lock!",
"Lock could not be opened!",
"Some error",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -193,11 +192,11 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
pollingManager.StopAsync(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is opening.<br/>Please wait until it is completely open.</b></h4>";
connector.Command.OpenLockAsync(bike); // Booking must be performed
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});

View file

@ -124,17 +124,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
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(
"Connection error when renting the bike!",
"Is WIFI/mobile network available and mobile data activated?",
"Context info",
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.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -200,16 +199,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
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(
"Error when renting the bike!",
"Bike could not be rented!",
"Some error",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -273,11 +272,11 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
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.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -409,7 +408,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
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;
@ -418,7 +417,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
"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
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -486,17 +485,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
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.DisplayAdvancedAlert(
"Connection error when reserving the bike!",
"Is WIFI/mobile network available and mobile data activated?",
"Context info",
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.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -564,16 +562,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
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(
"Error when reserving the bike!",
"Bike could not be reserved!",
"Some error",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -639,11 +637,11 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
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.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});

View file

@ -54,17 +54,17 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
pollingManager.StopAsync(); // 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 = string.Empty;
viewService.DisplayAlert(
"Submitting feedback failed!",
"Your feedback could not be send to server successfully.",
"A stable Internet connection is required. Connect to WIFI or to mobile network and activate mobile data. Try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -116,12 +116,12 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
pollingManager.StopAsync(); // 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
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -175,13 +175,13 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
pollingManager.StopAsync(); // 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
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});

View file

@ -69,7 +69,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
// Verify state after action
Assert.That(
subsequent.ButtonText,
Is.EqualTo("Cancel bike reservation"));
Is.EqualTo("Cancel reservation"));
Assert.That(
subsequent.IsButtonVisible,
Is.True);
@ -122,16 +122,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
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(
"Error when canceling the reservation!",
"Can not login user otto@mustermann.de. Mail address unknown or password invalid.",
"Reservation could not be canceled!",
"Your session has expired. Please login new and try again.",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -139,7 +139,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
// Verify state after action
Assert.That(
subsequent.ButtonText,
Is.EqualTo("Cancel bike reservation"));
Is.EqualTo("Cancel reservation"));
Assert.That(
subsequent.IsButtonVisible,
Is.True);
@ -191,17 +191,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
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.DisplayAdvancedAlert(
"Connection error when canceling the reservation!",
"Is WIFI/mobile network available and mobile data activated?",
"Context info",
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.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -209,7 +208,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
// Verify state after action
Assert.That(
subsequent.ButtonText,
Is.EqualTo("Cancel bike reservation"));
Is.EqualTo("Cancel reservation"));
Assert.That(
subsequent.IsButtonVisible,
Is.True);
@ -265,16 +264,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
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(
"Error when canceling the reservation!",
"Reservation could not be canceled!",
"Some error",
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -282,7 +281,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
// Verify state after action
Assert.That(
subsequent.ButtonText,
Is.EqualTo("Cancel bike reservation"));
Is.EqualTo("Cancel reservation"));
Assert.That(
subsequent.IsButtonVisible,
Is.True);
@ -336,11 +335,11 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
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.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -410,7 +409,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
// Verify state after action
Assert.That(
subsequent.ButtonText,
Is.EqualTo("Cancel bike reservation"));
Is.EqualTo("Cancel reservation"));
Assert.That(
subsequent.IsButtonVisible,
Is.True);
@ -466,17 +465,16 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
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(
"Connection error when renting the bike!",
"Is WIFI/mobile network available and mobile data activated?",
"Context info",
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.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -484,7 +482,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
// Verify state after action
Assert.That(
subsequent.ButtonText,
Is.EqualTo("Cancel bike reservation"));
Is.EqualTo("Cancel reservation"));
Assert.That(
subsequent.IsButtonVisible,
Is.True);
@ -540,17 +538,17 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
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(
"Error when renting the bike!",
"Bike could not be rented!",
"Some error",
String.Empty,
"OK");
bikesViewModel.ActionText = "Updating...";
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});
@ -558,7 +556,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
// Verify state after action
Assert.That(
subsequent.ButtonText,
Is.EqualTo("Cancel bike reservation"));
Is.EqualTo("Cancel reservation"));
Assert.That(
subsequent.IsButtonVisible,
Is.True);
@ -614,11 +612,11 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.CopriLock.RequestHandler
{
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
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.StartUpdateAyncPeridically(); // polling must be restarted again
pollingManager.StartAsync(); // polling must be restarted again
bikesViewModel.ActionText = string.Empty;
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
});

View file

@ -1,12 +1,16 @@
using System;
using NSubstitute;
using NUnit.Framework;
using TestFramework.Model.Services.Geolocation;
using TestFramework.Services.BluetoothLock;
using TINK.Model.Bikes.BikeInfoNS.BC;
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.Model.Bikes.BikeInfoNS.DriveNS;
using TINK.Model.Connector;
using TINK.Model.Device;
using TINK.Model.User;
using TINK.Services.BluetoothLock;
using TINK.Services.Geolocation;
using TINK.ViewModel;
using TINK.ViewModel.Bikes;
using TINK.ViewModel.Bikes.Bike;
@ -49,13 +53,19 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
new LocksServiceMock(), // lock service
(index) => { }, // bikeRemoveDelegate
null, // viewUpdateManager
NSubstitute.Substitute.For<ISmartDevice>(),
Substitute.For<ISmartDevice>(),
null, // viewService
new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("42", LockModel.ILockIt), new Drive(), DataSource.Copri, 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "42"), "My Station Name"),
NSubstitute.Substitute.For<IUser>(), // user
new ViewContext (PageContext.BikesAtStation, "FR1012"), // Context does not matter for this test.
NSubstitute.Substitute.For<IInUseStateInfoProvider>(),
NSubstitute.Substitute.For<IBikesViewModel>(),
new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable(
Substitute.For<IGeolocationService>(),
Substitute.For<ILocksService>(),
() => false /* not connected */,
(_) => Substitute.For<IConnector>(),
() => Substitute.For<IPollingUpdateTaskManager>(),
new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("42", LockModel.ILockIt), new Drive(), DataSource.Copri, 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "42"), "My Station Name"),
Substitute.For<IUser>(), // user
null /*ViewContext*/,
Substitute.For<IInUseStateInfoProvider>(),
Substitute.For<IBikesViewModel>(),
url => { }).GetType()); // stateInfoProvider
}

View file

@ -299,7 +299,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
Assert.AreEqual($"Rented since {DateTime.Parse("2020-10-12 08:38:12.374231+02"):dd. MMMM HH:mm}.", bike1537.StateText);
Assert.AreEqual("Available.", bike1315.StateText);
Assert.AreEqual("Available.", bike1543.StateText);
Assert.AreEqual("Close lock", bike1545.LockitButtonText);
Assert.AreEqual("Close lock", bike1545.ButtonText);
Assert.AreEqual(string.Empty, bike1545.LockitButtonText);
Assert.AreEqual("Open lock", bike1537.LockitButtonText);
Assert.AreEqual("DisposableDisconnected", bike1315.LockitButtonText);
Assert.AreEqual("DisposableDisconnected", bike1543.LockitButtonText);
@ -1108,8 +1109,6 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
await bikesAtStation.OnAppearingOrRefresh();
Assert.AreEqual("Offline.", bikesAtStation.StatusInfoText);
// Verify list of bikes
Assert.AreEqual(2, bikesAtStation.Count); // Count of bikes was 3. There is no more bike with id 26.
Assert.IsTrue(bikesAtStation.IsIdle);
@ -1199,8 +1198,6 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
await bikesAtStation.OnAppearingOrRefresh();
Assert.AreEqual("Connection interrupted, server unreachable.", bikesAtStation.StatusInfoText);
// Verify list of bikes
Assert.AreEqual(2, bikesAtStation.Count); // Count of bikes was 3. There is no more bike with id 26.
Assert.IsTrue(bikesAtStation.IsIdle);
@ -1291,8 +1288,6 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
await bikesAtStation.OnAppearingOrRefresh();
Assert.AreEqual("Connection interrupted.", bikesAtStation.StatusInfoText);
// Verify list of bikes
Assert.AreEqual(2, bikesAtStation.Count); // Count of bikes was 3. There is no more bike with id 26.
Assert.IsTrue(bikesAtStation.IsIdle);

View file

@ -406,9 +406,6 @@ namespace TestShareeLib.UseCases.Startup
Assert.AreEqual(Color.White, viewModel.TinkColor, "TINK bikes are hidden.");
Assert.AreEqual(Color.FromRgba(0, 0, 0, 0), viewModel.KonradColor, "Konrad bikes are shown.");
Assert.AreEqual("Offline.", viewModel.StatusInfoText);
}
finally
{
@ -497,8 +494,6 @@ namespace TestShareeLib.UseCases.Startup
Assert.AreEqual(Color.White, viewModel.TinkColor, "TINK bikes are hidden.");
Assert.AreEqual(Color.FromRgba(0, 0, 0, 0), viewModel.KonradColor, "Konrad bikes are shown.");
Assert.AreEqual("Connection interrupted, server unreachable.", viewModel.StatusInfoText);
}
finally
{
@ -588,8 +583,6 @@ namespace TestShareeLib.UseCases.Startup
Assert.AreEqual(Color.White, viewModel.TinkColor, "TINK bikes are hidden.");
Assert.AreEqual(Color.FromRgba(0, 0, 0, 0), viewModel.KonradColor, "Konrad bikes are shown.");
Assert.AreEqual("Connection interrupted.", viewModel.StatusInfoText);
}
finally
{

View file

@ -124,7 +124,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
var bike1537 = myBikes.FirstOrDefault(x => x.Id == "1537") as TINK.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
Assert.AreEqual($"Rented since {DateTime.Parse("2020-11-06 17:53:22.784681+01"):dd. MMMM HH:mm}.", bike1545.StateText);
Assert.AreEqual($"Rented since {DateTime.Parse("2020-10-12 08:38:12.374231+02"):dd. MMMM HH:mm}.", bike1537.StateText);
Assert.AreEqual("Close lock", bike1545.LockitButtonText);
Assert.AreEqual("Close lock", bike1545.ButtonText);
Assert.AreEqual(string.Empty, bike1545.LockitButtonText);
Assert.AreEqual("Open lock", bike1537.LockitButtonText);
Assert.IsFalse(myBikes.IsNoBikesOccupiedVisible);
@ -664,8 +665,6 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
await myBikes.OnAppearingOrRefresh();
Assert.AreEqual("Offline.", myBikes.StatusInfoText);
Assert.AreEqual(2, myBikes.Count);
Assert.IsTrue(myBikes.IsIdle);
Assert.IsTrue(myBikes.IsBikesListVisible, "If there are any bikes, list must be visible.");
@ -750,8 +749,6 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
await myBikes.OnAppearingOrRefresh();
Assert.AreEqual("Connection interrupted, server unreachable.", myBikes.StatusInfoText);
Assert.AreEqual(2, myBikes.Count);
Assert.IsTrue(myBikes.IsIdle);
Assert.IsTrue(myBikes.IsBikesListVisible, "If there are any bikes, list must be visible.");
@ -836,8 +833,6 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
await myBikes.OnAppearingOrRefresh();
Assert.AreEqual("Connection interrupted.", myBikes.StatusInfoText);
Assert.AreEqual(2, myBikes.Count);
Assert.IsTrue(myBikes.IsIdle);
Assert.IsTrue(myBikes.IsBikesListVisible, "If there are any bikes, list must be visible.");

View file

@ -13,12 +13,12 @@ namespace UITest.Fixtures.ObjectTests
{
var l_oManger = new PollingUpdateTaskManager(() => Task.Delay(1000));
await l_oManger.StartUpdateAyncPeridically(new PollingParameters(new System.TimeSpan(0, 0, 2), true));
await l_oManger.StartAsync(new PollingParameters(new System.TimeSpan(0, 0, 2), true));
l_oManger.StopUpdatePeridically().Wait();
l_oManger.StopAsync().Wait();
// Should not lead to dead lock.
l_oManger.StopUpdatePeridically().Wait();
l_oManger.StopAsync().Wait();
}
[Test]
@ -26,12 +26,12 @@ namespace UITest.Fixtures.ObjectTests
{
var l_oManger = new PollingUpdateTaskManager(() => Task.Delay(1000));
await l_oManger.StartUpdateAyncPeridically(new PollingParameters(new System.TimeSpan(0, 0, 2), true));
await l_oManger.StartAsync(new PollingParameters(new System.TimeSpan(0, 0, 2), true));
// Should not lead to dead lock.
await l_oManger.StartUpdateAyncPeridically(new PollingParameters(new System.TimeSpan(0, 0, 2), true));
await l_oManger.StartAsync(new PollingParameters(new System.TimeSpan(0, 0, 2), true));
l_oManger.StopUpdatePeridically().Wait();
l_oManger.StopAsync().Wait();
}
[Test]
@ -40,7 +40,7 @@ namespace UITest.Fixtures.ObjectTests
var l_oManger = new PollingUpdateTaskManager(() => Task.Delay(1000));
// Should not lead to dead lock.
await l_oManger.StartUpdateAyncPeridically(new PollingParameters(new System.TimeSpan(0, 0, 2), true));
await l_oManger.StartAsync(new PollingParameters(new System.TimeSpan(0, 0, 2), true));
}
}
}