sharee.bike-App/SharedBusinessLogic.Tests/ViewModel/BikesAtStation/TestBikesAtStationPageViewModel.cs
2024-04-09 12:53:23 +02:00

1305 lines
60 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using NSubstitute;
using NSubstitute.ExceptionExtensions;
using NUnit.Framework;
using Plugin.BLE.Abstractions.Contracts;
using SharedBusinessLogic.Tests.Framework.Model.Device;
using SharedBusinessLogic.Tests.Framework.Model.Services.Geolocation;
using SharedBusinessLogic.Tests.Framework.Model.User.Account;
using SharedBusinessLogic.Tests.Framework.Repository;
using ShareeBike.Model;
using ShareeBike.Model.Connector;
using ShareeBike.Model.Device;
using ShareeBike.Model.Services.CopriApi;
using ShareeBike.Model.Settings;
using ShareeBike.Repository;
using ShareeBike.Repository.Exception;
using ShareeBike.Services;
using ShareeBike.Services.BluetoothLock;
using ShareeBike.Services.BluetoothLock.Tdo;
using ShareeBike.Services.Geolocation;
using ShareeBike.Services.Permissions;
using ShareeBike.View;
using ShareeBike.ViewModel.BikesAtStation;
using ShareeBike.ViewModel.Map;
using ShareeBike.ViewModel.Settings;
using Xamarin.Forms;
using static ShareeBike.Repository.CopriCallsMemory;
namespace SharedBusinessLogic.Tests.Fixtures.ObjectTests.ViewModel
{
[TestFixture]
public class TestBikesAtStationPageViewModel
{
[Test]
public async Task TestConstruct_Droid_NotLoggedIn()
{
var geolocation = Substitute.For<IServicesContainer<IGeolocationService>>();
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
var permissions = Substitute.For<ILocationPermission>();
var bluetooth = Substitute.For<IBluetoothLE>();
var shareeBikeApp = new ShareeBikeApp(
new Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.Off }, { FilterHelper.CITYBIKE, FilterState.On } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.On } }),
new StartupSettings(),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new ShareeBike.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
new StoreMock(new ShareeBike.Model.User.Account.Account("", null, false, null, new List<string>())),
isConnectedFunc: () => true,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory001(sessionCookie)),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: null,
locationServicesContainer: geolocation,
locksService: locksService, // Cipher
device: new DeviceMock(), // Permissions
specialFolder: new SpecialFolderMock(),
cipher: null,
theme: null,
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var bikesAtStation = new BikesAtStationPageViewModel(
shareeBikeApp.ActiveUser,
permissions,
bluetooth,
Device.Android,
new ShareeBike.Model.Stations.StationNS.Station("FR103", new List<string>(), null), // Was station id 103 before switching from data provider CopriCallsMemory(SampleSets.ShareeFr01_Set1, 1, ...)
() => shareeBikeApp.GetIsConnected(),
(isConnected) => shareeBikeApp.GetConnector(isConnected),
geolocation.Active, // geolocation
locksService,
shareeBikeApp.Polling,
(url) => { },
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
viewService);
await bikesAtStation.OnAppearingOrRefresh();
Assert.That(bikesAtStation.StatusInfoText, Is.Empty);
// Verify list of bikes
Assert.That(bikesAtStation.Count, Is.EqualTo(2));
Assert.That(bikesAtStation.IsIdle, Is.True);
Assert.That(bikesAtStation.IsBikesListVisible, Is.True, "If there are any bikes, list must be visible.");
var bikeFR9999 = bikesAtStation.FirstOrDefault(x => x.Id == "FR9999") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel; // Was id 1315
var bikeFR9998 = bikesAtStation.FirstOrDefault(x => x.Id == "FR9998") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel; // Was id 1543
Assert.That(
bikeFR9999,
Is.Not.Null);
Assert.That(
bikeFR9998,
Is.Not.Null);
Assert.That(bikeFR9999.StateText, Is.EqualTo("Available."));
Assert.That(bikeFR9998.StateText, Is.EqualTo("Available."));
Assert.That(bikeFR9999.LockitButtonText, Is.EqualTo("NotLoggedIn"));
Assert.That(bikeFR9998.LockitButtonText, Is.EqualTo("NotLoggedIn"));
// Login hint/ no bikes frame
Assert.That(bikesAtStation.IsLoginRequiredHintVisible, Is.True);
Assert.That(bikesAtStation.IsNoBikesAtStationVisible, Is.False);
Assert.That(bikesAtStation.NoBikesAtStationText, Is.EqualTo(string.Empty));
}
[Test]
public async Task TestConstruct_Droid_NoBikes()
{
var geolocation = Substitute.For<IServicesContainer<IGeolocationService>>();
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
var permissions = Substitute.For<ILocationPermission>();
var bluetooth = Substitute.For<IBluetoothLE>();
const string MERCH_ID = "MyMerchId";
var shareeBikeApp = new ShareeBikeApp(
new Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.Off } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.On } }),
new StartupSettings(),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new ShareeBike.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
new StoreMock(new ShareeBike.Model.User.Account.Account("a@b", "123456789", false, "5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", new List<string> { "300001", "300029" })),
isConnectedFunc: () => true,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory(MERCH_ID, 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,
theme: null,
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var bikesAtStation = new BikesAtStationPageViewModel(
shareeBikeApp.ActiveUser,
permissions,
bluetooth,
Device.Android,
new ShareeBike.Model.Stations.StationNS.Station("102", new List<string>(), null /* position*/, operatorUri: new Uri("https://shareeapp-fr01.copri.eu//APIjsonserver")), // Station 102
() => shareeBikeApp.GetIsConnected(),
(isConnected) => shareeBikeApp.GetConnector(isConnected),
geolocation.Active, // geolocation
locksService,
shareeBikeApp.Polling,
(url) => { },
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
viewService);
await bikesAtStation.OnAppearingOrRefresh();
Assert.That(bikesAtStation.StatusInfoText, Is.Empty);
// Verify list of bikes
Assert.That(bikesAtStation.Count, Is.EqualTo(0));
Assert.That(bikesAtStation.IsIdle, Is.True);
Assert.That(bikesAtStation.IsBikesListVisible, Is.False, "If there are any bikes, list must be visible.");
// Login hint/ no bikes frame
Assert.That(bikesAtStation.IsLoginRequiredHintVisible, Is.False);
Assert.That(bikesAtStation.IsNoBikesAtStationVisible, Is.True);
Assert.That(bikesAtStation.NoBikesAtStationText, Is.EqualTo("There are currently no bicycles available at this station."));
}
[Test]
public async Task TestConstruct_Droid()
{
var geolocation = Substitute.For<IServicesContainer<IGeolocationService>>();
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
var permissions = Substitute.For<ILocationPermission>();
var bluetooth = Substitute.For<IBluetoothLE>();
// Fake location permissions to be set
permissions.CheckStatusAsync().Returns(Task.FromResult(Status.Granted));
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() }
}
);
const string MERCH_ID = "MyMerchId";
var shareeBikeApp = new ShareeBikeApp(
new Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.Off } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.On } }),
new StartupSettings(),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new ShareeBike.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
new StoreMock(new ShareeBike.Model.User.Account.Account("a@b", "123456789", false, "5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", new List<string> { "300001", "300029" })),
isConnectedFunc: () => true,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo(MERCH_ID, "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory(MERCH_ID, SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
merchantId: MERCH_ID, // Instance geolocation mocks both parts
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: null,
locationServicesContainer: geolocation,
locksService: locksService, // Cipher
device: new DeviceMock(), // Permissions,
specialFolder: new SpecialFolderMock(),
cipher: null,
theme: null,
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var bikesAtStation = new BikesAtStationPageViewModel(
shareeBikeApp.ActiveUser,
permissions,
bluetooth,
Device.Android,
new ShareeBike.Model.Stations.StationNS.Station("103", new List<string>(), null), // Station 103
() => shareeBikeApp.GetIsConnected(),
(isConnected) => shareeBikeApp.GetConnector(isConnected),
geolocation.Active, // geolocation
locksService,
shareeBikeApp.Polling,
(url) => { },
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
viewService);
await bikesAtStation.OnAppearingOrRefresh();
// Verify behavior
Received.InOrder(() =>
{
permissions.CheckStatusAsync();
var glDummy = geolocation.Active.Received().IsGeolcationEnabled;
var btDummy = bluetooth.Received().State;
locksService.GetLocksStateAsync(Arg.Any<IEnumerable<LockInfoAuthTdo>>(), Arg.Any<TimeSpan>());
});
Assert.That(bikesAtStation.StatusInfoText, Is.Empty);
// Verify list of bikes
Assert.That(bikesAtStation.Count, Is.EqualTo(4));
Assert.That(bikesAtStation.IsIdle, Is.True);
Assert.That(bikesAtStation.IsBikesListVisible, Is.True, "If there are any bikes, list must be visible.");
var bike1545 = bikesAtStation.FirstOrDefault(x => x.Id == "1545") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1537 = bikesAtStation.FirstOrDefault(x => x.Id == "1537") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1315 = bikesAtStation.FirstOrDefault(x => x.Id == "1315") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1543 = bikesAtStation.FirstOrDefault(x => x.Id == "1543") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
Assert.That(
bike1545,
Is.Not.Null);
Assert.That(
bike1537,
Is.Not.Null);
Assert.That(
bike1315,
Is.Not.Null);
Assert.That(
bike1543,
Is.Not.Null);
Assert.That(bike1545.StateText, Is.EqualTo($"Rented since {DateTime.Parse("2020-11-06 17:53:22.784681+01"):dd. MMMM HH:mm}."));
Assert.That(bike1537.StateText, Is.EqualTo($"Rented since {DateTime.Parse("2020-10-12 08:38:12.374231+02"):dd. MMMM HH:mm}."));
Assert.That(bike1315.StateText, Is.EqualTo("Available."));
Assert.That(bike1543.StateText, Is.EqualTo("Available."));
Assert.That(bike1545.ButtonText, Is.EqualTo("Close lock"));
Assert.That(bike1545.LockitButtonText, Is.EqualTo("BookedOpen"));
Assert.That(bike1537.LockitButtonText, Is.EqualTo("Open lock"));
Assert.That(bike1315.LockitButtonText, Is.EqualTo("DisposableDisconnected"));
Assert.That(bike1543.LockitButtonText, Is.EqualTo("DisposableDisconnected"));
// Login hint/ no bikes frame
Assert.That(bikesAtStation.IsLoginRequiredHintVisible, Is.False);
Assert.That(bikesAtStation.IsNoBikesAtStationVisible, Is.False);
Assert.That(bikesAtStation.NoBikesAtStationText, Is.EqualTo(string.Empty));
}
[Test]
public async Task TestConstruct_Droid_NoPermissions_OpenSettings()
{
var geolocation = Substitute.For<IServicesContainer<IGeolocationService>>();
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
var permissions = Substitute.For<ILocationPermission>();
var bluetooth = Substitute.For<IBluetoothLE>();
// Fake location permissions not to be set
permissions.CheckStatusAsync().Returns(Task.FromResult(Status.Denied));
// 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);
// 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() }
}
);
bluetooth.State.Returns(BluetoothState.On);
const string MERCH_ID = "MyMerchId";
var shareeBikeApp = new ShareeBikeApp(
new Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.Off } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.On } }),
new StartupSettings(),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new ShareeBike.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
new StoreMock(new ShareeBike.Model.User.Account.Account("a@b", "123456789", false, "5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", new List<string> { "300001", "300029" })),
isConnectedFunc: () => true,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo(MERCH_ID, "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory(MERCH_ID, SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
merchantId: MERCH_ID,
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: null,
locationServicesContainer: geolocation,
locksService: locksService, // Cipher
device: new DeviceMock(), // Permissions,
specialFolder: new SpecialFolderMock(),
cipher: null,
theme: null,
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var bikesAtStation = new BikesAtStationPageViewModel(
shareeBikeApp.ActiveUser,
permissions,
bluetooth,
Device.Android,
new ShareeBike.Model.Stations.StationNS.Station("103", new List<string>(), null), // Station 103
() => shareeBikeApp.GetIsConnected(),
(isConnected) => shareeBikeApp.GetConnector(isConnected),
geolocation.Active, // geolocation
locksService,
shareeBikeApp.Polling,
(url) => { },
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
viewService);
await bikesAtStation.OnAppearingOrRefresh();
// Verify behavior
Received.InOrder(() =>
{
permissions.CheckStatusAsync();
var glDummy = geolocation.Active.Received().IsGeolcationEnabled;
// permissions.RequestAsync(); // Ask user from permissions (disabled, since no secondary request allowed).
viewService.DisplayAlert(
"Hint",
"Please allow location sharing so that bike lock/locks can be managed.\r\nOpen sharing dialog?",
"Yes",
"No");
permissions.OpenAppSettings();
});
Assert.That(new List<string> { "Updating...", string.Empty }.Contains(bikesAtStation.StatusInfoText), Is.True);
// Verify list of bikes
Assert.That(bikesAtStation.Count, Is.EqualTo(4));
Assert.That(bikesAtStation.IsIdle, Is.True);
Assert.That(bikesAtStation.IsBikesListVisible, Is.True, "If there are any bikes, list must be visible.");
var bike1545 = bikesAtStation.FirstOrDefault(x => x.Id == "1545") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1537 = bikesAtStation.FirstOrDefault(x => x.Id == "1537") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1315 = bikesAtStation.FirstOrDefault(x => x.Id == "1315") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1543 = bikesAtStation.FirstOrDefault(x => x.Id == "1543") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
Assert.That(
bike1545,
Is.Not.Null);
Assert.That(
bike1537,
Is.Not.Null);
Assert.That(
bike1315,
Is.Not.Null);
Assert.That(
bike1543,
Is.Not.Null);
Assert.That(bike1545.StateText, Is.EqualTo($"Rented since {DateTime.Parse("2020-11-06 17:53:22.784681+01"):dd. MMMM HH:mm}."));
Assert.That(bike1537.StateText, Is.EqualTo($"Rented since {DateTime.Parse("2020-10-12 08:38:12.374231+02"):dd. MMMM HH:mm}."));
Assert.That(bike1315.StateText, Is.EqualTo("Available."));
Assert.That(bike1543.StateText, Is.EqualTo("Available."));
Assert.That(bike1545.ButtonText, Is.EqualTo("Connect lock"));
Assert.That(bike1537.ButtonText, Is.EqualTo("Connect lock"));
Assert.That(bike1315.LockitButtonText, Is.EqualTo("DisposableDisconnected"));
Assert.That(bike1543.LockitButtonText, Is.EqualTo("DisposableDisconnected"));
// Login hint/ no bikes frame
Assert.That(bikesAtStation.IsLoginRequiredHintVisible, Is.False);
Assert.That(bikesAtStation.IsNoBikesAtStationVisible, Is.False);
Assert.That(bikesAtStation.NoBikesAtStationText, Is.EqualTo(string.Empty));
}
[Test]
public async Task TestConstruct_Droid_NoPermissions()
{
var geolocation = Substitute.For<IServicesContainer<IGeolocationService>>();
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
var permissions = Substitute.For<ILocationPermission>();
var bluetooth = Substitute.For<IBluetoothLE>();
// Fake location permissions not to be set
permissions.CheckStatusAsync().Returns(Task.FromResult(Status.Denied));
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.
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() }
}
);
const string MERCH_ID = "MyMerchId";
var shareeBikeApp = new ShareeBikeApp(
new Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.Off } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.On } }),
new StartupSettings(),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new ShareeBike.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
new StoreMock(new ShareeBike.Model.User.Account.Account("a@b", "123456789", false, "5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", new List<string> { "300001", "300029" })),
isConnectedFunc: () => true,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo(MERCH_ID, "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory(MERCH_ID, SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
merchantId: MERCH_ID,
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: null,
locationServicesContainer: geolocation,
locksService: locksService, // Cipher
device: new DeviceMock(), // Permissions,
specialFolder: new SpecialFolderMock(),
cipher: null,
theme: null,
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var bikesAtStation = new BikesAtStationPageViewModel(
shareeBikeApp.ActiveUser,
permissions,
bluetooth,
Device.Android,
new ShareeBike.Model.Stations.StationNS.Station("103", new List<string>(), null), // Station 103
() => shareeBikeApp.GetIsConnected(),
(isConnected) => shareeBikeApp.GetConnector(isConnected),
geolocation.Active, // geolocation
locksService,
shareeBikeApp.Polling,
(url) => { },
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
viewService);
await bikesAtStation.OnAppearingOrRefresh();
// Verify behavior
Received.InOrder(() =>
{
permissions.CheckStatusAsync();
var glDummy = geolocation.Active.Received().IsGeolcationEnabled;
//permissions.RequestAsync(); // Ask user from permissions (disabled, since no secondary request allowed).
viewService.DisplayAlert(
"Hint",
"Please allow location sharing so that bike lock/locks can be managed.\r\nOpen sharing dialog?",
"Yes",
"No");
});
Assert.That(bikesAtStation.StatusInfoText, Is.Empty);
// Verify list of bikes
Assert.That(bikesAtStation.Count, Is.EqualTo(4));
Assert.That(bikesAtStation.IsIdle, Is.True);
Assert.That(bikesAtStation.IsBikesListVisible, Is.True, "If there are any bikes, list must be visible.");
var bike1545 = bikesAtStation.FirstOrDefault(x => x.Id == "1545") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1537 = bikesAtStation.FirstOrDefault(x => x.Id == "1537") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1315 = bikesAtStation.FirstOrDefault(x => x.Id == "1315") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1543 = bikesAtStation.FirstOrDefault(x => x.Id == "1543") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
Assert.That(
bike1545,
Is.Not.Null);
Assert.That(
bike1537,
Is.Not.Null);
Assert.That(
bike1315,
Is.Not.Null);
Assert.That(
bike1543,
Is.Not.Null);
Assert.That(bike1545.StateText, Is.EqualTo($"Rented since {DateTime.Parse("2020-11-06 17:53:22.784681+01"):dd. MMMM HH:mm}."));
Assert.That(bike1537.StateText, Is.EqualTo($"Rented since {DateTime.Parse("2020-10-12 08:38:12.374231+02"):dd. MMMM HH:mm}."));
Assert.That(bike1315.StateText, Is.EqualTo("Available."));
Assert.That(bike1543.StateText, Is.EqualTo("Available."));
Assert.That(bike1545.ButtonText, Is.EqualTo("Connect lock"));
Assert.That(bike1537.ButtonText, Is.EqualTo("Connect lock"));
Assert.That(bike1315.LockitButtonText, Is.EqualTo("DisposableDisconnected"));
Assert.That(bike1543.LockitButtonText, Is.EqualTo("DisposableDisconnected"));
// Login hint/ no bikes frame
Assert.That(bikesAtStation.IsLoginRequiredHintVisible, Is.False);
Assert.That(bikesAtStation.IsNoBikesAtStationVisible, Is.False);
Assert.That(bikesAtStation.NoBikesAtStationText, Is.EqualTo(string.Empty));
}
[Test]
public async Task TestConstruct_Droid_GeolocationOff()
{
var geolocation = Substitute.For<IServicesContainer<IGeolocationService>>();
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
var permissions = Substitute.For<ILocationPermission>();
var bluetooth = Substitute.For<IBluetoothLE>();
// Fake location permissions to be set
permissions.CheckStatusAsync().Returns(Task.FromResult(Status.Granted));
geolocation.Active.IsGeolcationEnabled.Returns(false); // Fake gps to be off
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() }
}
);
const string MERCH_ID = "MyMerchId";
var shareeBikeApp = new ShareeBikeApp(
new Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.Off } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.On } }),
new StartupSettings(),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new ShareeBike.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
new StoreMock(new ShareeBike.Model.User.Account.Account("a@b", "123456789", false, "5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", new List<string> { "300001", "300029" })),
isConnectedFunc: () => true,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo(MERCH_ID, "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory(MERCH_ID, SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
merchantId: MERCH_ID,
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: null,
locationServicesContainer: geolocation,
locksService: locksService, // Cipher
device: new DeviceMock(), // Permissions,
specialFolder: new SpecialFolderMock(),
cipher: null,
theme: null,
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var bikesAtStation = new BikesAtStationPageViewModel(
shareeBikeApp.ActiveUser,
permissions,
bluetooth,
Device.Android,
new ShareeBike.Model.Stations.StationNS.Station("103", new List<string>(), null), // Station 103
() => shareeBikeApp.GetIsConnected(),
(isConnected) => shareeBikeApp.GetConnector(isConnected),
geolocation.Active, // geolocation
locksService,
shareeBikeApp.Polling,
(url) => { },
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
viewService);
await bikesAtStation.OnAppearingOrRefresh();
// Verify behavior
Received.InOrder(() =>
{
permissions.CheckStatusAsync();
var glDummy = geolocation.Active.Received().IsGeolcationEnabled;
viewService.DisplayAlert(
"Hint",
"Please activate location so that bike lock can be found!",
"OK");
});
Assert.That(bikesAtStation.StatusInfoText, Is.Empty);
// Verify list of bikes
Assert.That(bikesAtStation.Count, Is.EqualTo(4));
Assert.That(bikesAtStation.IsIdle, Is.True);
Assert.That(bikesAtStation.IsBikesListVisible, Is.True, "If there are any bikes, list must be visible.");
var bike1545 = bikesAtStation.FirstOrDefault(x => x.Id == "1545") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1537 = bikesAtStation.FirstOrDefault(x => x.Id == "1537") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1315 = bikesAtStation.FirstOrDefault(x => x.Id == "1315") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1543 = bikesAtStation.FirstOrDefault(x => x.Id == "1543") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
Assert.That(
bike1545,
Is.Not.Null);
Assert.That(
bike1537,
Is.Not.Null);
Assert.That(
bike1315,
Is.Not.Null);
Assert.That(
bike1543,
Is.Not.Null);
Assert.That(bike1545.StateText, Is.EqualTo($"Rented since {DateTime.Parse("2020-11-06 17:53:22.784681+01"):dd. MMMM HH:mm}."));
Assert.That(bike1537.StateText, Is.EqualTo($"Rented since {DateTime.Parse("2020-10-12 08:38:12.374231+02"):dd. MMMM HH:mm}."));
Assert.That(bike1315.StateText, Is.EqualTo("Available."));
Assert.That(bike1543.StateText, Is.EqualTo("Available."));
Assert.That(bike1545.ButtonText, Is.EqualTo("Connect lock"));
Assert.That(bike1537.ButtonText, Is.EqualTo("Connect lock"));
Assert.That(bike1315.LockitButtonText, Is.EqualTo("DisposableDisconnected"));
Assert.That(bike1543.LockitButtonText, Is.EqualTo("DisposableDisconnected"));
// Login hint/ no bikes frame
Assert.That(bikesAtStation.IsLoginRequiredHintVisible, Is.False);
Assert.That(bikesAtStation.IsNoBikesAtStationVisible, Is.False);
Assert.That(bikesAtStation.NoBikesAtStationText, Is.EqualTo(string.Empty));
}
[Test]
public async Task TestConstruct_Droid_BluetoothOff()
{
var geolocation = Substitute.For<IServicesContainer<IGeolocationService>>();
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
var permissions = Substitute.For<ILocationPermission>();
var bluetooth = Substitute.For<IBluetoothLE>();
// Fake location permissions to be set
permissions.CheckStatusAsync().Returns(Task.FromResult(Status.Granted));
geolocation.Active.IsGeolcationEnabled.Returns(true); // Fake gps to be on
bluetooth.State.Returns(BluetoothState.Off); // // Fake bluetooth 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() }
}
);
const string MERCH_ID = "MyMerchId";
var shareeBikeApp = new ShareeBikeApp(
new Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.Off } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.On } }),
new StartupSettings(),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new ShareeBike.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
new StoreMock(new ShareeBike.Model.User.Account.Account("a@b", "123456789", false, "5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", new List<string> { "300001", "300029" })),
isConnectedFunc: () => true,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo(MERCH_ID, "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory(MERCH_ID, SampleSets.ShareeFr01_Set1, 1, sessionCookie)),
merchantId: MERCH_ID,
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: null,
locationServicesContainer: geolocation,
locksService: locksService, // Cipher
device: new DeviceMock(), // Permissions,
specialFolder: new SpecialFolderMock(),
cipher: null,
theme: null,
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var bikesAtStation = new BikesAtStationPageViewModel(
shareeBikeApp.ActiveUser,
permissions,
bluetooth,
Device.Android,
new ShareeBike.Model.Stations.StationNS.Station("103", new List<string>(), null), // Station 103
() => shareeBikeApp.GetIsConnected(),
(isConnected) => shareeBikeApp.GetConnector(isConnected),
geolocation.Active, // geolocation
locksService,
shareeBikeApp.Polling,
(url) => { },
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
viewService);
await bikesAtStation.OnAppearingOrRefresh();
// Verify behavior
Received.InOrder(() =>
{
permissions.CheckStatusAsync();
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(bikesAtStation.StatusInfoText, Is.Empty);
// Verify list of bikes
Assert.That(bikesAtStation.Count, Is.EqualTo(4));
Assert.That(bikesAtStation.IsIdle, Is.True);
Assert.That(bikesAtStation.IsBikesListVisible, Is.True, "If there are any bikes, list must be visible.");
var bike1545 = bikesAtStation.FirstOrDefault(x => x.Id == "1545") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1537 = bikesAtStation.FirstOrDefault(x => x.Id == "1537") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1315 = bikesAtStation.FirstOrDefault(x => x.Id == "1315") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
var bike1543 = bikesAtStation.FirstOrDefault(x => x.Id == "1543") as ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
Assert.That(
bike1545,
Is.Not.Null);
Assert.That(
bike1537,
Is.Not.Null);
Assert.That(
bike1315,
Is.Not.Null);
Assert.That(
bike1543,
Is.Not.Null);
Assert.That(bike1545.StateText, Is.EqualTo($"Rented since {DateTime.Parse("2020-11-06 17:53:22.784681+01"):dd. MMMM HH:mm}."));
Assert.That(bike1537.StateText, Is.EqualTo($"Rented since {DateTime.Parse("2020-10-12 08:38:12.374231+02"):dd. MMMM HH:mm}."));
Assert.That(bike1315.StateText, Is.EqualTo("Available."));
Assert.That(bike1543.StateText, Is.EqualTo("Available."));
Assert.That(bike1545.ButtonText, Is.EqualTo("Connect lock"));
Assert.That(bike1537.ButtonText, Is.EqualTo("Connect lock"));
Assert.That(bike1315.LockitButtonText, Is.EqualTo("DisposableDisconnected"));
Assert.That(bike1543.LockitButtonText, Is.EqualTo("DisposableDisconnected"));
// Login hint/ no bikes frame
Assert.That(bikesAtStation.IsLoginRequiredHintVisible, Is.False);
Assert.That(bikesAtStation.IsNoBikesAtStationVisible, Is.False);
Assert.That(bikesAtStation.NoBikesAtStationText, Is.EqualTo(string.Empty));
}
[Test]
public async Task TestConstructCitybike()
{
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
var permissions = Substitute.For<ILocationPermission>();
var bluetooth = Substitute.For<IBluetoothLE>();
bluetooth.State.Returns(BluetoothState.On);
locksService.TimeOut.Returns(timeOut);
timeOut.MultiConnect.Returns(new TimeSpan(0));
const string MERCH_ID = "MyMerchId";
var shareeBikeApp = new ShareeBikeApp(
new Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.Off } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.On } }),
new StartupSettings(),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new ShareeBike.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
new StoreMock(),
isConnectedFunc: () => true,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo(MERCH_ID, "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory001(sessionCookie)),
merchantId: MERCH_ID,
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: locksService, // Cipher
device: new DeviceMock(),
specialFolder: new SpecialFolderMock(),
cipher: null,
theme: null,
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var bikesAtStation = new BikesAtStationPageViewModel(
shareeBikeApp.ActiveUser,
permissions,
bluetooth,
Device.iOS,
new ShareeBike.Model.Stations.StationNS.Station("FR101", new List<string>(), null), // Was 31 before switching CopriCallsMemory(SampleSets.Set2, 1, ...)
() => shareeBikeApp.GetIsConnected(),
(isConnected) => shareeBikeApp.GetConnector(isConnected),
new GeolocationMock(),
locksService,
shareeBikeApp.Polling,
(url) => { },
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
viewService);
await bikesAtStation.OnAppearingOrRefresh();
Assert.That(new List<string> { "Updating...", string.Empty }.Contains(bikesAtStation.StatusInfoText), Is.True);
// Verify list of bikes
Assert.That(bikesAtStation.Count, Is.EqualTo(3)); // Was 1 before switch.
Assert.That(bikesAtStation.IsIdle, Is.True);
Assert.That(bikesAtStation.IsBikesListVisible, Is.True, "If there are any bikes, list must be visible.");
Assert.That(bikesAtStation.FirstOrDefault(x => x.Id == "FR1003").StateText, Is.EqualTo("Available.")); // Was 52 before switch.
Assert.That(bikesAtStation.FirstOrDefault(x => x.Id == "FR1002").StateText, Is.EqualTo("Available."));
Assert.That(bikesAtStation.FirstOrDefault(x => x.Id == "FR1001").StateText, Is.EqualTo("Available."));
// Login hint/ no bikes frame
Assert.That(bikesAtStation.IsLoginRequiredHintVisible, Is.True);
Assert.That(bikesAtStation.IsNoBikesAtStationVisible, Is.False);
Assert.That(bikesAtStation.NoBikesAtStationText, Is.EqualTo(string.Empty));
}
[Test]
public async Task TestConstructCitybike_NoBikes()
{
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
var permissions = Substitute.For<ILocationPermission>();
var bluetooth = Substitute.For<IBluetoothLE>();
bluetooth.State.Returns(BluetoothState.On);
locksService.TimeOut.Returns(timeOut);
timeOut.MultiConnect.Returns(new TimeSpan(0));
const string MERCH_ID = "MyMerchId";
var shareeBikeApp = new ShareeBikeApp(
new Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.Off }, { FilterHelper.CITYBIKE, FilterState.On } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.On } }),
new StartupSettings(),
new Uri("https://tinkwwp.copri-bike.de/APIjsonserver"),
new ShareeBike.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
new StoreMock(),
isConnectedFunc: () => true,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory(MERCH_ID, SampleSets.Set2, 1, sessionCookie)),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: locksService, // Cipher
device: new DeviceMock(),
specialFolder: new SpecialFolderMock(),
cipher: null,
theme: null,
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var bikesAtStation = new BikesAtStationPageViewModel(
shareeBikeApp.ActiveUser,
permissions,
bluetooth,
Device.iOS,
new ShareeBike.Model.Stations.StationNS.Station("4", new List<string>(), null),
() => shareeBikeApp.GetIsConnected(),
(isConnected) => shareeBikeApp.GetConnector(isConnected),
new GeolocationMock(),
locksService,
shareeBikeApp.Polling,
(url) => { },
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
viewService);
await bikesAtStation.OnAppearingOrRefresh();
Assert.That(new List<string> { "Updating...", string.Empty }.Contains(bikesAtStation.StatusInfoText), Is.True);
// Verify list of bikes
Assert.That(bikesAtStation.Count, Is.EqualTo(0));
Assert.That(bikesAtStation.IsIdle, Is.True);
Assert.That(bikesAtStation.IsBikesListVisible, Is.False, "If there are any bikes, list must be visible.");
// Login hint/ no bikes frame
Assert.That(bikesAtStation.IsLoginRequiredHintVisible, Is.False);
Assert.That(bikesAtStation.IsNoBikesAtStationVisible, Is.True);
Assert.That(bikesAtStation.NoBikesAtStationText, Is.EqualTo("There are currently no bicycles available at this station."));
}
[Test]
public async Task TestConstruct_LoggedIn()
{
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
var permissions = Substitute.For<ILocationPermission>();
var bluetooth = Substitute.For<IBluetoothLE>();
bluetooth.State.Returns(BluetoothState.On);
locksService.TimeOut.Returns(timeOut);
timeOut.MultiConnect.Returns(new TimeSpan(0));
var shareeBikeApp = new ShareeBikeApp(
new Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.Off }, { FilterHelper.CITYBIKE, FilterState.On } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.On } }),
new StartupSettings(),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new ShareeBike.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: locksService.GetType().FullName),
new StoreMock(new ShareeBike.Model.User.Account.Account(
LoginSessionCopriInfo.JavaministerHardwareNr1.Mail,
LoginSessionCopriInfo.JavaministerHardwareNr1.Pwd,
false,
"6103_112e96b36ba33de245943c5ffaf369cd_", // Was 4da3044c8657a04ba60e2eaa753bc51a before switching from data provider CopriCallsMemory(SampleSets.Set2, 1, ...)
new List<string> { FilterHelper.CARGOBIKE })),
isConnectedFunc: () => true,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory001(sessionCookie)),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: locksService, // Cipher
device: new DeviceMock(),
specialFolder: new SpecialFolderMock(),
cipher: null,
theme: null,
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var bikesAtStation = new BikesAtStationPageViewModel(
shareeBikeApp.ActiveUser,
permissions,
bluetooth,
Device.iOS,
new ShareeBike.Model.Stations.StationNS.Station("FR103", new List<string>(), null), // Was station id 4 before switching from data provider CopriCallsMemory(SampleSets.Set2, 1, ...)
() => shareeBikeApp.GetIsConnected(),
(isConnected) => shareeBikeApp.GetConnector(isConnected),
new GeolocationMock(),
locksService,
shareeBikeApp.Polling,
(url) => { },
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
viewService);
await bikesAtStation.OnAppearingOrRefresh();
Assert.That(new List<string> { "Updating...", string.Empty }.Contains(bikesAtStation.StatusInfoText), Is.True);
// Verify list of bikes
Assert.That(bikesAtStation.Count, Is.EqualTo(4)); // Count of bikes was 4 before switching from data provider CopriCallsMemory(SampleSets.Set2, 1, ...)
Assert.That(bikesAtStation.IsIdle, Is.True);
Assert.That(bikesAtStation.IsBikesListVisible, Is.True, "If there are any bikes, list must be visible.");
Assert.That(bikesAtStation.FirstOrDefault(x => x.Id == "FR9999").StateText, Is.EqualTo("Available."));
Assert.That(bikesAtStation.FirstOrDefault(x => x.Id == "FR9999").StateText, Is.EqualTo("Available."));
Assert.That(bikesAtStation.FirstOrDefault(x => x.Id == "FR1004").StateText, Is.EqualTo("Max. reservation time expired."));
Assert.That(bikesAtStation.FirstOrDefault(x => x.Id == "FR1544").StateText, Is.EqualTo($"Rented since {DateTime.Parse("2021-11-06 18:57:25.445447+01"):dd. MMMM HH:mm}.")); // Was 7
// Login hint/ no bikes frame
Assert.That(bikesAtStation.IsLoginRequiredHintVisible, Is.False);
Assert.That(bikesAtStation.IsNoBikesAtStationVisible, Is.False);
Assert.That(bikesAtStation.NoBikesAtStationText, Is.EqualTo(string.Empty));
}
[Test]
public async Task TestConstruct_Offline()
{
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
var permissions = Substitute.For<ILocationPermission>();
var bluetooth = Substitute.For<IBluetoothLE>();
bluetooth.State.Returns(BluetoothState.On);
locksService.TimeOut.Returns(timeOut);
timeOut.MultiConnect.Returns(new TimeSpan(0));
var shareeBikeApp = new ShareeBikeApp(
new Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.Off }, { FilterHelper.CITYBIKE, FilterState.On } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.On } }),
new StartupSettings(),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new ShareeBike.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
new StoreMock(),
isConnectedFunc: () => false,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory001(sessionCookie)),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: locksService, // Cipher
device: new DeviceMock(),
specialFolder: new SpecialFolderMock(),
cipher: null, // Not connected.
theme: null,
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var bikesAtStation = new BikesAtStationPageViewModel(
shareeBikeApp.ActiveUser,
permissions,
bluetooth,
Device.iOS,
new ShareeBike.Model.Stations.StationNS.Station("FR103", new List<string>(), null), // Was station id 4 before switching from data provider CopriCallsMemory(SampleSets.Set2, 1
() => shareeBikeApp.GetIsConnected(),
(isConnected) => shareeBikeApp.GetConnector(isConnected),
new GeolocationMock(),
locksService,
shareeBikeApp.Polling,
(url) => { },
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
viewService);
await bikesAtStation.OnAppearingOrRefresh();
// Verify list of bikes
Assert.That(bikesAtStation.Count, Is.EqualTo(2)); // Count of bikes was 3. There is no more bike with id 26.
Assert.That(bikesAtStation.IsIdle, Is.True);
Assert.That(bikesAtStation.IsBikesListVisible, Is.True, "If there are any bikes, list must be visible.");
Assert.That(bikesAtStation.FirstOrDefault(x => x.Id == "FR9999").StateText, Is.EqualTo("Available.")); // Was id 5
Assert.That(bikesAtStation.FirstOrDefault(x => x.Id == "FR9998").StateText, Is.EqualTo("Available.")); // Was is 14
// Login hint/ no bikes frame
Assert.That(bikesAtStation.IsLoginRequiredHintVisible, Is.True);
Assert.That(bikesAtStation.IsNoBikesAtStationVisible, Is.False);
Assert.That(bikesAtStation.NoBikesAtStationText, Is.EqualTo(string.Empty));
}
[Test]
public async Task TestConstruct_WebConnectCommunicationError()
{
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
var permissions = Substitute.For<ILocationPermission>();
var bluetooth = Substitute.For<IBluetoothLE>();
bluetooth.State.Returns(BluetoothState.On);
locksService.TimeOut.Returns(timeOut);
timeOut.MultiConnect.Returns(new TimeSpan(0));
var shareeBikeApp = new ShareeBikeApp(
new Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.Off }, { FilterHelper.CITYBIKE, FilterState.On } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.On } }),
new StartupSettings(),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new ShareeBike.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
new StoreMock(),
isConnectedFunc: () => false,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ShareeBike.Model.Connector.Connector(
uri,
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
null /*UI language */,
sessionCookie,
mail,
server: new CopriProviderHttps(
uri,
ShareeBikeApp.MerchantId,
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
null /*UI language */,
sessionCookie: sessionCookie,
cacheServer: new CopriCallsCacheMemory001(sessionCookie: sessionCookie),
httpsServer: new ExceptionServer((msg) => new WebConnectFailureException(msg, new Exception("Source expection."))))),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: locksService, // Cipher
device: new DeviceMock(),
specialFolder: new SpecialFolderMock(),
cipher: null, // Not connected.
theme: null,
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var bikesAtStation = new BikesAtStationPageViewModel(
shareeBikeApp.ActiveUser,
permissions,
bluetooth,
Device.iOS,
new ShareeBike.Model.Stations.StationNS.Station("FR103", new List<string>(), null), // Was station id 4 before switching from data provider CopriCallsCacheMemory()
() => shareeBikeApp.GetIsConnected(),
(isConnected) => shareeBikeApp.GetConnector(isConnected),
new GeolocationMock(),
locksService,
shareeBikeApp.Polling,
(url) => { },
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
viewService)
{
IsReportLevelVerbose = true
};
await bikesAtStation.OnAppearingOrRefresh();
// Verify list of bikes
Assert.That(bikesAtStation.Count, Is.EqualTo(2)); // Count of bikes was 3. There is no more bike with id 26.
Assert.That(bikesAtStation.IsIdle, Is.True);
Assert.That(bikesAtStation.IsBikesListVisible, Is.True, "If there are any bikes, list must be visible.");
Assert.That(bikesAtStation.FirstOrDefault(x => x.Id == "FR9999").StateText, Is.EqualTo("Available.")); // Was id 5
Assert.That(bikesAtStation.FirstOrDefault(x => x.Id == "FR9998").StateText, Is.EqualTo("Available.")); // Was is 14
// Login hint/ no bikes frame
Assert.That(bikesAtStation.IsLoginRequiredHintVisible, Is.True);
Assert.That(bikesAtStation.IsNoBikesAtStationVisible, Is.False);
Assert.That(bikesAtStation.NoBikesAtStationText, Is.EqualTo(string.Empty));
}
[Test]
public async Task TestShareeBikeApp_GeneralPurposeError()
{
var locksService = Substitute.For<ILocksService>();
var timeOut = Substitute.For<ITimeOutProvider>();
var viewService = Substitute.For<IViewService>();
var permissions = Substitute.For<ILocationPermission>();
var bluetooth = Substitute.For<IBluetoothLE>();
bluetooth.State.Returns(BluetoothState.On);
locksService.TimeOut.Returns(timeOut);
timeOut.MultiConnect.Returns(new TimeSpan(0));
var shareeBikeApp = new ShareeBikeApp(
new Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.Off }, { FilterHelper.CITYBIKE, FilterState.On } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.On }, { FilterHelper.CITYBIKE, FilterState.On } }),
new StartupSettings(),
new Uri("https://shareeapp-primary.copri-bike.de/APIjsonserver"),
new ShareeBike.Settings.PollingParameters(new TimeSpan(10000),
true),
Serilog.Events.LogEventLevel.Error,
activeLockService: locksService.GetType().FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
new StoreMock(),
isConnectedFunc: () => false,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ShareeBike.Model.Connector.Connector(
uri,
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
null /*UI language */,
sessionCookie,
mail,
server: new CopriProviderHttps(
uri,
ShareeBikeApp.MerchantId,
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
null /*UI language */,
sessionCookie: sessionCookie,
cacheServer: new CopriCallsCacheMemory001(sessionCookie: sessionCookie),
httpsServer: new ExceptionServer((msg) => new Exception(msg)))),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: locksService, // Cipher
device: new DeviceMock(),
specialFolder: new SpecialFolderMock(),
cipher: null, // Not connected.
theme: null,
postAction: (d, obj) => d(obj),
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown.
var bikesAtStation = new BikesAtStationPageViewModel(
shareeBikeApp.ActiveUser,
permissions,
bluetooth,
Device.iOS,
new ShareeBike.Model.Stations.StationNS.Station("FR103", new List<string>(), null), // Was station id 4 before switching from data provider CopriCallsCacheMemory()
() => shareeBikeApp.GetIsConnected(),
(isConnected) => shareeBikeApp.GetConnector(isConnected),
new GeolocationMock(),
locksService,
shareeBikeApp.Polling,
(url) => { },
(d, obj) => d(obj),
Substitute.For<ISmartDevice>(),
viewService)
{
IsReportLevelVerbose = true
};
await bikesAtStation.OnAppearingOrRefresh();
// Verify list of bikes
Assert.That(bikesAtStation.Count, Is.EqualTo(2)); // Count of bikes was 3. There is no more bike with id 26.
Assert.That(bikesAtStation.IsIdle, Is.True);
Assert.That(bikesAtStation.IsBikesListVisible, Is.True, "If there are any bikes, list must be visible.");
Assert.That(bikesAtStation.FirstOrDefault(x => x.Id == "FR9999").StateText, Is.EqualTo("Available.")); // Was id 5
Assert.That(bikesAtStation.FirstOrDefault(x => x.Id == "FR9998").StateText, Is.EqualTo("Available.")); // Was id 14.
// Login hint/ no bikes frame
Assert.That(bikesAtStation.IsLoginRequiredHintVisible, Is.True);
Assert.That(bikesAtStation.IsNoBikesAtStationVisible, Is.False);
Assert.That(bikesAtStation.NoBikesAtStationText, Is.EqualTo(string.Empty));
}
}
}