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

701 lines
29 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using NSubstitute;
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 SharedBusinessLogic.Tests.Framework.Services.BluetoothLock;
using ShareeBike.Model;
using ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock;
using ShareeBike.Model.Bikes.BikeInfoNS.BikeNS;
using ShareeBike.Model.Bikes.BikeInfoNS.DriveNS;
using ShareeBike.Model.Connector;
using ShareeBike.Model.Services.CopriApi;
using ShareeBike.Model.Settings;
using ShareeBike.Model.Stations.StationNS;
using ShareeBike.Repository;
using ShareeBike.Repository.Exception;
using ShareeBike.Services;
using ShareeBike.Services.Geolocation;
using ShareeBike.Services.Permissions;
using ShareeBike.View;
using ShareeBike.ViewModel.Map;
using ShareeBike.ViewModel.Settings;
using Xamarin.Forms;
using ShareeBike.Model.Bikes.BikeInfoNS;
using ShareeBike.Model.Stations.StationNS.Operator;
namespace SharedBusinessLogic.Tests.UseCases.Startup
{
[TestFixture]
public class TestMapPageViewModel
{
[Test]
public async Task TestConstruct()
{
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://tinkwwp.copri-bike.de/APIjsonserver"),
new ShareeBike.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: typeof(LocksServiceMock).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 CopriCallsMemory001v2NotLoggedIn(sessionCookie)),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: new LocksServiceMock(), // 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 viewService = Substitute.For<IViewService>();
var navigationService = Substitute.For<INavigation>();
var locationPermission = Substitute.For<ILocationPermission>();
locationPermission.CheckStatusAsync().Returns(Status.Granted);
var viewModel = new MapPageViewModel(
shareeBikeApp,
locationPermission,
Substitute.For<IBluetoothLE>(),
Substitute.For<IGeolocationService>(),
(mapspan) => { },
viewService,
navigationService);
try
{
await viewModel.OnAppearing(); // Is called when page shows.
Assert.That(viewModel.Exception, Is.Null);
// Verify pins on map
Assert.That(viewModel.Pins.Count, Is.EqualTo(27)); // Were 8 pins when loading from CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)
Assert.That(
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Green"))?.Tag,
Is.EqualTo("FR101"),
"Station FR105 must be marked green because there are bikes.");
Assert.That(
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Red"))?.Tag,
Is.EqualTo("KN12"),
"Station KN12 must be marked red because there is no bike."); // Was station id 31
// Verify buttons
Assert.That(viewModel.IsToggleVisible, Is.True, "ShareeBike and Citybike are activated in settings.");
Assert.That(viewModel.CargoColor, Is.EqualTo(Color.White), "ShareeBike bikes are shown.");
Assert.That(viewModel.CitybikeColor, Is.EqualTo(Color.FromRgba(0, 0, 0, 0)), "Citybike bikes are hidden.");
var statusInfoText = viewModel.StatusInfoText;
Assert.That(
statusInfoText,
Does.Contain("Updating...").Or.Contain(""),
"Unexpected text detected. Text might be \"Updating...\" or empty depending on activity of update thread.");
}
finally
{
await viewModel.OnDisappearing();
}
}
[Test]
public async Task TestConstruct_CitybikeActive()
{
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: typeof(LocksServiceMock).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 CopriCallsMemory001v2NotLoggedIn(sessionCookie)),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: new LocksServiceMock(), // 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 viewService = Substitute.For<IViewService>();
var navigationService = Substitute.For<INavigation>();
var locationPermission = Substitute.For<ILocationPermission>();
locationPermission.CheckStatusAsync().Returns(Status.Granted);
var viewModel = new MapPageViewModel(
shareeBikeApp,
locationPermission,
Substitute.For<IBluetoothLE>(),
Substitute.For<IGeolocationService>(),
(mapspan) => { },
viewService,
navigationService);
try
{
await viewModel.OnAppearing(); // Is called when page shows.
Assert.That(viewModel.Exception, Is.Null);
// Verify pins on map
Assert.That(viewModel.Pins.Count, Is.EqualTo(21)); // Were 2 pins when loading from CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)
Assert.That(
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Green"))?.Tag, // Was station 5
Is.EqualTo("FR103"),
"Station FR101 must be marked green because there is are bike.");
Assert.That(
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Red"))?.Tag, // Was station 14
Is.EqualTo("KN12"),
"Station KN12 must be marked red because there is no bike.");
// Verify buttons
Assert.That(viewModel.IsToggleVisible, Is.True, "ShareeBike and Citybike are activated in settings.");
Assert.That(viewModel.CargoColor, Is.EqualTo(Color.FromRgba(0, 0, 0, 0)), "ShareeBike bikes are hidden.");
Assert.That(viewModel.CitybikeColor, Is.EqualTo(Color.White), "Citybike bikes are shown.");
Assert.That(
new[] { "Updating...", "" }.Contains(viewModel.StatusInfoText), Is.True,
"Text might be \"Updating...\" or empty depending on acivity of update thread.");
}
finally
{
await viewModel.OnDisappearing();
}
}
[Test]
public async Task TestConstruct_CitybikeOnly()
{
var shareeBikeApp = new ShareeBikeApp(
new Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CITYBIKE, FilterState.On } }),
new GroupFilterSettings(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, FilterState.Off }, { 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: typeof(LocksServiceMock).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 CopriCallsMemory001v2NotLoggedIn(sessionCookie)),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: new LocksServiceMock(), // Cipher
device: new DeviceMock(),
specialFolder: new SpecialFolderMock(),
cipher: null,
theme: null,
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
var viewService = Substitute.For<IViewService>();
var navigationService = Substitute.For<INavigation>();
var locationPermission = Substitute.For<ILocationPermission>();
locationPermission.CheckStatusAsync().Returns(Status.Granted);
var viewModel = new MapPageViewModel(
shareeBikeApp,
locationPermission,
Substitute.For<Plugin.BLE.Abstractions.Contracts.IBluetoothLE>(),
Substitute.For<IGeolocationService>(),
(mapspan) => { },
viewService,
navigationService);
try
{
await viewModel.OnAppearing(); // Is called when page shows.
Assert.That(viewModel.Exception, Is.Null);
// Verify pins on map
Assert.That(viewModel.Pins.Count, Is.EqualTo(21)); // Were 2 when loading from CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)
Assert.That(
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Green"))?.Tag, // Was station id 31
Is.EqualTo("FR103"),
"Station FR101 must be marked green because there is are bike.");
Assert.That(
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Red"))?.Tag, // Was 14
Is.EqualTo("KN12"),
"Station KN12 must be marked red because there is no bike.");
// Verify buttons
Assert.That(viewModel.IsToggleVisible, Is.False, "ShareeBike and Citybike is deactivated from settings.");
Assert.That(
new[] { "Updating...", "" }.Contains(viewModel.StatusInfoText), Is.True,
"Text might be \"Updating...\" or empty depending on acivity of update thread.");
}
finally
{
await viewModel.OnDisappearing();
}
}
[Test]
public async Task TestConstruct_CargoOnly()
{
var shareeBikeApp = new ShareeBikeApp(
new Settings(
new GroupFilterMapPage(new Dictionary<string, FilterState> { { FilterHelper.CARGOBIKE, 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: typeof(LocksServiceMock).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 CopriCallsMemory001v2NotLoggedIn(sessionCookie)),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: new LocksServiceMock(), // Cipher
device: new DeviceMock(),
specialFolder: new SpecialFolderMock(),
cipher: null,
theme: null,
currentVersion: new Version(3, 2, 0, 115), // Current app version
lastVersion: new Version(3, 0, 173));
var viewService = Substitute.For<IViewService>();
var navigationService = Substitute.For<INavigation>();
var locationPermission = Substitute.For<ILocationPermission>();
locationPermission.CheckStatusAsync().Returns(Status.Granted);
var viewModel = new MapPageViewModel(
shareeBikeApp,
locationPermission,
Substitute.For<Plugin.BLE.Abstractions.Contracts.IBluetoothLE>(),
Substitute.For<IGeolocationService>(),
(mapspan) => { },
viewService,
navigationService);
try
{
await viewModel.OnAppearing(); // Is called when page shows.
Assert.That(viewModel.Exception, Is.Null);
// Verify pins on map
Assert.That(viewModel.Pins.Count, Is.EqualTo(27)); // Were 8 pin when loading from CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)
Assert.That(
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Green"))?.Tag,
Is.EqualTo("FR101"), // Was station id 4
"Station FR101 must be marked green because there is are bike.");
Assert.That(
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Red"))?.Tag, // Was 31
Is.EqualTo("KN12"), // Was station id 31
"Station KN12 must be marked red because there is no bike.");
// Verify buttons
Assert.That(viewModel.IsToggleVisible, Is.False, "ShareeBike and Citybike is deactivated from settings.");
Assert.That(
new[] { "Updating...", "" }.Contains(viewModel.StatusInfoText), Is.True,
"Text might be \"Updating...\" or empty depending on acivity of update thread.");
}
finally
{
await viewModel.OnDisappearing();
}
}
[Test]
public async Task TestConstruct_Offline()
{
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://tinkwwp.copri-bike.de/APIjsonserver"),
new ShareeBike.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
activeLockService: typeof(LocksServiceMock).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 CopriCallsMemory001v2NotLoggedIn(sessionCookie)),
merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: new LocksServiceMock(), // Cipher
device: new DeviceMock(),
specialFolder: new SpecialFolderMock(),
cipher: null,
theme: null,
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
var viewService = Substitute.For<IViewService>();
var navigationService = Substitute.For<INavigation>();
var locationPermission = Substitute.For<ILocationPermission>();
locationPermission.CheckStatusAsync().Returns(Status.Granted);
var viewModel = new MapPageViewModel(
shareeBikeApp,
locationPermission,
Substitute.For<IBluetoothLE>(),
Substitute.For<IGeolocationService>(),
(mapspan) => { },
viewService,
navigationService);
try
{
await viewModel.OnAppearing(); // Is called when page shows.
Assert.That(viewModel.Exception, Is.Null);
// Verify pins on map
Assert.That(viewModel.Pins.Count, Is.EqualTo(27)); // Were 8 pins when loading from CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)
Assert.That(
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Green"))?.Tag, // Was station id 4
Is.EqualTo("FR101"),
"Station FR101 must be marked green because there is are bike.");
Assert.That(
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Red"))?.Tag, // Was 31
Is.EqualTo("KN12"),
"Station KN12 must be marked red because there is no bike.");
// Verify buttons
Assert.That(viewModel.IsToggleVisible, Is.True, "ShareeBike and Citybike are activated in settings.");
Assert.That(viewModel.CargoColor, Is.EqualTo(Color.White), "ShareeBike bikes are hidden.");
Assert.That(viewModel.CitybikeColor, Is.EqualTo(Color.FromRgba(0, 0, 0, 0)), "Citybike bikes are shown.");
}
finally
{
await viewModel.OnDisappearing();
}
}
[Test]
public async Task TestConstruct_WebConnectCommunicationError()
{
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://tinkwwp.copri-bike.de/APIjsonserver"),
new ShareeBike.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
true /* IsReportLevelVerbose */,
activeLockService: typeof(LocksServiceMock).FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
new StoreMock(),
isConnectedFunc: () => false,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new 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 CopriCallsCacheMemory001v2NotLoggedIn(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: new LocksServiceMock(), // Cipher
device: new DeviceMock(),
specialFolder: new SpecialFolderMock(),
cipher: null,
theme: null,
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
var viewService = Substitute.For<IViewService>();
var navigationService = Substitute.For<INavigation>();
var locationPermission = Substitute.For<ILocationPermission>();
locationPermission.CheckStatusAsync().Returns(Status.Granted);
var viewModel = new MapPageViewModel(
shareeBikeApp,
locationPermission,
Substitute.For<Plugin.BLE.Abstractions.Contracts.IBluetoothLE>(),
Substitute.For<IGeolocationService>(),
(mapspan) => { },
viewService,
navigationService);
try
{
await viewModel.OnAppearing(); // Is called when page shows.
Assert.That(
viewModel.Exception.Message, Is.EqualTo("Simulated error thrown at GetStationsAsync."));
// Verify pins on map
Assert.That(viewModel.Pins.Count, Is.EqualTo(27));
Assert.That(
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Green"))?.Tag, // Was station id 4
Is.EqualTo("FR101"),
"Station FR101 must be marked green because there is are bike.");
Assert.That(
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Red"))?.Tag, // Was 31
Is.EqualTo("KN12"),
"Station KN12 must be marked red because there is no bike.");
// Verify buttons
Assert.That(viewModel.IsToggleVisible, Is.True, "ShareeBike and Citybike are activated in settings.");
Assert.That(viewModel.CargoColor, Is.EqualTo(Color.White), "ShareeBike bikes are hidden.");
Assert.That(viewModel.CitybikeColor, Is.EqualTo(Color.FromRgba(0, 0, 0, 0)), "Citybike bikes are shown.");
}
finally
{
await viewModel.OnDisappearing();
}
}
[Test]
public async Task TestConstruct_GeneralPurposeCommunicationError()
{
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://tinkwwp.copri-bike.de/APIjsonserver"),
new ShareeBike.Settings.PollingParameters(new TimeSpan(10000), true),
Serilog.Events.LogEventLevel.Error,
true /* IsReportLevelVerbose */,
activeLockService: typeof(LocksServiceMock).FullName,
activeGeolocationService: typeof(GeolocationMock).FullName),
new StoreMock(),
isConnectedFunc: () => false,
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new 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 CopriCallsCacheMemory001v2NotLoggedIn(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: new LocksServiceMock(), // Cipher
device: new DeviceMock(),
specialFolder: new SpecialFolderMock(),
cipher: null,
theme: null,
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
var viewService = Substitute.For<IViewService>();
var navigationService = Substitute.For<INavigation>();
var locationPermission = Substitute.For<ILocationPermission>();
locationPermission.CheckStatusAsync().Returns(Status.Granted);
var viewModel = new MapPageViewModel(
shareeBikeApp,
locationPermission,
Substitute.For<Plugin.BLE.Abstractions.Contracts.IBluetoothLE>(),
Substitute.For<IGeolocationService>(),
(mapspan) => { },
viewService,
navigationService);
try
{
await viewModel.OnAppearing(); // Is called when page shows.
Assert.That(
viewModel.Exception.Message, Is.EqualTo("Simulated error thrown at GetStationsAsync."));
// Verify pins on map
Assert.That(viewModel.Pins.Count, Is.EqualTo(27));
Assert.That(
viewModel.Pins.Where(pin => pin.Icon.Id.Contains("Open_Green")).Select(pin => pin.Tag.ToString()),
Does.Contain("FR101"), // Was station id 4
"Station FR103 must be marked green because there is are bike.");
Assert.That(
viewModel.Pins.Where(pin => pin.Icon.Id.Contains("Open_Red")).Select(pin => pin.Tag.ToString()),
Does.Contain("KN12"), // Was station id 31
"Station 31 must be marked red because there is no bike.");
// Verify buttons
Assert.That(viewModel.IsToggleVisible, Is.True, "ShareeBike and Citybike are activated in settings.");
Assert.That(viewModel.CargoColor, Is.EqualTo(Color.White), "ShareeBike bikes are hidden.");
Assert.That(viewModel.CitybikeColor, Is.EqualTo(Color.FromRgba(0, 0, 0, 0)), "Citybike bikes are shown.");
}
finally
{
await viewModel.OnDisappearing();
}
}
[Test]
public void TestGetStationColors()
{
var stationIds = new List<string>() { "FR101", "BVB9003", "BVB9001" };
var bikeGroupFr101 = Substitute.For<IBikeGroupCol>();
var bikeGroupBVB9003 = Substitute.For<IBikeGroupCol>();
var bikeGroupBVB9001 = Substitute.For<IBikeGroupCol>();
bikeGroupFr101.AvailableCount.Returns(1);
bikeGroupBVB9003.AvailableCount.Returns(7);
bikeGroupBVB9001.AvailableCount.Returns(0);
var stations = new List<Station>
{
new Station("FR101", new List<string>() /* group */, Substitute.For<IPosition>(), bikeGropCol: bikeGroupFr101),
new Station("BVB9003", new List<string>() /* group */, Substitute.For<IPosition>(), bikeGropCol: bikeGroupBVB9003),
new Station("BVB9001", new List<string>() /* group */, Substitute.For<IPosition>(), bikeGropCol : bikeGroupBVB9001)
};
var bikes = new List<ShareeBike.Model.Bikes.BikeInfoNS.BC.BikeInfo> {
// Add a reserved bike to station "FR101"
new BikeInfo(
new Bike("Id1", LockModel.ILockIt),
new DriveMutable(),
ShareeBike.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
123, // Lock id
new Guid(),
new byte[0],
new byte[0],
new byte[0],
DateTime.Parse("2023-03-26 15:19"),
"a@b",
"FR101",
new Uri("https://1.2.3.4"),
new RentalDescription(),
() => DateTime.Now)
};
var colorList = MapPageViewModel.GetStationColors(stationIds, stations, bikes);
Assert.That(colorList[0], Is.EqualTo(Color.LightBlue), "1 bike reserved/ rented.");
Assert.That(colorList[1], Is.EqualTo(Color.Green), "7 available bikes.");
Assert.That(colorList[2], Is.EqualTo(Color.Red), "No bike");
}
[Test]
public void TestGetStationColorsNullIds()
{
var colorList = MapPageViewModel.GetStationColors(null, null, null);
Assert.That(colorList.Count, Is.EqualTo(0));
}
[Test]
public void TestGetStationColorsNoStations()
{
var stationIds = new List<string>() { "FR101", "BVB9003", "BVB9001" };
var bikes = new List<ShareeBike.Model.Bikes.BikeInfoNS.BC.BikeInfo> {
// Add a reserved bike to station "FR101"
new BikeInfo(
new Bike("Id1", LockModel.ILockIt),
new DriveMutable(),
ShareeBike.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
123, // Lock id
new Guid(),
new byte[0],
new byte[0],
new byte[0],
DateTime.Parse("2023-03-26 15:19"),
"a@b",
"FR101",
new Uri("https://1.2.3.4"),
new RentalDescription(),
() => DateTime.Now)
};
var colorList = MapPageViewModel.GetStationColors(stationIds, null, bikes);
Assert.That(colorList[0], Is.EqualTo(Color.LightBlue), "1 bike reserved/ rented.");
Assert.That(colorList[1], Is.EqualTo(Color.Red), "No bike.");
Assert.That(colorList[2], Is.EqualTo(Color.Red), "No bike");
}
[Test]
public void TestGetStationColorsNoBikes()
{
var stationIds = new List<string>() { "FR101", "BVB9003", "BVB9001" };
var bikeGroupFr101 = Substitute.For<IBikeGroupCol>();
var bikeGroupBVB9003 = Substitute.For<IBikeGroupCol>();
var bikeGroupBVB9001 = Substitute.For<IBikeGroupCol>();
bikeGroupFr101.AvailableCount.Returns(1);
bikeGroupBVB9003.AvailableCount.Returns(7);
bikeGroupBVB9001.AvailableCount.Returns(0);
var stations = new List<Station>
{
new Station("FR101", new List<string>() /* group */, Substitute.For<IPosition>(), bikeGropCol: bikeGroupFr101),
new Station("BVB9003", new List<string>() /* group */, Substitute.For<IPosition>(),bikeGropCol: bikeGroupBVB9003),
new Station("BVB9001", new List<string>() /* group */, Substitute.For<IPosition>(), bikeGropCol: bikeGroupBVB9001)
};
var colorList = MapPageViewModel.GetStationColors(stationIds, stations, null);
Assert.That(colorList[0], Is.EqualTo(Color.Green), "No bike reserved/ rented.");
Assert.That(colorList[1], Is.EqualTo(Color.Green), "7 available bikes.");
Assert.That(colorList[2], Is.EqualTo(Color.Red), "No bike");
}
}
}