mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2025-01-22 04:24:28 +01:00
Initial version
This commit is contained in:
parent
41b618cb27
commit
e4fb48f6ab
24 changed files with 4387 additions and 0 deletions
17
TestShareeLib/Model/Bike/BC/TestBikeInfo.cs
Normal file
17
TestShareeLib/Model/Bike/BC/TestBikeInfo.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
using TINK.Model.Bike.BC;
|
||||||
|
|
||||||
|
namespace TestTINKLib.Fixtures.ObjectTests.Bike.BC
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestBikeInfo
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestCtorCopyNull()
|
||||||
|
{
|
||||||
|
Assert.Throws<System.ArgumentException>(
|
||||||
|
() => new BikeInfo(null),
|
||||||
|
"Verify that no unspecific reference not set to... exception is thrown");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
80
TestShareeLib/Model/Bike/BC/TestBikeMutable.cs
Normal file
80
TestShareeLib/Model/Bike/BC/TestBikeMutable.cs
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using TINK.Model.Bike;
|
||||||
|
using TINK.Model.Bikes.Bike;
|
||||||
|
using TINK.Model.State;
|
||||||
|
|
||||||
|
namespace TestTINKLib
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
class TestBikeMutable
|
||||||
|
{
|
||||||
|
private class BikeInfoMutable : TINK.Model.Bike.BC.BikeInfoMutable
|
||||||
|
{
|
||||||
|
public BikeInfoMutable(
|
||||||
|
int id,
|
||||||
|
bool isDemo = false,
|
||||||
|
IEnumerable<string> group = null,
|
||||||
|
WheelType? wheelType = null,
|
||||||
|
TypeOfBike? typeOfBike = null,
|
||||||
|
string description = null,
|
||||||
|
int? currentStationId = null,
|
||||||
|
Uri operatorUri = null,
|
||||||
|
TariffDescription tariffDescription = null,
|
||||||
|
Func<DateTime> dateTimeProvider = null,
|
||||||
|
IStateInfo stateInfo = null) : base(id, isDemo, group, wheelType, typeOfBike, description, currentStationId, operatorUri, tariffDescription, dateTimeProvider, stateInfo)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestConstruct()
|
||||||
|
{
|
||||||
|
var l_oBike = new BikeInfoMutable(
|
||||||
|
42,
|
||||||
|
false,
|
||||||
|
new List<string> { "TINK" },
|
||||||
|
WheelType.Two,
|
||||||
|
TypeOfBike.Cargo);
|
||||||
|
|
||||||
|
Assert.AreEqual(42, l_oBike.Id);
|
||||||
|
Assert.IsFalse(l_oBike.IsDemo);
|
||||||
|
Assert.AreEqual(WheelType.Two, l_oBike.WheelType);
|
||||||
|
Assert.AreEqual(TypeOfBike.Cargo, l_oBike.TypeOfBike);
|
||||||
|
Assert.AreEqual(InUseStateEnum.Disposable, l_oBike.State.Value);
|
||||||
|
Assert.IsNull(l_oBike.CurrentStation);
|
||||||
|
|
||||||
|
l_oBike = new BikeInfoMutable(
|
||||||
|
17,
|
||||||
|
true,
|
||||||
|
new List<string> { "TINK" },
|
||||||
|
WheelType.Mono,
|
||||||
|
TypeOfBike.Allround,
|
||||||
|
"Test description",
|
||||||
|
1);
|
||||||
|
|
||||||
|
Assert.AreEqual(17, l_oBike.Id);
|
||||||
|
Assert.IsTrue(l_oBike.IsDemo);
|
||||||
|
Assert.AreEqual(WheelType.Mono, l_oBike.WheelType);
|
||||||
|
Assert.AreEqual(TypeOfBike.Allround, l_oBike.TypeOfBike);
|
||||||
|
Assert.AreEqual(InUseStateEnum.Disposable, l_oBike.State.Value);
|
||||||
|
Assert.AreEqual(1, l_oBike.CurrentStation);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestToString()
|
||||||
|
{
|
||||||
|
var l_oBike = new BikeInfoMutable(3, false, new List<string> { "TINK" }, WheelType.Two, TypeOfBike.Cargo, dateTimeProvider: () => new DateTime(1970, 1, 1));
|
||||||
|
|
||||||
|
Assert.AreEqual(
|
||||||
|
"Id=3, wheel(s)=Two, type=Cargo, demo=False, state=Disposable, location=On the road.",
|
||||||
|
l_oBike.ToString());
|
||||||
|
|
||||||
|
l_oBike = new BikeInfoMutable(3, true, new List<string> { "TINK" }, WheelType.Trike, TypeOfBike.Allround, "Test description", 5, dateTimeProvider: () => new DateTime(1970, 1, 1));
|
||||||
|
Assert.AreEqual(
|
||||||
|
"Id=3, wheel(s)=Trike, type=Allround, demo=True, state=Disposable, location=Station 5.",
|
||||||
|
l_oBike.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
59
TestShareeLib/Model/Bike/BC/TestBikeSerializeJSON.cs
Normal file
59
TestShareeLib/Model/Bike/BC/TestBikeSerializeJSON.cs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using TINK.Model.Bike;
|
||||||
|
using TINK.Model.State;
|
||||||
|
|
||||||
|
using BikeInfoMutable = TINK.Model.Bike.BC.BikeInfoMutable;
|
||||||
|
|
||||||
|
namespace TestTINKLib
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Exclude from build beause serialization... see below.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
public class TestBikeSerializeJSON
|
||||||
|
{
|
||||||
|
[Test, Ignore("Disabled because serialization does no more work due to inheritance since commit ec14b93b.")]
|
||||||
|
public void TestConstruct_SerializeJSON_Disposable()
|
||||||
|
{
|
||||||
|
// Create object to test.
|
||||||
|
var l_oBikeSource = new BikeInfoMutable(3, false, new List<string> { "TINK" }, WheelType.Two, TypeOfBike.Cargo, p_oDateTimeProvider: () => new DateTime(1970, 1, 1));
|
||||||
|
|
||||||
|
// Verify prerequisites
|
||||||
|
Assert.AreEqual(InUseStateEnum.Disposable, l_oBikeSource.State.Value);
|
||||||
|
Assert.IsNull(l_oBikeSource.State.MailAddress);
|
||||||
|
Assert.IsNull(l_oBikeSource.State.Code);
|
||||||
|
Assert.IsNull(l_oBikeSource.State.From);
|
||||||
|
|
||||||
|
// Serialize object and verify.
|
||||||
|
var l_oDetected = JsonConvert.SerializeObject(l_oBikeSource, Formatting.Indented, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto });
|
||||||
|
const string EXPECTED = @"
|
||||||
|
{
|
||||||
|
""Id"": 3,
|
||||||
|
""CurrentStation"": null,
|
||||||
|
""WheelType"": 1,
|
||||||
|
""TypeOfBike"": 1,
|
||||||
|
""State"": {
|
||||||
|
""StateInfoObject"": {
|
||||||
|
""$type"": ""TINK.Model.State.StateAvailableInfo, TINKLib""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}";
|
||||||
|
|
||||||
|
Assert.AreEqual(
|
||||||
|
TestHelper.PrepareXmlForStringCompare(EXPECTED),
|
||||||
|
TestHelper.PrepareXmlForStringCompare(l_oDetected));
|
||||||
|
|
||||||
|
// Deserialize object.
|
||||||
|
var l_oBikeTarget = JsonConvert.DeserializeObject<BikeInfoMutable>(l_oDetected, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto });
|
||||||
|
|
||||||
|
// Verify state.
|
||||||
|
Assert.AreEqual(InUseStateEnum.Disposable, l_oBikeTarget.State.Value);
|
||||||
|
Assert.IsNull(l_oBikeTarget.State.MailAddress);
|
||||||
|
Assert.IsNull(l_oBikeTarget.State.Code);
|
||||||
|
Assert.IsNull(l_oBikeTarget.State.From);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
47
TestShareeLib/Model/Bike/BluetoothLock/TestBikeInfo.cs
Normal file
47
TestShareeLib/Model/Bike/BluetoothLock/TestBikeInfo.cs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using TINK.Model.Bike.BluetoothLock;
|
||||||
|
using TINK.Model.State;
|
||||||
|
|
||||||
|
namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestBikeInfo
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestCtorCopyNull()
|
||||||
|
{
|
||||||
|
Assert.Throws<System.ArgumentException>(
|
||||||
|
() => new BikeInfo(null, null),
|
||||||
|
"Verify that no unspecific reference not set to... exception is thrown");
|
||||||
|
|
||||||
|
Assert.Throws<System.ArgumentException>(
|
||||||
|
() => new BikeInfo(new TINK.Model.Bike.BC.BikeInfo(12,1), null),
|
||||||
|
"Verify that no unspecific reference not set to... exception is thrown");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCtorAvailable()
|
||||||
|
{
|
||||||
|
Assert.AreEqual (12,new BikeInfo(12, 5200544, new Guid("00000000-0000-0000-0000-000000000001"), 13).Id);
|
||||||
|
Assert.AreEqual(13, new BikeInfo(12, 5200544, new Guid("00000000-0000-0000-0000-000000000001"), 13).CurrentStation);
|
||||||
|
Assert.AreEqual(InUseStateEnum.Disposable, new BikeInfo(12, 5200544, new Guid("00000000-0000-0000-0000-000000000001"), 13).State.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCtorRequested()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(12, new BikeInfo(12, 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", 13, null, null, dateTimeProvider: () => new DateTime(2019, 1, 1)).Id);
|
||||||
|
Assert.AreEqual(112, new BikeInfo(12, 112, new Guid(), null, null, null, new DateTime(2020,1,1), "a@b", 13, null, null, dateTimeProvider: () => new DateTime(2019, 1, 1)).LockInfo.Id);
|
||||||
|
Assert.AreEqual(InUseStateEnum.Reserved, new BikeInfo(12, 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", 13, null, null, dateTimeProvider: () => new DateTime(2019, 1, 1)).State.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCtorBooked()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(12, new BikeInfo(12, 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", 13, null /*operator uri*/).Id);
|
||||||
|
Assert.AreEqual(112, new BikeInfo(12, 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", 13, null /*operator uri*/).LockInfo.Id);
|
||||||
|
Assert.AreEqual(InUseStateEnum.Booked, new BikeInfo(12, 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", 13, null /*operator uri*/).State.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
172
TestShareeLib/Model/Bike/BluetoothLock/TestLockInfo.cs
Normal file
172
TestShareeLib/Model/Bike/BluetoothLock/TestLockInfo.cs
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using TINK.Model.Bike.BluetoothLock;
|
||||||
|
namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestLockInfo
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestCtor()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(
|
||||||
|
LockingState.Disconnected,
|
||||||
|
new LockInfo.Builder { Id = 123 }.Build().State);
|
||||||
|
|
||||||
|
Assert.AreEqual(
|
||||||
|
123,
|
||||||
|
new LockInfo.Builder { Id = 123 }.Build().Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestEquals()
|
||||||
|
{
|
||||||
|
Assert.IsTrue(new LockInfo.Builder {
|
||||||
|
Id = 2,
|
||||||
|
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
|
||||||
|
Seed = new byte[] { 1, 2 },
|
||||||
|
UserKey = new byte[] { 7, 2 },
|
||||||
|
AdminKey = new byte[] { 2, 1 },
|
||||||
|
State = LockingState.Closed}.Build() == new LockInfo.Builder {
|
||||||
|
Id = 2,
|
||||||
|
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
|
||||||
|
Seed = new byte[] { 1, 2 },
|
||||||
|
UserKey = new byte[] { 7, 2 },
|
||||||
|
AdminKey = new byte[] { 2, 1 },
|
||||||
|
State = LockingState.Closed
|
||||||
|
}.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestEqualsFalse_Id()
|
||||||
|
{
|
||||||
|
Assert.IsFalse(new LockInfo.Builder
|
||||||
|
{
|
||||||
|
Id = 2,
|
||||||
|
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
|
||||||
|
Seed = new byte[] { 1, 2 },
|
||||||
|
UserKey = new byte[] { 7, 2 },
|
||||||
|
AdminKey = new byte[] { 2, 1 },
|
||||||
|
State = LockingState.Closed
|
||||||
|
}.Build() == new LockInfo.Builder
|
||||||
|
{
|
||||||
|
Id = 3,
|
||||||
|
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
|
||||||
|
Seed = new byte[] { 1, 2 },
|
||||||
|
UserKey = new byte[] { 7, 2 },
|
||||||
|
AdminKey = new byte[] { 2, 1 },
|
||||||
|
State = LockingState.Closed
|
||||||
|
}.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestEqualsFalse_Guid()
|
||||||
|
{
|
||||||
|
Assert.IsFalse(new LockInfo.Builder
|
||||||
|
{
|
||||||
|
Id = 2,
|
||||||
|
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
|
||||||
|
Seed = new byte[] { 1, 2 },
|
||||||
|
UserKey = new byte[] { 7, 2 },
|
||||||
|
AdminKey = new byte[] { 2, 1 },
|
||||||
|
State = LockingState.Closed
|
||||||
|
}.Build() == new LockInfo.Builder
|
||||||
|
{
|
||||||
|
Id = 2,
|
||||||
|
Guid = new Guid("1000f00d-1212-efde-1523-785fef13d123"),
|
||||||
|
Seed = new byte[] { 1, 2 },
|
||||||
|
UserKey = new byte[] { 7, 2 },
|
||||||
|
AdminKey = new byte[] { 2, 1 },
|
||||||
|
State = LockingState.Closed
|
||||||
|
}.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestEqualsFalse_Seed()
|
||||||
|
{
|
||||||
|
Assert.IsFalse(new LockInfo.Builder
|
||||||
|
{
|
||||||
|
Id = 2,
|
||||||
|
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
|
||||||
|
Seed = new byte[] { 1, 2 },
|
||||||
|
UserKey = new byte[] { 7, 2 },
|
||||||
|
AdminKey = new byte[] { 2, 1 },
|
||||||
|
State = LockingState.Closed
|
||||||
|
}.Build() == new LockInfo.Builder
|
||||||
|
{
|
||||||
|
Id = 2,
|
||||||
|
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
|
||||||
|
Seed = new byte[] { 5, 2 },
|
||||||
|
UserKey = new byte[] { 7, 2 },
|
||||||
|
AdminKey = new byte[] { 2, 1 },
|
||||||
|
State = LockingState.Closed
|
||||||
|
}.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestEqualsFalse_UserKey()
|
||||||
|
{
|
||||||
|
Assert.IsFalse(new LockInfo.Builder
|
||||||
|
{
|
||||||
|
Id = 2,
|
||||||
|
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
|
||||||
|
Seed = new byte[] { 1, 2 },
|
||||||
|
UserKey = new byte[] { 7, 2 },
|
||||||
|
AdminKey = new byte[] { 2, 1 },
|
||||||
|
State = LockingState.Closed
|
||||||
|
}.Build() == new LockInfo.Builder
|
||||||
|
{
|
||||||
|
Id = 2,
|
||||||
|
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
|
||||||
|
Seed = new byte[] { 1, 2 },
|
||||||
|
UserKey = new byte[] { 9, 2 },
|
||||||
|
AdminKey = new byte[] { 2, 1 },
|
||||||
|
State = LockingState.Closed
|
||||||
|
}.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestEqualsFalse_AdminKey()
|
||||||
|
{
|
||||||
|
Assert.IsFalse(new LockInfo.Builder
|
||||||
|
{
|
||||||
|
Id = 2,
|
||||||
|
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
|
||||||
|
Seed = new byte[] { 1, 2 },
|
||||||
|
UserKey = new byte[] { 7, 2 },
|
||||||
|
AdminKey = new byte[] { 2, 1 },
|
||||||
|
State = LockingState.Closed
|
||||||
|
}.Build() == new LockInfo.Builder
|
||||||
|
{
|
||||||
|
Id = 2,
|
||||||
|
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
|
||||||
|
Seed = new byte[] { 1, 2 },
|
||||||
|
UserKey = new byte[] { 7, 2 },
|
||||||
|
AdminKey = new byte[] { 11, 1 },
|
||||||
|
State = LockingState.Closed
|
||||||
|
}.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestEqualsFalse_LockingState()
|
||||||
|
{
|
||||||
|
Assert.IsFalse(new LockInfo.Builder
|
||||||
|
{
|
||||||
|
Id = 2,
|
||||||
|
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
|
||||||
|
Seed = new byte[] { 1, 2 },
|
||||||
|
UserKey = new byte[] { 7, 2 },
|
||||||
|
AdminKey = new byte[] { 2, 1 },
|
||||||
|
State = LockingState.Closed
|
||||||
|
}.Build() == new LockInfo.Builder
|
||||||
|
{
|
||||||
|
Id = 2,
|
||||||
|
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
|
||||||
|
Seed = new byte[] { 1, 2 },
|
||||||
|
UserKey = new byte[] { 7, 2 },
|
||||||
|
AdminKey = new byte[] { 2, 1 },
|
||||||
|
State = LockingState.Open
|
||||||
|
}.Build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
53
TestShareeLib/Model/Bike/BluetoothLock/TestLockInfoHelper.cs
Normal file
53
TestShareeLib/Model/Bike/BluetoothLock/TestLockInfoHelper.cs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using TINK.Model.Bike.BluetoothLock;
|
||||||
|
using TINK.Services.BluetoothLock.Tdo;
|
||||||
|
|
||||||
|
namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestLockInfoHelper
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestUpdateById_State()
|
||||||
|
{
|
||||||
|
var locksInfo = new List<LockInfo> {
|
||||||
|
new LockInfo.Builder { Id = 12, Seed = new byte[] { 3, 5 }, UserKey = new byte[] {2, 1 }, State = LockingState.Unknown }.Build(),
|
||||||
|
new LockInfo.Builder { Id = 14, Seed = new byte[] { 3, 1 }, UserKey = new byte[] {2, 7 }, State = LockingState.Open }.Build(),
|
||||||
|
new LockInfo.Builder { Id = 3, Seed = new byte[] { 1, 5 }, UserKey = new byte[] {2, 9 }, State = LockingState.Closed }.Build(),
|
||||||
|
};
|
||||||
|
|
||||||
|
var locksInfoTdo = new List<LockInfoTdo> {
|
||||||
|
new LockInfoTdo.Builder { Id =14, State = LockitLockingState.Closed}.Build()
|
||||||
|
};
|
||||||
|
|
||||||
|
var resultList = locksInfo.UpdateById(locksInfoTdo);
|
||||||
|
|
||||||
|
var result = resultList.FirstOrDefault(x => x.Id == 14);
|
||||||
|
Assert.NotNull(result, "Target element was removed.");
|
||||||
|
Assert.AreEqual(LockingState.Closed, result.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestUpdateById_Guid()
|
||||||
|
{
|
||||||
|
var locksInfo = new List<LockInfo> {
|
||||||
|
new LockInfo.Builder { Id = 12, Seed = new byte[] { 3, 5 }, UserKey = new byte[] {2, 1 }, State = LockingState.Unknown }.Build(),
|
||||||
|
new LockInfo.Builder { Id = 14, Seed = new byte[] { 3, 1 }, UserKey = new byte[] {2, 7 }, State = LockingState.Open }.Build(),
|
||||||
|
new LockInfo.Builder { Id = 3, Seed = new byte[] { 1, 5 }, UserKey = new byte[] {2, 9 }, State = LockingState.Closed }.Build(),
|
||||||
|
};
|
||||||
|
|
||||||
|
var locksInfoTdo = new List<LockInfoTdo> {
|
||||||
|
new LockInfoTdo.Builder { Id =14, Guid = new System.Guid("00000000-0000-0000-0000-e57e6b9aee16"), State = LockitLockingState.Open}.Build()
|
||||||
|
};
|
||||||
|
|
||||||
|
var resultList = locksInfo.UpdateById(locksInfoTdo);
|
||||||
|
|
||||||
|
var result = resultList.FirstOrDefault(x => x.Id == 14);
|
||||||
|
Assert.NotNull(result, "Target element was removed.");
|
||||||
|
Assert.AreEqual(new Guid("00000000-0000-0000-0000-e57e6b9aee16"), result.Guid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using TINK.Model.Bike.BluetoothLock;
|
||||||
|
|
||||||
|
namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestLockInfoMutable
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestCtor()
|
||||||
|
{
|
||||||
|
var lockInfo = new LockInfoMutable(
|
||||||
|
1,
|
||||||
|
new Guid("00000000-0000-0000-0000-e57e6b9aee16"),
|
||||||
|
new byte[] { 1, 2, 3 }, // User key
|
||||||
|
new byte[] { 1, 23 }, // Admin key
|
||||||
|
new byte[] { 1, 12 }, // Seed
|
||||||
|
LockingState.Closed);
|
||||||
|
|
||||||
|
Assert.AreEqual(1, lockInfo.Id);
|
||||||
|
Assert.AreEqual(new Guid("00000000-0000-0000-0000-e57e6b9aee16"), lockInfo.Guid);
|
||||||
|
Assert.IsTrue((new byte[] { 1, 2, 3 }).SequenceEqual(lockInfo.UserKey));
|
||||||
|
Assert.IsTrue((new byte[] { 1, 23 }).SequenceEqual(lockInfo.AdminKey));
|
||||||
|
Assert.IsTrue((new byte[] { 1, 12 }).SequenceEqual(lockInfo.Seed));
|
||||||
|
Assert.AreEqual(LockingState.Closed, lockInfo.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSetGuid()
|
||||||
|
{
|
||||||
|
var lockInfo = new LockInfoMutable(1, new Guid(), new byte[] { 1, 2, 3 }, new byte[] { 1, 23 }, new byte[] { 1, 12 }, LockingState.Closed);
|
||||||
|
|
||||||
|
lockInfo.Guid = new Guid("00000000-0000-0000-0000-e57e6b9aee16");
|
||||||
|
Assert.AreEqual(new Guid("00000000-0000-0000-0000-e57e6b9aee16"), lockInfo.Guid);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestLoad()
|
||||||
|
{
|
||||||
|
|
||||||
|
var lockInfo = new LockInfoMutable(
|
||||||
|
2,
|
||||||
|
new Guid(),
|
||||||
|
new byte[] { 5, 4 }, // User key
|
||||||
|
new byte[] { 14, 223 }, // Admin key
|
||||||
|
new byte[] { 3, 4, 5 }, // Seed
|
||||||
|
LockingState.Closed);
|
||||||
|
|
||||||
|
lockInfo.Load(
|
||||||
|
1,
|
||||||
|
new Guid("00000000-0000-0000-0000-e57e6b9aee16"),
|
||||||
|
new byte[] { 1, 12 }, // Seed
|
||||||
|
new byte[] { 1, 2, 3 }, // User key)
|
||||||
|
new byte[] { 1, 23 });
|
||||||
|
|
||||||
|
Assert.AreEqual(1, lockInfo.Id);
|
||||||
|
Assert.AreEqual(new Guid("00000000-0000-0000-0000-e57e6b9aee16"), lockInfo.Guid);
|
||||||
|
Assert.IsTrue((new byte[] { 1, 2, 3 }).SequenceEqual(lockInfo.UserKey));
|
||||||
|
Assert.IsTrue((new byte[] { 1, 23 }).SequenceEqual(lockInfo.AdminKey));
|
||||||
|
Assert.IsTrue((new byte[] { 1, 12 }).SequenceEqual(lockInfo.Seed));
|
||||||
|
Assert.AreEqual(LockingState.Closed, lockInfo.State);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
46
TestShareeLib/Model/Bike/TestBike.cs
Normal file
46
TestShareeLib/Model/Bike/TestBike.cs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace TestTINKLib.Fixtures.ObjectTests.Bike
|
||||||
|
{
|
||||||
|
using TINK.Model.Bike;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class TestBike
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestConstruct()
|
||||||
|
{
|
||||||
|
var l_oBike = new Bike(43);
|
||||||
|
Assert.AreEqual(43, l_oBike.Id);
|
||||||
|
Assert.AreEqual(null, l_oBike.TypeOfBike);
|
||||||
|
Assert.AreEqual(null, l_oBike.WheelType);
|
||||||
|
|
||||||
|
l_oBike = new Bike(43, WheelType.Mono, TypeOfBike.Cargo);
|
||||||
|
|
||||||
|
Assert.AreEqual(43, l_oBike.Id);
|
||||||
|
Assert.AreEqual(TypeOfBike.Cargo, l_oBike.TypeOfBike);
|
||||||
|
Assert.AreEqual(WheelType.Mono, l_oBike.WheelType);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCompare()
|
||||||
|
{
|
||||||
|
var l_oBike1 = new Bike(43);
|
||||||
|
Assert.AreEqual(43, l_oBike1.Id);
|
||||||
|
Assert.AreEqual(null, l_oBike1.TypeOfBike);
|
||||||
|
Assert.AreEqual(null, l_oBike1.WheelType);
|
||||||
|
|
||||||
|
var l_oBike2 = new Bike(42, WheelType.Two, TypeOfBike.Allround);
|
||||||
|
Assert.IsFalse(l_oBike1 == l_oBike2);
|
||||||
|
|
||||||
|
l_oBike2 = new Bike(43, WheelType.Mono, TypeOfBike.Allround);
|
||||||
|
Assert.IsFalse(l_oBike1 == l_oBike2);
|
||||||
|
|
||||||
|
l_oBike2 = new Bike(43, WheelType.Two, TypeOfBike.Cargo);
|
||||||
|
Assert.IsFalse(l_oBike1 == l_oBike2);
|
||||||
|
|
||||||
|
l_oBike2 = new Bike(43, null, null);
|
||||||
|
Assert.IsTrue(l_oBike1 == l_oBike2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
TestShareeLib/Model/Bike/TestBikeCollection.cs
Normal file
22
TestShareeLib/Model/Bike/TestBikeCollection.cs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using TINK.Model.Bike;
|
||||||
|
|
||||||
|
|
||||||
|
namespace TestTINKLib
|
||||||
|
{
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class TestBikeCollection
|
||||||
|
{
|
||||||
|
/// <summary> Tests the member.</summary>
|
||||||
|
[Test]
|
||||||
|
public void TestConstruct()
|
||||||
|
{
|
||||||
|
var l_oColl = new BikeCollection();
|
||||||
|
|
||||||
|
Assert.AreEqual(0, l_oColl.Count);
|
||||||
|
Assert.IsNull(l_oColl.GetById(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
109
TestShareeLib/Model/Bike/TestBikeCollectionMutable.cs
Normal file
109
TestShareeLib/Model/Bike/TestBikeCollectionMutable.cs
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using TINK.Model.Bike;
|
||||||
|
using TINK.Model.Bikes.Bike;
|
||||||
|
using TINK.Model.State;
|
||||||
|
|
||||||
|
using BikeInfo = TINK.Model.Bike.BC.BikeInfo;
|
||||||
|
using BikeInfoMutable = TINK.Model.Bike.BC.BikeInfoMutable;
|
||||||
|
|
||||||
|
namespace TestTINKLib
|
||||||
|
{
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class TestBikeCollectionMutable
|
||||||
|
{
|
||||||
|
private class BikeInfoMutable : TINK.Model.Bike.BC.BikeInfoMutable
|
||||||
|
{
|
||||||
|
public BikeInfoMutable(
|
||||||
|
int id,
|
||||||
|
bool isDemo = false,
|
||||||
|
IEnumerable<string> group = null,
|
||||||
|
WheelType? wheelType = null,
|
||||||
|
TypeOfBike? typeOfBike = null,
|
||||||
|
string description = null,
|
||||||
|
int? currentStationId = null,
|
||||||
|
Uri operatorUri = null,
|
||||||
|
TariffDescription tariffDescription = null,
|
||||||
|
Func<DateTime> dateTimeProvider = null,
|
||||||
|
IStateInfo stateInfo = null) : base(id, isDemo, group, wheelType, typeOfBike, description, currentStationId, operatorUri, tariffDescription, dateTimeProvider, stateInfo)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Tests the member.</summary>
|
||||||
|
[Test]
|
||||||
|
public void TestAdd()
|
||||||
|
{
|
||||||
|
var l_oColl = new BikeCollectionMutable();
|
||||||
|
|
||||||
|
l_oColl.Add(new BikeInfoMutable(57, false, new List<string> { "TINK" }, WheelType.Two, TypeOfBike.Allround));
|
||||||
|
|
||||||
|
Assert.Throws<Exception>(() => l_oColl.Add(new BikeInfoMutable(57, false, new List<string> { "TINK" }, WheelType.Trike, TypeOfBike.Cargo)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestUpdate_Null()
|
||||||
|
{
|
||||||
|
var l_oBikeRequested = new BikeInfoMutable(20, false, new List<string> { "TINK" }, WheelType.Trike, TypeOfBike.Allround);
|
||||||
|
l_oBikeRequested.State.Load(new StateInfo(() => DateTime.Now, DateTime.Now, "john@long", "1234"));
|
||||||
|
|
||||||
|
var l_oBikeColl = new BikeCollectionMutable
|
||||||
|
{
|
||||||
|
new BikeInfoMutable(63, false, new List<string> { "TINK" }, WheelType.Two, TypeOfBike.Allround),
|
||||||
|
new BikeInfoMutable(57, false, new List<string> { "TINK" }, WheelType.Trike, TypeOfBike.Cargo),
|
||||||
|
l_oBikeRequested,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Verify initial state
|
||||||
|
Assert.NotNull(l_oBikeColl.GetById(63));
|
||||||
|
Assert.AreEqual(InUseStateEnum.Disposable, l_oBikeColl.GetById(57).State.Value);
|
||||||
|
Assert.AreEqual(InUseStateEnum.Reserved, l_oBikeColl.GetById(20).State.Value);
|
||||||
|
Assert.Null(l_oBikeColl.GetById(33));
|
||||||
|
|
||||||
|
l_oBikeColl.Update(null);
|
||||||
|
|
||||||
|
// Verify modified state
|
||||||
|
Assert.Null(l_oBikeColl.GetById(63));
|
||||||
|
Assert.Null(l_oBikeColl.GetById(57));
|
||||||
|
Assert.Null(l_oBikeColl.GetById(20));
|
||||||
|
Assert.Null(l_oBikeColl.GetById(33));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestUpdate()
|
||||||
|
{
|
||||||
|
var l_oBikeRequested = new BikeInfoMutable(20, false, new List<string> { "TINK" }, WheelType.Trike, TypeOfBike.Allround);
|
||||||
|
l_oBikeRequested.State.Load(new StateInfo(() => DateTime.Now, DateTime.Now, "john@long", "1234"));
|
||||||
|
|
||||||
|
var l_oBikeColl = new BikeCollectionMutable
|
||||||
|
{
|
||||||
|
new BikeInfoMutable(63, false, new List<string> { "TINK" }, WheelType.Two, TypeOfBike.Allround),
|
||||||
|
new BikeInfoMutable(57, false, new List<string> { "TINK" }, WheelType.Trike, TypeOfBike.Cargo),
|
||||||
|
l_oBikeRequested,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Verify initial state
|
||||||
|
Assert.NotNull(l_oBikeColl.GetById(63)); // Will be removed
|
||||||
|
Assert.AreEqual(InUseStateEnum.Disposable, l_oBikeColl.GetById(57).State.Value); // Will be requested
|
||||||
|
Assert.AreEqual(InUseStateEnum.Reserved, l_oBikeColl.GetById(20).State.Value); // Will be booked
|
||||||
|
Assert.Null(l_oBikeColl.GetById(33)); //
|
||||||
|
|
||||||
|
var l_oBikeResponse = new List<BikeInfo>
|
||||||
|
{
|
||||||
|
new BikeInfo(57, false, new List<string> {"TINK" }, WheelType.Trike, TypeOfBike.Allround, "Test description", 7, null /*operator uri*/, null, DateTime.Now, "john@long,", "1234"),
|
||||||
|
new BikeInfo(20, false, new List<string> {"TINK" }, WheelType.Trike, TypeOfBike.Allround, "Test description", 7, null /*operator uri*/, null, DateTime.Now, "john@long,", "1234"),
|
||||||
|
new BikeInfo(33, 7, null /*operator uri*/, null, false, new List<string> {"TINK" }, WheelType.Trike, TypeOfBike.Allround),
|
||||||
|
};
|
||||||
|
|
||||||
|
l_oBikeColl.Update(l_oBikeResponse);
|
||||||
|
|
||||||
|
// Verify modified state
|
||||||
|
Assert.Null(l_oBikeColl.GetById(63));
|
||||||
|
Assert.AreEqual(InUseStateEnum.Booked, l_oBikeColl.GetById(57).State.Value);
|
||||||
|
Assert.AreEqual(InUseStateEnum.Booked, l_oBikeColl.GetById(20).State.Value);
|
||||||
|
Assert.NotNull(l_oBikeColl.GetById(33));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
67
TestShareeLib/Model/Bike/TestBikeCollectionSerializeJSON.cs
Normal file
67
TestShareeLib/Model/Bike/TestBikeCollectionSerializeJSON.cs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
using TINK.Model.Bike;
|
||||||
|
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using TINK.Model.State;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using BikeInfoMutable = TINK.Model.Bike.BC.BikeInfoMutable;
|
||||||
|
|
||||||
|
namespace TestTINKLib
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Exclude from build beause serialization... see below.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
public class TestBikeCollectionSerializeJSON
|
||||||
|
{
|
||||||
|
[Test, Ignore("Disabled because serialization does no more work due to inheritance since commit ec14b93b.")]
|
||||||
|
public void Test_SerializeJSON()
|
||||||
|
{
|
||||||
|
var l_oCollSource = new BikeCollectionMutable
|
||||||
|
{
|
||||||
|
new BikeInfoMutable(57, false, new List<string> { "TINK" }, WheelType.Two, TypeOfBike.Allround)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Verify prerequisites.
|
||||||
|
Assert.AreEqual(1, l_oCollSource.Count);
|
||||||
|
Assert.AreEqual(57, l_oCollSource[0].Id);
|
||||||
|
Assert.AreEqual(InUseStateEnum.Disposable, l_oCollSource[0].State.Value);
|
||||||
|
Assert.IsNull(l_oCollSource[0].State.MailAddress);
|
||||||
|
Assert.IsNull(l_oCollSource[0].State.Code);
|
||||||
|
Assert.IsNull(l_oCollSource[0].State.From);
|
||||||
|
|
||||||
|
// Serialize object and verify json
|
||||||
|
var l_oDetected = JsonConvert.SerializeObject(l_oCollSource, Formatting.Indented, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto });
|
||||||
|
const string EXPECTED = @"
|
||||||
|
[
|
||||||
|
{
|
||||||
|
""Id"": 57,
|
||||||
|
""CurrentStation"": null,
|
||||||
|
""WheelType"": 1,
|
||||||
|
""TypeOfBike"": 0,
|
||||||
|
""State"": {
|
||||||
|
""StateInfoObject"": {
|
||||||
|
""$type"": ""TINK.Model.State.StateAvailableInfo, TINKLib""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]";
|
||||||
|
|
||||||
|
Assert.AreEqual(
|
||||||
|
TestHelper.PrepareXmlForStringCompare(EXPECTED),
|
||||||
|
TestHelper.PrepareXmlForStringCompare(l_oDetected));
|
||||||
|
|
||||||
|
// Deserialize object.
|
||||||
|
var l_oBikeCollectionTarget = JsonConvert.DeserializeObject<BikeCollectionMutable>(l_oDetected, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto });
|
||||||
|
|
||||||
|
// Verify state.
|
||||||
|
Assert.AreEqual(1, l_oBikeCollectionTarget.Count);
|
||||||
|
Assert.AreEqual(57, l_oBikeCollectionTarget[0].Id);
|
||||||
|
Assert.AreEqual(InUseStateEnum.Disposable, l_oBikeCollectionTarget[0].State.Value);
|
||||||
|
Assert.IsNull(l_oBikeCollectionTarget[0].State.MailAddress);
|
||||||
|
Assert.IsNull(l_oBikeCollectionTarget[0].State.Code);
|
||||||
|
Assert.IsNull(l_oBikeCollectionTarget[0].State.From);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using TINK.Model.State;
|
||||||
|
|
||||||
|
|
||||||
|
namespace TestTINKLib.Fixtures.Bike
|
||||||
|
{
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class TestStateBookedInfoSerializeJSON
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestSerializeJSON()
|
||||||
|
{
|
||||||
|
// Create object to test.
|
||||||
|
var l_oInfoSource = new StateOccupiedInfo(
|
||||||
|
new DateTime(2017, 09, 20, 23, 05, 0),
|
||||||
|
"Heinz@mueller",
|
||||||
|
"17 xxb");
|
||||||
|
|
||||||
|
// Serialize object and verify.
|
||||||
|
var l_oDetected = JsonConvert.SerializeObject(l_oInfoSource);
|
||||||
|
const string EXPECTED = @"
|
||||||
|
{
|
||||||
|
""From"":""2017 - 09 - 20T23: 05:00"",
|
||||||
|
""MailAddress"":""Heinz@mueller"",
|
||||||
|
""Code"":""17 xxb""
|
||||||
|
}";
|
||||||
|
Assert.AreEqual(
|
||||||
|
TestHelper.PrepareXmlForStringCompare(EXPECTED.Replace("\n", string.Empty).Replace("\r", string.Empty)),
|
||||||
|
TestHelper.PrepareXmlForStringCompare(l_oDetected.Replace("\n", string.Empty).Replace("\r", string.Empty)));
|
||||||
|
|
||||||
|
// Deserialize object and verify.
|
||||||
|
var l_oInfoTarget = JsonConvert.DeserializeObject<StateOccupiedInfo>(l_oDetected);
|
||||||
|
Assert.AreEqual(InUseStateEnum.Booked, l_oInfoTarget.Value);
|
||||||
|
Assert.AreEqual("Heinz@mueller", l_oInfoTarget.MailAddress);
|
||||||
|
Assert.AreEqual("17 xxb", l_oInfoTarget.Code);
|
||||||
|
Assert.AreEqual(new DateTime(2017, 9, 20, 23, 5, 0), l_oInfoTarget.From);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
86
TestShareeLib/Model/TestBikeCollectionFilter.cs
Normal file
86
TestShareeLib/Model/TestBikeCollectionFilter.cs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using TINK.Model;
|
||||||
|
using TINK.Model.Bike;
|
||||||
|
|
||||||
|
namespace TestTINKLib.Fixtures.ObjectTests.Bike
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestBikeCollectionFilter
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestGetAtStation()
|
||||||
|
{
|
||||||
|
var coll = new BikeCollection(
|
||||||
|
new Dictionary<int, TINK.Model.Bike.BC.BikeInfo>
|
||||||
|
{
|
||||||
|
{3, new TINK.Model.Bike.BC.BikeInfo(7, 3 /* Stadion id */) },
|
||||||
|
{7, new TINK.Model.Bike.BC.BikeInfo(8, 12 /* Stadion id */) },
|
||||||
|
{12, new TINK.Model.Bike.BC.BikeInfo(33, 12 /* Stadion id */) }
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.AreEqual(
|
||||||
|
0,
|
||||||
|
BikeCollectionFilter.GetAtStation(null, 12).Count);
|
||||||
|
|
||||||
|
Assert.AreEqual(
|
||||||
|
0,
|
||||||
|
coll.GetAtStation(null).Count);
|
||||||
|
|
||||||
|
Assert.AreEqual(
|
||||||
|
0,
|
||||||
|
coll.GetAtStation(22).Count);
|
||||||
|
|
||||||
|
Assert.AreEqual(
|
||||||
|
1,
|
||||||
|
coll.GetAtStation(3).Count);
|
||||||
|
|
||||||
|
Assert.AreEqual(
|
||||||
|
2,
|
||||||
|
coll.GetAtStation(12).Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestGetLockIt_Null()
|
||||||
|
{
|
||||||
|
Assert.That(
|
||||||
|
BikeCollectionFilter.GetLockIt(null).Count,
|
||||||
|
Is.EqualTo(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestGetLockIt_NoLockIt()
|
||||||
|
{
|
||||||
|
// Holds no LockIt bikes
|
||||||
|
var coll = new BikeCollection(
|
||||||
|
new Dictionary<int, TINK.Model.Bike.BC.BikeInfo>
|
||||||
|
{
|
||||||
|
{7, new TINK.Model.Bike.BC.BikeInfo(8, 12 /* Stadion id */) },
|
||||||
|
{12, new TINK.Model.Bike.BC.BikeInfo(33, 12 /* Stadion id */) }
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.AreEqual(
|
||||||
|
0,
|
||||||
|
coll.GetLockIt().Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestGetLockIt()
|
||||||
|
{
|
||||||
|
|
||||||
|
// Holds no LockIt bike with matching station number.
|
||||||
|
var coll = new BikeCollection(
|
||||||
|
new Dictionary<int, TINK.Model.Bike.BC.BikeInfo>
|
||||||
|
{
|
||||||
|
{7, new TINK.Model.Bike.BC.BikeInfo(8, 12 /* Stadion id */) },
|
||||||
|
{11, new TINK.Model.Bike.BluetoothLock.BikeInfo(33, 5200544, new Guid("00000000-0000-0000-0000-000000000001"),12 /* Stadion id */) },
|
||||||
|
{12, new TINK.Model.Bike.BC.BikeInfo(33, 12 /* Stadion id */) }
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.AreEqual(
|
||||||
|
1,
|
||||||
|
coll.GetLockIt().Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using TINK.Model.Repository.Response;
|
||||||
|
|
||||||
|
namespace TestTINKLib.Fixtures.ObjectTests.Bike
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestBikesAvailableResponse
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestDeserializeStationEmpty()
|
||||||
|
{
|
||||||
|
// Response for bike 231 is a real world answer.
|
||||||
|
var l_oBikes = JsonConvert.DeserializeObject<BikesAvailableResponse>(@"
|
||||||
|
{
|
||||||
|
""apiserver"" : ""https://app.tink-konstanz.de"",
|
||||||
|
""response"" : ""bikes_available"",
|
||||||
|
""bikes"" : {
|
||||||
|
""231"" : {
|
||||||
|
""bike"" : ""231"",
|
||||||
|
""description"" : ""Stadtrad"",
|
||||||
|
""system"" : ""BC"",
|
||||||
|
""bike_group"" : ""Konrad"",
|
||||||
|
""station"" : """",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""gps"" : ""9.1594501, 47.6749928""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""copri_version"" : ""3.0.0.0"",
|
||||||
|
""authcookie"" : """",
|
||||||
|
""response_state"" : ""OK""
|
||||||
|
}
|
||||||
|
");
|
||||||
|
|
||||||
|
Assert.IsNull(l_oBikes.bikes[231].station);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDeserializeStationInfoMissing()
|
||||||
|
{
|
||||||
|
// Response for bike 231 might not be real world answer.
|
||||||
|
var l_oBikes = JsonConvert.DeserializeObject<BikesAvailableResponse>(@"
|
||||||
|
{
|
||||||
|
""apiserver"" : ""https://app.tink-konstanz.de"",
|
||||||
|
""response"" : ""bikes_available"",
|
||||||
|
""bikes"" : {
|
||||||
|
""231"" : {
|
||||||
|
""bike"" : ""231"",
|
||||||
|
""description"" : ""Stadtrad"",
|
||||||
|
""system"" : ""BC"",
|
||||||
|
""bike_group"" : ""Konrad"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""gps"" : ""9.1594501, 47.6749928""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""copri_version"" : ""3.0.0.0"",
|
||||||
|
""authcookie"" : """",
|
||||||
|
""response_state"" : ""OK""
|
||||||
|
}
|
||||||
|
");
|
||||||
|
|
||||||
|
Assert.IsNull(l_oBikes.bikes[231].station);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
TestShareeLib/Repository/Response/TestJsonConvert.cs
Normal file
26
TestShareeLib/Repository/Response/TestJsonConvert.cs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
using TINK.Repository.Exception;
|
||||||
|
using TINK.Repository.Response;
|
||||||
|
|
||||||
|
namespace TestShareeLib.Model.Repository.Response
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestJsonConvert
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestDeserializeObject()
|
||||||
|
{
|
||||||
|
Assert.That(
|
||||||
|
() => JsonConvert.DeserializeObject<TariffDescription>(
|
||||||
|
@"{
|
||||||
|
""eur_per_hour"" : ""10.00"",
|
||||||
|
""abo_eur_per_month"" : ""920.00"",
|
||||||
|
""free_hours"" : ""3.00"",
|
||||||
|
""number"" : ""5494"",
|
||||||
|
-- this is not JSON !
|
||||||
|
""name"" : ""Tester Basic""
|
||||||
|
}"),
|
||||||
|
Throws.InstanceOf<DeserializationException>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
97
TestShareeLib/Repository/Response/TestTariffDescription.cs
Normal file
97
TestShareeLib/Repository/Response/TestTariffDescription.cs
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
using TINK.Repository.Response;
|
||||||
|
|
||||||
|
namespace TestShareeLib.Repository.Response
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestTariffDescription
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestDeserialize()
|
||||||
|
{
|
||||||
|
var tariffDescription = JsonConvert.DeserializeObject<TariffDescription>(
|
||||||
|
@"{
|
||||||
|
""eur_per_hour"" : ""10.00"",
|
||||||
|
""abo_eur_per_month"" : ""920.00"",
|
||||||
|
""free_hours"" : ""3.00"",
|
||||||
|
""number"" : ""5494"",
|
||||||
|
""name"" : ""Tester Basic""
|
||||||
|
}");
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
tariffDescription.eur_per_hour,
|
||||||
|
Is.EqualTo("10.00"));
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
tariffDescription.abo_eur_per_month,
|
||||||
|
Is.EqualTo("920.00"));
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
tariffDescription.free_hours,
|
||||||
|
Is.EqualTo("3.00"));
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
tariffDescription.number,
|
||||||
|
Is.EqualTo("5494"));
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
tariffDescription.name,
|
||||||
|
Is.EqualTo("Tester Basic"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verifies that missing elements are initialized correctly.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestDeserialize_Missing()
|
||||||
|
{
|
||||||
|
var tariffDescription = JsonConvert.DeserializeObject<TariffDescription>(
|
||||||
|
@"{
|
||||||
|
""number"" : ""5494"",
|
||||||
|
""name"" : ""Tester Basic""
|
||||||
|
}");
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
tariffDescription.eur_per_hour,
|
||||||
|
Is.Null);
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
tariffDescription.abo_eur_per_month,
|
||||||
|
Is.Null);
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
tariffDescription.free_hours,
|
||||||
|
Is.Null);
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
tariffDescription.number,
|
||||||
|
Is.EqualTo("5494"));
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
tariffDescription.name,
|
||||||
|
Is.EqualTo("Tester Basic"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verifies that unknown elemts in JSON to not lead to firing of exceptions.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestDeserialize_NewElement()
|
||||||
|
{
|
||||||
|
var tariffDescription = JsonConvert.DeserializeObject<TariffDescription>(
|
||||||
|
@"{
|
||||||
|
""number"" : ""5494"",
|
||||||
|
""name"" : ""Tester Basic"",
|
||||||
|
""FancyNewElement"" : ""Yeah""
|
||||||
|
}");
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
tariffDescription.number,
|
||||||
|
Is.EqualTo("5494"));
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
tariffDescription.name,
|
||||||
|
Is.EqualTo("Tester Basic"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
68
TestShareeLib/Services/TestServicesContainerMutable.cs
Normal file
68
TestShareeLib/Services/TestServicesContainerMutable.cs
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using TINK.Services;
|
||||||
|
|
||||||
|
namespace TestShareeLib.Services
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestServicesContainerMutable
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestCtor()
|
||||||
|
{
|
||||||
|
var typeA = new MyTypeA();
|
||||||
|
var typeB = new MyTypeB();
|
||||||
|
|
||||||
|
var serviceContainer = new ServicesContainerMutable<object>(
|
||||||
|
new List<object> { typeA, typeB, typeB },
|
||||||
|
typeA.GetType().FullName);
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
serviceContainer,
|
||||||
|
Is.EqualTo(new List<object> { typeA, typeB}).AsCollection);
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
serviceContainer.Active,
|
||||||
|
Is.EqualTo(typeA));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSetActive()
|
||||||
|
{
|
||||||
|
var typeA = new MyTypeA();
|
||||||
|
var typeB = new MyTypeB();
|
||||||
|
|
||||||
|
var serviceContainer = new ServicesContainerMutable<object>(
|
||||||
|
new List<object> { typeA, typeB },
|
||||||
|
typeA.GetType().FullName);
|
||||||
|
|
||||||
|
serviceContainer.SetActive(typeB.GetType().FullName);
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
serviceContainer.Active,
|
||||||
|
Is.EqualTo(typeB));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSetActiveNotExists()
|
||||||
|
{
|
||||||
|
var typeA = new MyTypeA();
|
||||||
|
var typeB = new MyTypeB();
|
||||||
|
|
||||||
|
var serviceContainer = new ServicesContainerMutable<object>(
|
||||||
|
new List<object> { typeA, typeB },
|
||||||
|
typeA.GetType().FullName);
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
() => serviceContainer.SetActive(new MyTypeC().GetType().FullName),
|
||||||
|
Throws.TypeOf<ArgumentException>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MyTypeA {}
|
||||||
|
|
||||||
|
private class MyTypeB { }
|
||||||
|
|
||||||
|
private class MyTypeC { }
|
||||||
|
}
|
||||||
|
}
|
18
TestShareeLib/TestHelper.cs
Normal file
18
TestShareeLib/TestHelper.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
namespace TestTINKLib
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides helper functionality. Used in TestShareeLib and TestTINKLib.
|
||||||
|
/// </summary>
|
||||||
|
public static class TestHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Eases comparison of xml- files.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="p_strXmlFile"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string PrepareXmlForStringCompare(string p_strXmlFile)
|
||||||
|
{
|
||||||
|
return p_strXmlFile.Replace("\r\n", string.Empty).Replace("\t", string.Empty).Replace(" ", string.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
TestShareeLib/TestShareeLib.csproj
Normal file
43
TestShareeLib/TestShareeLib.csproj
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Mocks\**" />
|
||||||
|
<Compile Remove="Model\Repository\**" />
|
||||||
|
<EmbeddedResource Remove="Mocks\**" />
|
||||||
|
<EmbeddedResource Remove="Model\Repository\**" />
|
||||||
|
<None Remove="Mocks\**" />
|
||||||
|
<None Remove="Model\Repository\**" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Model\Bike\BC\TestBikeSerializeJSON.cs" />
|
||||||
|
<Compile Remove="Model\Bike\TestBikeCollectionSerializeJSON.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="Model\Bike\BC\TestBikeSerializeJSON.cs" />
|
||||||
|
<None Include="Model\Bike\TestBikeCollectionSerializeJSON.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="NSubstitute" Version="4.2.2" />
|
||||||
|
<PackageReference Include="NUnit" Version="3.13.1" />
|
||||||
|
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\TINKLib\TINKLib.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Model\Connector\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
31
TestShareeLib/TestShareeLib.sln
Normal file
31
TestShareeLib/TestShareeLib.sln
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.31229.75
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestShareeLib", "TestShareeLib.csproj", "{FE15D644-F638-48B8-AD63-A3A9D01A8033}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TINKLib", "..\TINKLib\TINKLib.csproj", "{F3C0288B-7527-42B0-AA43-CC461766D6E1}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{FE15D644-F638-48B8-AD63-A3A9D01A8033}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{FE15D644-F638-48B8-AD63-A3A9D01A8033}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{FE15D644-F638-48B8-AD63-A3A9D01A8033}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{FE15D644-F638-48B8-AD63-A3A9D01A8033}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{F3C0288B-7527-42B0-AA43-CC461766D6E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{F3C0288B-7527-42B0-AA43-CC461766D6E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{F3C0288B-7527-42B0-AA43-CC461766D6E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{F3C0288B-7527-42B0-AA43-CC461766D6E1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {C3C5F7B8-9710-4F33-9FD9-D7DE9DE9ED29}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
|
@ -0,0 +1,963 @@
|
||||||
|
using NSubstitute;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TINK.Model.Bike.BluetoothLock;
|
||||||
|
using TINK.Model.Bikes.Bike.BluetoothLock;
|
||||||
|
using TINK.Model.Connector;
|
||||||
|
using TINK.Model.Repository.Exception;
|
||||||
|
using TINK.Services.BluetoothLock;
|
||||||
|
using TINK.Services.BluetoothLock.Exception;
|
||||||
|
using TINK.Services.BluetoothLock.Tdo;
|
||||||
|
using TINK.Model.Services.Geolocation;
|
||||||
|
using TINK.Model.State;
|
||||||
|
using TINK.View;
|
||||||
|
using TINK.ViewModel;
|
||||||
|
using TINK.ViewModel.Bikes;
|
||||||
|
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
|
||||||
|
using TINK.Model.User;
|
||||||
|
using TINK.Model.Repository.Request;
|
||||||
|
using TINK.Model.Repository.Response;
|
||||||
|
using TINK.Repository.Exception;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestBookedUnknown
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test construction of object.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void Testctor()
|
||||||
|
{
|
||||||
|
var handler = new BookedUnknown(
|
||||||
|
Substitute.For<IBikeInfoMutable>(),
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => Substitute.For<IConnector>(),
|
||||||
|
Substitute.For<IGeolocation>(),
|
||||||
|
Substitute.For<ILocksService>(),
|
||||||
|
() => Substitute.For<IPollingUpdateTaskManager>(),
|
||||||
|
Substitute.For<IViewService>(),
|
||||||
|
Substitute.For<IBikesViewModel>(),
|
||||||
|
Substitute.For<IUser>());
|
||||||
|
|
||||||
|
// Verify prerequisites.
|
||||||
|
Assert.AreEqual("Open lock & continue renting", handler.ButtonText);
|
||||||
|
Assert.IsTrue(handler.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Close lock", handler.LockitButtonText);
|
||||||
|
Assert.IsTrue(handler.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Opens lock
|
||||||
|
/// Final state: Booked opened.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestOpen()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new BookedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].OpenAsync()
|
||||||
|
.Returns(Task.FromResult((LockitLockingState?)LockitLockingState.Open)); // Return lock state indicating success
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Opening lock...";
|
||||||
|
locks.Received()[0].OpenAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "Reading charging level...";
|
||||||
|
locks[bike.Id].GetBatteryPercentageAsync();
|
||||||
|
bikesViewModel.ActionText = "Updating lock state...";
|
||||||
|
connector.Command.UpdateLockingStateAsync(bike, null);
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Closed" after action
|
||||||
|
Assert.AreEqual("Close lock & return bike", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Open lock
|
||||||
|
/// Final state: Same as initial state.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestOpenOpenFailsOutOfReachException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new BookedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].OpenAsync()
|
||||||
|
.Returns<Task<LockitLockingState?>>(x => throw new OutOfReachException());
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Closed);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Opening lock...";
|
||||||
|
locks.Received()[0].OpenAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
viewService.DisplayAlert("Lock can not be opened!", "Lock cannot be opened until bike is near.", "OK");
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Disconnected" after action
|
||||||
|
Assert.AreEqual(nameof(BookedDisconnected), subsequent.ButtonText);
|
||||||
|
Assert.IsFalse(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Open lock
|
||||||
|
/// Final state: Same as initial state.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestOpenOpenFailsCouldntOpenBoldBlockedException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new BookedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].OpenAsync()
|
||||||
|
.Returns<Task<LockitLockingState?>>(x => throw new CouldntOpenBoldBlockedException());
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Closed);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Opening lock...";
|
||||||
|
locks.Received()[0].OpenAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
viewService.DisplayAlert("Lock can not be opened!", "Lock is blocked. Please ensure that no obstacle prevents lock from opening and try again.", "OK");
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Unknown" after action
|
||||||
|
Assert.AreEqual("Open lock & continue renting", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Open lock
|
||||||
|
/// Final state: Same as initial state.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestOpenOpenFailsCouldntOpenInconsistentStateExecptionClosed()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new BookedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].OpenAsync()
|
||||||
|
.Returns<Task<LockitLockingState?>>(x => throw new CouldntOpenInconsistentStateExecption(LockingState.Closed));
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Closed);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Opening lock...";
|
||||||
|
locks.Received()[0].OpenAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
viewService.DisplayAlert("Lock can not be opened!", "After try to open lock state closed is reported.", "OK");
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Closed" after action
|
||||||
|
Assert.AreEqual("Return bike", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Open lock & continue renting", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Open lock
|
||||||
|
/// Final state: Same as initial state.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestOpenOpenFailsCouldntOpenInconsistentStateExecption()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new BookedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].OpenAsync()
|
||||||
|
.Returns<Task<LockitLockingState?>>(x => throw new CouldntOpenInconsistentStateExecption(LockingState.Unknown));
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Closed);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Opening lock...";
|
||||||
|
locks.Received()[0].OpenAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
viewService.DisplayAlert("Lock can not be opened!", "Lock reports unknown bold position.", "OK");
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Disconnected" after action
|
||||||
|
Assert.AreEqual("Open lock & continue renting", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Open lock
|
||||||
|
/// Final state: Same as initial state.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestOpenOpenFailsException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new BookedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].OpenAsync()
|
||||||
|
.Returns<Task<LockitLockingState?>>(x => throw new Exception("Exception message."));
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Closed);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Opening lock...";
|
||||||
|
locks.Received()[0].OpenAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
viewService.DisplayAlert("Lock can not be opened!", "Exception message.", "OK");
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Disconnected" after action
|
||||||
|
Assert.AreEqual(nameof(BookedDisconnected), subsequent.ButtonText);
|
||||||
|
Assert.IsFalse(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Open lock
|
||||||
|
/// Final state: Booked open.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestOpenUpdateLockingStateFailsWebConnectFailureException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new BookedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].OpenAsync()
|
||||||
|
.Returns(LockitLockingState.Open);
|
||||||
|
|
||||||
|
connector.Command.UpdateLockingStateAsync(bike, null).Returns(x => throw new WebConnectFailureException("Context info", new System.Exception("hoppla")));
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Open);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Opening lock...";
|
||||||
|
locks.Received()[0].OpenAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "Reading charging level...";
|
||||||
|
locks[bike.Id].GetBatteryPercentageAsync();
|
||||||
|
bikesViewModel.ActionText = "Updating lock state...";
|
||||||
|
connector.Command.UpdateLockingStateAsync(bike, null);
|
||||||
|
bikesViewModel.ActionText = "No web error on updating locking status.";
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Closed" after action
|
||||||
|
Assert.AreEqual("Close lock & return bike", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Open lock
|
||||||
|
/// Final state: Booked open.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestOpenUpdateLockingStateFailsException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new BookedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].OpenAsync()
|
||||||
|
.Returns(LockitLockingState.Open);
|
||||||
|
|
||||||
|
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()).Returns(x => throw new Exception("Exception message."));
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Open);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Opening lock...";
|
||||||
|
locks.Received()[0].OpenAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "Reading charging level...";
|
||||||
|
locks[bike.Id].GetBatteryPercentageAsync();
|
||||||
|
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 = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Closed" after action
|
||||||
|
Assert.AreEqual("Close lock & return bike", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Open lock
|
||||||
|
/// Final state: Booked open.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestOpenUpdateLockingStateFailsResponseException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new BookedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].OpenAsync()
|
||||||
|
.Returns(LockitLockingState.Open);
|
||||||
|
|
||||||
|
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()).Returns(x =>
|
||||||
|
throw new ReturnBikeException(JsonConvert.DeserializeObject<ReservationCancelReturnResponse>(@"{ ""response_text"" : ""Some invalid data received!""}"), "Outer message."));
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Open);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Opening lock...";
|
||||||
|
locks.Received()[0].OpenAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "Reading charging level...";
|
||||||
|
locks[bike.Id].GetBatteryPercentageAsync();
|
||||||
|
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 = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Closed" after action
|
||||||
|
Assert.AreEqual("Close lock & return bike", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Close lock
|
||||||
|
/// Final state: Booked closed.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestClose()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new BookedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].CloseAsync()
|
||||||
|
.Returns(Task.FromResult((LockitLockingState?)LockitLockingState.Closed)); // Return lock state indicating success
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption2().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Closing lock...";
|
||||||
|
locks.Received()[0].CloseAsync(); // Lock must be 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 = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Closed" after action
|
||||||
|
Assert.AreEqual("Return bike", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Open lock & continue renting", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Close lock
|
||||||
|
/// Final state: Same as initial state.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestCloseCloseFailsOutOfReachException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new BookedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].CloseAsync()
|
||||||
|
.Returns<Task<LockitLockingState?>>(x => throw new OutOfReachException());
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Open);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption2().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Closing lock...";
|
||||||
|
locks.Received()[0].CloseAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
viewService.DisplayAlert("Lock can not be closed!", "Lock cannot be closed until bike is near.", "OK");
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked disconnected" after action
|
||||||
|
Assert.AreEqual("BookedDisconnected", subsequent.ButtonText);
|
||||||
|
Assert.IsFalse(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Close lock
|
||||||
|
/// Final state: Same as initial state.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestCloseCloseFailsException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new BookedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].CloseAsync()
|
||||||
|
.Returns<Task<LockitLockingState?>>(x => throw new Exception("Exception message."));
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Open);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption2().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Closing lock...";
|
||||||
|
locks.Received()[0].CloseAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
viewService.DisplayAlert("Lock can not be closed!", "Exception message.", "OK");
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Disconnected" after action
|
||||||
|
Assert.AreEqual("BookedDisconnected", subsequent.ButtonText);
|
||||||
|
Assert.IsFalse(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Close lock
|
||||||
|
/// Final state: Booked closed.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestCloseUpdateLockingStateFailsWebConnectFailureException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new BookedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
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.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption2().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Closing lock...";
|
||||||
|
locks.Received()[0].CloseAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "Updating lock state...";
|
||||||
|
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
|
||||||
|
bikesViewModel.ActionText = "No web error on updating locking status.";
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Closed" after action
|
||||||
|
Assert.AreEqual("Return bike", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Open lock & continue renting", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: close lock
|
||||||
|
/// Final state: Booked closed.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestCloseUpdateLockingStateFailsException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new BookedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
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.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption2().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Closing lock...";
|
||||||
|
locks.Received()[0].CloseAsync(); // Lock must be 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 = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Closed" after action
|
||||||
|
Assert.AreEqual("Return bike", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Open lock & continue renting", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: close lock
|
||||||
|
/// Final state: Booked closed.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestCloseUpdateLockingStateFailsResponseException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new BookedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
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.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption2().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Closing lock...";
|
||||||
|
locks.Received()[0].CloseAsync(); // Lock must be 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 = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Closed" after action
|
||||||
|
Assert.AreEqual("Return bike", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Open lock & continue renting", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,961 @@
|
||||||
|
using NSubstitute;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TINK.Model.Bike.BluetoothLock;
|
||||||
|
using TINK.Model.Bikes.Bike.BluetoothLock;
|
||||||
|
using TINK.Model.Connector;
|
||||||
|
using TINK.Model.Repository.Exception;
|
||||||
|
using TINK.Services.BluetoothLock;
|
||||||
|
using TINK.Services.BluetoothLock.Exception;
|
||||||
|
using TINK.Services.BluetoothLock.Tdo;
|
||||||
|
using TINK.Model.Services.Geolocation;
|
||||||
|
using TINK.Model.State;
|
||||||
|
using TINK.View;
|
||||||
|
using TINK.ViewModel;
|
||||||
|
using TINK.ViewModel.Bikes;
|
||||||
|
using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
|
||||||
|
using TINK.Model.User;
|
||||||
|
using TINK.Model.Repository.Request;
|
||||||
|
using TINK.Model.Repository.Response;
|
||||||
|
using TINK.Repository.Exception;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||||
|
{
|
||||||
|
public class TestReservedUnknown
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestBookedUnknown
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test construction of object.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void Testctor()
|
||||||
|
{
|
||||||
|
var handler = new ReservedUnknown(
|
||||||
|
Substitute.For<IBikeInfoMutable>(),
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => Substitute.For<IConnector>(),
|
||||||
|
Substitute.For<IGeolocation>(),
|
||||||
|
Substitute.For<ILocksService>(),
|
||||||
|
() => Substitute.For<IPollingUpdateTaskManager>(),
|
||||||
|
Substitute.For<IViewService>(),
|
||||||
|
Substitute.For<IBikesViewModel>(),
|
||||||
|
Substitute.For<IUser>());
|
||||||
|
|
||||||
|
// Verify prerequisites.
|
||||||
|
Assert.AreEqual("Open lock & rent bike", handler.ButtonText);
|
||||||
|
Assert.IsFalse(handler.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Close lock", handler.LockitButtonText);
|
||||||
|
Assert.IsTrue(handler.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Opens lock
|
||||||
|
/// Final state: Booked opened.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestOpen()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new ReservedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].OpenAsync()
|
||||||
|
.Returns(Task.FromResult((LockitLockingState?)LockitLockingState.Open)); // Return lock state indicating success
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Opening lock...";
|
||||||
|
locks.Received()[0].OpenAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "Reading charging level...";
|
||||||
|
locks[bike.Id].GetBatteryPercentageAsync();
|
||||||
|
bikesViewModel.ActionText = "Updating lock state...";
|
||||||
|
connector.Command.UpdateLockingStateAsync(bike, null);
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Closed" after action
|
||||||
|
Assert.AreEqual("Close lock & return bike", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Open lock
|
||||||
|
/// Final state: Same as initial state.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestOpenOpenFailsOutOfReachException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new ReservedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].OpenAsync()
|
||||||
|
.Returns<Task<LockitLockingState?>>(x => throw new OutOfReachException());
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Closed);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Opening lock...";
|
||||||
|
locks.Received()[0].OpenAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
viewService.DisplayAlert("Lock can not be opened!", "Lock cannot be opened until bike is near.", "OK");
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Disconnected" after action
|
||||||
|
Assert.AreEqual(nameof(BookedDisconnected), subsequent.ButtonText);
|
||||||
|
Assert.IsFalse(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Open lock
|
||||||
|
/// Final state: Same as initial state.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestOpenOpenFailsCouldntOpenBoldBlockedException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new ReservedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].OpenAsync()
|
||||||
|
.Returns<Task<LockitLockingState?>>(x => throw new CouldntOpenBoldBlockedException());
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Closed);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Opening lock...";
|
||||||
|
locks.Received()[0].OpenAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
viewService.DisplayAlert("Lock can not be opened!", "Lock is blocked. Please ensure that no obstacle prevents lock from opening and try again.", "OK");
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Unknown" after action
|
||||||
|
Assert.AreEqual("Open lock & continue renting", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Open lock
|
||||||
|
/// Final state: Same as initial state.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestOpenOpenFailsCouldntOpenInconsistentStateExecptionClosed()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new ReservedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].OpenAsync()
|
||||||
|
.Returns<Task<LockitLockingState?>>(x => throw new CouldntOpenInconsistentStateExecption(LockingState.Closed));
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Closed);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Opening lock...";
|
||||||
|
locks.Received()[0].OpenAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
viewService.DisplayAlert("Lock can not be opened!", "After try to open lock state closed is reported.", "OK");
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Closed" after action
|
||||||
|
Assert.AreEqual("Return bike", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Open lock & continue renting", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Open lock
|
||||||
|
/// Final state: Same as initial state.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestOpenOpenFailsCouldntOpenInconsistentStateExecption()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new ReservedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].OpenAsync()
|
||||||
|
.Returns<Task<LockitLockingState?>>(x => throw new CouldntOpenInconsistentStateExecption(LockingState.Unknown));
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Closed);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Opening lock...";
|
||||||
|
locks.Received()[0].OpenAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
viewService.DisplayAlert("Lock can not be opened!", "Lock reports unknown bold position.", "OK");
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Disconnected" after action
|
||||||
|
Assert.AreEqual("Open lock & continue renting", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Open lock
|
||||||
|
/// Final state: Same as initial state.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestOpenOpenFailsException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new ReservedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].OpenAsync()
|
||||||
|
.Returns<Task<LockitLockingState?>>(x => throw new Exception("Exception message."));
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Closed);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Opening lock...";
|
||||||
|
locks.Received()[0].OpenAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
viewService.DisplayAlert("Lock can not be opened!", "Exception message.", "OK");
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Disconnected" after action
|
||||||
|
Assert.AreEqual(nameof(BookedDisconnected), subsequent.ButtonText);
|
||||||
|
Assert.IsFalse(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Open lock
|
||||||
|
/// Final state: Booked open.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestOpenUpdateLockingStateFailsWebConnectFailureException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new ReservedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].OpenAsync()
|
||||||
|
.Returns(LockitLockingState.Open);
|
||||||
|
|
||||||
|
connector.Command.UpdateLockingStateAsync(bike, null).Returns(x => throw new WebConnectFailureException("Context info", new System.Exception("hoppla")));
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Open);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Opening lock...";
|
||||||
|
locks.Received()[0].OpenAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "Reading charging level...";
|
||||||
|
locks[bike.Id].GetBatteryPercentageAsync();
|
||||||
|
bikesViewModel.ActionText = "Updating lock state...";
|
||||||
|
connector.Command.UpdateLockingStateAsync(bike, null);
|
||||||
|
bikesViewModel.ActionText = "No web error on updating locking status.";
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Closed" after action
|
||||||
|
Assert.AreEqual("Close lock & return bike", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Open lock
|
||||||
|
/// Final state: Booked open.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestOpenUpdateLockingStateFailsException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new ReservedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].OpenAsync()
|
||||||
|
.Returns(LockitLockingState.Open);
|
||||||
|
|
||||||
|
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()).Returns(x => throw new Exception("Exception message."));
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Open);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Opening lock...";
|
||||||
|
locks.Received()[0].OpenAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "Reading charging level...";
|
||||||
|
locks[bike.Id].GetBatteryPercentageAsync();
|
||||||
|
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 = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Closed" after action
|
||||||
|
Assert.AreEqual("Close lock & return bike", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Open lock
|
||||||
|
/// Final state: Booked open.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestOpenUpdateLockingStateFailsResponseException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new ReservedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].OpenAsync()
|
||||||
|
.Returns(LockitLockingState.Open);
|
||||||
|
|
||||||
|
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()).Returns(x =>
|
||||||
|
throw new ReturnBikeException(JsonConvert.DeserializeObject<ReservationCancelReturnResponse>(@"{ ""response_text"" : ""Some invalid data received!""}"), "Outer message."));
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Open);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Opening lock...";
|
||||||
|
locks.Received()[0].OpenAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "Reading charging level...";
|
||||||
|
locks[bike.Id].GetBatteryPercentageAsync();
|
||||||
|
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 = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Closed" after action
|
||||||
|
Assert.AreEqual("Close lock & return bike", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Close lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Close lock
|
||||||
|
/// Final state: Booked closed.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestClose()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new ReservedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].CloseAsync()
|
||||||
|
.Returns(Task.FromResult((LockitLockingState?)LockitLockingState.Closed)); // Return lock state indicating success
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption2().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Closing lock...";
|
||||||
|
locks.Received()[0].CloseAsync(); // Lock must be 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 = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Closed" after action
|
||||||
|
Assert.AreEqual("Return bike", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Open lock & continue renting", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCloseCloseFailsOutOfReachException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new ReservedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].CloseAsync()
|
||||||
|
.Returns<Task<LockitLockingState?>>(x => throw new OutOfReachException());
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Open);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption2().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Closing lock...";
|
||||||
|
locks.Received()[0].CloseAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
viewService.DisplayAlert("Lock can not be closed!", "Lock cannot be closed until bike is near.", "OK");
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked disconnected" after action
|
||||||
|
Assert.AreEqual("BookedDisconnected", subsequent.ButtonText);
|
||||||
|
Assert.IsFalse(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Close lock
|
||||||
|
/// Final state: Same as initial state.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestCloseCloseFailsException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new ReservedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
bikesViewModel,
|
||||||
|
activeUser);
|
||||||
|
|
||||||
|
locks[0].CloseAsync()
|
||||||
|
.Returns<Task<LockitLockingState?>>(x => throw new Exception("Exception message."));
|
||||||
|
|
||||||
|
bike.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
bike.LockInfo.State.Returns(LockingState.Open);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption2().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Closing lock...";
|
||||||
|
locks.Received()[0].CloseAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
viewService.DisplayAlert("Lock can not be closed!", "Exception message.", "OK");
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Disconnected" after action
|
||||||
|
Assert.AreEqual("BookedDisconnected", subsequent.ButtonText);
|
||||||
|
Assert.IsFalse(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Search lock", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: Close lock
|
||||||
|
/// Final state: Booked closed.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestCloseUpdateLockingStateFailsWebConnectFailureException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new ReservedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
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.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption2().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Closing lock...";
|
||||||
|
locks.Received()[0].CloseAsync(); // Lock must be closed
|
||||||
|
bikesViewModel.ActionText = "Updating lock state...";
|
||||||
|
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
|
||||||
|
bikesViewModel.ActionText = "No web error on updating locking status.";
|
||||||
|
bikesViewModel.ActionText = "Updating...";
|
||||||
|
pollingManager.StartUpdateAyncPeridically(); // polling must be restarted again
|
||||||
|
bikesViewModel.ActionText = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Closed" after action
|
||||||
|
Assert.AreEqual("Return bike", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Open lock & continue renting", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: close lock
|
||||||
|
/// Final state: Booked closed.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestCloseUpdateLockingStateFailsException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new ReservedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
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.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption2().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Closing lock...";
|
||||||
|
locks.Received()[0].CloseAsync(); // Lock must be 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 = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Closed" after action
|
||||||
|
Assert.AreEqual("Return bike", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Open lock & continue renting", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use case: close lock
|
||||||
|
/// Final state: Booked closed.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestCloseUpdateLockingStateFailsResponseException()
|
||||||
|
{
|
||||||
|
var bike = Substitute.For<IBikeInfoMutable>();
|
||||||
|
var connector = Substitute.For<IConnector>();
|
||||||
|
var command = Substitute.For<ICommand>();
|
||||||
|
var geolocation = Substitute.For<IGeolocation>();
|
||||||
|
var locks = Substitute.For<ILocksService>();
|
||||||
|
var pollingManager = Substitute.For<IPollingUpdateTaskManager>();
|
||||||
|
var viewService = Substitute.For<IViewService>();
|
||||||
|
var bikesViewModel = Substitute.For<IBikesViewModel>();
|
||||||
|
var activeUser = Substitute.For<IUser>();
|
||||||
|
|
||||||
|
var handler = new ReservedUnknown(
|
||||||
|
bike,
|
||||||
|
() => true, // isConnectedDelegate
|
||||||
|
(isConnexted) => connector,
|
||||||
|
geolocation,
|
||||||
|
locks,
|
||||||
|
() => pollingManager,
|
||||||
|
viewService,
|
||||||
|
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.State.Value.Returns(InUseStateEnum.Booked);
|
||||||
|
|
||||||
|
var subsequent = handler.HandleRequestOption2().Result;
|
||||||
|
|
||||||
|
// Verify behaviour
|
||||||
|
Received.InOrder(() =>
|
||||||
|
{
|
||||||
|
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
|
||||||
|
bikesViewModel.ActionText = "One moment please...";
|
||||||
|
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
|
||||||
|
bikesViewModel.ActionText = "Closing lock...";
|
||||||
|
locks.Received()[0].CloseAsync(); // Lock must be 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 = "";
|
||||||
|
bikesViewModel.Received(1).IsIdle = true; // GUI must be unlocked
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify state "Booked Closed" after action
|
||||||
|
Assert.AreEqual("Return bike", subsequent.ButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsButtonVisible);
|
||||||
|
Assert.AreEqual("Open lock & continue renting", subsequent.LockitButtonText);
|
||||||
|
Assert.IsTrue(subsequent.IsLockitButtonVisible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
121
TestShareeLib/ViewModel/Settings/TestServicesViewModel.cs
Normal file
121
TestShareeLib/ViewModel/Settings/TestServicesViewModel.cs
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace TINK.ViewModel.Settings
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestServicesViewModel
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestCtor()
|
||||||
|
{
|
||||||
|
var servicesViewModel = new ServicesViewModel(
|
||||||
|
new List<string> {
|
||||||
|
"ServiceA",
|
||||||
|
"ServiceB",
|
||||||
|
"ServiceB", // Dupes are removed
|
||||||
|
"ServiceC" },
|
||||||
|
new Dictionary<string, string> {
|
||||||
|
{ "ServiceA", "Top service of type A" },
|
||||||
|
{ "ServiceB", "Supertop service of type B" },
|
||||||
|
{ "OldsService", "This entry is discarded" }},
|
||||||
|
"ServiceB");
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
servicesViewModel.ServicesTextList,
|
||||||
|
Is.EqualTo(new List<string> {
|
||||||
|
"ServiceC",
|
||||||
|
"Supertop service of type B",
|
||||||
|
"Top service of type A" }).AsCollection);
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
servicesViewModel.Active,
|
||||||
|
Is.EqualTo("ServiceB"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCtorInvalidActive()
|
||||||
|
{
|
||||||
|
Assert.That(
|
||||||
|
() => new ServicesViewModel(
|
||||||
|
new List<string> { "ServiceA", "ServiceB", "ServiceB", "ServiceC" },
|
||||||
|
new Dictionary<string, string> { { "ServiceA", "Top service of type A" }, { "ServiceB", "Supertop service of type B" } },
|
||||||
|
"ServiceX"),
|
||||||
|
Throws.TypeOf<ArgumentException>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCtorInvalidServiceNames()
|
||||||
|
{
|
||||||
|
Assert.That(
|
||||||
|
() => new ServicesViewModel(
|
||||||
|
new List<string> { "ServiceA", "ServiceB", "ServiceC" },
|
||||||
|
new Dictionary<string, string> { { "ServiceA", "Top fast" }, { "ServiceB", "Top fast" } },
|
||||||
|
"ServiceB"),
|
||||||
|
Throws.TypeOf<ArgumentException>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestGetActiveTextDisplayTextAvailable()
|
||||||
|
{
|
||||||
|
var servicesViewModel = new ServicesViewModel(
|
||||||
|
new List<string> {
|
||||||
|
"ServiceB"},
|
||||||
|
new Dictionary<string, string> {
|
||||||
|
{ "ServiceB", "Supertop service of type B" }},
|
||||||
|
"ServiceB");
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
servicesViewModel.ActiveText,
|
||||||
|
Is.EqualTo("Supertop service of type B"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestGetActiveTextNoDisplayText()
|
||||||
|
{
|
||||||
|
var servicesViewModel = new ServicesViewModel(
|
||||||
|
new List<string> {
|
||||||
|
"ServiceB"},
|
||||||
|
new Dictionary<string, string>(),
|
||||||
|
"ServiceB");
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
servicesViewModel.ActiveText,
|
||||||
|
Is.EqualTo("ServiceB"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSetActiveText()
|
||||||
|
{
|
||||||
|
var servicesViewModel = new ServicesViewModel(
|
||||||
|
new List<string> {
|
||||||
|
"ServiceA",
|
||||||
|
"ServiceB" },
|
||||||
|
new Dictionary<string, string>(),
|
||||||
|
"ServiceB")
|
||||||
|
{
|
||||||
|
ActiveText = "ServiceA"
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
servicesViewModel.ActiveText,
|
||||||
|
Is.EqualTo("ServiceA"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSetActiveTextInvalid()
|
||||||
|
{
|
||||||
|
var servicesViewModel = new ServicesViewModel(
|
||||||
|
new List<string> {
|
||||||
|
"ServiceA",
|
||||||
|
"ServiceB" },
|
||||||
|
new Dictionary<string, string>(),
|
||||||
|
"ServiceB");
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
() => servicesViewModel.ActiveText = "ServiceX",
|
||||||
|
Throws.InstanceOf<ArgumentException>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue