mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2024-09-27 17:36:29 +02:00
935 lines
33 KiB
C#
935 lines
33 KiB
C#
using System;
|
|
using System.Threading.Tasks;
|
|
using Newtonsoft.Json;
|
|
using NSubstitute;
|
|
using NUnit.Framework;
|
|
using ShareeBike.Model.Connector;
|
|
using ShareeBike.Model.Services.CopriApi;
|
|
using ShareeBike.Repository;
|
|
using ShareeBike.Repository.Response;
|
|
using ShareeBike.Repository.Response.Stations;
|
|
using ShareeBike.Services.CopriApi;
|
|
|
|
namespace SharedBusinessLogic.Tests.Model.Connector
|
|
{
|
|
[TestFixture]
|
|
public class TestCachedQueryLoggedIn
|
|
{
|
|
/// <summary>
|
|
/// Verifies that available bikes are not considered to by kind of MyBikes.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task TestGetBikesOccupiedAsyncMyBikesNone()
|
|
{
|
|
var server = Substitute.For<ICachedCopriServer>();
|
|
|
|
var bikesAvailable = JsonConvert.DeserializeObject<BikesAvailableResponse>(@"
|
|
{
|
|
""bikes"": {
|
|
""FR1005"": {
|
|
""system"": ""Sigo"",
|
|
""state"": ""available"",
|
|
""bike"": ""FR1005"",
|
|
""station"": ""REN0"",
|
|
}
|
|
},
|
|
""copri_version"": ""4.1.12.5"",
|
|
}");
|
|
|
|
var bikesOccupied = JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(@"
|
|
{
|
|
""bikes_occupied"": { },
|
|
""copri_version"": ""4.1.12.5"",
|
|
}");
|
|
|
|
var resultAvailable = new Result<BikesAvailableResponse>(
|
|
typeof(CopriCallsHttps), // Marks that response was taken from cache
|
|
bikesAvailable,
|
|
new GeneralData());
|
|
|
|
var resultOccupied = new Result<BikesReservedOccupiedResponse>(
|
|
typeof(CopriCallsHttps),
|
|
bikesOccupied,
|
|
new GeneralData());
|
|
|
|
server.GetBikesAvailable(false).Returns(Task.FromResult(resultAvailable));
|
|
server.GetBikesOccupied(false).Returns(Task.FromResult(resultOccupied));
|
|
|
|
var query = new CachedQueryLoggedIn(
|
|
server,
|
|
"SessionCookie",
|
|
"Mail",
|
|
() => new DateTime(2022, 7, 16));
|
|
|
|
var bikesResponse = await query.GetBikesOccupiedAsync();
|
|
|
|
Assert.That(
|
|
bikesResponse.Response.Count,
|
|
Is.EqualTo(0));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifies that available bikes with Co2Saving entry set are considered to by kind of MyBikes.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task TestGetBikesOccupiedAsyncMyBikesOneFeedbackPending()
|
|
{
|
|
var server = Substitute.For<ICachedCopriServer>();
|
|
|
|
var bikesAvailable = JsonConvert.DeserializeObject<BikesAvailableResponse>(@"
|
|
{
|
|
""bikes"": {
|
|
""FR1005"": {
|
|
""system"": ""Sigo"",
|
|
""state"": ""available"",
|
|
""bike"": ""FR1005"",
|
|
""station"": ""REN0"",
|
|
""co2saving"" : """"
|
|
}
|
|
},
|
|
""copri_version"": ""4.1.12.5"",
|
|
}");
|
|
|
|
var bikesOccupied = JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(@"
|
|
{
|
|
""bikes_occupied"": { },
|
|
""copri_version"": ""4.1.12.5"",
|
|
}");
|
|
|
|
var resultAvailable = new Result<BikesAvailableResponse>(
|
|
typeof(CopriCallsHttps),
|
|
bikesAvailable,
|
|
new GeneralData());
|
|
|
|
var resultOccupied = new Result<BikesReservedOccupiedResponse>(
|
|
typeof(CopriCallsHttps),
|
|
bikesOccupied,
|
|
new GeneralData());
|
|
|
|
server.GetBikesAvailable(false).Returns(Task.FromResult(resultAvailable));
|
|
server.GetBikesOccupied(false).Returns(Task.FromResult(resultOccupied));
|
|
|
|
var query = new CachedQueryLoggedIn(
|
|
server,
|
|
"SessionCookie",
|
|
"Mail",
|
|
() => new DateTime(2022, 7, 16));
|
|
|
|
var bikesResponse = await query.GetBikesOccupiedAsync();
|
|
|
|
Assert.That(
|
|
bikesResponse.Response.Count,
|
|
Is.EqualTo(1));
|
|
}
|
|
|
|
/// <summary>
|
|
/// .
|
|
/// </summary>
|
|
[Test]
|
|
public async Task TestGetBikesOccupiedAsyncMyBikesOneOccupied()
|
|
{
|
|
var server = Substitute.For<ICachedCopriServer>();
|
|
|
|
var bikesAvailable = JsonConvert.DeserializeObject<BikesAvailableResponse>(@"
|
|
{
|
|
""bikes"": { },
|
|
""copri_version"": ""4.1.12.5"",
|
|
}");
|
|
|
|
var bikesOccupied = JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(@"
|
|
{
|
|
""bikes_occupied"": {
|
|
""FR1005"": {
|
|
""lock_state"": ""occupied"",
|
|
""system"": ""Sigo"",
|
|
""state"": ""occupied"",
|
|
""bike"": ""FR1005"",
|
|
""station"": ""REN0"",
|
|
}
|
|
},
|
|
""copri_version"": ""4.1.12.5"",
|
|
}");
|
|
|
|
var resultAvailable = new Result<BikesAvailableResponse>(
|
|
typeof(CopriCallsHttps),
|
|
bikesAvailable,
|
|
new GeneralData());
|
|
|
|
var resultOccupied = new Result<BikesReservedOccupiedResponse>(
|
|
typeof(CopriCallsHttps),
|
|
bikesOccupied,
|
|
new GeneralData());
|
|
|
|
server.GetBikesAvailable(false).Returns(Task.FromResult(resultAvailable)); // Get bikes from copri
|
|
server.GetBikesOccupied(false).Returns(Task.FromResult(resultOccupied)); // Get bikes from cache
|
|
|
|
var query = new CachedQueryLoggedIn(
|
|
server,
|
|
"SessionCookie",
|
|
"Mail",
|
|
() => new DateTime(2022, 7, 16));
|
|
|
|
var bikesResponse = await query.GetBikesOccupiedAsync();
|
|
|
|
Assert.That(
|
|
bikesResponse.Response.Count,
|
|
Is.EqualTo(1));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Scenario: Call of GetBikesAvailable fails data is taken from cache.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task TestGetBikesOccupiedAsyncGetAvailableFailsMyBikeOneFeedbackPending()
|
|
{
|
|
var server = Substitute.For<ICachedCopriServer>();
|
|
|
|
var bikesAvailable = JsonConvert.DeserializeObject<BikesAvailableResponse>(@"
|
|
{
|
|
""bikes"": {
|
|
""FR1005"": {
|
|
""system"": ""Sigo"",
|
|
""state"": ""available"",
|
|
""bike"": ""FR1005"",
|
|
""station"": ""REN0"",
|
|
""co2saving"" : """"
|
|
}
|
|
},
|
|
""copri_version"": ""4.1.12.5"",
|
|
}");
|
|
|
|
var bikesOccupied = JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(@"
|
|
{
|
|
""bikes_occupied"": { },
|
|
""copri_version"": ""4.1.12.5"",
|
|
}");
|
|
|
|
var resultAvailable = new Result<BikesAvailableResponse>(
|
|
typeof(CopriCallsMonkeyStore),
|
|
bikesAvailable,
|
|
new GeneralData());
|
|
|
|
var resultOccupied = new Result<BikesReservedOccupiedResponse>(
|
|
typeof(CopriCallsMonkeyStore),
|
|
bikesOccupied,
|
|
new GeneralData());
|
|
|
|
server.GetBikesAvailable(false).Returns(Task.FromResult(resultAvailable));
|
|
server.GetBikesOccupied(true).Returns(Task.FromResult(resultOccupied));
|
|
|
|
var query = new CachedQueryLoggedIn(
|
|
server,
|
|
"SessionCookie",
|
|
"Mail",
|
|
() => new DateTime(2022, 7, 16));
|
|
|
|
var bikesResponse = await query.GetBikesOccupiedAsync();
|
|
|
|
Assert.That(
|
|
bikesResponse.Response.Count,
|
|
Is.EqualTo(1));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Scenario: Call of GetBikesAvailable succeeds but because call of GetBikesOccupied fails data is taken from cache.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task TestGetBikesOccupiedAsyncGetGetBikesOccupiedFailsMyBikeFeedbackPending()
|
|
{
|
|
var server = Substitute.For<ICachedCopriServer>();
|
|
|
|
var bikesAvailableCopri = JsonConvert.DeserializeObject<BikesAvailableResponse>(@"
|
|
{
|
|
""bikes"": { },
|
|
""copri_version"": ""4.1.12.5"",
|
|
}");
|
|
|
|
var bikesAvailableCache = JsonConvert.DeserializeObject<BikesAvailableResponse>(@"
|
|
{
|
|
""bikes"": {
|
|
""FR1005"": {
|
|
""system"": ""Sigo"",
|
|
""state"": ""available"",
|
|
""bike"": ""FR1005"",
|
|
""station"": ""REN0"",
|
|
""co2saving"" : """"
|
|
}
|
|
},
|
|
""copri_version"": ""4.1.12.5"",
|
|
}");
|
|
|
|
var bikesOccupied = JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(@"
|
|
{
|
|
""bikes_occupied"": { },
|
|
""copri_version"": ""4.1.12.5"",
|
|
}");
|
|
|
|
var resultAvailableCopri = new Result<BikesAvailableResponse>(
|
|
typeof(CopriCallsHttps), // Marks that response was taken from copri
|
|
bikesAvailableCache,
|
|
new GeneralData());
|
|
|
|
var resultAvailableCache = new Result<BikesAvailableResponse>(
|
|
typeof(CopriCallsMonkeyStore), // Marks that response was taken from cache
|
|
bikesAvailableCache,
|
|
new GeneralData());
|
|
|
|
var resultOccupied = new Result<BikesReservedOccupiedResponse>(
|
|
typeof(CopriCallsMonkeyStore),
|
|
bikesOccupied,
|
|
new GeneralData());
|
|
|
|
server.GetBikesAvailable(false).Returns(Task.FromResult(resultAvailableCopri)); // Get bikes from copri
|
|
server.GetBikesOccupied(false).Returns(Task.FromResult(resultOccupied)); // Get bikes from copri fails
|
|
server.GetBikesAvailable(true).Returns(Task.FromResult(resultAvailableCache)); // Get bikes from cache
|
|
|
|
var query = new CachedQueryLoggedIn(
|
|
server,
|
|
"SessionCookie",
|
|
"Mail",
|
|
() => new DateTime(2022, 7, 16));
|
|
|
|
var bikesResponse = await query.GetBikesOccupiedAsync();
|
|
|
|
Assert.That(
|
|
bikesResponse.Response.Count,
|
|
Is.EqualTo(1));
|
|
}
|
|
|
|
private const string BIKESAVAILABLE = @"{
|
|
""copri_version"" : ""4.1.0.0"",
|
|
""bikes"" : {},
|
|
""response_state"" : ""OK"",
|
|
""apiserver"" : ""https://app.tink-konstanz.de"",
|
|
""authcookie"" : """",
|
|
""response"" : ""bikes_available"",
|
|
""bikes"" : {
|
|
""2352"" : {
|
|
""description"" : ""Cargo Long"",
|
|
""state"" : ""available"",
|
|
""bike"" : ""1"",
|
|
""gps"" : { ""latitude"": ""47.669888"", ""longitude"": ""9.167749"" },
|
|
""station"" : ""9""
|
|
}
|
|
}
|
|
}";
|
|
|
|
private const string BIKESAVAILABLE2 = @"{
|
|
""lang"" : ""de"",
|
|
""user_group"" : [
|
|
""FR300103"",
|
|
""FR300101""
|
|
],
|
|
""uri_primary"" : ""https://shareeapp-primary.copri.eu"",
|
|
""bikes_occupied"" : {
|
|
""160317"" : {
|
|
""station"" : ""FR101"",
|
|
""bike_type"" : {
|
|
""category"" : ""cargo"",
|
|
""wheels"" : ""2""
|
|
},
|
|
""rental_minute_all"" : 2666,
|
|
""description"" : ""Lastenrad Oliver Pieper"",
|
|
""unit_price"" : ""2.00"",
|
|
""end_time"" : ""2023-10-29 12:03:28"",
|
|
""total_price"" : ""0.00"",
|
|
""K_u"" : ""[72, 41, 3, -121, -121, -40, -125, -92, -70, -78, -12, -73, 11, -31, 108, 63, -22, 28, -73, 35, 0, 0, 0, 0]"",
|
|
""real_clock"" : ""1 day 20:26"",
|
|
""rentalog"" : """",
|
|
""bike"" : ""FR1011"",
|
|
""gps"" : {
|
|
""latitude"" : ""47.9765599546954"",
|
|
""longitude"" : ""7.82557798549533""
|
|
},
|
|
""request_time"" : ""2023-10-27 15:37:16.296418+02"",
|
|
""aa_ride"" : ""0"",
|
|
""state"" : ""occupied"",
|
|
""lock_state"" : ""unlocked"",
|
|
""K_seed"" : ""[-77, 79, -81, -34, 107, -34, -100, -29, 124, 30, -50, -63, -111, 0, 22, -19]"",
|
|
""Ilockit_ID"" : ""ISHAREIT-2200536"",
|
|
""system"" : ""Ilockit"",
|
|
""computed_hours"" : ""44.1"",
|
|
""freed_time"" : ""- 00:20"",
|
|
""bike_group"" : [
|
|
""FR300101""
|
|
],
|
|
""start_time"" : ""2023-10-27 15:37:24.371987+02"",
|
|
""rental_description"" : {
|
|
""tarif_elements"" : {
|
|
""4"" : [
|
|
""Max. Gebühr"",
|
|
""24,00 € / 24 Std""
|
|
],
|
|
""1"" : [
|
|
""Mietgebühr"",
|
|
""2,00 € / 30 Min ""
|
|
],
|
|
""7"" : [
|
|
""Aktuelle Mietzeit"",
|
|
""1 Tag 20 Std 26 Min ""
|
|
],
|
|
""2"" : [
|
|
""ab 2. Tag"",
|
|
""3,00 € / 30 Min ""
|
|
],
|
|
""6"" : [
|
|
""Gratis Mietzeit"",
|
|
""20 Min / Tag""
|
|
]
|
|
},
|
|
""reserve_timerange"" : ""15"",
|
|
""name"" : ""E-Lastenrad private"",
|
|
""id"" : ""5533""
|
|
},
|
|
""discount"" : ""-100%"",
|
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu""
|
|
}
|
|
},
|
|
""bike_info_html"" : ""site/bike_info_sharee_230922.html"",
|
|
""agb_checked"" : ""1"",
|
|
""user_tour"" : [],
|
|
""last_used_operator"" : {
|
|
""operator_name"" : ""TeilRad GmbH"",
|
|
""operator_phone"" : ""+49 761 45370097"",
|
|
""operator_email"" : ""hotline@sharee.bike"",
|
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr""
|
|
},
|
|
""user_id"" : ""ohauff@posteo.de"",
|
|
""impress_html"" : ""site/impress_1.html"",
|
|
""authcookie"" : ""5781_f172cf59108fe53e7524c841847fee69_shoo0faiNg"",
|
|
""faq_app_fullurl"" : ""https://sharee.bike/faq/fahrrad-nutzung"",
|
|
""tariff_info_html"" : ""site/tarif_info_sharee_230922.html"",
|
|
""agb_html"" : ""site/agb_sharee_2.html"",
|
|
""response"" : ""bikes_available"",
|
|
""bikes"" : {
|
|
""FR1545"" : {
|
|
""Ilockit_GUID"" : ""00000000-0000-0000-0000-e38bf9d32234"",
|
|
""description"" : ""C2-02-00545"",
|
|
""lock_state"" : ""locked"",
|
|
""system"" : ""Ilockit"",
|
|
""Ilockit_ID"" : ""ISHAREIT-2200545"",
|
|
""state"" : ""available"",
|
|
""aa_ride"" : ""0"",
|
|
""smartlock_type"" : {
|
|
""battery"" : {
|
|
""charge_current_percent"" : ""100""
|
|
},
|
|
""engine"" : {
|
|
""manufacturer"" : ""Ilockit""
|
|
}
|
|
},
|
|
""bike_type"" : {
|
|
""battery"" : {
|
|
""charge_max_bars"" : ""5"",
|
|
""charge_current_bars"" : ""0"",
|
|
""charge_current_percent"" : ""0"",
|
|
""hidden"" : ""0"",
|
|
""backend_accessible"" : ""0""
|
|
},
|
|
""engine"" : {
|
|
""manufacturer"" : ""dummy""
|
|
},
|
|
""category"" : ""cargo"",
|
|
""wheels"" : ""2""
|
|
},
|
|
""station"" : ""FR101"",
|
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
|
""gps"" : {
|
|
""latitude"" : ""47.9767844"",
|
|
""longitude"" : ""7.8258182""
|
|
},
|
|
""bike"" : ""FR1545"",
|
|
""bike_group"" : [
|
|
""FR300101""
|
|
],
|
|
""authed"" : ""1"",
|
|
""rental_description"" : {
|
|
""id"" : ""5533"",
|
|
""reserve_timerange"" : ""15"",
|
|
""name"" : ""E-Lastenrad private"",
|
|
""tarif_type"" : ""3"",
|
|
""tarif_elements"" : {
|
|
""6"" : [
|
|
""Gratis Mietzeit"",
|
|
""20 Min / Tag""
|
|
],
|
|
""2"" : [
|
|
""ab 2. Tag"",
|
|
""3,00 € / 30 Min ""
|
|
],
|
|
""4"" : [
|
|
""Max. Gebühr"",
|
|
""24,00 € / 24 Std""
|
|
],
|
|
""1"" : [
|
|
""Mietgebühr"",
|
|
""2,00 € / 30 Min ""
|
|
]
|
|
}
|
|
}
|
|
},
|
|
""FR1012"" : {
|
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
|
""bike"" : ""FR1012"",
|
|
""gps"" : {
|
|
""latitude"" : ""47.998034725897"",
|
|
""longitude"" : ""7.78498157858849""
|
|
},
|
|
""bike_group"" : [
|
|
""FR300101""
|
|
],
|
|
""rental_description"" : {
|
|
""rental_info"" : {
|
|
""1"" : [
|
|
""Tracking"",
|
|
""Ich stimme der Speicherung (Tracking) meiner Fahrstrecke zwecks wissenschaftlicher Auswertung und Berechnung der CO2-Einsparung zu!""
|
|
]
|
|
},
|
|
""tarif_elements"" : {
|
|
""1"" : [
|
|
""Mietgebühr"",
|
|
""2,00 € / 30 Min ""
|
|
],
|
|
""4"" : [
|
|
""Max. Gebühr"",
|
|
""24,00 € / 24 Std""
|
|
],
|
|
""6"" : [
|
|
""Gratis Mietzeit"",
|
|
""20 Min / Tag""
|
|
],
|
|
""2"" : [
|
|
""ab 2. Tag"",
|
|
""3,00 € / 30 Min ""
|
|
]
|
|
},
|
|
""reserve_timerange"" : ""15"",
|
|
""name"" : ""E-Lastenrad private"",
|
|
""id"" : ""5533"",
|
|
""tarif_type"" : ""3""
|
|
},
|
|
""authed"" : ""1"",
|
|
""description"" : ""Contributor-bike devel"",
|
|
""Ilockit_GUID"" : ""00000000-0000-0000-0000-ef6655036de7"",
|
|
""lock_state"" : ""locked"",
|
|
""system"" : ""Ilockit"",
|
|
""Ilockit_ID"" : ""ISHAREIT-2309492"",
|
|
""state"" : ""available"",
|
|
""bike_type"" : {
|
|
""engine"" : {
|
|
""manufacturer"" : ""dummy""
|
|
},
|
|
""battery"" : {
|
|
""charge_current_bars"" : ""5"",
|
|
""charge_max_bars"" : ""5"",
|
|
""backend_accessible"" : ""0"",
|
|
""charge_current_percent"" : ""100"",
|
|
""hidden"" : ""0""
|
|
},
|
|
""category"" : ""cargo"",
|
|
""wheels"" : ""2""
|
|
},
|
|
""smartlock_type"" : {
|
|
""engine"" : {
|
|
""manufacturer"" : ""Ilockit""
|
|
},
|
|
""battery"" : {
|
|
""charge_current_percent"" : """"
|
|
}
|
|
},
|
|
""aa_ride"" : ""0"",
|
|
""station"" : ""FR103""
|
|
},
|
|
},
|
|
""aowner"" : ""186"",
|
|
""init_map"" : {
|
|
""radius"" : ""2.9"",
|
|
""center"" : {
|
|
""longitude"" : ""7.825490"",
|
|
""latitude"" : ""47.976634""
|
|
}
|
|
},
|
|
""new_authcoo"" : ""0"",
|
|
""apiserver"" : ""https://shareeapp-fr01.copri.eu"",
|
|
""merchant_id"" : ""shoo0faiNg"",
|
|
""privacy_html"" : ""site/privacy_sharee_2.html"",
|
|
""response_state"" : ""OK, nothing todo"",
|
|
""debuglevel"" : ""104"",
|
|
""clearing_cache"" : ""0"",
|
|
""copri_version"" : ""4.1.23.20"",
|
|
""project_id"" : ""Freiburg""
|
|
}";
|
|
|
|
private const string BIKESAVAILABLEEMPTY = @"{
|
|
""copri_version"" : ""4.1.0.0"",
|
|
""bikes"" : {},
|
|
""response_state"" : ""OK"",
|
|
""apiserver"" : ""https://app.tink-konstanz.de"",
|
|
""authcookie"" : """",
|
|
""response"" : ""bikes_available"",
|
|
""bikes"" : {
|
|
}
|
|
}";
|
|
|
|
private const string BIKESOCCUPIED = @"{
|
|
""authcookie"" : ""6103_f782a208d9399291ba8d086b5dcc2509_12345678"",
|
|
""debuglevel"" : ""2"",
|
|
""user_group"" : [ ""ShareeBike"" ],
|
|
""user_id"" : ""javaminister@gmail.com"",
|
|
""response"" : ""user_bikes_occupied"",
|
|
""response_state"" : ""OK"",
|
|
""response_text"" : ""Die Liste der reservierten und gebuchten Fahrräder wurde erfolgreich geladen"",
|
|
""apiserver"" : ""https://tinkwwp.copri-bike.de"",
|
|
""bikes_occupied"" : {
|
|
""89004"" : {
|
|
""start_time"" : ""2018-01-27 17:33:00.989464+01"",
|
|
""station"" : ""9"",
|
|
""unit_price"" : ""2.00"",
|
|
""tariff_description"": {
|
|
""free_hours"" : ""0.5"",
|
|
""name"" : ""ShareeBike Tarif"",
|
|
""max_eur_per_day"" : ""9.00""
|
|
},
|
|
""timeCode"" : ""2061"",
|
|
""description"" : ""Cargo Long"",
|
|
""bike"" : ""4"",
|
|
""total_price"" : ""20.00"",
|
|
""state"" : ""requested"",
|
|
""real_hours"" : ""66.05"",
|
|
""bike_group"" : [ ""ShareeBike"" ],
|
|
""now_time"" : ""2018-01-30 11:36:45"",
|
|
""request_time"" : ""2018-01-27 17:33:00.989464+01"",
|
|
""computed_hours"" : ""10.0""
|
|
}
|
|
}
|
|
}";
|
|
|
|
private const string STATIONSALL = @"{
|
|
""copri_version"" : ""4.1.0.0"",
|
|
""stations"" : {
|
|
""5"" : {
|
|
""station"" : ""5"",
|
|
""bike_soll"" : ""0"",
|
|
""bike_ist"" : ""7"",
|
|
""station_group"" : [ ""ShareeBike"" ],
|
|
""gps"" : { ""latitude"": ""47.66756"", ""longitude"": ""9.16477"" },
|
|
""state"" : ""available"",
|
|
""description"" : """"
|
|
},
|
|
""13"" : {
|
|
""station"" : ""13"",
|
|
""bike_soll"" : ""4"",
|
|
""bike_ist"" : ""1"",
|
|
""station_group"" : [ ""ShareeBike"" ],
|
|
""gps"" : { ""latitude"": ""47.657756"", ""longitude"": ""9.176084"" },
|
|
""state"" : ""available"",
|
|
""description"" : """"
|
|
},
|
|
""30"" : {
|
|
""station"" : ""30"",
|
|
""bike_soll"" : ""5"",
|
|
""bike_ist"" : ""0"",
|
|
""station_group"" : [ ""ShareeBike"", ""Citybike"" ],
|
|
""gps"" : { ""latitude"": ""47.657766"", ""longitude"": ""9.176094"" },
|
|
""state"" : ""available"",
|
|
""description"" : ""Test für Stadtradstation""
|
|
}
|
|
},
|
|
""user_group"" : [ ""Citybike"", ""ShareeBike"" ],
|
|
""response_state"" : ""OK"",
|
|
""authcookie"" : ""6103_f782a208d9399291ba8d086b5dcc2509_12345678"",
|
|
""debuglevel"" : ""2"",
|
|
""response"" : ""stations_all"",
|
|
""user_id"" : ""javaminister@gmail.com"",
|
|
""apiserver"" : ""https://tinkwwp.copri-bike.de""
|
|
}";
|
|
|
|
/// <summary>
|
|
/// Response updated (manually edited) combining JSON form responses <see cref="STATIONSALL"/> and <see cref="BIKESOCCUPIED"/>
|
|
/// </summary>
|
|
private const string STATIONSALLV2 = @"{
|
|
""copri_version"" : ""4.1.0.0"",
|
|
""stations"" : {
|
|
""5"" : {
|
|
""station"" : ""5"",
|
|
""bike_soll"" : ""0"",
|
|
""bike_ist"" : ""7"",
|
|
""station_group"" : [ ""ShareeBike"" ],
|
|
""gps"" : { ""latitude"": ""47.66756"", ""longitude"": ""9.16477"" },
|
|
""state"" : ""available"",
|
|
""description"" : """"
|
|
},
|
|
""13"" : {
|
|
""station"" : ""13"",
|
|
""bike_soll"" : ""4"",
|
|
""bike_ist"" : ""1"",
|
|
""station_group"" : [ ""ShareeBike"" ],
|
|
""gps"" : { ""latitude"": ""47.657756"", ""longitude"": ""9.176084"" },
|
|
""state"" : ""available"",
|
|
""description"" : """"
|
|
},
|
|
""30"" : {
|
|
""station"" : ""30"",
|
|
""bike_soll"" : ""5"",
|
|
""bike_ist"" : ""0"",
|
|
""station_group"" : [ ""ShareeBike"", ""Citybike"" ],
|
|
""gps"" : { ""latitude"": ""47.657766"", ""longitude"": ""9.176094"" },
|
|
""state"" : ""available"",
|
|
""description"" : ""Test für Stadtradstation""
|
|
}
|
|
},
|
|
""bikes_occupied"" : {
|
|
""89004"" : {
|
|
""start_time"" : ""2018-01-27 17:33:00.989464+01"",
|
|
""station"" : ""9"",
|
|
""unit_price"" : ""2.00"",
|
|
""tariff_description"": {
|
|
""free_hours"" : ""0.5"",
|
|
""name"" : ""ShareeBike Tarif"",
|
|
""max_eur_per_day"" : ""9.00""
|
|
},
|
|
""timeCode"" : ""2061"",
|
|
""description"" : ""Cargo Long"",
|
|
""bike"" : ""4"",
|
|
""total_price"" : ""20.00"",
|
|
""state"" : ""requested"",
|
|
""real_hours"" : ""66.05"",
|
|
""bike_group"" : [ ""ShareeBike"" ],
|
|
""now_time"" : ""2018-01-30 11:36:45"",
|
|
""request_time"" : ""2018-01-27 17:33:00.989464+01"",
|
|
""computed_hours"" : ""10.0""
|
|
}
|
|
},
|
|
|
|
""user_group"" : [ ""Citybike"", ""ShareeBike"" ],
|
|
""response_state"" : ""OK"",
|
|
""authcookie"" : ""6103_f782a208d9399291ba8d086b5dcc2509_12345678"",
|
|
""debuglevel"" : ""2"",
|
|
""response"" : ""stations_all"",
|
|
""user_id"" : ""javaminister@gmail.com"",
|
|
""apiserver"" : ""https://tinkwwp.copri-bike.de""
|
|
}";
|
|
|
|
private const string STATIONSALLEMPTY = @"{
|
|
""copri_version"" : ""4.1.0.0"",
|
|
""stations"" : {
|
|
},
|
|
""user_group"" : [ ""Citybike"", ""ShareeBike"" ],
|
|
""response_state"" : ""OK"",
|
|
""authcookie"" : ""6103_f782a208d9399291ba8d086b5dcc2509_12345678"",
|
|
""debuglevel"" : ""2"",
|
|
""response"" : ""stations_all"",
|
|
""user_id"" : ""javaminister@gmail.com"",
|
|
""apiserver"" : ""https://tinkwwp.copri-bike.de""
|
|
}";
|
|
|
|
[Test]
|
|
public async Task TestGetStations_StationsFromCache()
|
|
{
|
|
var server = Substitute.For<ICachedCopriServer>();
|
|
|
|
server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
|
|
typeof(CopriCallsMonkeyStore),
|
|
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALLV2),
|
|
new GeneralData(),
|
|
new Exception("Bang when getting stations..."))));
|
|
|
|
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAndStationsAsync();
|
|
|
|
Assert.That(result.Response.StationsAll.Count, Is.EqualTo(3));
|
|
Assert.That(result.Response.BikesOccupied.Count, Is.EqualTo(1));
|
|
Assert.That(result.Source, Is.EqualTo(typeof(CopriCallsMonkeyStore)));
|
|
Assert.That(result.Exception.Message, Is.EqualTo("Bang when getting stations..."));
|
|
}
|
|
|
|
[Test]
|
|
public async Task TestGetStations()
|
|
{
|
|
var server = Substitute.For<ICachedCopriServer>();
|
|
|
|
server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
|
|
typeof(CopriCallsHttps),
|
|
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALLV2),
|
|
new GeneralData())));
|
|
|
|
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAndStationsAsync();
|
|
|
|
Assert.That(result.Response.StationsAll.Count, Is.EqualTo(3));
|
|
Assert.That(result.Response.BikesOccupied.Count, Is.EqualTo(1));
|
|
Assert.That(result.Source, Is.EqualTo(typeof(CopriCallsHttps)));
|
|
Assert.That(result.Exception, Is.Null);
|
|
}
|
|
|
|
[Test]
|
|
public async Task TestGetBikesAsync_BikesAvailableFromCache()
|
|
{
|
|
var server = Substitute.For<ICachedCopriServer>();
|
|
|
|
server.GetBikesAvailable().Returns(Task.Run(() => new Result<BikesAvailableResponse>(
|
|
typeof(CopriCallsMonkeyStore),
|
|
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
|
|
new GeneralData(),
|
|
new Exception("Bang, bikes avail..."))));
|
|
|
|
server.GetBikesOccupied(true).Returns(Task.Run(() => new Result<BikesReservedOccupiedResponse>(
|
|
typeof(CopriCallsHttps),
|
|
JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED),
|
|
new GeneralData())));
|
|
|
|
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAsync();
|
|
|
|
Assert.That(result.Response.Count, Is.EqualTo(2));
|
|
Assert.That(result.Source, Is.EqualTo(typeof(CopriCallsMonkeyStore)));
|
|
Assert.That(result.Exception.Message, Is.EqualTo("Bang, bikes avail..."));
|
|
|
|
await server.Received().GetBikesAvailable();
|
|
await server.Received().GetBikesOccupied(true);
|
|
|
|
server.DidNotReceive().AddToCache(Arg.Any<Result<BikesAvailableResponse>>());
|
|
server.DidNotReceive().AddToCache(Arg.Any<Result<BikesReservedOccupiedResponse>>());
|
|
}
|
|
|
|
[Test]
|
|
public async Task TestGetBikesAsync_BikesOccupiedFromCache()
|
|
{
|
|
var server = Substitute.For<ICachedCopriServer>();
|
|
|
|
server.GetBikesAvailable(false).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
|
|
typeof(CopriCallsHttps),
|
|
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLEEMPTY),
|
|
new GeneralData())));
|
|
|
|
server.GetBikesOccupied(false).Returns(Task.Run(() => new Result<BikesReservedOccupiedResponse>(
|
|
typeof(CopriCallsMonkeyStore),
|
|
JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED),
|
|
new GeneralData(),
|
|
new Exception("Bang, error bikes occupied"))));
|
|
|
|
server.GetBikesAvailable(true).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
|
|
typeof(CopriCallsMonkeyStore),
|
|
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
|
|
new GeneralData())));
|
|
|
|
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAsync();
|
|
|
|
Assert.That(result.Response.Count, Is.EqualTo(2));
|
|
Assert.That(result.Source, Is.EqualTo(typeof(CopriCallsMonkeyStore)));
|
|
Assert.That(result.Exception.Message, Is.EqualTo("Bang, error bikes occupied"));
|
|
|
|
await server.Received().GetBikesAvailable();
|
|
await server.Received().GetBikesOccupied();
|
|
|
|
server.DidNotReceive().AddToCache(Arg.Any<Result<BikesAvailableResponse>>());
|
|
server.DidNotReceive().AddToCache(Arg.Any< Result<BikesReservedOccupiedResponse>>());
|
|
}
|
|
|
|
[Test]
|
|
public async Task TestGetBikesAsync([Values("", "MyBike")] string bikeFilter)
|
|
{
|
|
var server = Substitute.For<ICachedCopriServer>();
|
|
|
|
var resultBikesAvailableResponse = new Result<BikesAvailableResponse>(
|
|
typeof(CopriCallsHttps),
|
|
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
|
|
new GeneralData());
|
|
|
|
var resultBikesOccupiedResponse = new Result<BikesReservedOccupiedResponse>(
|
|
typeof(CopriCallsHttps),
|
|
JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED),
|
|
new GeneralData());
|
|
|
|
server.GetBikesAvailable(bikeId: bikeFilter).Returns(Task.Run(() => resultBikesAvailableResponse));
|
|
|
|
server.GetBikesOccupied().Returns(Task.Run(() => resultBikesOccupiedResponse));
|
|
|
|
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAsync(bikeId: bikeFilter);
|
|
|
|
Assert.That(result.Response.Count, Is.EqualTo(2));
|
|
Assert.That(result.Source, Is.EqualTo(typeof(CopriCallsHttps)));
|
|
Assert.That(result.Exception, Is.Null);
|
|
|
|
await server.Received().GetBikesAvailable(bikeId: bikeFilter);
|
|
await server.Received().GetBikesOccupied();
|
|
server.Received().AddToCache(resultBikesAvailableResponse, bikeId: bikeFilter);
|
|
server.Received().AddToCache(resultBikesOccupiedResponse);
|
|
}
|
|
|
|
[Test]
|
|
public async Task TestGetBikesOccupied()
|
|
{
|
|
var server = Substitute.For<ICachedCopriServer>();
|
|
|
|
server.GetBikesAvailable().Returns(Task.Run(() => new Result<BikesAvailableResponse>(
|
|
typeof(CopriCallsHttps),
|
|
JsonConvert.DeserializeObject<BikesAvailableResponse>("{}"),
|
|
new GeneralData())));
|
|
|
|
server.GetBikesOccupied().Returns(Task.Run(() => new Result<BikesReservedOccupiedResponse>(
|
|
typeof(CopriCallsHttps),
|
|
JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED),
|
|
new GeneralData())));
|
|
|
|
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesOccupiedAsync();
|
|
|
|
Assert.That(result.Response.Count, Is.EqualTo(1));
|
|
Assert.That(result.Source, Is.EqualTo(typeof(CopriCallsHttps)));
|
|
Assert.That(result.Exception, Is.Null);
|
|
}
|
|
|
|
[Test]
|
|
public async Task TestGetBikesAsyncOperatorUri()
|
|
{
|
|
var server = Substitute.For<ICachedCopriServer>();
|
|
|
|
var resultBikesAvailableResponse = new Result<BikesAvailableResponse>(
|
|
typeof(CopriCallsHttps),
|
|
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE2),
|
|
new GeneralData());
|
|
|
|
var uri = new Uri("https://shareeapp-fr01.copri.eu//APIjsonserver");
|
|
var station = "StationX";
|
|
|
|
server.GetBikesAvailable(operatorUri: Arg.Any<Uri>(), stationId: station).Returns(Task.Run(() => resultBikesAvailableResponse));
|
|
|
|
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAsync(uri, station);
|
|
|
|
await server.DidNotReceive().GetBikesOccupied();
|
|
await server.DidNotReceive().GetBikesOccupied(Arg.Any<bool>());
|
|
server.Received().AddToCache(Arg.Any<Result<BikesAvailableResponse>>(), Arg.Any<Uri>(), station);
|
|
|
|
Assert.That(result.Response.Count, Is.EqualTo(3));
|
|
Assert.That(result.Source, Is.EqualTo(typeof(CopriCallsHttps)));
|
|
Assert.That(result.Exception, Is.Null);
|
|
|
|
await server.Received().GetBikesAvailable(operatorUri: uri, stationId: station);
|
|
server.Received().AddToCache(resultBikesAvailableResponse, operatorUri: uri, stationId: station);
|
|
await server.DidNotReceive().GetBikesOccupied();
|
|
server.DidNotReceive().AddToCache(Arg.Any<Result<BikesReservedOccupiedResponse>>());
|
|
}
|
|
|
|
[Test]
|
|
public async Task TestGetBikesAsyncOperatorUriCache()
|
|
{
|
|
var server = Substitute.For<ICachedCopriServer>();
|
|
|
|
var uri = new Uri("https://shareeapp-fr01.copri.eu//APIjsonserver");
|
|
|
|
server.GetBikesAvailable(operatorUri: Arg.Any<Uri>()).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
|
|
typeof(CopriCallsMonkeyStore),
|
|
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE2),
|
|
new GeneralData())));
|
|
|
|
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAsync(uri);
|
|
|
|
await server.Received().GetBikesAvailable(operatorUri: uri);
|
|
await server.DidNotReceive().GetBikesOccupied();
|
|
await server.DidNotReceive().GetBikesOccupied(Arg.Any<bool>());
|
|
server.DidNotReceive().AddToCache(Arg.Any<Result<BikesAvailableResponse>>(), Arg.Any<Uri>());
|
|
server.DidNotReceive().AddToCache(Arg.Any<Result<BikesReservedOccupiedResponse>>());
|
|
|
|
Assert.That(result.Response.Count, Is.EqualTo(3));
|
|
Assert.That(result.Source, Is.EqualTo(typeof(CopriCallsMonkeyStore)));
|
|
Assert.That(result.Exception, Is.Null);
|
|
}
|
|
}
|
|
}
|