mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2025-01-21 20:14:27 +01:00
Tests fixed.
This commit is contained in:
parent
4df8aa98aa
commit
8aa3089f32
15 changed files with 779 additions and 82 deletions
|
@ -23,7 +23,7 @@
|
|||
<br />Version ACTIVE_APPNAME: <b>CURRENT_VERSION_TINKAPP</b>.
|
||||
<div class="content_title2">Entwickler</div>
|
||||
<div style=""></div>
|
||||
<br />Programmierung ACTIVE_APPNAME: O. Hauff, o.hauff@sharee.bike.<br />
|
||||
<br />Programmierung ACTIVE_APPNAME: O. Hauff, app@sharee.bike<br />
|
||||
<div class="content_title2">Verwendete Bibliotheken</div>
|
||||
<div style=""></div>
|
||||
<br /><table>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<br />Version ACTIVE_APPNAME: <b>CURRENT_VERSION_TINKAPP</b>.
|
||||
<div class="content_title2">Entwickler</div>
|
||||
<div style=""></div>
|
||||
<br />Programmierung ACTIVE_APPNAME: O. Hauff, o.hauff@sharee.bike.<br />
|
||||
<br />Programmierung ACTIVE_APPNAME: O. Hauff, app@sharee.bike<br />
|
||||
<div class="content_title2">Verwendete Bibliotheken</div>
|
||||
<div style=""></div>
|
||||
<br /><table>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<br />Version ACTIVE_APPNAME: <b>CURRENT_VERSION_TINKAPP</b>.
|
||||
<div class="content_title2">Entwickler</div>
|
||||
<div style=""></div>
|
||||
<br />Programmierung ACTIVE_APPNAME: O. Hauff, o.hauff@sharee.bike.<br />
|
||||
<br />Programmierung ACTIVE_APPNAME: O. Hauff, app@sharee.bike<br />
|
||||
<div class="content_title2">Verwendete Bibliotheken</div>
|
||||
<div style=""></div>
|
||||
<br /><table>
|
||||
|
|
|
@ -36,36 +36,36 @@ namespace TINK.Model.Connector
|
|||
/// If communication fails an exception is thrown.
|
||||
/// </summary>
|
||||
public async Task<IAccount> DoLogin(
|
||||
string p_strMail,
|
||||
string p_strPassword,
|
||||
string p_strDeviceId)
|
||||
string mail,
|
||||
string password,
|
||||
string deviceId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(p_strMail))
|
||||
if (string.IsNullOrEmpty(mail))
|
||||
{
|
||||
throw new ArgumentNullException("Can not loging user. Mail address must not be null or empty.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(p_strPassword))
|
||||
if (string.IsNullOrEmpty(password))
|
||||
{
|
||||
throw new ArgumentNullException("Can not loging user. Password must not be null or empty.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(p_strDeviceId))
|
||||
if (string.IsNullOrEmpty(deviceId))
|
||||
{
|
||||
throw new ArgumentNullException("Can not loging user. Device not be null or empty.");
|
||||
}
|
||||
|
||||
AuthorizationResponse l_oResponse;
|
||||
AuthorizationResponse response;
|
||||
try
|
||||
{
|
||||
l_oResponse = (await CopriServer.DoAuthorizationAsync(p_strMail, p_strPassword, p_strDeviceId)).GetIsResponseOk(p_strMail);
|
||||
response = (await CopriServer.DoAuthorizationAsync(mail, password, deviceId)).GetIsResponseOk(mail);
|
||||
}
|
||||
catch (System.Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
var l_oAccount = l_oResponse.GetAccount(MerchantId, p_strMail, p_strPassword);
|
||||
var l_oAccount = response.GetAccount(MerchantId, mail, password);
|
||||
|
||||
// Log in state changes. Notify parent object to update.
|
||||
LoginStateChanged?.Invoke(this, new LoginStateChangedEventArgs(l_oAccount.SessionCookie, l_oAccount.Mail));
|
||||
|
@ -83,9 +83,9 @@ namespace TINK.Model.Connector
|
|||
/// <summary>
|
||||
/// Request to reserve a bike.
|
||||
/// </summary>
|
||||
/// <param name="p_oBike">Bike to book.</param>
|
||||
/// <param name="bike">Bike to book.</param>
|
||||
public async Task DoReserve(
|
||||
Bikes.Bike.BC.IBikeInfoMutable p_oBike)
|
||||
Bikes.Bike.BC.IBikeInfoMutable bike)
|
||||
{
|
||||
Log.ForContext<Command>().Error("Unexpected booking request detected. No user logged in.");
|
||||
await Task.CompletedTask;
|
||||
|
|
|
@ -5,12 +5,13 @@ namespace TINK.Model.Connector
|
|||
public static class FilteredConnectorFactory
|
||||
{
|
||||
/// <summary> Creates a filter object. </summary>
|
||||
/// <param name="group"></param>
|
||||
/// <param name="group">Filter to apply on stations and bikes.</param>
|
||||
/// <param name="connector">Connector to connect to COPRI.</param>
|
||||
public static IFilteredConnector Create(IEnumerable<string> group, IConnector connector)
|
||||
{
|
||||
return group != null
|
||||
? (IFilteredConnector) new FilteredConnector(group, connector)
|
||||
: new NullFilterConnector(connector);
|
||||
: new NullFilterConnector(connector); // Do not apply filtering.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ namespace TINK.Model.Connector
|
|||
{
|
||||
if (loginResponse == null)
|
||||
{
|
||||
throw new ArgumentNullException("p_oLoginResponse");
|
||||
throw new ArgumentNullException(nameof(loginResponse));
|
||||
}
|
||||
|
||||
return new Account(
|
||||
|
@ -165,13 +165,13 @@ namespace TINK.Model.Connector
|
|||
}
|
||||
|
||||
/// <summary> Gets bikes available from copri server response.</summary>
|
||||
/// <param name="p_oBikesAvailableResponse">Response to create collection from.</param>
|
||||
/// <param name="bikesAvailableResponse">Response to create collection from.</param>
|
||||
/// <returns>New collection of available bikes.</returns>
|
||||
public static BikeCollection GetBikesAvailable(
|
||||
this BikesAvailableResponse p_oBikesAvailableResponse)
|
||||
this BikesAvailableResponse bikesAvailableResponse)
|
||||
{
|
||||
return GetBikesAll(
|
||||
p_oBikesAvailableResponse,
|
||||
bikesAvailableResponse,
|
||||
new BikesReservedOccupiedResponse(), // There are no occupied bikes.
|
||||
string.Empty,
|
||||
() => DateTime.Now);
|
||||
|
@ -198,8 +198,8 @@ namespace TINK.Model.Connector
|
|||
public static BikeCollection GetBikesAll(
|
||||
BikesAvailableResponse bikesAvailableResponse,
|
||||
BikesReservedOccupiedResponse bikesOccupiedResponse,
|
||||
string p_strMail,
|
||||
Func<DateTime> p_oDateTimeProvider)
|
||||
string mail,
|
||||
Func<DateTime> dateTimeProvider)
|
||||
{
|
||||
var bikesDictionary = new Dictionary<string, BikeInfo>();
|
||||
var duplicates = new Dictionary<string, BikeInfo>();
|
||||
|
@ -242,8 +242,8 @@ namespace TINK.Model.Connector
|
|||
{
|
||||
BikeInfo bikeInfo = BikeInfoFactory.Create(
|
||||
bikeInfoResponse,
|
||||
p_strMail,
|
||||
p_oDateTimeProvider);
|
||||
mail,
|
||||
dateTimeProvider);
|
||||
|
||||
if (bikeInfo == null)
|
||||
{
|
||||
|
|
|
@ -147,7 +147,7 @@ namespace TINK.Model
|
|||
public TinkApp(
|
||||
Settings.Settings settings,
|
||||
IStore accountStore,
|
||||
Func<bool, Uri, string, string, TimeSpan, IConnector> connectorFactory,
|
||||
Func<bool, Uri, string /* session cookie*/, string /* mail address*/, TimeSpan, IConnector> connectorFactory,
|
||||
IServicesContainer<IGeolocation> geolocationServicesContainer,
|
||||
ILocksService locksService,
|
||||
ISmartDevice device,
|
||||
|
|
|
@ -6,12 +6,12 @@ namespace TINK.Model.User.Account
|
|||
public static class AccountExtensions
|
||||
{
|
||||
/// <summary> Gets information whether user is logged in or not from account object. </summary>
|
||||
/// <param name="p_oAccount">Object to get information from.</param>
|
||||
/// <param name="account">Object to get information from.</param>
|
||||
/// <returns>True if user is logged in, false if not.</returns>
|
||||
public static bool GetIsLoggedIn(this IAccount p_oAccount)
|
||||
public static bool GetIsLoggedIn(this IAccount account)
|
||||
{
|
||||
return !string.IsNullOrEmpty(p_oAccount.Mail)
|
||||
&& !string.IsNullOrEmpty(p_oAccount.SessionCookie);
|
||||
return !string.IsNullOrEmpty(account.Mail)
|
||||
&& !string.IsNullOrEmpty(account.SessionCookie);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -12,10 +12,6 @@ namespace TINK.Model.User.Account
|
|||
/// </summary>
|
||||
private Account m_oAccount;
|
||||
|
||||
/// <summary> Prevents an invalid instance to be created. </summary>
|
||||
private AccountMutable()
|
||||
{
|
||||
}
|
||||
|
||||
public AccountMutable(IAccount p_oSource)
|
||||
{
|
||||
|
|
|
@ -13,15 +13,13 @@ namespace TINK.Model.User
|
|||
/// </summary>
|
||||
public class User : IUser
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds account data.
|
||||
/// </summary>
|
||||
private readonly AccountMutable m_oAccount;
|
||||
/// <summary> Holds account data. </summary>
|
||||
private AccountMutable Account { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Provides storing functionality.
|
||||
/// </summary>
|
||||
private IStore m_oStore;
|
||||
private IStore Store { get; }
|
||||
|
||||
/// <summary> Holds the id of the device. </summary>
|
||||
public string DeviceId { get; }
|
||||
|
@ -34,10 +32,10 @@ namespace TINK.Model.User
|
|||
IAccount account,
|
||||
string deviceId)
|
||||
{
|
||||
m_oStore = accountStore
|
||||
Store = accountStore
|
||||
?? throw new ArgumentException("Can not instantiate user- object. No store functionality available.");
|
||||
DeviceId = deviceId;
|
||||
m_oAccount = new AccountMutable(account);
|
||||
Account = new AccountMutable(account);
|
||||
}
|
||||
|
||||
/// <summary> Is fired wheneverlogin state changes. </summary>
|
||||
|
@ -46,19 +44,14 @@ namespace TINK.Model.User
|
|||
/// <summary>
|
||||
/// Holds a value indicating whether user is logged in or not.
|
||||
/// </summary>
|
||||
public bool IsLoggedIn {
|
||||
get
|
||||
{
|
||||
return m_oAccount.GetIsLoggedIn();
|
||||
}
|
||||
}
|
||||
public bool IsLoggedIn => Account.GetIsLoggedIn();
|
||||
|
||||
/// <summary>
|
||||
/// Holds the mail address.
|
||||
/// </summary>
|
||||
public string Mail
|
||||
{
|
||||
get { return m_oAccount.Mail; }
|
||||
get { return Account.Mail; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -66,24 +59,24 @@ namespace TINK.Model.User
|
|||
/// </summary>
|
||||
public string SessionCookie
|
||||
{
|
||||
get { return m_oAccount.SessionCookie; }
|
||||
get { return Account.SessionCookie; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Holds the password.
|
||||
/// </summary>
|
||||
public string Password
|
||||
{
|
||||
get { return m_oAccount.Pwd; }
|
||||
get { return Account.Pwd; }
|
||||
}
|
||||
|
||||
/// <summary>Holds the debug level.</summary>
|
||||
public Permissions DebugLevel
|
||||
{
|
||||
get { return m_oAccount.DebugLevel; }
|
||||
get { return Account.DebugLevel; }
|
||||
}
|
||||
|
||||
/// <summary> Holds the group of the bike (TINK, Konrad, ...).</summary>
|
||||
public IEnumerable<string> Group { get { return m_oAccount.Group; } }
|
||||
public IEnumerable<string> Group { get { return Account.Group; } }
|
||||
|
||||
/// <summary> Logs in user. </summary>
|
||||
/// <param name="p_oAccount">Account to use for login.</param>
|
||||
|
@ -93,7 +86,7 @@ namespace TINK.Model.User
|
|||
{
|
||||
if (IsLoggedIn)
|
||||
{
|
||||
throw new Exception($"Can not log in user {mail} because user {m_oAccount} is already logged in.");
|
||||
throw new Exception($"Can not log in user {mail} because user {Account} is already logged in.");
|
||||
}
|
||||
|
||||
// Check if password might be valid before connecting to copri.
|
||||
|
@ -113,10 +106,10 @@ namespace TINK.Model.User
|
|||
public async Task Login(IAccount account)
|
||||
{
|
||||
// Update account instance from copri data.
|
||||
m_oAccount.Copy(account);
|
||||
Account.Copy(account);
|
||||
|
||||
// Save data to store.
|
||||
await m_oStore.Save(m_oAccount);
|
||||
await Store.Save(Account);
|
||||
|
||||
// Nothing to do because state did not change.
|
||||
StateChanged?.Invoke(this, new EventArgs());
|
||||
|
@ -128,7 +121,7 @@ namespace TINK.Model.User
|
|||
{
|
||||
var l_oPreviousState = IsLoggedIn;
|
||||
|
||||
m_oAccount.Copy(m_oStore.Delete(m_oAccount));
|
||||
Account.Copy(Store.Delete(Account));
|
||||
|
||||
if (IsLoggedIn == l_oPreviousState)
|
||||
{
|
||||
|
@ -144,11 +137,11 @@ namespace TINK.Model.User
|
|||
/// Some user may be "TINK"- user only, some "Konrad" and some may be "TINK" and "Konrad" users.
|
||||
/// </summary>
|
||||
/// <param name="p_oAccount">Account to filter with.</param>
|
||||
/// <param name="p_oSource">Groups to filter..</param>
|
||||
/// <param name="source">Groups to filter..</param>
|
||||
/// <returns>Filtered bike groups.</returns>
|
||||
public IEnumerable<string> DoFilter(IEnumerable<string> p_oSource = null)
|
||||
public IEnumerable<string> DoFilter(IEnumerable<string> source = null)
|
||||
{
|
||||
return m_oAccount.DoFilter(p_oSource);
|
||||
return Account.DoFilter(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1264,7 +1264,7 @@ namespace TINK.Repository
|
|||
}
|
||||
}";
|
||||
|
||||
private const SampleSets DEFAULT_SAMPLE_SET = SampleSets.Set2;
|
||||
private const SampleSets DEFAULT_SAMPLE_SET = SampleSets.Set2;
|
||||
|
||||
private const int DEFAULT_STAGE_INDEX = 1;
|
||||
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
using System;
|
||||
using TINK.Model;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Repository;
|
||||
using TINK.Model.Services.CopriApi.ServerUris;
|
||||
using static TINK.Repository.CopriCallsMemory;
|
||||
using TINK.Services;
|
||||
using NSubstitute;
|
||||
using TINK.Model.Services.Geolocation;
|
||||
|
@ -12,8 +10,8 @@ using TINK.Services.BluetoothLock;
|
|||
using TINK.Model.Device;
|
||||
using TINK.Model.User.Account;
|
||||
using Plugin.Permissions.Abstractions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using TestShareeLib.Repository;
|
||||
|
||||
namespace TestTINKLib.Fixtures.UseCases.Logout
|
||||
{
|
||||
|
@ -32,9 +30,8 @@ namespace TestTINKLib.Fixtures.UseCases.Logout
|
|||
|
||||
accountStore.Load().Returns(account);
|
||||
account.Mail.Returns("javaminister@gmail.com");
|
||||
account.Pwd.Returns("javaminister");
|
||||
account.SessionCookie.Returns("4da3044c8657a04ba60e2eaa753bc51a");
|
||||
account.Group.Returns(new List<string> { "TINK" });
|
||||
account.Pwd.Returns("*********");
|
||||
account.SessionCookie.Returns("6103_112e96b36ba33de245943c5ffaf369cd_");
|
||||
|
||||
// No user logged in is initial state to verify.
|
||||
var l_oTinkApp = new TinkApp(
|
||||
|
@ -44,8 +41,8 @@ namespace TestTINKLib.Fixtures.UseCases.Logout
|
|||
activeUri: new Uri(CopriServerUriList.TINK_DEVEL)),
|
||||
accountStore,
|
||||
(isConnected, uri, sessionCookie, mail, expiresAfter) => string.IsNullOrEmpty(sessionCookie)
|
||||
? new ConnectorCache(sessionCookie, mail, new CopriCallsMemory(SampleSets.Set2, 1))
|
||||
: new ConnectorCache(sessionCookie, mail, new CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)),
|
||||
? new ConnectorCache(sessionCookie, mail, new CopriCallsMemory001())
|
||||
: new ConnectorCache(sessionCookie, mail, new CopriCallsMemory001(sessionCookie)),
|
||||
Substitute.For<IServicesContainer<IGeolocation>>(),
|
||||
locksService,
|
||||
device,
|
||||
|
@ -57,17 +54,29 @@ namespace TestTINKLib.Fixtures.UseCases.Logout
|
|||
lastVersion: new Version(3, 0, 173)); // Current app version. Must be larger or equal 3.0.173 to
|
||||
|
||||
Assert.IsTrue(l_oTinkApp.ActiveUser.IsLoggedIn);
|
||||
Assert.AreEqual(13, l_oTinkApp.GetConnector(true).Query.GetBikesAsync().Result.Response.Count);
|
||||
Assert.AreEqual(2, l_oTinkApp.GetConnector(true).Query.GetBikesOccupiedAsync().Result.Response.Count);
|
||||
Assert.AreEqual("4da3044c8657a04ba60e2eaa753bc51a", l_oTinkApp.GetConnector(true).Command.SessionCookie);
|
||||
// There are 6 bikes available and 2, one reserved and one rented by javaminsiter.
|
||||
Assert.AreEqual(
|
||||
8,
|
||||
l_oTinkApp.GetConnector(true).Query.GetBikesAsync().Result.Response.Count,
|
||||
"Sum of bikes is 6 occupied plus 2 occupied.");
|
||||
Assert.AreEqual(2,
|
||||
l_oTinkApp.GetConnector(true).Query.GetBikesOccupiedAsync().Result.Response.Count,
|
||||
"Javaminster occupies 2 bikes.");
|
||||
Assert.AreEqual("6103_112e96b36ba33de245943c5ffaf369cd_", l_oTinkApp.GetConnector(true).Command.SessionCookie);
|
||||
|
||||
// Log user out.
|
||||
l_oTinkApp.GetConnector(true).Command.DoLogout().Wait();
|
||||
l_oTinkApp.ActiveUser.Logout();
|
||||
|
||||
Assert.IsFalse(l_oTinkApp.ActiveUser.IsLoggedIn);
|
||||
Assert.AreEqual(11, l_oTinkApp.GetConnector(true).Query.GetBikesAsync().Result.Response.Count);
|
||||
Assert.AreEqual(0, l_oTinkApp.GetConnector(true).Query.GetBikesOccupiedAsync().Result.Response.Count);
|
||||
Assert.AreEqual(
|
||||
6,
|
||||
l_oTinkApp.GetConnector(true).Query.GetBikesAsync().Result.Response.Count,
|
||||
"Sum of bikes is 6 occupied, no one occupied because no user is logged in");
|
||||
Assert.AreEqual(
|
||||
0,
|
||||
l_oTinkApp.GetConnector(true).Query.GetBikesOccupiedAsync().Result.Response.Count,
|
||||
"If no user is logged in no occupied bikes are shown.");
|
||||
Assert.IsNull(l_oTinkApp.GetConnector(true).Command.SessionCookie);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,10 +13,10 @@ using TINK.Model.Device;
|
|||
using TINK.Model.User.Account;
|
||||
using Plugin.Permissions.Abstractions;
|
||||
using System.Threading.Tasks;
|
||||
using TestShareeLib.Repository;
|
||||
|
||||
namespace TestTINKLib.Fixtures.UseCases.Login
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
public class TestTinkApp
|
||||
{
|
||||
|
@ -37,8 +37,8 @@ namespace TestTINKLib.Fixtures.UseCases.Login
|
|||
activeUri: new Uri(CopriServerUriList.TINK_DEVEL)),
|
||||
accountStore,
|
||||
(isConnected, uri, sessionCookie, mail, expiresAfter) => string.IsNullOrEmpty(sessionCookie)
|
||||
? new ConnectorCache(sessionCookie, mail, new CopriCallsMemory(SampleSets.Set2, 1)) as IConnector
|
||||
: new ConnectorCache(sessionCookie, mail, new CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)),
|
||||
? new ConnectorCache(sessionCookie, mail, new CopriCallsMemory001()) as IConnector
|
||||
: new ConnectorCache(sessionCookie, mail, new CopriCallsMemory001(sessionCookie)),
|
||||
Substitute.For<IServicesContainer<IGeolocation>>(),
|
||||
locksService,
|
||||
device,
|
||||
|
@ -50,18 +50,30 @@ namespace TestTINKLib.Fixtures.UseCases.Login
|
|||
lastVersion: new Version(3, 0, 173) /* Current app version. Must be larger or equal 3.0.173 to lastVersion*/);
|
||||
|
||||
Assert.IsFalse(l_oTinkApp.ActiveUser.IsLoggedIn);
|
||||
Assert.AreEqual(11, l_oTinkApp.GetConnector(true).Query.GetBikesAsync().Result.Response.Count);
|
||||
Assert.AreEqual(0, l_oTinkApp.GetConnector(true).Query.GetBikesOccupiedAsync().Result.Response.Count);
|
||||
Assert.AreEqual(
|
||||
6,
|
||||
l_oTinkApp.GetConnector(true).Query.GetBikesAsync().Result.Response.Count,
|
||||
"Sum of bikes is 6 occupied, no one occupied because no user is logged in");
|
||||
Assert.AreEqual(
|
||||
0,
|
||||
l_oTinkApp.GetConnector(true).Query.GetBikesOccupiedAsync().Result.Response.Count,
|
||||
"If no user is logged in no occupied bikes are shown.");
|
||||
Assert.IsNull(l_oTinkApp.GetConnector(true).Command.SessionCookie);
|
||||
|
||||
// Log user out.
|
||||
var l_oAccount = l_oTinkApp.GetConnector(true).Command.DoLogin("javaminister@gmail.com", "javaminister", "HwId1000000000000").Result;
|
||||
var l_oAccount = l_oTinkApp.GetConnector(true).Command.DoLogin("javaminister@gmail.com", "*********", "HwId1000000000000").Result;
|
||||
await l_oTinkApp.ActiveUser.Login(l_oAccount);
|
||||
|
||||
Assert.IsTrue(l_oTinkApp.ActiveUser.IsLoggedIn);
|
||||
Assert.AreEqual(13, l_oTinkApp.GetConnector(true).Query.GetBikesAsync().Result.Response.Count);
|
||||
Assert.AreEqual(2, l_oTinkApp.GetConnector(true).Query.GetBikesOccupiedAsync().Result.Response.Count);
|
||||
Assert.AreEqual("4da3044c8657a04ba60e2eaa753bc51a", l_oTinkApp.GetConnector(true).Command.SessionCookie);
|
||||
Assert.AreEqual(
|
||||
8,
|
||||
l_oTinkApp.GetConnector(true).Query.GetBikesAsync().Result.Response.Count,
|
||||
"Sum of bikes is 6 occupied plus 2 occupied.");
|
||||
Assert.AreEqual(
|
||||
2,
|
||||
l_oTinkApp.GetConnector(true).Query.GetBikesOccupiedAsync().Result.Response.Count,
|
||||
"Javaminster occupies 2 bikes.");
|
||||
Assert.AreEqual("6103_112e96b36ba33de245943c5ffaf369cd_", l_oTinkApp.GetConnector(true).Command.SessionCookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
283
TestShareeLib/Repository/CopriCallMemoryBase.cs
Normal file
283
TestShareeLib/Repository/CopriCallMemoryBase.cs
Normal file
|
@ -0,0 +1,283 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Repository;
|
||||
using TINK.Repository.Request;
|
||||
using TINK.Repository.Response;
|
||||
|
||||
namespace TestShareeLib.Repository
|
||||
{
|
||||
/// <summary> Provides functionality for keeping a set of COPRI responses. </summary>
|
||||
public abstract class CopriCallMemoryBase
|
||||
{
|
||||
private string BikesAvailableResponse { get; }
|
||||
|
||||
private string BikesOccupiedResponse { get; }
|
||||
|
||||
private string AuthResponse { get; }
|
||||
|
||||
private string AuthOutResponse { get; }
|
||||
|
||||
private string Stations { get; }
|
||||
|
||||
private string BookingRequestResponse { get; }
|
||||
|
||||
private string CancelBookingRequestResponse { get; }
|
||||
|
||||
private IRequestBuilder requestBuilder;
|
||||
|
||||
public CopriCallMemoryBase(
|
||||
string bikesAvailableResponse = null,
|
||||
string bikesOccupiedResponse = null,
|
||||
string authResponse = null,
|
||||
string authOutResponse = null,
|
||||
string stations = null,
|
||||
string bookingRequestResponse = null,
|
||||
string cancelBookingRequestResponse = null,
|
||||
string sessionCookie = null)
|
||||
{
|
||||
SessionCookie = sessionCookie;
|
||||
|
||||
BikesAvailableResponse = bikesAvailableResponse;
|
||||
BikesOccupiedResponse = bikesOccupiedResponse;
|
||||
AuthResponse = authResponse;
|
||||
AuthOutResponse = authOutResponse;
|
||||
BookingRequestResponse = bookingRequestResponse;
|
||||
CancelBookingRequestResponse = cancelBookingRequestResponse;
|
||||
|
||||
Stations = stations;
|
||||
|
||||
requestBuilder = string.IsNullOrEmpty(sessionCookie)
|
||||
? new RequestBuilder(MerchantId) as IRequestBuilder
|
||||
: new RequestBuilderLoggedIn(MerchantId, sessionCookie);
|
||||
|
||||
}
|
||||
|
||||
/// <summary> Holds the session id of the logged in user, null otherwise. </summary>
|
||||
public string SessionCookie { get; private set; }
|
||||
|
||||
/// <summary> Logs user in. </summary>
|
||||
/// <param name="p_oUser">User to log in.</param>
|
||||
/// <param name="deviceId">Id specifying user and hardware.</param>
|
||||
/// <param name="mailAddress">Mailaddress of user to log in.</param>
|
||||
/// <param name="password">Password to log in.</param>
|
||||
/// <remarks>Response which holds auth cookie <see cref="ResponseBase.authcookie"/></remarks>
|
||||
public async Task<AuthorizationResponse> DoAuthorizationAsync(
|
||||
string mailAddress,
|
||||
string password,
|
||||
string deviceId)
|
||||
=> await Task.Run(() => DoAuthorize(AuthResponse, mailAddress, password, deviceId));
|
||||
|
||||
/// <summary> Logs user out. </summary>
|
||||
/// <param name="sessionCookie">User to log in.</param>
|
||||
/// <remarks>Response which holds auth cookie <see cref="ResponseBase.authcookie"/></remarks>
|
||||
public async Task<AuthorizationoutResponse> DoAuthoutAsync()
|
||||
=> await Task.Run(() => DoAuthout(AuthOutResponse, SessionCookie));
|
||||
|
||||
/// <summary>
|
||||
/// Gets list of bikes from memory.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<BikesAvailableResponse> GetBikesAvailableAsync()
|
||||
=> await Task.Run(() => GetBikesAvailable(BikesAvailableResponse, null, SessionCookie));
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of bikes reserved/ booked by acctive user from Copri.
|
||||
/// </summary>
|
||||
/// <param name="p_strSessionCookie">Cookie to authenticate user.</param>
|
||||
/// <returns>Response holding list of bikes.</returns>
|
||||
public async Task<BikesReservedOccupiedResponse> GetBikesOccupiedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
requestBuilder.GetBikesOccupied(); // Non mock implementation if ICopriServer call this member as well. To ensure comparable behaviour this member is called here as well.
|
||||
}
|
||||
catch (NotSupportedException)
|
||||
{
|
||||
// No user logged in.
|
||||
await Task.CompletedTask;
|
||||
return ResponseHelper.GetBikesOccupiedNone();
|
||||
}
|
||||
return await Task.Run(() => GetBikesOccupied(BikesOccupiedResponse, SessionCookie));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get list of stations from file.
|
||||
/// </summary>
|
||||
/// <param name="p_strCookie">Auto cookie of user if user is logged in.</param>
|
||||
/// <returns>List of files.</returns>
|
||||
public async Task<StationsAvailableResponse> GetStationsAsync()
|
||||
=> await Task.Run(() => GetStationsAll(Stations, null, SessionCookie));
|
||||
|
||||
/// <summary>
|
||||
/// Gets booking request response.
|
||||
/// </summary>
|
||||
/// <param name="bikeId">Id of the bike to book.</param>
|
||||
/// <returns>Booking response.</returns>
|
||||
public async Task<ReservationBookingResponse> DoReserveAsync(string bikeId, Uri operatorUri)
|
||||
=> await Task.Run(() => DoReserve(BookingRequestResponse, bikeId, SessionCookie));
|
||||
|
||||
/// <summary>
|
||||
/// Gets canel booking request response.
|
||||
/// </summary>
|
||||
/// <param name="bikeId">Id of the bike to book.</param>
|
||||
/// <param name="p_strCookie">Cookie of the logged in user.</param>
|
||||
/// <returns>Response on cancel booking request.</returns>
|
||||
public async Task<ReservationCancelReturnResponse> DoCancelReservationAsync(string bikeId, Uri operatorUri)
|
||||
=> await Task.Run(() => DoCancelReservation(CancelBookingRequestResponse, bikeId, SessionCookie));
|
||||
|
||||
|
||||
/// <summary> Gets the merchant id.</summary>
|
||||
public string MerchantId => TinkApp.MerchantId;
|
||||
|
||||
/// <summary> Returns false because cached values are returned. </summary>
|
||||
public bool IsConnected => false;
|
||||
|
||||
/// <summary> Logs user in. </summary>
|
||||
/// <param name="p_oUser">User to log in.</param>
|
||||
/// <param name="p_strDeviceId">Id specifying user and hardware.</param>
|
||||
/// <param name="p_strMailAddress">Mailaddress of user to log in.</param>
|
||||
/// <param name="p_strPassword">Password to log in.</param>
|
||||
/// <remarks>Response which holds auth cookie <see cref="ResponseBase.authcookie"/></remarks>
|
||||
public static AuthorizationResponse DoAuthorize(
|
||||
string DoAuthResponse,
|
||||
string p_strMailAddress,
|
||||
string p_strPassword,
|
||||
string p_strDeviceId)
|
||||
{
|
||||
return p_strMailAddress == "javaminister@gmail.com"
|
||||
&& p_strPassword == "*********" &&
|
||||
p_strDeviceId == "HwId1000000000000"
|
||||
? JsonConvertRethrow.DeserializeObject<ResponseContainer<AuthorizationResponse>>(DoAuthResponse).shareejson
|
||||
: JsonConvertRethrow.DeserializeObject<ResponseContainer<AuthorizationResponse>>(DO_AUTH_Unknown_User_FILE).shareejson;
|
||||
|
||||
}
|
||||
|
||||
/// <summary> Logs user in. </summary>
|
||||
/// <remarks>Response which holds auth cookie <see cref="ResponseBase.authcookie"/></remarks>
|
||||
public static AuthorizationoutResponse DoAuthout(
|
||||
string authOutResponse,
|
||||
string sessionCookie)
|
||||
{
|
||||
// Response contains auth cookie of user "JavaministerHardwareNr1"
|
||||
// For this reason do not return answer if mail and pwd do not match.
|
||||
|
||||
return !string.IsNullOrEmpty(sessionCookie)
|
||||
? JsonConvertRethrow.DeserializeObject<ResponseContainer<AuthorizationoutResponse>>(authOutResponse).shareejson
|
||||
: throw new NotSupportedException();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets list of bikes from memory.
|
||||
/// </summary>
|
||||
/// <param name="p_strMerchantId">Id of the merchant.</param>
|
||||
/// <param name="p_strSessionCookie">Auto cookie of user if user is logged in.</param>
|
||||
/// <param name="p_eSampleSet">Set of samples.</param>
|
||||
/// <param name="p_lStageIndex">Index of the stage.</param>
|
||||
/// <returns></returns>
|
||||
public static BikesAvailableResponse GetBikesAvailable(
|
||||
string BikesAvailableResponse,
|
||||
string p_strMerchantId,
|
||||
string p_strSessionCookie = null) => CopriCallsStatic.DeserializeResponse<BikesAvailableResponse>(BikesAvailableResponse);
|
||||
|
||||
/// <summary>
|
||||
/// Gets stations response.
|
||||
/// </summary>
|
||||
/// <param name="merchantId">Id of the merchant.</param>
|
||||
/// <param name="cookie">Auto cookie of user if user is logged in.</param>
|
||||
/// <param name="p_eSampleSet"></param>
|
||||
/// <param name="p_lStageIndex"></param>
|
||||
/// <returns></returns>
|
||||
public static StationsAvailableResponse GetStationsAll(
|
||||
string stations,
|
||||
string merchantId,
|
||||
string cookie = null)
|
||||
=> JsonConvertRethrow.DeserializeObject<ResponseContainer<StationsAvailableResponse>>(stations).shareejson;
|
||||
|
||||
/// <summary>
|
||||
/// Gets booking request response.
|
||||
/// </summary>
|
||||
/// <param name="bikeId">Id of the bike.</param>
|
||||
/// <param name="sessionCookie">Identifies the logged in user.</param>
|
||||
/// <param name="sampleSet">Sample set to use.</param>
|
||||
/// <param name="stageIndex">Index of the stage.</param>
|
||||
/// <returns></returns>
|
||||
public static ReservationBookingResponse DoReserve(
|
||||
string bookingRequestResponse,
|
||||
string bikeId,
|
||||
string sessionCookie)
|
||||
=> JsonConvertRethrow.DeserializeObject<ResponseContainer<ReservationBookingResponse>>(bookingRequestResponse).shareejson;
|
||||
|
||||
/// <summary>
|
||||
/// Gets canel booking request response.
|
||||
/// </summary>
|
||||
/// <param name="bikeId">Id of the bike to book.</param>
|
||||
/// <param name="cookie">Cookie of the logged in user.</param>
|
||||
/// <returns>Response on cancel booking request.</returns>
|
||||
public static ReservationCancelReturnResponse DoCancelReservation(
|
||||
string cancelBookingRequestResponse,
|
||||
string bikeId,
|
||||
string cookie)
|
||||
=> JsonConvertRethrow.DeserializeObject<ResponseContainer<ReservationCancelReturnResponse>>(cancelBookingRequestResponse).shareejson;
|
||||
|
||||
public Task<ReservationBookingResponse> CalculateAuthKeysAsync(string bikeId, Uri operatorUri)
|
||||
=> null;
|
||||
|
||||
public Task<ReservationBookingResponse> UpdateLockingStateAsync(
|
||||
string bikeId,
|
||||
LocationDto geolocation,
|
||||
lock_state state,
|
||||
double batteryLevel,
|
||||
Uri operatorUri)
|
||||
=> null;
|
||||
|
||||
public Task<ReservationBookingResponse> DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri)
|
||||
=> null;
|
||||
|
||||
public Task<ReservationCancelReturnResponse> DoReturn(
|
||||
string bikeId,
|
||||
LocationDto geolocation,
|
||||
ISmartDevice smartDevice,
|
||||
Uri operatorUri)
|
||||
=> null;
|
||||
|
||||
public Task<SubmitFeedbackResponse> DoSubmitFeedback(string bikeId, string message, bool isBikeBroken, Uri operatorUri)
|
||||
=> null;
|
||||
|
||||
/// <summary> Submits mini survey to copri server. </summary>
|
||||
/// <param name="answers">Collection of answers.</param>
|
||||
public Task<ResponseBase> DoSubmitMiniSurvey(IDictionary<string, string> answers)
|
||||
=> null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of bikes reserved/ booked by acctive user from Copri.
|
||||
/// </summary>
|
||||
/// <param name="sessionCookie">Cookie to authenticate user.</param>
|
||||
/// <param name="SampleSet">Sample set to use.</param>
|
||||
/// <param name="p_lStageIndex">Index of the stage.</param>
|
||||
/// <returns>Response holding list of bikes.</returns>
|
||||
public static BikesReservedOccupiedResponse GetBikesOccupied(
|
||||
string bikesOccupied,
|
||||
string sessionCookie = null)
|
||||
{
|
||||
var response = CopriCallsStatic.DeserializeResponse<BikesReservedOccupiedResponse>(bikesOccupied);
|
||||
return sessionCookie != null && (response?.authcookie?.Contains(sessionCookie) ?? false)
|
||||
? response
|
||||
: ResponseHelper.GetBikesOccupiedNone(sessionCookie);
|
||||
|
||||
}
|
||||
|
||||
public const string DO_AUTH_Unknown_User_FILE = @"
|
||||
{
|
||||
""shareejson"" : {
|
||||
""response"" : ""authorization"",
|
||||
""authcookie"" : 0,
|
||||
""response_state"" : ""Failure: cannot generate authcookie"",
|
||||
""apiserver"" : ""https://tinkwwp.copri-bike.de""
|
||||
}
|
||||
}";
|
||||
}
|
||||
}
|
403
TestShareeLib/Repository/CopriCallsMemory001.cs
Normal file
403
TestShareeLib/Repository/CopriCallsMemory001.cs
Normal file
|
@ -0,0 +1,403 @@
|
|||
using TINK.Repository;
|
||||
|
||||
namespace TestShareeLib.Repository
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds some COPRI responses for testing purposes.
|
||||
/// </summary>
|
||||
/// <remarks> Holds some demo Meinkonrad and LastenradBayern bikes
|
||||
/// </remarks>
|
||||
public class CopriCallsMemory001 : CopriCallMemoryBase, ICopriServer
|
||||
{
|
||||
public CopriCallsMemory001(string sessionCookie = null) : base(
|
||||
bikesAvailableResponse: BikesAvailableResponse,
|
||||
bikesOccupiedResponse: BikesOccupiedResponse,
|
||||
authResponse: AuthResponse,
|
||||
authOutResponse: AuthOutResponse,
|
||||
sessionCookie: sessionCookie)
|
||||
{ }
|
||||
|
||||
private static string AuthResponse => @"{
|
||||
""shareejson"": {
|
||||
""clearing_cache"": ""0"",
|
||||
""privacy_html"": ""site/privacy.html"",
|
||||
""user_id"": ""javaminister@gmail.com"",
|
||||
""impress_html"": ""site/impress.html"",
|
||||
""tariff_info_html"": ""site/tariff_info_1.html"",
|
||||
""lang"": ""DE"",
|
||||
""last_used_operator"": {
|
||||
""operator_name"": ""sharee.bike | TeilRad GmbH"",
|
||||
""operator_hours"": ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||
""operator_phone"": ""+49 761 45370097"",
|
||||
""operator_email"": ""hotline@sharee.bike"",
|
||||
""operator_color"": ""#009699""
|
||||
},
|
||||
""response"": ""authorization"",
|
||||
""agb_checked"": ""0"",
|
||||
""agb_html"": ""site/agb.html"",
|
||||
""response_text"": ""Herzlich willkommen im Fahrradmietsystem"",
|
||||
""bike_info_html"": ""site/bike_info.html"",
|
||||
""debuglevel"": ""1"",
|
||||
""uri_primary"": ""https://shareeapp-primary.copri.eu"",
|
||||
""response_state"": ""OK, nothing todo"",
|
||||
""new_authcoo"": ""1"",
|
||||
""user_tour"": [],
|
||||
""authcookie"": ""6103_112e96b36ba33de245943c5ffaf369cd_oiF2kahH"",
|
||||
""copri_version"": ""4.1.8.21"",
|
||||
""apiserver"": ""https://shareeapp-fr01.copri.eu"",
|
||||
""user_group"": []
|
||||
}
|
||||
}";
|
||||
|
||||
private static string AuthOutResponse = @"{
|
||||
""shareejson"": {
|
||||
""copri_version"": ""4.1.8.21"",
|
||||
""authcookie"": ""1"",
|
||||
""user_tour"": [],
|
||||
""user_group"": null,
|
||||
""apiserver"": ""https://shareeapp-fr01.copri.eu"",
|
||||
""debuglevel"": ""1"",
|
||||
""uri_primary"": ""https://shareeapp-primary.copri.eu"",
|
||||
""bike_info_html"": ""site/bike_info.html"",
|
||||
""response_state"": ""OK, logout"",
|
||||
""new_authcoo"": ""0"",
|
||||
""lang"": ""DE"",
|
||||
""last_used_operator"": {
|
||||
""operator_hours"": ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||
""operator_name"": ""sharee.bike | TeilRad GmbH"",
|
||||
""operator_email"": ""hotline@sharee.bike"",
|
||||
""operator_phone"": ""+49 761 45370097"",
|
||||
""operator_color"": ""#009699""
|
||||
},
|
||||
""tariff_info_html"": ""site/tariff_info_1.html"",
|
||||
""impress_html"": ""site/impress.html"",
|
||||
""response_text"": ""Auf Wiedersehen."",
|
||||
""agb_html"": ""site/agb.html"",
|
||||
""response"": ""authout"",
|
||||
""agb_checked"": ""0"",
|
||||
""privacy_html"": ""site/privacy.html"",
|
||||
""clearing_cache"": ""0"",
|
||||
""user_id"": ""javaminister@gmail.com""
|
||||
}
|
||||
}";
|
||||
|
||||
private static string BikesOccupiedResponse => @"{
|
||||
""shareejson"": {
|
||||
""authcookie"": ""6103_112e96b36ba33de245943c5ffaf369cd_oiF2kahH"",
|
||||
""copri_version"": ""4.1.8.21"",
|
||||
""user_tour"": [],
|
||||
""user_group"": [
|
||||
""FR300103"",
|
||||
""FR300101""
|
||||
],
|
||||
""bikes_occupied"": {
|
||||
""157056"": {
|
||||
""K_seed"": ""[-20, -104, -112, -49, 3, -74, -43, -115, -53, 34, -48, -29, -64, -90, -26, -74]"",
|
||||
""uri_operator"": ""https://shareeapp-fr01.copri.eu"",
|
||||
""bike"": ""FR1544"",
|
||||
""unit_price"": ""3.00"",
|
||||
""description"": ""Contributor-Paul"",
|
||||
""station"": ""FR103"",
|
||||
""request_time"": ""2021-11-06 18:57:20.034438+01"",
|
||||
""Ilockit_ID"": ""ISHAREIT-2200544"",
|
||||
""total_price"": ""25.50"",
|
||||
""bike_group"": [
|
||||
""FR300103""
|
||||
],
|
||||
""K_u"": ""[43, -16, 72, -5, 23, -117, 43, 57, 124, -106, -115, 97, -93, -30, -34, -7, -21, 119, 109, 92, 0, 0, 0, 0]"",
|
||||
""computed_hours"": ""8.50"",
|
||||
""end_time"": ""2021-11-08 21:14:35"",
|
||||
""state"": ""occupied"",
|
||||
""tariff_description"": {
|
||||
""eur_per_hour"": ""3.00"",
|
||||
""number"": ""5494"",
|
||||
""max_eur_per_day"": ""10.00"",
|
||||
""name"": ""Tester Basic"",
|
||||
""free_hours"": ""0.50"",
|
||||
""track_info"": ""Ich stimme der Speicherung (Tracking) meiner Fahrstrecke zwecks wissenschaftlicher Auswertung und Berechnung der CO2-Einsparung zu!"",
|
||||
""operator_agb"": ""Mit der Mietrad Anmietung wird folgender Betreiber <a href='https://shareeapp-fr01.copri.eu/site/agb.html'>AGB</a> zugestimmt (als Demo sharee AGB).""
|
||||
},
|
||||
""lock_state"": ""locked"",
|
||||
""system"": ""Ilockit"",
|
||||
""gps"": {
|
||||
""latitude"": ""47.9994661873206"",
|
||||
""longitude"": ""7.7904340904206""
|
||||
},
|
||||
""real_hours"": ""50.2833333333333"",
|
||||
""Ilockit_GUID"": ""00000000-0000-0000-0000-dc969f648732"",
|
||||
""start_time"": ""2021-11-06 18:57:25.445447+01""
|
||||
},
|
||||
""157072"": {
|
||||
""bike"": ""FR1004"",
|
||||
""K_seed"": ""[-31, -81, -41, 95, 112, -113, -78, -22, 84, -112, -73, 31, -125, -49, 125, 10]"",
|
||||
""uri_operator"": ""https://shareeapp-fr01.copri.eu"",
|
||||
""bike_group"": [
|
||||
""FR300103""
|
||||
],
|
||||
""total_price"": ""0.00"",
|
||||
""description"": ""Contributor-Recumbent"",
|
||||
""station"": ""FR103"",
|
||||
""request_time"": ""2021-11-08 21:10:24.829395+01"",
|
||||
""Ilockit_ID"": ""ISHAREIT-2302373"",
|
||||
""unit_price"": ""3.00"",
|
||||
""end_time"": ""2021-11-08 21:10:00+01"",
|
||||
""state"": ""requested"",
|
||||
""tariff_description"": {
|
||||
""operator_agb"": ""Mit der Mietrad Anmietung wird folgender Betreiber <a href='https://shareeapp-fr01.copri.eu/site/agb.html'>AGB</a> zugestimmt (als Demo sharee AGB)."",
|
||||
""free_hours"": ""0.50"",
|
||||
""name"": ""Tester Basic"",
|
||||
""max_eur_per_day"": ""10.00"",
|
||||
""eur_per_hour"": ""3.00"",
|
||||
""number"": ""5494""
|
||||
},
|
||||
""computed_hours"": ""0"",
|
||||
""K_u"": ""[126, -125, 125, 83, 104, -121, -80, 40, 77, -35, 81, 27, 89, -124, -37, 57, 118, -113, 71, -37, 0, 0, 0, 0]"",
|
||||
""start_time"": ""2021-11-08 21:10:24.829395+01"",
|
||||
""gps"": {
|
||||
""latitude"": ""47.9980777"",
|
||||
""longitude"": ""7.7848769""
|
||||
},
|
||||
""lock_state"": ""locked"",
|
||||
""system"": ""Ilockit"",
|
||||
""real_hours"": ""0"",
|
||||
""Ilockit_GUID"": ""00000000-0000-0000-0000-fe3962c08bcc""
|
||||
}
|
||||
},
|
||||
""apiserver"": ""https://shareeapp-fr01.copri.eu"",
|
||||
""uri_primary"": ""https://shareeapp-primary.copri.eu"",
|
||||
""debuglevel"": ""1"",
|
||||
""bike_info_html"": ""site/bike_info.html"",
|
||||
""new_authcoo"": ""0"",
|
||||
""response_state"": ""OK, nothing todo"",
|
||||
""last_used_operator"": {
|
||||
""operator_color"": ""#008dd2"",
|
||||
""operator_phone"": ""+49 089 / 111111111"",
|
||||
""operator_email"": ""hotline@lastenraddemo.bayern"",
|
||||
""operator_hours"": ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||
""operator_name"": ""Lastenrad Bayern"",
|
||||
""operator_logo"": """"
|
||||
},
|
||||
""lang"": ""DE"",
|
||||
""impress_html"": ""site/impress.html"",
|
||||
""tariff_info_html"": ""site/tariff_info_1.html"",
|
||||
""agb_html"": ""site/agb.html"",
|
||||
""response"": ""user_bikes_occupied"",
|
||||
""agb_checked"": ""1"",
|
||||
""privacy_html"": ""site/privacy.html"",
|
||||
""clearing_cache"": ""0"",
|
||||
""user_id"": ""ohauff@posteo.de""
|
||||
}
|
||||
}";
|
||||
|
||||
private static string BikesAvailableResponse => @"{
|
||||
""shareejson"": {
|
||||
""agb_checked"": ""1"",
|
||||
""response"": ""bikes_available"",
|
||||
""agb_html"": ""site/agb.html"",
|
||||
""impress_html"": ""site/impress.html"",
|
||||
""tariff_info_html"": ""site/tariff_info_1.html"",
|
||||
""lang"": ""DE"",
|
||||
""last_used_operator"": {
|
||||
""operator_color"": ""#008dd2"",
|
||||
""operator_email"": ""hotline@lastenraddemo.bayern"",
|
||||
""operator_phone"": ""+49 089 / 111111111"",
|
||||
""operator_name"": ""Lastenrad Bayern"",
|
||||
""operator_hours"": ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||
""operator_logo"": """"
|
||||
},
|
||||
""user_id"": ""ohauff@posteo.de"",
|
||||
""clearing_cache"": ""0"",
|
||||
""privacy_html"": ""site/privacy.html"",
|
||||
""bikes"": {
|
||||
""FR1543"": {
|
||||
""system"": ""Ilockit"",
|
||||
""gps"": {
|
||||
""longitude"": ""7.8255321"",
|
||||
""latitude"": ""47.9767121""
|
||||
},
|
||||
""lock_state"": ""locked"",
|
||||
""Ilockit_GUID"": ""00000000-0000-0000-0000-cc141a6f68bb"",
|
||||
""state"": ""available"",
|
||||
""tariff_description"": {
|
||||
""free_hours"": ""0.50"",
|
||||
""name"": ""Tester Basic"",
|
||||
""eur_per_hour"": ""3.00"",
|
||||
""number"": ""5494"",
|
||||
""1543"": {
|
||||
""operator_agb"": ""Mit der Mietrad Anmietung wird folgender Betreiber <a href='https://shareeapp-fr01.copri.eu/site/agb.html'>AGB</a> zugestimmt (als Demo sharee AGB).""
|
||||
},
|
||||
""max_eur_per_day"": ""10.00""
|
||||
},
|
||||
""bike_group"": [
|
||||
""FR300103""
|
||||
],
|
||||
""station"": ""FR101"",
|
||||
""description"": ""Contributor-bike Dominik"",
|
||||
""Ilockit_ID"": ""ISHAREIT-2200543"",
|
||||
""authed"": ""1"",
|
||||
""bike"": ""FR1543"",
|
||||
""uri_operator"": ""https://shareeapp-fr01.copri.eu""
|
||||
},
|
||||
""FR1003"": {
|
||||
""bike"": ""FR1003"",
|
||||
""authed"": ""1"",
|
||||
""uri_operator"": ""https://shareeapp-fr01.copri.eu"",
|
||||
""bike_group"": [
|
||||
""FR300101""
|
||||
],
|
||||
""Ilockit_ID"": ""ISHAREIT-2200545"",
|
||||
""station"": ""FR101"",
|
||||
""description"": ""Stadtrad"",
|
||||
""tariff_description"": {
|
||||
""max_eur_per_day"": ""10.00"",
|
||||
""number"": ""5491"",
|
||||
""eur_per_hour"": ""2.00"",
|
||||
""1003"": {
|
||||
""operator_agb"": ""Mit der Mietrad Anmietung wird folgender Betreiber <a href='https://shareeapp-fr01.copri.eu/site/agb.html'>AGB</a> zugestimmt (als Demo sharee AGB).""
|
||||
},
|
||||
""free_hours"": ""0.50"",
|
||||
""name"": ""Vauban Basic""
|
||||
},
|
||||
""state"": ""available"",
|
||||
""Ilockit_GUID"": ""00000000-0000-0000-0000-e38bf9d32234"",
|
||||
""system"": ""Ilockit"",
|
||||
""gps"": {
|
||||
""longitude"": ""7.8255772"",
|
||||
""latitude"": ""47.9765188""
|
||||
},
|
||||
""lock_state"": ""locked""
|
||||
},
|
||||
""FR1540"": {
|
||||
""bike_group"": [
|
||||
""FR300103""
|
||||
],
|
||||
""Ilockit_ID"": ""ISHAREIT-2200540"",
|
||||
""description"": ""Contributor-bike Dieter"",
|
||||
""station"": ""FR101"",
|
||||
""bike"": ""FR1540"",
|
||||
""authed"": ""1"",
|
||||
""uri_operator"": ""https://shareeapp-fr01.copri.eu"",
|
||||
""Ilockit_GUID"": ""00000000-0000-0000-0000-fc3c002a2add"",
|
||||
""system"": ""Ilockit"",
|
||||
""gps"": {
|
||||
""longitude"": ""7.8256267"",
|
||||
""latitude"": ""47.976803""
|
||||
},
|
||||
""lock_state"": ""locked"",
|
||||
""tariff_description"": {
|
||||
""1540"": {
|
||||
""operator_agb"": ""Mit der Mietrad Anmietung wird folgender Betreiber <a href='https://shareeapp-fr01.copri.eu/site/agb.html'>AGB</a> zugestimmt (als Demo sharee AGB).""
|
||||
},
|
||||
""free_hours"": ""0.50"",
|
||||
""name"": ""Tester Basic"",
|
||||
""max_eur_per_day"": ""10.00"",
|
||||
""eur_per_hour"": ""3.00"",
|
||||
""number"": ""5494""
|
||||
},
|
||||
""state"": ""available""
|
||||
},
|
||||
""FR1002"": {
|
||||
""bike_group"": [
|
||||
""FR300101""
|
||||
],
|
||||
""description"": ""Lasten-Dreirad"",
|
||||
""station"": ""FR101"",
|
||||
""Ilockit_ID"": ""ISHAREIT-2200539"",
|
||||
""authed"": ""1"",
|
||||
""bike"": ""FR1002"",
|
||||
""uri_operator"": ""https://shareeapp-fr01.copri.eu"",
|
||||
""gps"": {
|
||||
""latitude"": ""47.976552"",
|
||||
""longitude"": ""7.8255068""
|
||||
},
|
||||
""system"": ""Ilockit"",
|
||||
""lock_state"": ""locked"",
|
||||
""Ilockit_GUID"": ""00000000-0000-0000-0000-f0b4a692e169"",
|
||||
""state"": ""available"",
|
||||
""tariff_description"": {
|
||||
""max_eur_per_day"": ""10.00"",
|
||||
""1002"": {
|
||||
""operator_agb"": ""Mit der Mietrad Anmietung wird folgender Betreiber <a href='https://shareeapp-fr01.copri.eu/site/agb.html'>AGB</a> zugestimmt (als Demo sharee AGB).""
|
||||
},
|
||||
""eur_per_hour"": ""2.00"",
|
||||
""number"": ""5491"",
|
||||
""free_hours"": ""0.50"",
|
||||
""name"": ""Vauban Basic""
|
||||
}
|
||||
},
|
||||
""FR1538"": {
|
||||
""uri_operator"": ""https://shareeapp-fr01.copri.eu"",
|
||||
""authed"": ""1"",
|
||||
""bike"": ""FR1538"",
|
||||
""station"": ""FR105"",
|
||||
""description"": ""Contributor-bike Rainer"",
|
||||
""Ilockit_ID"": ""ISHAREIT-2200538"",
|
||||
""bike_group"": [
|
||||
""FR300103""
|
||||
],
|
||||
""state"": ""available"",
|
||||
""tariff_description"": {
|
||||
""max_eur_per_day"": ""10.00"",
|
||||
""eur_per_hour"": ""3.00"",
|
||||
""number"": ""5494"",
|
||||
""1538"": {
|
||||
""operator_agb"": ""Mit der Mietrad Anmietung wird folgender Betreiber <a href='https://shareeapp-fr01.copri.eu/site/agb.html'>AGB</a> zugestimmt (als Demo sharee AGB).""
|
||||
},
|
||||
""free_hours"": ""0.50"",
|
||||
""name"": ""Tester Basic""
|
||||
},
|
||||
""gps"": {
|
||||
""latitude"": ""47.9275957"",
|
||||
""longitude"": ""7.973976""
|
||||
},
|
||||
""lock_state"": ""locked"",
|
||||
""system"": ""Ilockit"",
|
||||
""Ilockit_GUID"": ""00000000-0000-0000-0000-db0319a2555b""
|
||||
},
|
||||
""FR1001"": {
|
||||
""bike_group"": [
|
||||
""FR300101""
|
||||
],
|
||||
""station"": ""FR101"",
|
||||
""description"": ""Lastenrad"",
|
||||
""Ilockit_ID"": ""ISHAREIT-2200536"",
|
||||
""authed"": ""1"",
|
||||
""bike"": ""FR1001"",
|
||||
""uri_operator"": ""https://shareeapp-fr01.copri.eu"",
|
||||
""lock_state"": ""locked"",
|
||||
""gps"": {
|
||||
""latitude"": ""47.9765091"",
|
||||
""longitude"": ""7.8255631""
|
||||
},
|
||||
""system"": ""Ilockit"",
|
||||
""Ilockit_GUID"": ""00000000-0000-0000-0000-caa87760e53e"",
|
||||
""state"": ""available"",
|
||||
""tariff_description"": {
|
||||
""free_hours"": ""0.50"",
|
||||
""name"": ""Vauban Basic"",
|
||||
""eur_per_hour"": ""2.00"",
|
||||
""number"": ""5491"",
|
||||
""max_eur_per_day"": ""10.00"",
|
||||
""1001"": {
|
||||
""operator_agb"": ""Mit der Mietrad Anmietung wird folgender Betreiber <a href='https://shareeapp-fr01.copri.eu/site/agb.html'>AGB</a> zugestimmt (als Demo sharee AGB).""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
""user_group"": [
|
||||
""FR300103"",
|
||||
""FR300101""
|
||||
],
|
||||
""apiserver"": ""https://shareeapp-fr01.copri.eu"",
|
||||
""user_tour"": [],
|
||||
""authcookie"": ""6103_112e96b36ba33de245943c5ffaf369cd_oiF2kahH"",
|
||||
""copri_version"": ""4.1.8.21"",
|
||||
""response_state"": ""OK, nothing todo"",
|
||||
""new_authcoo"": ""0"",
|
||||
""bike_info_html"": ""site/bike_info.html"",
|
||||
""debuglevel"": ""1"",
|
||||
""uri_primary"": ""https://shareeapp-primary.copri.eu""
|
||||
}
|
||||
}";
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue