sharee.bike-App/TestTINKLib/Fixtures/ObjectTests/ViewModel/TestMyBikesPageViewModel.cs

831 lines
44 KiB
C#
Raw Normal View History

2021-07-12 21:31:46 +02:00
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TestTINKLib.Mocks.Connector;
using TINK.Model;
using TINK.Model.Connector;
using TINK.Repository.Exception;
using TINK.View;
using TINK.Model.Services.CopriApi;
using TINK.Repository;
using static TINK.Repository.CopriCallsMemory;
using TINK.ViewModel.Map;
using TINK.ViewModel.Settings;
using Plugin.BLE.Abstractions.Contracts;
using TINK.Services.BluetoothLock;
using NSubstitute;
using TINK.Services.BluetoothLock.Tdo;
using TINK.ViewModel.MyBikes;
2021-11-07 19:42:59 +01:00
using TINK.Services.Permissions;
2021-07-12 21:31:46 +02:00
using Xamarin.Forms;
2022-04-10 17:38:34 +02:00
using TINK.Services.Geolocation;
2021-07-12 21:31:46 +02:00
using NSubstitute.ExceptionExtensions;
using TINK.Services;
using TINK.Model.Device;
2021-11-14 23:27:29 +01:00
using TestFramework.Model.Device;
using TestFramework.Repository;
using TestFramework.Model.User.Account;
using TestFramework.Model.Services.Geolocation;
2021-07-12 21:31:46 +02:00
namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
{
[TestFixture]
public class TestMyBikesPageViewModel
{
[Test]
public async Task TestConstruct_Droid()
{
var geolocation = Substitute.For<IServicesContainer<IGeolocation>>();
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
2021-11-07 19:42:59 +01:00
var permissions = Substitute.For<ILocationPermission>();
2021-07-12 21:31:46 +02:00
var bluetooth = Substitute.For<IBluetoothLE>();
locksService.TimeOut.Returns(timeOut);
timeOut.MultiConnect.Returns(new TimeSpan(0));
// Fake location permissions to be set
2021-11-07 19:42:59 +01:00
permissions.CheckStatusAsync().Returns(Task.FromResult(Status.Granted));
2021-07-12 21:31:46 +02:00
geolocation.Active.IsGeolcationEnabled.Returns(true); // Fake gps to be on
bluetooth.State.Returns(BluetoothState.On); // Fake bluetooth to be on
// Fake bluetooth answer for locks with id 2200545 and 2200537.
locksService.GetLocksStateAsync(Arg.Any<IEnumerable<LockInfoAuthTdo>>(), Arg.Any<TimeSpan>()).Returns(
new List<LockInfoTdo> {
{ new LockInfoTdo.Builder { Id = 2200545, State = LockitLockingState.Open }.Build() },
{ new LockInfoTdo.Builder { Id = 2200537, State = LockitLockingState.Closed }.Build() }
}
);
var tinkApp = new TinkApp(
new TINK.Model.Settings.Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { "TINK", FilterState.On }, { "Konrad", FilterState.Off } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { "TINK", FilterState.On }, { "Konrad", FilterState.On } }),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new TINK.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
2022-04-10 17:38:34 +02:00
new StoreMock(new TINK.Model.User.Account.Account("a@b", "123456789", false, "5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", new List<string> { "300001", "300029" })),
2021-07-12 21:31:46 +02:00
isConnectedFunc: () => true,
2022-04-10 17:38:34 +02:00
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), sessionCookie, mail, new CopriCallsMemory(SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: null,
locationServicesContainer: geolocation,
locksService: locksService, // Cipher
device: new DeviceMock(), // Permissions,
specialFolder: new SpecialFolderMock(),
cipher: null,
2021-07-12 21:31:46 +02:00
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var myBikes = new MyBikesPageViewModel(
tinkApp.ActiveUser,
permissions, /* permissions */
bluetooth, /* bluetooth */
Device.Android,
() => tinkApp.GetIsConnected(),
(isConnected) => tinkApp.GetConnector(isConnected),
geolocation.Active, // geolocation
locksService,
2022-01-04 18:59:16 +01:00
tinkApp.Stations,
2021-07-12 21:31:46 +02:00
tinkApp.Polling,
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
2022-01-22 18:30:23 +01:00
viewService,
url => { });
2021-07-12 21:31:46 +02:00
await myBikes.OnAppearing();
// Verify behaviour
Received.InOrder(() =>
{
2021-11-07 19:42:59 +01:00
permissions.CheckStatusAsync();
2021-07-12 21:31:46 +02:00
var glDummy = geolocation.Active.Received().IsGeolcationEnabled;
var btDummy = bluetooth.Received().State;
locksService.GetLocksStateAsync(Arg.Any<IEnumerable<LockInfoAuthTdo>>(), Arg.Any<TimeSpan>());
});
Assert.IsEmpty(myBikes.StatusInfoText);
Assert.AreEqual(2, myBikes.Count);
Assert.IsTrue(myBikes.IsIdle);
Assert.IsTrue(myBikes.IsBikesListVisible, "If there are any bikes, list must be visible.");
var bike1545 = myBikes.FirstOrDefault(x => x.Id == "1545") as TINK.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1537 = myBikes.FirstOrDefault(x => x.Id == "1537") as TINK.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
2022-01-04 18:59:16 +01:00
Assert.AreEqual($"Rented since {DateTime.Parse("2020-11-06 17:53:22.784681+01"):dd. MMMM HH:mm}.", bike1545.StateText);
Assert.AreEqual($"Rented since {DateTime.Parse("2020-10-12 08:38:12.374231+02"):dd. MMMM HH:mm}.", bike1537.StateText);
2021-07-12 21:31:46 +02:00
Assert.AreEqual("Close lock", bike1545.LockitButtonText);
Assert.AreEqual("Open lock & continue renting", bike1537.LockitButtonText);
Assert.IsFalse(myBikes.IsNoBikesOccupiedVisible);
Assert.IsEmpty(myBikes.NoBikesOccupiedText);
}
[Test]
public async Task TestConstruct_Droid_NoPermissions_OpenSettings()
{
var geolocation = Substitute.For<IServicesContainer<IGeolocation>>();
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
2021-11-07 19:42:59 +01:00
var permissions = Substitute.For<ILocationPermission>();
2021-07-12 21:31:46 +02:00
var bluetooth = Substitute.For<IBluetoothLE>();
locksService.TimeOut.Returns(timeOut);
timeOut.MultiConnect.Returns(new TimeSpan(0));
// Fake location permissions not to be set
2021-11-07 19:42:59 +01:00
permissions.CheckStatusAsync().Returns(Task.FromResult(Status.Denied));
2021-07-12 21:31:46 +02:00
// Fake anwser on question whether to open permissions dialog
viewService.DisplayAlert(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<string>(), Arg.Any<string>()).Returns(true);
locksService.GetLocksStateAsync(Arg.Any<IEnumerable<LockInfoAuthTdo>>(), Arg.Any<TimeSpan>()).Returns(
new List<LockInfoTdo> {
{ new LockInfoTdo.Builder { Id = 2200545, State = LockitLockingState.Open }.Build() },
{ new LockInfoTdo.Builder { Id = 2200537, State = LockitLockingState.Closed }.Build() }
}
);
var tinkApp = new TinkApp(
new TINK.Model.Settings.Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { "TINK", FilterState.On }, { "Konrad", FilterState.Off } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { "TINK", FilterState.On }, { "Konrad", FilterState.On } }),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new TINK.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
2022-01-04 18:59:16 +01:00
new StoreMock(new TINK.Model.User.Account.Account("a@b", "123456789", false, "5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", new List<string> { "300001", "300029" })),
2021-07-12 21:31:46 +02:00
isConnectedFunc: () => true,
2022-04-10 17:38:34 +02:00
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), sessionCookie, mail, new CopriCallsMemory(SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: null,
locationServicesContainer: geolocation,
locksService: locksService, // Cipher
device: new DeviceMock(), // Permissions,
specialFolder: new SpecialFolderMock(),
cipher: null,
2021-07-12 21:31:46 +02:00
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var myBikes = new MyBikesPageViewModel(
tinkApp.ActiveUser,
permissions, /* permissions */
bluetooth, /* bluetooth */
Device.Android,
() => tinkApp.GetIsConnected(),
(isConnected) => tinkApp.GetConnector(isConnected),
geolocation.Active, // geolocation
locksService,
2022-01-04 18:59:16 +01:00
tinkApp.Stations,
2021-07-12 21:31:46 +02:00
tinkApp.Polling,
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
2022-01-22 18:30:23 +01:00
viewService,
url => { });
2021-07-12 21:31:46 +02:00
await myBikes.OnAppearing();
// Verify behaviour
Received.InOrder(() =>
{
2021-11-07 19:42:59 +01:00
permissions.CheckStatusAsync();
2021-07-12 21:31:46 +02:00
var glDummy = geolocation.Active.Received().IsGeolcationEnabled;
2021-11-07 19:42:59 +01:00
permissions.RequestAsync(); // Ask user from permissions.
2021-07-12 21:31:46 +02:00
viewService.DisplayAlert(
"Hint",
"Please allow location sharing so that bike lock/locks can be managed.\r\nOpen sharing dialog?",
"Yes",
"No");
permissions.OpenAppSettings();
});
Assert.IsEmpty(myBikes.StatusInfoText);
Assert.AreEqual(2, myBikes.Count);
Assert.IsTrue(myBikes.IsIdle);
Assert.IsTrue(myBikes.IsBikesListVisible, "If there are any bikes, list must be visible.");
var bike1545 = myBikes.FirstOrDefault(x => x.Id == "1545") as TINK.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1537 = myBikes.FirstOrDefault(x => x.Id == "1537") as TINK.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
2022-01-04 18:59:16 +01:00
Assert.AreEqual($"Rented since {DateTime.Parse("2020-11-06 17:53:22.784681+01"):dd. MMMM HH:mm}.", bike1545.StateText);
Assert.AreEqual($"Rented since {DateTime.Parse("2020-10-12 08:38:12.374231+02"):dd. MMMM HH:mm}.", bike1537.StateText);
2021-07-12 21:31:46 +02:00
Assert.AreEqual("Search lock", bike1545.LockitButtonText);
Assert.AreEqual("Search lock", bike1537.LockitButtonText);
Assert.IsFalse(myBikes.IsNoBikesOccupiedVisible);
Assert.IsEmpty(myBikes.NoBikesOccupiedText);
}
[Test]
public async Task TestConstruct_Droid_NoPermissions()
{
var geolocation = Substitute.For<IServicesContainer<IGeolocation>>();
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
2021-11-07 19:42:59 +01:00
var permissions = Substitute.For<ILocationPermission>();
2021-07-12 21:31:46 +02:00
var bluetooth = Substitute.For<IBluetoothLE>();
locksService.TimeOut.Returns(timeOut);
timeOut.MultiConnect.Returns(new TimeSpan(0));
// Fake location permissions not to be set
2021-11-07 19:42:59 +01:00
permissions.CheckStatusAsync().Returns(Task.FromResult(Status.Denied));
2021-07-12 21:31:46 +02:00
permissions.OpenAppSettings().Throws<Exception>(); // Ensures that method is not called and fixture succeeds.
// Fake anwser on question whether to open permissions dialog
viewService.DisplayAlert(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<string>(), Arg.Any<string>()).Returns(false);
// Fake bluetooth answer for locks with id 2200545 and 2200537.
var lockInfoTdo = new List<LockInfoTdo> {
{ new LockInfoTdo.Builder { Id = 2200545, State = LockitLockingState.Open }.Build() },
{ new LockInfoTdo.Builder { Id = 2200537, State = LockitLockingState.Closed }.Build() }
};
locksService.GetLocksStateAsync(Arg.Any<IEnumerable<LockInfoAuthTdo>>(), Arg.Any<TimeSpan>()).Returns(lockInfoTdo);
var tinkApp = new TinkApp(
new TINK.Model.Settings.Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { "TINK", FilterState.On }, { "Konrad", FilterState.Off } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { "TINK", FilterState.On }, { "Konrad", FilterState.On } }),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new TINK.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
2022-01-04 18:59:16 +01:00
new StoreMock(new TINK.Model.User.Account.Account("a@b", "123456789", false, "5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", new List<string> { "300001", "300029" })),
2021-07-12 21:31:46 +02:00
isConnectedFunc: () => true,
2022-04-10 17:38:34 +02:00
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), sessionCookie, mail, new CopriCallsMemory(SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: null,
locationServicesContainer: geolocation,
locksService: locksService, // Cipher
device: new DeviceMock(), // Permissions,
specialFolder: new SpecialFolderMock(),
cipher: null,
2021-07-12 21:31:46 +02:00
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var myBikes = new MyBikesPageViewModel(
tinkApp.ActiveUser,
permissions, /* permissions */
bluetooth, /* bluetooth */
Device.Android,
() => tinkApp.GetIsConnected(),
(isConnected) => tinkApp.GetConnector(isConnected),
geolocation.Active, // geolocation
locksService,
2022-01-04 18:59:16 +01:00
tinkApp.Stations,
2021-07-12 21:31:46 +02:00
tinkApp.Polling,
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
2022-01-22 18:30:23 +01:00
viewService,
url => { });
2021-07-12 21:31:46 +02:00
await myBikes.OnAppearing();
// Verify behaviour
Received.InOrder(() =>
{
2021-11-07 19:42:59 +01:00
permissions.CheckStatusAsync();
2021-07-12 21:31:46 +02:00
var glDummy = geolocation.Active.Received().IsGeolcationEnabled;
2021-11-07 19:42:59 +01:00
permissions.RequestAsync(); // Ask user from permissions.
2021-07-12 21:31:46 +02:00
viewService.DisplayAlert(
"Hint",
"Please allow location sharing so that bike lock/locks can be managed.\r\nOpen sharing dialog?",
"Yes",
"No");
});
Assert.IsEmpty(myBikes.StatusInfoText);
Assert.AreEqual(2, myBikes.Count);
Assert.IsTrue(myBikes.IsIdle);
Assert.IsTrue(myBikes.IsBikesListVisible, "If there are any bikes, list must be visible.");
var bike1545 = myBikes.FirstOrDefault(x => x.Id == "1545") as TINK.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1537 = myBikes.FirstOrDefault(x => x.Id == "1537") as TINK.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
2022-01-04 18:59:16 +01:00
Assert.AreEqual($"Rented since {DateTime.Parse("2020-11-06 17:53:22.784681+01"):dd. MMMM HH:mm}.", bike1545.StateText);
Assert.AreEqual($"Rented since {DateTime.Parse("2020-10-12 08:38:12.374231+02"):dd. MMMM HH:mm}.", bike1537.StateText);
2021-07-12 21:31:46 +02:00
Assert.AreEqual("Search lock", bike1545.LockitButtonText);
Assert.AreEqual("Search lock", bike1537.LockitButtonText);
Assert.IsFalse(myBikes.IsNoBikesOccupiedVisible);
Assert.IsEmpty(myBikes.NoBikesOccupiedText);
}
[Test]
public async Task TestConstruct_Droid_GeolocationOff()
{
var geolocation = Substitute.For<IServicesContainer<IGeolocation>>();
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
2021-11-07 19:42:59 +01:00
var permissions = Substitute.For<ILocationPermission>();
2021-07-12 21:31:46 +02:00
var bluetooth = Substitute.For<IBluetoothLE>();
locksService.TimeOut.Returns(timeOut);
timeOut.MultiConnect.Returns(new TimeSpan(0));
// Fake location permissions to be set
2021-11-07 19:42:59 +01:00
permissions.CheckStatusAsync().Returns(Task.FromResult(Status.Granted));
2021-07-12 21:31:46 +02:00
geolocation.Active.IsGeolcationEnabled.Returns(false); // Fake gps to be off
// Fake bluetooth answer for locks with id 2200545 and 2200537.
locksService.GetLocksStateAsync(Arg.Any<IEnumerable<LockInfoAuthTdo>>(), Arg.Any<TimeSpan>()).Returns(
new List<LockInfoTdo> {
{ new LockInfoTdo.Builder { Id = 2200545, State = LockitLockingState.Open }.Build() },
{ new LockInfoTdo.Builder { Id = 2200537, State = LockitLockingState.Closed }.Build() }
}
);
var tinkApp = new TinkApp(
new TINK.Model.Settings.Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { "TINK", FilterState.On }, { "Konrad", FilterState.Off } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { "TINK", FilterState.On }, { "Konrad", FilterState.On } }),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new TINK.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
2022-01-04 18:59:16 +01:00
new StoreMock(new TINK.Model.User.Account.Account("a@b", "123456789", false, "5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", new List<string> { "300001", "300029" })),
2021-07-12 21:31:46 +02:00
isConnectedFunc: () => true,
2022-04-10 17:38:34 +02:00
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), sessionCookie, mail, new CopriCallsMemory(SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: null,
locationServicesContainer: geolocation,
locksService: locksService, // Cipher
device: new DeviceMock(), // Permissions,
specialFolder: new SpecialFolderMock(),
cipher: null,
2021-07-12 21:31:46 +02:00
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var myBikes = new MyBikesPageViewModel(
tinkApp.ActiveUser,
permissions, /* permissions */
bluetooth, /* bluetooth */
Device.Android,
() => tinkApp.GetIsConnected(),
(isConnected) => tinkApp.GetConnector(isConnected),
geolocation.Active, // geolocation
locksService,
2022-01-04 18:59:16 +01:00
tinkApp.Stations,
2021-07-12 21:31:46 +02:00
tinkApp.Polling,
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
2022-01-22 18:30:23 +01:00
viewService,
url => { });
2021-07-12 21:31:46 +02:00
await myBikes.OnAppearing();
// Verify behaviour
Received.InOrder(() =>
{
2021-11-07 19:42:59 +01:00
permissions.CheckStatusAsync();
2021-07-12 21:31:46 +02:00
var glDummy = geolocation.Active.Received().IsGeolcationEnabled;
viewService.DisplayAlert(
"Hint",
"Please activate location so that bike lock can be found!",
"OK");
});
Assert.IsEmpty(myBikes.StatusInfoText);
Assert.AreEqual(2, myBikes.Count);
Assert.IsTrue(myBikes.IsIdle);
Assert.IsTrue(myBikes.IsBikesListVisible, "If there are any bikes, list must be visible.");
var bike1545 = myBikes.FirstOrDefault(x => x.Id == "1545") as TINK.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1537 = myBikes.FirstOrDefault(x => x.Id == "1537") as TINK.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
2022-01-04 18:59:16 +01:00
Assert.AreEqual($"Rented since {DateTime.Parse("2020-11-06 17:53:22.784681+01"):dd. MMMM HH:mm}.", bike1545.StateText);
Assert.AreEqual($"Rented since {DateTime.Parse("2020-10-12 08:38:12.374231+02"):dd. MMMM HH:mm}.", bike1537.StateText);
2021-07-12 21:31:46 +02:00
Assert.AreEqual("Search lock", bike1545.LockitButtonText);
Assert.AreEqual("Search lock", bike1537.LockitButtonText);
Assert.IsFalse(myBikes.IsNoBikesOccupiedVisible);
Assert.IsEmpty(myBikes.NoBikesOccupiedText);
}
[Test]
public async Task TestConstruct_Droid_BluetoothOff()
{
var geolocation = Substitute.For<IServicesContainer<IGeolocation>>();
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
2021-11-07 19:42:59 +01:00
var permissions = Substitute.For<ILocationPermission>();
2021-07-12 21:31:46 +02:00
var bluetooth = Substitute.For<IBluetoothLE>();
locksService.TimeOut.Returns(timeOut);
timeOut.MultiConnect.Returns(new TimeSpan(0));
// Fake location permissions to be set
2021-11-07 19:42:59 +01:00
permissions.CheckStatusAsync().Returns(Task.FromResult(Status.Granted));
2021-07-12 21:31:46 +02:00
geolocation.Active.IsGeolcationEnabled.Returns(true); // Fake gps to be on
bluetooth.State.Returns(BluetoothState.Off); // Fake bluetooth to be off
var lockInfoTdo = new List<LockInfoTdo> {
{ new LockInfoTdo.Builder { Id = 2200545, State = LockitLockingState.Open }.Build() },
{ new LockInfoTdo.Builder { Id = 2200537, State = LockitLockingState.Closed }.Build() }
};
locksService.GetLocksStateAsync(Arg.Any<IEnumerable<LockInfoAuthTdo>>(), Arg.Any<TimeSpan>()).Returns(lockInfoTdo);
var tinkApp = new TinkApp(
new TINK.Model.Settings.Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { "TINK", FilterState.On }, { "Konrad", FilterState.Off } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { "TINK", FilterState.On }, { "Konrad", FilterState.On } }),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new TINK.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
2022-01-04 18:59:16 +01:00
new StoreMock(new TINK.Model.User.Account.Account("a@b", "123456789", false, "5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", new List<string> { "300001", "300029" })),
2021-07-12 21:31:46 +02:00
isConnectedFunc: () => true,
2022-04-10 17:38:34 +02:00
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), sessionCookie, mail, new CopriCallsMemory(SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: null,
locationServicesContainer: geolocation,
locksService: locksService, // Cipher
device: new DeviceMock(), // Permissions,
specialFolder: new SpecialFolderMock(),
cipher: null,
2021-07-12 21:31:46 +02:00
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var myBikes = new MyBikesPageViewModel(
tinkApp.ActiveUser,
permissions, /* permissions */
bluetooth, /* bluetooth */
Device.Android,
() => tinkApp.GetIsConnected(),
(isConnected) => tinkApp.GetConnector(isConnected),
geolocation.Active, // geolocation
locksService,
2022-01-04 18:59:16 +01:00
tinkApp.Stations,
2021-07-12 21:31:46 +02:00
tinkApp.Polling,
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
2022-01-22 18:30:23 +01:00
viewService,
url => { });
2021-07-12 21:31:46 +02:00
await myBikes.OnAppearing();
// Verify behaviour
Received.InOrder(() =>
{
2021-11-07 19:42:59 +01:00
permissions.CheckStatusAsync();
2021-07-12 21:31:46 +02:00
var glDummy = geolocation.Active.Received().IsGeolcationEnabled;
var btDummy = bluetooth.Received().State;
viewService.DisplayAlert(
"Hint",
"Please enable Bluetooth to manage bike lock/locks.",
"OK");
});
Assert.That(
myBikes.StatusInfoText,
Is.Empty,
"Status info text must be empty.");
2021-07-12 21:31:46 +02:00
Assert.AreEqual(2, myBikes.Count);
Assert.IsTrue(myBikes.IsIdle);
Assert.IsTrue(myBikes.IsBikesListVisible, "If there are any bikes, list must be visible.");
var bike1545 = myBikes.FirstOrDefault(x => x.Id == "1545") as TINK.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1537 = myBikes.FirstOrDefault(x => x.Id == "1537") as TINK.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
2022-01-04 18:59:16 +01:00
Assert.AreEqual($"Rented since {DateTime.Parse("2020-11-06 17:53:22.784681+01"):dd. MMMM HH:mm}.", bike1545.StateText);
Assert.AreEqual($"Rented since {DateTime.Parse("2020-10-12 08:38:12.374231+02"):dd. MMMM HH:mm}.", bike1537.StateText);
2021-07-12 21:31:46 +02:00
Assert.AreEqual("Search lock", bike1545.LockitButtonText);
Assert.AreEqual("Search lock", bike1537.LockitButtonText);
Assert.IsFalse(myBikes.IsNoBikesOccupiedVisible);
Assert.That(
myBikes.NoBikesOccupiedText,
Is.Empty,
"Label which informs that no bikes are reserved/ rented must be empty.");
2021-07-12 21:31:46 +02:00
}
[Test]
public async Task TestConstruct_NoBikesOccupied()
{
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
2021-11-07 19:42:59 +01:00
var permissions = Substitute.For<ILocationPermission>();
2021-07-12 21:31:46 +02:00
var bluetooth = Substitute.For<IBluetoothLE>();
locksService.TimeOut.Returns(timeOut);
timeOut.MultiConnect.Returns(new TimeSpan(0));
var tinkApp = new TinkApp(
new TINK.Model.Settings.Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { "TINK", FilterState.On }, { "Konrad", FilterState.Off } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { "TINK", FilterState.On }, { "Konrad", FilterState.On } }),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new TINK.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
2022-01-04 18:59:16 +01:00
new StoreMock(new TINK.Model.User.Account.Account("a@b", "123456789", false, "Invalid_SessionCookie", new List<string> { "TINK" })),
2022-04-10 17:38:34 +02:00
isConnectedFunc: () => true,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), sessionCookie, mail, new CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocation>>(),
locksService: locksService, // Cipher
device: new DeviceMock(),
specialFolder: new SpecialFolderMock(),
cipher: null,
2021-07-12 21:31:46 +02:00
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var myBikes = new MyBikesPageViewModel(
tinkApp.ActiveUser,
2021-11-07 19:42:59 +01:00
permissions, // Permissions,
2021-07-12 21:31:46 +02:00
bluetooth,
Device.iOS,
() => tinkApp.GetIsConnected(),
(isConnected) => tinkApp.GetConnector(isConnected),
new GeolocationMock(),
locksService,
2022-01-04 18:59:16 +01:00
tinkApp.Stations,
2021-07-12 21:31:46 +02:00
tinkApp.Polling,
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
2022-01-22 18:30:23 +01:00
viewService,
url => { });
2021-07-12 21:31:46 +02:00
await myBikes.OnAppearing();
Assert.IsTrue(new List<string> { "Updating...", string.Empty }.Contains(myBikes.StatusInfoText));
Assert.AreEqual(0, myBikes.Count);
Assert.IsTrue(myBikes.IsIdle);
Assert.IsFalse(myBikes.IsBikesListVisible, "If there are any bikes, list must be visible.");
Assert.IsTrue(myBikes.IsNoBikesOccupiedVisible);
Assert.AreEqual("Momentan sind keine Fahrräder auf Benutzer a@b reserviert/ gebucht.", myBikes.NoBikesOccupiedText);
}
[Test]
public async Task TestConstruct_Offline()
{
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
2021-11-07 19:42:59 +01:00
var permissions = Substitute.For<ILocationPermission>();
2021-07-12 21:31:46 +02:00
var bluetooth = Substitute.For<IBluetoothLE>();
locksService.TimeOut.Returns(timeOut);
timeOut.MultiConnect.Returns(new TimeSpan(0));
var tinkApp = new TinkApp(
new TINK.Model.Settings.Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { "TINK", FilterState.On }, { "Konrad", FilterState.Off } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { "TINK", FilterState.On }, { "Konrad", FilterState.On } }),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new TINK.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
2022-01-04 18:59:16 +01:00
new StoreMock(new TINK.Model.User.Account.Account("a@b", "123456789", false, "4da3044c8657a04ba60e2eaa753bc51a", new List<string> { "TINK" })),
2022-04-10 17:38:34 +02:00
isConnectedFunc: () => false,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), sessionCookie, mail, new CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: null,
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocation>>(),
locksService: locksService, // Cipher
device: new DeviceMock(), // Permissions
specialFolder: new SpecialFolderMock(),
cipher: null, // Offline
2021-07-12 21:31:46 +02:00
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var myBikes = new MyBikesPageViewModel(
tinkApp.ActiveUser,
2022-01-04 18:54:03 +01:00
permissions, // Permissions,
2021-07-12 21:31:46 +02:00
bluetooth,
Device.iOS,
() => tinkApp.GetIsConnected(),
(isConnected) => tinkApp.GetConnector(isConnected),
new GeolocationMock(),
locksService,
2022-01-04 18:59:16 +01:00
tinkApp.Stations,
2021-07-12 21:31:46 +02:00
tinkApp.Polling,
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
2022-01-22 18:30:23 +01:00
viewService,
url => { });
2021-07-12 21:31:46 +02:00
await myBikes.OnAppearing();
Assert.AreEqual("Offline.", myBikes.StatusInfoText);
Assert.AreEqual(2, myBikes.Count);
Assert.IsTrue(myBikes.IsIdle);
Assert.IsTrue(myBikes.IsBikesListVisible, "If there are any bikes, list must be visible.");
2022-04-25 22:15:15 +02:00
Assert.AreEqual("Rented since 28. November 13:06.", myBikes.FirstOrDefault(x => x.Id == "7").StateText);
Assert.AreEqual("Rented since 28. November 11:01.", myBikes.FirstOrDefault(x => x.Id == "8").StateText);
2021-07-12 21:31:46 +02:00
Assert.IsFalse(myBikes.IsNoBikesOccupiedVisible);
Assert.AreEqual(string.Empty, myBikes.NoBikesOccupiedText);
}
[Test]
public async Task TestTinkApp_WebConnectCommunicationError()
{
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
2021-11-07 19:42:59 +01:00
var permissions = Substitute.For<ILocationPermission>();
2021-07-12 21:31:46 +02:00
var bluetooth = Substitute.For<IBluetoothLE>();
locksService.TimeOut.Returns(timeOut);
timeOut.MultiConnect.Returns(new TimeSpan(0));
var tinkApp = new TinkApp(
new TINK.Model.Settings.Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { "TINK", FilterState.On }, { "Konrad", FilterState.Off } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { "TINK", FilterState.On }, { "Konrad", FilterState.On } }),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new TINK.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
2022-01-04 18:59:16 +01:00
new StoreMock(new TINK.Model.User.Account.Account("a@b", "123456789", false, "4da3044c8657a04ba60e2eaa753bc51a", new List<string> { "TINK" })),
2022-04-10 17:38:34 +02:00
isConnectedFunc: () => false,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new TINK.Model.Connector.Connector(
uri,
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
sessionCookie,
mail,
server: new CopriProviderHttps(
uri,
TinkApp.MerchantId,
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
sessionCookie: sessionCookie,
cacheServer: new CopriCallsCacheMemory(sessionCookie: sessionCookie),
httpsServer: new ExceptionServer((msg) => new WebConnectFailureException(msg, new Exception("Source expection."))))),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocation>>(),
locksService: locksService, // Cipher
device: new DeviceMock(),
specialFolder: new SpecialFolderMock(),
cipher: null, // Offline
2021-07-12 21:31:46 +02:00
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var myBikes = new MyBikesPageViewModel(
tinkApp.ActiveUser,
2022-01-04 18:54:03 +01:00
permissions, // Permissions,
2021-07-12 21:31:46 +02:00
bluetooth,
Device.iOS,
() => tinkApp.GetIsConnected(),
(isConnected) => tinkApp.GetConnector(isConnected),
new GeolocationMock(),
locksService,
2022-01-04 18:59:16 +01:00
tinkApp.Stations,
2021-07-12 21:31:46 +02:00
tinkApp.Polling,
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
2022-01-22 18:30:23 +01:00
viewService,
url => { })
2021-07-12 21:31:46 +02:00
{
IsReportLevelVerbose = true
};
await myBikes.OnAppearing();
Assert.AreEqual("Connection interrupted, server unreachable.", myBikes.StatusInfoText);
Assert.AreEqual(2, myBikes.Count);
Assert.IsTrue(myBikes.IsIdle);
Assert.IsTrue(myBikes.IsBikesListVisible, "If there are any bikes, list must be visible.");
2022-04-25 22:15:15 +02:00
Assert.AreEqual("Rented since 28. November 13:06.", myBikes.FirstOrDefault(x => x.Id == "7").StateText);
Assert.AreEqual("Rented since 28. November 11:01.", myBikes.FirstOrDefault(x => x.Id == "8").StateText);
2021-07-12 21:31:46 +02:00
Assert.IsFalse(myBikes.IsNoBikesOccupiedVisible);
Assert.AreEqual(string.Empty, myBikes.NoBikesOccupiedText);
}
[Test]
public async Task TestTinkApp_GeneralPurposeError()
{
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
2021-11-07 19:42:59 +01:00
var permissions = Substitute.For<ILocationPermission>();
2021-07-12 21:31:46 +02:00
var bluetooth = Substitute.For<IBluetoothLE>();
locksService.TimeOut.Returns(timeOut);
timeOut.MultiConnect.Returns(new TimeSpan(0));
var tinkApp = new TinkApp(
new TINK.Model.Settings.Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { "TINK", FilterState.On }, { "Konrad", FilterState.Off } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { "TINK", FilterState.On }, { "Konrad", FilterState.On } }),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new TINK.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
2022-01-04 18:59:16 +01:00
new StoreMock(new TINK.Model.User.Account.Account("a@b", "123456789", false, "4da3044c8657a04ba60e2eaa753bc51a", new List<string> { "TINK" })),
2022-04-10 17:38:34 +02:00
isConnectedFunc: () => false,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new TINK.Model.Connector.Connector(
uri,
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
sessionCookie,
mail,
server: new CopriProviderHttps(
uri,
TinkApp.MerchantId,
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
sessionCookie: sessionCookie,
cacheServer: new CopriCallsCacheMemory(sessionCookie: sessionCookie),
httpsServer: new ExceptionServer((msg) => new Exception(msg)))),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: null,
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocation>>(),
locksService: locksService, // Cipher
device: new DeviceMock(), // Permissions.
specialFolder: new SpecialFolderMock(),
cipher: null, // Offline
2021-07-12 21:31:46 +02:00
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var myBikes = new MyBikesPageViewModel(
tinkApp.ActiveUser,
2022-01-04 18:54:03 +01:00
permissions, // Permissions,
2021-07-12 21:31:46 +02:00
bluetooth,
Device.iOS,
() => tinkApp.GetIsConnected(),
(isConnected) => tinkApp.GetConnector(isConnected),
new GeolocationMock(),
locksService,
2022-01-04 18:59:16 +01:00
tinkApp.Stations,
2021-07-12 21:31:46 +02:00
tinkApp.Polling,
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
2022-01-22 18:30:23 +01:00
viewService,
url => { })
2021-07-12 21:31:46 +02:00
{
IsReportLevelVerbose = true
};
await myBikes.OnAppearing();
Assert.AreEqual("Connection interrupted.", myBikes.StatusInfoText);
Assert.AreEqual(2, myBikes.Count);
Assert.IsTrue(myBikes.IsIdle);
Assert.IsTrue(myBikes.IsBikesListVisible, "If there are any bikes, list must be visible.");
2022-04-25 22:15:15 +02:00
Assert.AreEqual("Rented since 28. November 13:06.", myBikes.FirstOrDefault(x => x.Id == "7").StateText);
Assert.AreEqual("Rented since 28. November 11:01.", myBikes.FirstOrDefault(x => x.Id == "8").StateText);
2021-07-12 21:31:46 +02:00
Assert.IsFalse(myBikes.IsNoBikesOccupiedVisible);
Assert.AreEqual(string.Empty, myBikes.NoBikesOccupiedText);
}
}
}