mirror of
https://github.com/Smaug123/WoofWare.Myriad
synced 2025-10-12 23:48:42 +00:00
Fix treatment of slashes and add tests (#28)
This commit is contained in:
@@ -266,9 +266,9 @@ namespace PureGym
|
|||||||
module SessionsAggregate =
|
module SessionsAggregate =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsAggregate =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsAggregate =
|
||||||
let Duration = node.["duration"].AsValue().GetValue<int> ()
|
let Duration = node.["Duration"].AsValue().GetValue<int> ()
|
||||||
let Visits = node.["visits"].AsValue().GetValue<int> ()
|
let Visits = node.["Visits"].AsValue().GetValue<int> ()
|
||||||
let Activities = node.["activities"].AsValue().GetValue<int> ()
|
let Activities = node.["Activities"].AsValue().GetValue<int> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
Activities = Activities
|
Activities = Activities
|
||||||
@@ -283,9 +283,9 @@ namespace PureGym
|
|||||||
module VisitGym =
|
module VisitGym =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : VisitGym =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : VisitGym =
|
||||||
let Status = node.["status"].AsValue().GetValue<string> ()
|
let Status = node.["Status"].AsValue().GetValue<string> ()
|
||||||
let Name = node.["name"].AsValue().GetValue<string> ()
|
let Name = node.["Name"].AsValue().GetValue<string> ()
|
||||||
let Id = node.["id"].AsValue().GetValue<int> ()
|
let Id = node.["Id"].AsValue().GetValue<int> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
Id = Id
|
Id = Id
|
||||||
@@ -300,13 +300,13 @@ namespace PureGym
|
|||||||
module Visit =
|
module Visit =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Visit =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Visit =
|
||||||
let Gym = VisitGym.jsonParse node.["gym"]
|
let Gym = VisitGym.jsonParse node.["Gym"]
|
||||||
let Duration = node.["duration"].AsValue().GetValue<int> ()
|
let Duration = node.["Duration"].AsValue().GetValue<int> ()
|
||||||
|
|
||||||
let StartTime =
|
let StartTime =
|
||||||
node.["startTime"].AsValue().GetValue<string> () |> System.DateTime.Parse
|
node.["StartTime"].AsValue().GetValue<string> () |> System.DateTime.Parse
|
||||||
|
|
||||||
let IsDurationEstimated = node.["isDurationEstimated"].AsValue().GetValue<bool> ()
|
let IsDurationEstimated = node.["IsDurationEstimated"].AsValue().GetValue<bool> ()
|
||||||
|
|
||||||
{
|
{
|
||||||
IsDurationEstimated = IsDurationEstimated
|
IsDurationEstimated = IsDurationEstimated
|
||||||
@@ -322,8 +322,8 @@ namespace PureGym
|
|||||||
module SessionsSummary =
|
module SessionsSummary =
|
||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsSummary =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : SessionsSummary =
|
||||||
let ThisWeek = SessionsAggregate.jsonParse node.["thisWeek"]
|
let ThisWeek = SessionsAggregate.jsonParse node.["ThisWeek"]
|
||||||
let Total = SessionsAggregate.jsonParse node.["total"]
|
let Total = SessionsAggregate.jsonParse node.["Total"]
|
||||||
|
|
||||||
{
|
{
|
||||||
Total = Total
|
Total = Total
|
||||||
@@ -338,11 +338,11 @@ module Sessions =
|
|||||||
/// Parse from a JSON node.
|
/// Parse from a JSON node.
|
||||||
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Sessions =
|
let jsonParse (node : System.Text.Json.Nodes.JsonNode) : Sessions =
|
||||||
let Visits =
|
let Visits =
|
||||||
node.["visits"].AsArray ()
|
node.["Visits"].AsArray ()
|
||||||
|> Seq.map (fun elt -> Visit.jsonParse elt)
|
|> Seq.map (fun elt -> Visit.jsonParse elt)
|
||||||
|> List.ofSeq
|
|> List.ofSeq
|
||||||
|
|
||||||
let Summary = SessionsSummary.jsonParse node.["summary"]
|
let Summary = SessionsSummary.jsonParse node.["Summary"]
|
||||||
|
|
||||||
{
|
{
|
||||||
Summary = Summary
|
Summary = Summary
|
||||||
|
@@ -22,10 +22,13 @@ module PureGymApi =
|
|||||||
async {
|
async {
|
||||||
let! ct = Async.CancellationToken
|
let! ct = Async.CancellationToken
|
||||||
|
|
||||||
|
let uri =
|
||||||
|
System.Uri (client.BaseAddress, System.Uri ("v1/gyms/", System.UriKind.Relative))
|
||||||
|
|
||||||
let httpMessage =
|
let httpMessage =
|
||||||
new System.Net.Http.HttpRequestMessage (
|
new System.Net.Http.HttpRequestMessage (
|
||||||
Method = System.Net.Http.HttpMethod.Get,
|
Method = System.Net.Http.HttpMethod.Get,
|
||||||
RequestUri = System.Uri (client.BaseAddress.ToString () + "/v1/gyms/")
|
RequestUri = uri
|
||||||
)
|
)
|
||||||
|
|
||||||
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
|
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
|
||||||
@@ -44,14 +47,19 @@ module PureGymApi =
|
|||||||
async {
|
async {
|
||||||
let! ct = Async.CancellationToken
|
let! ct = Async.CancellationToken
|
||||||
|
|
||||||
|
let uri =
|
||||||
|
System.Uri (
|
||||||
|
client.BaseAddress,
|
||||||
|
System.Uri (
|
||||||
|
"v1/gyms/{gym_id}/attendance".Replace ("{gym_id}", gymId.ToString ()),
|
||||||
|
System.UriKind.Relative
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
let httpMessage =
|
let httpMessage =
|
||||||
new System.Net.Http.HttpRequestMessage (
|
new System.Net.Http.HttpRequestMessage (
|
||||||
Method = System.Net.Http.HttpMethod.Get,
|
Method = System.Net.Http.HttpMethod.Get,
|
||||||
RequestUri =
|
RequestUri = uri
|
||||||
System.Uri (
|
|
||||||
client.BaseAddress.ToString ()
|
|
||||||
+ "/v1/gyms/{gym_id}/attendance".Replace ("{gym_id}", gymId.ToString ())
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
|
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
|
||||||
@@ -70,10 +78,13 @@ module PureGymApi =
|
|||||||
async {
|
async {
|
||||||
let! ct = Async.CancellationToken
|
let! ct = Async.CancellationToken
|
||||||
|
|
||||||
|
let uri =
|
||||||
|
System.Uri (client.BaseAddress, System.Uri ("v1/member", System.UriKind.Relative))
|
||||||
|
|
||||||
let httpMessage =
|
let httpMessage =
|
||||||
new System.Net.Http.HttpRequestMessage (
|
new System.Net.Http.HttpRequestMessage (
|
||||||
Method = System.Net.Http.HttpMethod.Get,
|
Method = System.Net.Http.HttpMethod.Get,
|
||||||
RequestUri = System.Uri (client.BaseAddress.ToString () + "/v1/member")
|
RequestUri = uri
|
||||||
)
|
)
|
||||||
|
|
||||||
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
|
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
|
||||||
@@ -92,14 +103,19 @@ module PureGymApi =
|
|||||||
async {
|
async {
|
||||||
let! ct = Async.CancellationToken
|
let! ct = Async.CancellationToken
|
||||||
|
|
||||||
|
let uri =
|
||||||
|
System.Uri (
|
||||||
|
client.BaseAddress,
|
||||||
|
System.Uri (
|
||||||
|
"v1/gyms/{gym_id}".Replace ("{gym_id}", gymId.ToString ()),
|
||||||
|
System.UriKind.Relative
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
let httpMessage =
|
let httpMessage =
|
||||||
new System.Net.Http.HttpRequestMessage (
|
new System.Net.Http.HttpRequestMessage (
|
||||||
Method = System.Net.Http.HttpMethod.Get,
|
Method = System.Net.Http.HttpMethod.Get,
|
||||||
RequestUri =
|
RequestUri = uri
|
||||||
System.Uri (
|
|
||||||
client.BaseAddress.ToString ()
|
|
||||||
+ "/v1/gyms/{gym_id}".Replace ("{gym_id}", gymId.ToString ())
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
|
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
|
||||||
@@ -118,10 +134,13 @@ module PureGymApi =
|
|||||||
async {
|
async {
|
||||||
let! ct = Async.CancellationToken
|
let! ct = Async.CancellationToken
|
||||||
|
|
||||||
|
let uri =
|
||||||
|
System.Uri (client.BaseAddress, System.Uri ("v1/member/activity", System.UriKind.Relative))
|
||||||
|
|
||||||
let httpMessage =
|
let httpMessage =
|
||||||
new System.Net.Http.HttpRequestMessage (
|
new System.Net.Http.HttpRequestMessage (
|
||||||
Method = System.Net.Http.HttpMethod.Get,
|
Method = System.Net.Http.HttpMethod.Get,
|
||||||
RequestUri = System.Uri (client.BaseAddress.ToString () + "/v1/member/activity")
|
RequestUri = uri
|
||||||
)
|
)
|
||||||
|
|
||||||
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
|
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
|
||||||
@@ -136,22 +155,27 @@ module PureGymApi =
|
|||||||
}
|
}
|
||||||
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
||||||
|
|
||||||
member _.GetSessions (fromDate : DateTime, toDate : DateTime, ct : CancellationToken option) =
|
member _.GetSessions (fromDate : DateOnly, toDate : DateOnly, ct : CancellationToken option) =
|
||||||
async {
|
async {
|
||||||
let! ct = Async.CancellationToken
|
let! ct = Async.CancellationToken
|
||||||
|
|
||||||
|
let uri =
|
||||||
|
System.Uri (
|
||||||
|
client.BaseAddress,
|
||||||
|
System.Uri (
|
||||||
|
("/v2/gymSessions/member"
|
||||||
|
+ "?fromDate="
|
||||||
|
+ ((fromDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode)
|
||||||
|
+ "&toDate="
|
||||||
|
+ ((toDate.ToString "yyyy-MM-dd") |> System.Web.HttpUtility.UrlEncode)),
|
||||||
|
System.UriKind.Relative
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
let httpMessage =
|
let httpMessage =
|
||||||
new System.Net.Http.HttpRequestMessage (
|
new System.Net.Http.HttpRequestMessage (
|
||||||
Method = System.Net.Http.HttpMethod.Get,
|
Method = System.Net.Http.HttpMethod.Get,
|
||||||
RequestUri =
|
RequestUri = uri
|
||||||
System.Uri (
|
|
||||||
client.BaseAddress.ToString ()
|
|
||||||
+ ("/v2/gymSessions/member"
|
|
||||||
+ "?fromDate="
|
|
||||||
+ ((fromDate.ToString "yyyy-MM-ddTHH:mm:ss") |> System.Web.HttpUtility.UrlEncode)
|
|
||||||
+ "&toDate="
|
|
||||||
+ ((toDate.ToString "yyyy-MM-ddTHH:mm:ss") |> System.Web.HttpUtility.UrlEncode))
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
|
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
|
||||||
|
@@ -128,38 +128,52 @@ type MemberActivityDto =
|
|||||||
[<WoofWare.Myriad.Plugins.JsonParse>]
|
[<WoofWare.Myriad.Plugins.JsonParse>]
|
||||||
type SessionsAggregate =
|
type SessionsAggregate =
|
||||||
{
|
{
|
||||||
|
[<JsonPropertyName "Activities">]
|
||||||
Activities : int
|
Activities : int
|
||||||
|
[<JsonPropertyName "Visits">]
|
||||||
Visits : int
|
Visits : int
|
||||||
|
[<JsonPropertyName "Duration">]
|
||||||
Duration : int
|
Duration : int
|
||||||
}
|
}
|
||||||
|
|
||||||
[<WoofWare.Myriad.Plugins.JsonParse>]
|
[<WoofWare.Myriad.Plugins.JsonParse>]
|
||||||
type VisitGym =
|
type VisitGym =
|
||||||
{
|
{
|
||||||
|
[<JsonPropertyName "Id">]
|
||||||
Id : int
|
Id : int
|
||||||
|
[<JsonPropertyName "Name">]
|
||||||
Name : string
|
Name : string
|
||||||
|
[<JsonPropertyName "Status">]
|
||||||
Status : string
|
Status : string
|
||||||
}
|
}
|
||||||
|
|
||||||
[<WoofWare.Myriad.Plugins.JsonParse>]
|
[<WoofWare.Myriad.Plugins.JsonParse>]
|
||||||
type Visit =
|
type Visit =
|
||||||
{
|
{
|
||||||
|
[<JsonPropertyName "IsDurationEstimated">]
|
||||||
IsDurationEstimated : bool
|
IsDurationEstimated : bool
|
||||||
|
[<JsonPropertyName "StartTime">]
|
||||||
StartTime : DateTime
|
StartTime : DateTime
|
||||||
|
[<JsonPropertyName "Duration">]
|
||||||
Duration : int
|
Duration : int
|
||||||
|
[<JsonPropertyName "Gym">]
|
||||||
Gym : VisitGym
|
Gym : VisitGym
|
||||||
}
|
}
|
||||||
|
|
||||||
[<WoofWare.Myriad.Plugins.JsonParse>]
|
[<WoofWare.Myriad.Plugins.JsonParse>]
|
||||||
type SessionsSummary =
|
type SessionsSummary =
|
||||||
{
|
{
|
||||||
|
[<JsonPropertyName "Total">]
|
||||||
Total : SessionsAggregate
|
Total : SessionsAggregate
|
||||||
|
[<JsonPropertyName "ThisWeek">]
|
||||||
ThisWeek : SessionsAggregate
|
ThisWeek : SessionsAggregate
|
||||||
}
|
}
|
||||||
|
|
||||||
[<WoofWare.Myriad.Plugins.JsonParse>]
|
[<WoofWare.Myriad.Plugins.JsonParse>]
|
||||||
type Sessions =
|
type Sessions =
|
||||||
{
|
{
|
||||||
|
[<JsonPropertyName "Summary">]
|
||||||
Summary : SessionsSummary
|
Summary : SessionsSummary
|
||||||
|
[<JsonPropertyName "Visits">]
|
||||||
Visits : Visit list
|
Visits : Visit list
|
||||||
}
|
}
|
||||||
|
@@ -22,6 +22,7 @@ type IPureGymApi =
|
|||||||
[<Get "v1/member/activity">]
|
[<Get "v1/member/activity">]
|
||||||
abstract GetMemberActivity : ?ct : CancellationToken -> Task<MemberActivityDto>
|
abstract GetMemberActivity : ?ct : CancellationToken -> Task<MemberActivityDto>
|
||||||
|
|
||||||
[<Get "v2/gymSessions/member">]
|
// We'll use this one to check handling of absolute URIs too
|
||||||
|
[<Get "/v2/gymSessions/member">]
|
||||||
abstract GetSessions :
|
abstract GetSessions :
|
||||||
[<Query>] fromDate : DateTime * [<Query>] toDate : DateTime * ?ct : CancellationToken -> Task<Sessions>
|
[<Query>] fromDate : DateOnly * [<Query>] toDate : DateOnly * ?ct : CancellationToken -> Task<Sessions>
|
||||||
|
17
MyriadPlugin.Test/HttpClient.fs
Normal file
17
MyriadPlugin.Test/HttpClient.fs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
namespace MyriadPlugin.Test
|
||||||
|
|
||||||
|
open System.Net.Http
|
||||||
|
|
||||||
|
/// Simple implementation of an HttpClient.
|
||||||
|
type HttpClientMock (result : HttpRequestMessage -> Async<HttpResponseMessage>) =
|
||||||
|
inherit HttpClient ()
|
||||||
|
|
||||||
|
override this.SendAsync (message, ct) =
|
||||||
|
Async.StartAsTask (result message, cancellationToken = ct)
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module HttpClientMock =
|
||||||
|
let make (baseUrl : System.Uri) (handler : HttpRequestMessage -> Async<HttpResponseMessage>) =
|
||||||
|
let result = new HttpClientMock (handler)
|
||||||
|
result.BaseAddress <- baseUrl
|
||||||
|
result
|
@@ -8,10 +8,13 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="TestPureGymJson.fs" />
|
<Compile Include="HttpClient.fs" />
|
||||||
<Compile Include="TestSurface.fs" />
|
<Compile Include="TestSurface.fs" />
|
||||||
<Compile Include="TestRemoveOptions.fs" />
|
<Compile Include="TestRemoveOptions.fs" />
|
||||||
<Compile Include="TestJsonParse.fs" />
|
<Compile Include="TestJsonParse.fs" />
|
||||||
|
<Compile Include="PureGymDtos.fs" />
|
||||||
|
<Compile Include="TestPureGymJson.fs" />
|
||||||
|
<Compile Include="TestRestApi.fs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
264
MyriadPlugin.Test/PureGymDtos.fs
Normal file
264
MyriadPlugin.Test/PureGymDtos.fs
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
namespace MyriadPlugin.Test
|
||||||
|
|
||||||
|
open PureGym
|
||||||
|
open System
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module PureGymDtos =
|
||||||
|
|
||||||
|
let gymOpeningHoursCases =
|
||||||
|
[
|
||||||
|
"""{"openingHours": [], "isAlwaysOpen": false}""",
|
||||||
|
{
|
||||||
|
GymOpeningHours.OpeningHours = []
|
||||||
|
IsAlwaysOpen = false
|
||||||
|
}
|
||||||
|
"""{"openingHours": ["something"], "isAlwaysOpen": false}""",
|
||||||
|
{
|
||||||
|
GymOpeningHours.OpeningHours = [ "something" ]
|
||||||
|
IsAlwaysOpen = false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
let gymAccessOptionsCases =
|
||||||
|
List.allPairs [ true ; false ] [ true ; false ]
|
||||||
|
|> List.map (fun (a, b) ->
|
||||||
|
let s = sprintf """{"pinAccess": %b, "qrCodeAccess": %b}""" a b
|
||||||
|
|
||||||
|
s,
|
||||||
|
{
|
||||||
|
GymAccessOptions.PinAccess = a
|
||||||
|
QrCodeAccess = b
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
let gymAddressCases =
|
||||||
|
[
|
||||||
|
"""{"addressLine1": "", "postCode": "hi", "town": ""}""",
|
||||||
|
{
|
||||||
|
GymAddress.AddressLine1 = ""
|
||||||
|
AddressLine2 = None
|
||||||
|
AddressLine3 = None
|
||||||
|
County = None
|
||||||
|
Postcode = "hi"
|
||||||
|
Town = ""
|
||||||
|
}
|
||||||
|
"""{"addressLine1": "", "addressLine2": null, "postCode": "hi", "town": ""}""",
|
||||||
|
{
|
||||||
|
GymAddress.AddressLine1 = ""
|
||||||
|
AddressLine2 = None
|
||||||
|
AddressLine3 = None
|
||||||
|
County = None
|
||||||
|
Postcode = "hi"
|
||||||
|
Town = ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
let gymLocationCases =
|
||||||
|
[
|
||||||
|
"""{"latitude": 1.0, "longitude": 3.0}""",
|
||||||
|
{
|
||||||
|
GymLocation.Latitude = 1.0
|
||||||
|
Longitude = 3.0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
let gymCases =
|
||||||
|
let ovalJson =
|
||||||
|
"""{"name":"London Oval","id":19,"status":2,"address":{"addressLine1":"Canterbury Court","addressLine2":"Units 4, 4A, 5 And 5A","addressLine3":"Kennington Park","town":"LONDON","county":null,"postcode":"SW9 6DE"},"phoneNumber":"+44 3444770005","emailAddress":"info.londonoval@puregym.com","staffMembers":null,"gymOpeningHours":{"isAlwaysOpen":true,"openingHours":[]},"reasonsToJoin":null,"accessOptions":{"pinAccess":true,"qrCodeAccess":true},"virtualTourUrl":null,"personalTrainersUrl":null,"webViewUrl":null,"floorPlanUrl":null,"location":{"longitude":"-0.110252","latitude":"51.480401"},"timeZone":"Europe/London","reopenDate":"2021-04-12T00:00:00+01 Europe/London"}"""
|
||||||
|
|
||||||
|
let oval =
|
||||||
|
{
|
||||||
|
Gym.Name = "London Oval"
|
||||||
|
Id = 19
|
||||||
|
Status = 2
|
||||||
|
Address =
|
||||||
|
{
|
||||||
|
AddressLine1 = "Canterbury Court"
|
||||||
|
AddressLine2 = Some "Units 4, 4A, 5 And 5A"
|
||||||
|
AddressLine3 = Some "Kennington Park"
|
||||||
|
Town = "LONDON"
|
||||||
|
County = None
|
||||||
|
Postcode = "SW9 6DE"
|
||||||
|
}
|
||||||
|
PhoneNumber = "+44 3444770005"
|
||||||
|
EmailAddress = "info.londonoval@puregym.com"
|
||||||
|
GymOpeningHours =
|
||||||
|
{
|
||||||
|
IsAlwaysOpen = true
|
||||||
|
OpeningHours = []
|
||||||
|
}
|
||||||
|
AccessOptions =
|
||||||
|
{
|
||||||
|
PinAccess = true
|
||||||
|
QrCodeAccess = true
|
||||||
|
}
|
||||||
|
Location =
|
||||||
|
{
|
||||||
|
Longitude = -0.110252
|
||||||
|
Latitude = 51.480401
|
||||||
|
}
|
||||||
|
TimeZone = "Europe/London"
|
||||||
|
ReopenDate = "2021-04-12T00:00:00+01 Europe/London"
|
||||||
|
}
|
||||||
|
|
||||||
|
[ ovalJson, oval ]
|
||||||
|
|
||||||
|
let memberCases =
|
||||||
|
let me =
|
||||||
|
{
|
||||||
|
Id = 1234567
|
||||||
|
CompoundMemberId = "12A123456"
|
||||||
|
FirstName = "Patrick"
|
||||||
|
LastName = "Stevens"
|
||||||
|
HomeGymId = 19
|
||||||
|
HomeGymName = "London Oval"
|
||||||
|
EmailAddress = "someone@somewhere"
|
||||||
|
GymAccessPin = "00000000"
|
||||||
|
DateOfBirth = DateOnly (1994, 01, 02)
|
||||||
|
MobileNumber = "+44 1234567"
|
||||||
|
Postcode = "W1A 1AA"
|
||||||
|
MembershipName = "Corporate"
|
||||||
|
MembershipLevel = 12
|
||||||
|
SuspendedReason = 0
|
||||||
|
MemberStatus = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
let meJson =
|
||||||
|
"""{
|
||||||
|
"id": 1234567,
|
||||||
|
"compoundMemberId": "12A123456",
|
||||||
|
"firstName": "Patrick",
|
||||||
|
"lastName": "Stevens",
|
||||||
|
"homeGymId": 19,
|
||||||
|
"homeGymName": "London Oval",
|
||||||
|
"emailAddress": "someone@somewhere",
|
||||||
|
"gymAccessPin": "00000000",
|
||||||
|
"dateofBirth": "1994-01-02",
|
||||||
|
"mobileNumber": "+44 1234567",
|
||||||
|
"postCode": "W1A 1AA",
|
||||||
|
"membershipName": "Corporate",
|
||||||
|
"membershipLevel": 12,
|
||||||
|
"suspendedReason": 0,
|
||||||
|
"memberStatus": 2
|
||||||
|
}"""
|
||||||
|
|
||||||
|
[ meJson, me ]
|
||||||
|
|
||||||
|
let gymAttendanceCases =
|
||||||
|
let json =
|
||||||
|
"""{
|
||||||
|
"description": "65",
|
||||||
|
"totalPeopleInGym": 65,
|
||||||
|
"totalPeopleInClasses": 2,
|
||||||
|
"totalPeopleSuffix": null,
|
||||||
|
"isApproximate": false,
|
||||||
|
"attendanceTime": "2023-12-27T18:54:09.5101697",
|
||||||
|
"lastRefreshed": "2023-12-27T18:54:09.5101697Z",
|
||||||
|
"lastRefreshedPeopleInClasses": "2023-12-27T18:50:26.0782286Z",
|
||||||
|
"maximumCapacity": 0
|
||||||
|
}"""
|
||||||
|
|
||||||
|
let expected =
|
||||||
|
{
|
||||||
|
Description = "65"
|
||||||
|
TotalPeopleInGym = 65
|
||||||
|
TotalPeopleInClasses = 2
|
||||||
|
TotalPeopleSuffix = None
|
||||||
|
IsApproximate = false
|
||||||
|
AttendanceTime =
|
||||||
|
DateTime (2023, 12, 27, 18, 54, 09, 510, 169, DateTimeKind.Utc)
|
||||||
|
+ TimeSpan.FromTicks 7L
|
||||||
|
LastRefreshed =
|
||||||
|
DateTime (2023, 12, 27, 18, 54, 09, 510, 169, DateTimeKind.Utc)
|
||||||
|
+ TimeSpan.FromTicks 7L
|
||||||
|
LastRefreshedPeopleInClasses =
|
||||||
|
DateTime (2023, 12, 27, 18, 50, 26, 078, 228, DateTimeKind.Utc)
|
||||||
|
+ TimeSpan.FromTicks 6L
|
||||||
|
MaximumCapacity = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
[ json, expected ]
|
||||||
|
|
||||||
|
let memberActivityDtoCases =
|
||||||
|
let json =
|
||||||
|
"""{"totalDuration":2217,"averageDuration":48,"totalVisits":46,"totalClasses":0,"isEstimated":false,"lastRefreshed":"2023-12-27T19:00:56.0309892Z"}"""
|
||||||
|
|
||||||
|
let value =
|
||||||
|
{
|
||||||
|
TotalDuration = 2217
|
||||||
|
AverageDuration = 48
|
||||||
|
TotalVisits = 46
|
||||||
|
TotalClasses = 0
|
||||||
|
IsEstimated = false
|
||||||
|
LastRefreshed =
|
||||||
|
DateTime (2023, 12, 27, 19, 00, 56, 030, 989, DateTimeKind.Utc)
|
||||||
|
+ TimeSpan.FromTicks 2L
|
||||||
|
}
|
||||||
|
|
||||||
|
[ json, value ]
|
||||||
|
|
||||||
|
let sessionsCases =
|
||||||
|
let json =
|
||||||
|
"""{
|
||||||
|
"Summary":{"Total":{"Activities":0,"Visits":10,"Duration":445},"ThisWeek":{"Activities":0,"Visits":0,"Duration":0}},
|
||||||
|
"Visits":[
|
||||||
|
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-21T10:12:00","Duration":50,"Name":null},
|
||||||
|
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-20T12:05:00","Duration":80,"Name":null},
|
||||||
|
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-17T19:37:00","Duration":46,"Name":null},
|
||||||
|
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-16T12:19:00","Duration":37,"Name":null},
|
||||||
|
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-15T11:14:00","Duration":47,"Name":null},
|
||||||
|
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-13T10:30:00","Duration":36,"Name":null},
|
||||||
|
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-10T16:18:00","Duration":32,"Name":null},
|
||||||
|
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-05T22:36:00","Duration":40,"Name":null},
|
||||||
|
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-03T17:59:00","Duration":48,"Name":null},
|
||||||
|
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-01T21:41:00","Duration":29,"Name":null}],
|
||||||
|
"Activities":[]}
|
||||||
|
"""
|
||||||
|
|
||||||
|
let singleVisit startTime duration =
|
||||||
|
{
|
||||||
|
IsDurationEstimated = false
|
||||||
|
Gym =
|
||||||
|
{
|
||||||
|
Id = 19
|
||||||
|
Name = "London Oval"
|
||||||
|
Status = "Blocked"
|
||||||
|
}
|
||||||
|
StartTime = startTime
|
||||||
|
Duration = duration
|
||||||
|
}
|
||||||
|
|
||||||
|
let expected =
|
||||||
|
{
|
||||||
|
Summary =
|
||||||
|
{
|
||||||
|
Total =
|
||||||
|
{
|
||||||
|
Activities = 0
|
||||||
|
Visits = 10
|
||||||
|
Duration = 445
|
||||||
|
}
|
||||||
|
ThisWeek =
|
||||||
|
{
|
||||||
|
Activities = 0
|
||||||
|
Visits = 0
|
||||||
|
Duration = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Visits =
|
||||||
|
[
|
||||||
|
singleVisit (DateTime (2023, 12, 21, 10, 12, 00)) 50
|
||||||
|
singleVisit (DateTime (2023, 12, 20, 12, 05, 00)) 80
|
||||||
|
singleVisit (DateTime (2023, 12, 17, 19, 37, 00)) 46
|
||||||
|
singleVisit (DateTime (2023, 12, 16, 12, 19, 00)) 37
|
||||||
|
singleVisit (DateTime (2023, 12, 15, 11, 14, 00)) 47
|
||||||
|
singleVisit (DateTime (2023, 12, 13, 10, 30, 00)) 36
|
||||||
|
singleVisit (DateTime (2023, 12, 10, 16, 18, 00)) 32
|
||||||
|
singleVisit (DateTime (2023, 12, 05, 22, 36, 00)) 40
|
||||||
|
singleVisit (DateTime (2023, 12, 03, 17, 59, 00)) 48
|
||||||
|
singleVisit (DateTime (2023, 12, 01, 21, 41, 00)) 29
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
[ json, expected ]
|
@@ -1,4 +1,4 @@
|
|||||||
namespace PureGym.Test
|
namespace MyriadPlugin.Test
|
||||||
|
|
||||||
open System
|
open System
|
||||||
open System.Text.Json.Nodes
|
open System.Text.Json.Nodes
|
||||||
@@ -9,300 +9,59 @@ open PureGym
|
|||||||
[<TestFixture>]
|
[<TestFixture>]
|
||||||
module TestPureGymJson =
|
module TestPureGymJson =
|
||||||
|
|
||||||
let gymOpeningHoursCases =
|
let gymOpeningHoursCases = PureGymDtos.gymOpeningHoursCases |> List.map TestCaseData
|
||||||
[
|
|
||||||
"""{"openingHours": [], "isAlwaysOpen": false}""",
|
|
||||||
{
|
|
||||||
GymOpeningHours.OpeningHours = []
|
|
||||||
IsAlwaysOpen = false
|
|
||||||
}
|
|
||||||
"""{"openingHours": ["something"], "isAlwaysOpen": false}""",
|
|
||||||
{
|
|
||||||
GymOpeningHours.OpeningHours = [ "something" ]
|
|
||||||
IsAlwaysOpen = false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|> List.map TestCaseData
|
|
||||||
|
|
||||||
[<TestCaseSource(nameof (gymOpeningHoursCases))>]
|
[<TestCaseSource(nameof gymOpeningHoursCases)>]
|
||||||
let ``GymOpeningHours JSON parse`` (json : string, expected : GymOpeningHours) =
|
let ``GymOpeningHours JSON parse`` (json : string, expected : GymOpeningHours) =
|
||||||
JsonNode.Parse json |> GymOpeningHours.jsonParse |> shouldEqual expected
|
JsonNode.Parse json |> GymOpeningHours.jsonParse |> shouldEqual expected
|
||||||
|
|
||||||
let gymAccessOptionsCases =
|
let gymAccessOptionsCases =
|
||||||
List.allPairs [ true ; false ] [ true ; false ]
|
PureGymDtos.gymAccessOptionsCases |> List.map TestCaseData
|
||||||
|> List.map (fun (a, b) ->
|
|
||||||
let s = sprintf """{"pinAccess": %b, "qrCodeAccess": %b}""" a b
|
|
||||||
|
|
||||||
s,
|
[<TestCaseSource(nameof gymAccessOptionsCases)>]
|
||||||
{
|
|
||||||
GymAccessOptions.PinAccess = a
|
|
||||||
QrCodeAccess = b
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|> List.map TestCaseData
|
|
||||||
|
|
||||||
[<TestCaseSource(nameof (gymAccessOptionsCases))>]
|
|
||||||
let ``GymAccessOptions JSON parse`` (json : string, expected : GymAccessOptions) =
|
let ``GymAccessOptions JSON parse`` (json : string, expected : GymAccessOptions) =
|
||||||
JsonNode.Parse json |> GymAccessOptions.jsonParse |> shouldEqual expected
|
JsonNode.Parse json |> GymAccessOptions.jsonParse |> shouldEqual expected
|
||||||
|
|
||||||
let gymLocationCases =
|
let gymLocationCases = PureGymDtos.gymLocationCases |> List.map TestCaseData
|
||||||
[
|
|
||||||
"""{"latitude": 1.0, "longitude": 3.0}""",
|
|
||||||
{
|
|
||||||
GymLocation.Latitude = 1.0
|
|
||||||
Longitude = 3.0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|> List.map TestCaseData
|
|
||||||
|
|
||||||
[<TestCaseSource(nameof (gymLocationCases))>]
|
[<TestCaseSource(nameof gymLocationCases)>]
|
||||||
let ``GymLocation JSON parse`` (json : string, expected : GymLocation) =
|
let ``GymLocation JSON parse`` (json : string, expected : GymLocation) =
|
||||||
JsonNode.Parse json |> GymLocation.jsonParse |> shouldEqual expected
|
JsonNode.Parse json |> GymLocation.jsonParse |> shouldEqual expected
|
||||||
|
|
||||||
let gymAddressCases =
|
let gymAddressCases = PureGymDtos.gymAddressCases |> List.map TestCaseData
|
||||||
[
|
|
||||||
"""{"addressLine1": "", "postCode": "hi", "town": ""}""",
|
|
||||||
{
|
|
||||||
GymAddress.AddressLine1 = ""
|
|
||||||
AddressLine2 = None
|
|
||||||
AddressLine3 = None
|
|
||||||
County = None
|
|
||||||
Postcode = "hi"
|
|
||||||
Town = ""
|
|
||||||
}
|
|
||||||
"""{"addressLine1": "", "addressLine2": null, "postCode": "hi", "town": ""}""",
|
|
||||||
{
|
|
||||||
GymAddress.AddressLine1 = ""
|
|
||||||
AddressLine2 = None
|
|
||||||
AddressLine3 = None
|
|
||||||
County = None
|
|
||||||
Postcode = "hi"
|
|
||||||
Town = ""
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|> List.map TestCaseData
|
|
||||||
|
|
||||||
[<TestCaseSource(nameof (gymAddressCases))>]
|
[<TestCaseSource(nameof gymAddressCases)>]
|
||||||
let ``GymAddress JSON parse`` (json : string, expected : GymAddress) =
|
let ``GymAddress JSON parse`` (json : string, expected : GymAddress) =
|
||||||
JsonNode.Parse (json, Nullable (JsonNodeOptions (PropertyNameCaseInsensitive = true)))
|
JsonNode.Parse (json, Nullable (JsonNodeOptions (PropertyNameCaseInsensitive = true)))
|
||||||
|> GymAddress.jsonParse
|
|> GymAddress.jsonParse
|
||||||
|> shouldEqual expected
|
|> shouldEqual expected
|
||||||
|
|
||||||
let gymCases =
|
let gymCases = PureGymDtos.gymCases |> List.map TestCaseData
|
||||||
let ovalJson =
|
|
||||||
"""{"name":"London Oval","id":19,"status":2,"address":{"addressLine1":"Canterbury Court","addressLine2":"Units 4, 4A, 5 And 5A","addressLine3":"Kennington Park","town":"LONDON","county":null,"postcode":"SW9 6DE"},"phoneNumber":"+44 3444770005","emailAddress":"info.londonoval@puregym.com","staffMembers":null,"gymOpeningHours":{"isAlwaysOpen":true,"openingHours":[]},"reasonsToJoin":null,"accessOptions":{"pinAccess":true,"qrCodeAccess":true},"virtualTourUrl":null,"personalTrainersUrl":null,"webViewUrl":null,"floorPlanUrl":null,"location":{"longitude":"-0.110252","latitude":"51.480401"},"timeZone":"Europe/London","reopenDate":"2021-04-12T00:00:00+01 Europe/London"}"""
|
|
||||||
|
|
||||||
let oval =
|
[<TestCaseSource(nameof gymCases)>]
|
||||||
{
|
|
||||||
Gym.Name = "London Oval"
|
|
||||||
Id = 19
|
|
||||||
Status = 2
|
|
||||||
Address =
|
|
||||||
{
|
|
||||||
AddressLine1 = "Canterbury Court"
|
|
||||||
AddressLine2 = Some "Units 4, 4A, 5 And 5A"
|
|
||||||
AddressLine3 = Some "Kennington Park"
|
|
||||||
Town = "LONDON"
|
|
||||||
County = None
|
|
||||||
Postcode = "SW9 6DE"
|
|
||||||
}
|
|
||||||
PhoneNumber = "+44 3444770005"
|
|
||||||
EmailAddress = "info.londonoval@puregym.com"
|
|
||||||
GymOpeningHours =
|
|
||||||
{
|
|
||||||
IsAlwaysOpen = true
|
|
||||||
OpeningHours = []
|
|
||||||
}
|
|
||||||
AccessOptions =
|
|
||||||
{
|
|
||||||
PinAccess = true
|
|
||||||
QrCodeAccess = true
|
|
||||||
}
|
|
||||||
Location =
|
|
||||||
{
|
|
||||||
Longitude = -0.110252
|
|
||||||
Latitude = 51.480401
|
|
||||||
}
|
|
||||||
TimeZone = "Europe/London"
|
|
||||||
ReopenDate = "2021-04-12T00:00:00+01 Europe/London"
|
|
||||||
}
|
|
||||||
|
|
||||||
[ ovalJson, oval ] |> List.map TestCaseData
|
|
||||||
|
|
||||||
[<TestCaseSource(nameof (gymCases))>]
|
|
||||||
let ``Gym JSON parse`` (json : string, expected : Gym) =
|
let ``Gym JSON parse`` (json : string, expected : Gym) =
|
||||||
JsonNode.Parse json |> Gym.jsonParse |> shouldEqual expected
|
JsonNode.Parse json |> Gym.jsonParse |> shouldEqual expected
|
||||||
|
|
||||||
let memberCases =
|
let memberCases = PureGymDtos.memberCases |> List.map TestCaseData
|
||||||
let me =
|
|
||||||
{
|
|
||||||
Id = 1234567
|
|
||||||
CompoundMemberId = "12A123456"
|
|
||||||
FirstName = "Patrick"
|
|
||||||
LastName = "Stevens"
|
|
||||||
HomeGymId = 19
|
|
||||||
HomeGymName = "London Oval"
|
|
||||||
EmailAddress = "someone@somewhere"
|
|
||||||
GymAccessPin = "00000000"
|
|
||||||
DateOfBirth = DateOnly (1994, 01, 02)
|
|
||||||
MobileNumber = "+44 1234567"
|
|
||||||
Postcode = "W1A 1AA"
|
|
||||||
MembershipName = "Corporate"
|
|
||||||
MembershipLevel = 12
|
|
||||||
SuspendedReason = 0
|
|
||||||
MemberStatus = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
let meJson =
|
|
||||||
"""{
|
|
||||||
"id": 1234567,
|
|
||||||
"compoundMemberId": "12A123456",
|
|
||||||
"firstName": "Patrick",
|
|
||||||
"lastName": "Stevens",
|
|
||||||
"homeGymId": 19,
|
|
||||||
"homeGymName": "London Oval",
|
|
||||||
"emailAddress": "someone@somewhere",
|
|
||||||
"gymAccessPin": "00000000",
|
|
||||||
"dateofBirth": "1994-01-02",
|
|
||||||
"mobileNumber": "+44 1234567",
|
|
||||||
"postCode": "W1A 1AA",
|
|
||||||
"membershipName": "Corporate",
|
|
||||||
"membershipLevel": 12,
|
|
||||||
"suspendedReason": 0,
|
|
||||||
"memberStatus": 2
|
|
||||||
}"""
|
|
||||||
|
|
||||||
[ meJson, me ] |> List.map TestCaseData
|
|
||||||
|
|
||||||
[<TestCaseSource(nameof memberCases)>]
|
[<TestCaseSource(nameof memberCases)>]
|
||||||
let ``Member JSON parse`` (json : string, expected : Member) =
|
let ``Member JSON parse`` (json : string, expected : Member) =
|
||||||
json |> JsonNode.Parse |> Member.jsonParse |> shouldEqual expected
|
json |> JsonNode.Parse |> Member.jsonParse |> shouldEqual expected
|
||||||
|
|
||||||
let gymAttendanceCases =
|
let gymAttendanceCases = PureGymDtos.gymAttendanceCases |> List.map TestCaseData
|
||||||
let json =
|
|
||||||
"""{
|
|
||||||
"description": "65",
|
|
||||||
"totalPeopleInGym": 65,
|
|
||||||
"totalPeopleInClasses": 2,
|
|
||||||
"totalPeopleSuffix": null,
|
|
||||||
"isApproximate": false,
|
|
||||||
"attendanceTime": "2023-12-27T18:54:09.5101697",
|
|
||||||
"lastRefreshed": "2023-12-27T18:54:09.5101697Z",
|
|
||||||
"lastRefreshedPeopleInClasses": "2023-12-27T18:50:26.0782286Z",
|
|
||||||
"maximumCapacity": 0
|
|
||||||
}"""
|
|
||||||
|
|
||||||
let expected =
|
|
||||||
{
|
|
||||||
Description = "65"
|
|
||||||
TotalPeopleInGym = 65
|
|
||||||
TotalPeopleInClasses = 2
|
|
||||||
TotalPeopleSuffix = None
|
|
||||||
IsApproximate = false
|
|
||||||
AttendanceTime =
|
|
||||||
DateTime (2023, 12, 27, 18, 54, 09, 510, 169, DateTimeKind.Utc)
|
|
||||||
+ TimeSpan.FromTicks 7L
|
|
||||||
LastRefreshed =
|
|
||||||
DateTime (2023, 12, 27, 18, 54, 09, 510, 169, DateTimeKind.Utc)
|
|
||||||
+ TimeSpan.FromTicks 7L
|
|
||||||
LastRefreshedPeopleInClasses =
|
|
||||||
DateTime (2023, 12, 27, 18, 50, 26, 078, 228, DateTimeKind.Utc)
|
|
||||||
+ TimeSpan.FromTicks 6L
|
|
||||||
MaximumCapacity = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
[ json, expected ] |> List.map TestCaseData
|
|
||||||
|
|
||||||
[<TestCaseSource(nameof gymAttendanceCases)>]
|
[<TestCaseSource(nameof gymAttendanceCases)>]
|
||||||
let ``GymAttendance JSON parse`` (json : string, expected : GymAttendance) =
|
let ``GymAttendance JSON parse`` (json : string, expected : GymAttendance) =
|
||||||
json |> JsonNode.Parse |> GymAttendance.jsonParse |> shouldEqual expected
|
json |> JsonNode.Parse |> GymAttendance.jsonParse |> shouldEqual expected
|
||||||
|
|
||||||
let memberActivityDtoCases =
|
let memberActivityDtoCases =
|
||||||
let json =
|
PureGymDtos.memberActivityDtoCases |> List.map TestCaseData
|
||||||
"""{"totalDuration":2217,"averageDuration":48,"totalVisits":46,"totalClasses":0,"isEstimated":false,"lastRefreshed":"2023-12-27T19:00:56.0309892Z"}"""
|
|
||||||
|
|
||||||
let value =
|
|
||||||
{
|
|
||||||
TotalDuration = 2217
|
|
||||||
AverageDuration = 48
|
|
||||||
TotalVisits = 46
|
|
||||||
TotalClasses = 0
|
|
||||||
IsEstimated = false
|
|
||||||
LastRefreshed =
|
|
||||||
DateTime (2023, 12, 27, 19, 00, 56, 030, 989, DateTimeKind.Utc)
|
|
||||||
+ TimeSpan.FromTicks 2L
|
|
||||||
}
|
|
||||||
|
|
||||||
[ json, value ] |> List.map TestCaseData
|
|
||||||
|
|
||||||
[<TestCaseSource(nameof memberActivityDtoCases)>]
|
[<TestCaseSource(nameof memberActivityDtoCases)>]
|
||||||
let ``MemberActivityDto JSON parse`` (json : string, expected : MemberActivityDto) =
|
let ``MemberActivityDto JSON parse`` (json : string, expected : MemberActivityDto) =
|
||||||
json |> JsonNode.Parse |> MemberActivityDto.jsonParse |> shouldEqual expected
|
json |> JsonNode.Parse |> MemberActivityDto.jsonParse |> shouldEqual expected
|
||||||
|
|
||||||
let sessionsCases =
|
let sessionsCases = PureGymDtos.sessionsCases |> List.map TestCaseData
|
||||||
let json =
|
|
||||||
"""{
|
|
||||||
"Summary":{"Total":{"Activities":0,"Visits":10,"Duration":445},"ThisWeek":{"Activities":0,"Visits":0,"Duration":0}},
|
|
||||||
"Visits":[
|
|
||||||
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-21T10:12:00","Duration":50,"Name":null},
|
|
||||||
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-20T12:05:00","Duration":80,"Name":null},
|
|
||||||
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-17T19:37:00","Duration":46,"Name":null},
|
|
||||||
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-16T12:19:00","Duration":37,"Name":null},
|
|
||||||
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-15T11:14:00","Duration":47,"Name":null},
|
|
||||||
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-13T10:30:00","Duration":36,"Name":null},
|
|
||||||
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-10T16:18:00","Duration":32,"Name":null},
|
|
||||||
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-05T22:36:00","Duration":40,"Name":null},
|
|
||||||
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-03T17:59:00","Duration":48,"Name":null},
|
|
||||||
{"IsDurationEstimated":false,"Gym":{"Id":19,"Name":"London Oval","Status":"Blocked","Location":null,"GymAccess":null,"ContactInfo":null,"TimeZone":null},"StartTime":"2023-12-01T21:41:00","Duration":29,"Name":null}],
|
|
||||||
"Activities":[]}
|
|
||||||
"""
|
|
||||||
|
|
||||||
let singleVisit startTime duration =
|
|
||||||
{
|
|
||||||
IsDurationEstimated = false
|
|
||||||
Gym =
|
|
||||||
{
|
|
||||||
Id = 19
|
|
||||||
Name = "London Oval"
|
|
||||||
Status = "Blocked"
|
|
||||||
}
|
|
||||||
StartTime = startTime
|
|
||||||
Duration = duration
|
|
||||||
}
|
|
||||||
|
|
||||||
let expected =
|
|
||||||
{
|
|
||||||
Summary =
|
|
||||||
{
|
|
||||||
Total =
|
|
||||||
{
|
|
||||||
Activities = 0
|
|
||||||
Visits = 10
|
|
||||||
Duration = 445
|
|
||||||
}
|
|
||||||
ThisWeek =
|
|
||||||
{
|
|
||||||
Activities = 0
|
|
||||||
Visits = 0
|
|
||||||
Duration = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Visits =
|
|
||||||
[
|
|
||||||
singleVisit (DateTime (2023, 12, 21, 10, 12, 00)) 50
|
|
||||||
singleVisit (DateTime (2023, 12, 20, 12, 05, 00)) 80
|
|
||||||
singleVisit (DateTime (2023, 12, 17, 19, 37, 00)) 46
|
|
||||||
singleVisit (DateTime (2023, 12, 16, 12, 19, 00)) 37
|
|
||||||
singleVisit (DateTime (2023, 12, 15, 11, 14, 00)) 47
|
|
||||||
singleVisit (DateTime (2023, 12, 13, 10, 30, 00)) 36
|
|
||||||
singleVisit (DateTime (2023, 12, 10, 16, 18, 00)) 32
|
|
||||||
singleVisit (DateTime (2023, 12, 05, 22, 36, 00)) 40
|
|
||||||
singleVisit (DateTime (2023, 12, 03, 17, 59, 00)) 48
|
|
||||||
singleVisit (DateTime (2023, 12, 01, 21, 41, 00)) 29
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
[ json, expected ] |> List.map TestCaseData
|
|
||||||
|
|
||||||
[<TestCaseSource(nameof sessionsCases)>]
|
[<TestCaseSource(nameof sessionsCases)>]
|
||||||
let ``Sessions JSON parse`` (json : string, expected : Sessions) =
|
let ``Sessions JSON parse`` (json : string, expected : Sessions) =
|
||||||
|
238
MyriadPlugin.Test/TestRestApi.fs
Normal file
238
MyriadPlugin.Test/TestRestApi.fs
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
namespace MyriadPlugin.Test
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.Net
|
||||||
|
open System.Net.Http
|
||||||
|
open NUnit.Framework
|
||||||
|
open PureGym
|
||||||
|
open FsUnitTyped
|
||||||
|
|
||||||
|
[<TestFixture>]
|
||||||
|
module TestRestApi =
|
||||||
|
// several of these, to check behaviour around treatment of initial slashes
|
||||||
|
let baseUris =
|
||||||
|
[
|
||||||
|
// Everything is relative to the root:
|
||||||
|
"https://example.com"
|
||||||
|
// Everything is also relative to the root, because `foo` is not a subdir:
|
||||||
|
"https://example.com/foo"
|
||||||
|
// Everything is relative to `foo`, because `foo` is a subdir
|
||||||
|
"https://example.com/foo/"
|
||||||
|
]
|
||||||
|
|> List.map Uri
|
||||||
|
|
||||||
|
let gymsCases =
|
||||||
|
PureGymDtos.gymCases
|
||||||
|
|> List.collect (fun (json, gym) -> [ $"[%s{json}]", [ gym ] ; $"[%s{json}, %s{json}]", [ gym ; gym ] ])
|
||||||
|
|> List.allPairs baseUris
|
||||||
|
|> List.map TestCaseData
|
||||||
|
|
||||||
|
[<TestCaseSource(nameof gymsCases)>]
|
||||||
|
let ``Test GetGyms`` (baseUri : Uri, (json : string, expected : Gym list)) =
|
||||||
|
let proc (message : HttpRequestMessage) : HttpResponseMessage Async =
|
||||||
|
async {
|
||||||
|
message.Method |> shouldEqual HttpMethod.Get
|
||||||
|
|
||||||
|
// URI is relative in the attribute on the IPureGymApi member,
|
||||||
|
// so this never gets redirected
|
||||||
|
let expectedUri =
|
||||||
|
match baseUri.ToString () with
|
||||||
|
| "https://example.com/" -> "https://example.com/v1/gyms/"
|
||||||
|
| "https://example.com/foo" -> "https://example.com/v1/gyms/"
|
||||||
|
| "https://example.com/foo/" -> "https://example.com/foo/v1/gyms/"
|
||||||
|
| s -> failwith $"Unrecognised base URI: %s{s}"
|
||||||
|
|
||||||
|
message.RequestUri.ToString () |> shouldEqual expectedUri
|
||||||
|
|
||||||
|
let content = new StringContent (json)
|
||||||
|
let resp = new HttpResponseMessage (HttpStatusCode.OK)
|
||||||
|
resp.Content <- content
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
use client = HttpClientMock.make baseUri proc
|
||||||
|
let api = PureGymApi.make client
|
||||||
|
|
||||||
|
api.GetGyms().Result |> shouldEqual expected
|
||||||
|
|
||||||
|
let gymAttendanceCases =
|
||||||
|
PureGymDtos.gymAttendanceCases
|
||||||
|
|> List.allPairs baseUris
|
||||||
|
|> List.map TestCaseData
|
||||||
|
|
||||||
|
[<TestCaseSource(nameof gymAttendanceCases)>]
|
||||||
|
let ``Test GetGymAttendance`` (baseUri : Uri, (json : string, expected : GymAttendance)) =
|
||||||
|
let requestedGym = 3
|
||||||
|
|
||||||
|
let proc (message : HttpRequestMessage) : HttpResponseMessage Async =
|
||||||
|
async {
|
||||||
|
message.Method |> shouldEqual HttpMethod.Get
|
||||||
|
|
||||||
|
// URI is relative in the attribute on the IPureGymApi member,
|
||||||
|
// so this never gets redirected
|
||||||
|
let expectedUri =
|
||||||
|
match baseUri.ToString () with
|
||||||
|
| "https://example.com/" -> $"https://example.com/v1/gyms/%i{requestedGym}/attendance"
|
||||||
|
| "https://example.com/foo" -> $"https://example.com/v1/gyms/%i{requestedGym}/attendance"
|
||||||
|
| "https://example.com/foo/" -> $"https://example.com/foo/v1/gyms/%i{requestedGym}/attendance"
|
||||||
|
| s -> failwith $"Unrecognised base URI: %s{s}"
|
||||||
|
|
||||||
|
message.RequestUri.ToString () |> shouldEqual expectedUri
|
||||||
|
|
||||||
|
let content = new StringContent (json)
|
||||||
|
let resp = new HttpResponseMessage (HttpStatusCode.OK)
|
||||||
|
resp.Content <- content
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
use client = HttpClientMock.make baseUri proc
|
||||||
|
let api = PureGymApi.make client
|
||||||
|
|
||||||
|
api.GetGymAttendance(requestedGym).Result |> shouldEqual expected
|
||||||
|
|
||||||
|
let memberCases =
|
||||||
|
PureGymDtos.memberCases |> List.allPairs baseUris |> List.map TestCaseData
|
||||||
|
|
||||||
|
[<TestCaseSource(nameof memberCases)>]
|
||||||
|
let ``Test GetMember`` (baseUri : Uri, (json : string, expected : Member)) =
|
||||||
|
let proc (message : HttpRequestMessage) : HttpResponseMessage Async =
|
||||||
|
async {
|
||||||
|
message.Method |> shouldEqual HttpMethod.Get
|
||||||
|
|
||||||
|
// URI is relative in the attribute on the IPureGymApi member,
|
||||||
|
// so this never gets redirected
|
||||||
|
let expectedUri =
|
||||||
|
match baseUri.ToString () with
|
||||||
|
| "https://example.com/" -> "https://example.com/v1/member"
|
||||||
|
| "https://example.com/foo" -> "https://example.com/v1/member"
|
||||||
|
| "https://example.com/foo/" -> "https://example.com/foo/v1/member"
|
||||||
|
| s -> failwith $"Unrecognised base URI: %s{s}"
|
||||||
|
|
||||||
|
message.RequestUri.ToString () |> shouldEqual expectedUri
|
||||||
|
|
||||||
|
let content = new StringContent (json)
|
||||||
|
let resp = new HttpResponseMessage (HttpStatusCode.OK)
|
||||||
|
resp.Content <- content
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
use client = HttpClientMock.make baseUri proc
|
||||||
|
let api = PureGymApi.make client
|
||||||
|
|
||||||
|
api.GetMember().Result |> shouldEqual expected
|
||||||
|
|
||||||
|
let gymCases =
|
||||||
|
PureGymDtos.gymCases |> List.allPairs baseUris |> List.map TestCaseData
|
||||||
|
|
||||||
|
[<TestCaseSource(nameof gymCases)>]
|
||||||
|
let ``Test GetGym`` (baseUri : Uri, (json : string, expected : Gym)) =
|
||||||
|
let requestedGym = 3
|
||||||
|
|
||||||
|
let proc (message : HttpRequestMessage) : HttpResponseMessage Async =
|
||||||
|
async {
|
||||||
|
message.Method |> shouldEqual HttpMethod.Get
|
||||||
|
|
||||||
|
// URI is relative in the attribute on the IPureGymApi member,
|
||||||
|
// so this never gets redirected
|
||||||
|
let expectedUri =
|
||||||
|
match baseUri.ToString () with
|
||||||
|
| "https://example.com/" -> $"https://example.com/v1/gyms/%i{requestedGym}"
|
||||||
|
| "https://example.com/foo" -> $"https://example.com/v1/gyms/%i{requestedGym}"
|
||||||
|
| "https://example.com/foo/" -> $"https://example.com/foo/v1/gyms/%i{requestedGym}"
|
||||||
|
| s -> failwith $"Unrecognised base URI: %s{s}"
|
||||||
|
|
||||||
|
message.RequestUri.ToString () |> shouldEqual expectedUri
|
||||||
|
|
||||||
|
let content = new StringContent (json)
|
||||||
|
let resp = new HttpResponseMessage (HttpStatusCode.OK)
|
||||||
|
resp.Content <- content
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
use client = HttpClientMock.make baseUri proc
|
||||||
|
let api = PureGymApi.make client
|
||||||
|
|
||||||
|
api.GetGym(requestedGym).Result |> shouldEqual expected
|
||||||
|
|
||||||
|
let memberActivityCases =
|
||||||
|
PureGymDtos.memberActivityDtoCases
|
||||||
|
|> List.allPairs baseUris
|
||||||
|
|> List.map TestCaseData
|
||||||
|
|
||||||
|
[<TestCaseSource(nameof memberActivityCases)>]
|
||||||
|
let ``Test GetMemberActivity`` (baseUri : Uri, (json : string, expected : MemberActivityDto)) =
|
||||||
|
let proc (message : HttpRequestMessage) : HttpResponseMessage Async =
|
||||||
|
async {
|
||||||
|
message.Method |> shouldEqual HttpMethod.Get
|
||||||
|
|
||||||
|
// URI is relative in the attribute on the IPureGymApi member,
|
||||||
|
// so this never gets redirected
|
||||||
|
let expectedUri =
|
||||||
|
match baseUri.ToString () with
|
||||||
|
| "https://example.com/" -> "https://example.com/v1/member/activity"
|
||||||
|
| "https://example.com/foo" -> "https://example.com/v1/member/activity"
|
||||||
|
| "https://example.com/foo/" -> "https://example.com/foo/v1/member/activity"
|
||||||
|
| s -> failwith $"Unrecognised base URI: %s{s}"
|
||||||
|
|
||||||
|
message.RequestUri.ToString () |> shouldEqual expectedUri
|
||||||
|
|
||||||
|
let content = new StringContent (json)
|
||||||
|
let resp = new HttpResponseMessage (HttpStatusCode.OK)
|
||||||
|
resp.Content <- content
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
use client = HttpClientMock.make baseUri proc
|
||||||
|
let api = PureGymApi.make client
|
||||||
|
|
||||||
|
api.GetMemberActivity().Result |> shouldEqual expected
|
||||||
|
|
||||||
|
let dates =
|
||||||
|
[
|
||||||
|
for month = 1 to 3 do
|
||||||
|
// span the number 12, to catch muddling up month and day
|
||||||
|
for day = 11 to 13 do
|
||||||
|
yield DateOnly (2023, month, day)
|
||||||
|
]
|
||||||
|
|
||||||
|
let sessionsCases =
|
||||||
|
PureGymDtos.sessionsCases
|
||||||
|
|> List.allPairs dates
|
||||||
|
|> List.allPairs dates
|
||||||
|
|> List.allPairs baseUris
|
||||||
|
|> List.map TestCaseData
|
||||||
|
|
||||||
|
let inline dateOnlyToString (d : DateOnly) : string =
|
||||||
|
let month = if d.Month < 10 then $"0%i{d.Month}" else $"%i{d.Month}"
|
||||||
|
let day = if d.Day < 10 then $"0%i{d.Day}" else $"%i{d.Day}"
|
||||||
|
$"{d.Year}-{month}-{day}"
|
||||||
|
|
||||||
|
[<TestCaseSource(nameof sessionsCases)>]
|
||||||
|
let ``Test GetSessions``
|
||||||
|
(
|
||||||
|
baseUri : Uri,
|
||||||
|
(startDate : DateOnly, (endDate : DateOnly, (json : string, expected : Sessions)))
|
||||||
|
)
|
||||||
|
=
|
||||||
|
let proc (message : HttpRequestMessage) : HttpResponseMessage Async =
|
||||||
|
async {
|
||||||
|
message.Method |> shouldEqual HttpMethod.Get
|
||||||
|
|
||||||
|
// This one is specified as being absolute, in its attribute on the IPureGymApi type
|
||||||
|
let expectedUri =
|
||||||
|
let fromDate = dateOnlyToString startDate
|
||||||
|
let toDate = dateOnlyToString endDate
|
||||||
|
$"https://example.com/v2/gymSessions/member?fromDate=%s{fromDate}&toDate=%s{toDate}"
|
||||||
|
|
||||||
|
message.RequestUri.ToString () |> shouldEqual expectedUri
|
||||||
|
|
||||||
|
let content = new StringContent (json)
|
||||||
|
let resp = new HttpResponseMessage (HttpStatusCode.OK)
|
||||||
|
resp.Content <- content
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
use client = HttpClientMock.make baseUri proc
|
||||||
|
let api = PureGymApi.make client
|
||||||
|
|
||||||
|
api.GetSessions(startDate, endDate).Result |> shouldEqual expected
|
@@ -204,6 +204,7 @@ RestEase is complex, and handles a lot of different stuff.
|
|||||||
* Parameters are serialised solely with `ToString`, and there's no control over this; nor is there control over encoding in any sense.
|
* Parameters are serialised solely with `ToString`, and there's no control over this; nor is there control over encoding in any sense.
|
||||||
* Deserialisation follows the same logic as the `JsonParse` generator, and it generally assumes you're using types which `JsonParse` is applied to.
|
* Deserialisation follows the same logic as the `JsonParse` generator, and it generally assumes you're using types which `JsonParse` is applied to.
|
||||||
* Headers are not yet supported.
|
* Headers are not yet supported.
|
||||||
|
* You have to specify the `BaseAddress` on the input client yourself, and you can't have the same client talking to a different `BaseAddress` this way unless you manually set it before making any different request.
|
||||||
* I haven't yet worked out how to integrate this with a mocked HTTP client; you can always mock up an `HttpClient`, but I prefer to use a mock which defines a single member `SendAsync`.
|
* I haven't yet worked out how to integrate this with a mocked HTTP client; you can always mock up an `HttpClient`, but I prefer to use a mock which defines a single member `SendAsync`.
|
||||||
* Anonymous parameters are currently forbidden.
|
* Anonymous parameters are currently forbidden.
|
||||||
* Every function must take an optional `CancellationToken` (which is good practice anyway); so arguments are forced to be tupled. This is a won't-fix for as long as F# requires tupled arguments if any of the args are optional.
|
* Every function must take an optional `CancellationToken` (which is good practice anyway); so arguments are forced to be tupled. This is a won't-fix for as long as F# requires tupled arguments if any of the args are optional.
|
||||||
|
@@ -184,8 +184,7 @@ module internal HttpClientGenerator =
|
|||||||
)
|
)
|
||||||
|
|
||||||
let requestUriTrailer =
|
let requestUriTrailer =
|
||||||
// TODO: more principled treatment of the slash
|
(SynExpr.CreateConstString info.UrlTemplate, info.Args)
|
||||||
(SynExpr.CreateConstString ("/" + info.UrlTemplate.TrimStart '/'), info.Args)
|
|
||||||
||> List.fold (fun template arg ->
|
||> List.fold (fun template arg ->
|
||||||
(template, arg.Attributes)
|
(template, arg.Attributes)
|
||||||
||> List.fold (fun template attr ->
|
||> List.fold (fun template attr ->
|
||||||
@@ -278,27 +277,24 @@ module internal HttpClientGenerator =
|
|||||||
|> SynExpr.CreateParen
|
|> SynExpr.CreateParen
|
||||||
|
|
||||||
let requestUri =
|
let requestUri =
|
||||||
|
let uriIdent = SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Uri" ])
|
||||||
|
|
||||||
SynExpr.App (
|
SynExpr.App (
|
||||||
ExprAtomicFlag.Atomic,
|
ExprAtomicFlag.Atomic,
|
||||||
false,
|
false,
|
||||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Uri" ]),
|
uriIdent,
|
||||||
SynExpr.CreateParen (
|
SynExpr.CreateParenedTuple
|
||||||
SynExpr.plus
|
[
|
||||||
(SynExpr.App (
|
SynExpr.CreateLongIdent (SynLongIdent.Create [ "client" ; "BaseAddress" ])
|
||||||
ExprAtomicFlag.Atomic,
|
SynExpr.CreateApp (
|
||||||
false,
|
uriIdent,
|
||||||
SynExpr.CreateLongIdent (
|
SynExpr.CreateParenedTuple
|
||||||
SynLongIdent.SynLongIdent (
|
[
|
||||||
[ Ident.Create "client" ; Ident.Create "BaseAddress" ; Ident.Create "ToString" ],
|
|
||||||
[ range0 ; range0 ],
|
|
||||||
[ None ; None ; None ]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
SynExpr.CreateConst SynConst.Unit,
|
|
||||||
range0
|
|
||||||
))
|
|
||||||
requestUriTrailer
|
requestUriTrailer
|
||||||
),
|
SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "UriKind" ; "Relative" ])
|
||||||
|
]
|
||||||
|
)
|
||||||
|
],
|
||||||
range0
|
range0
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -324,7 +320,7 @@ module internal HttpClientGenerator =
|
|||||||
SynLongIdent.Create
|
SynLongIdent.Create
|
||||||
[ "System" ; "Net" ; "Http" ; "HttpMethod" ; httpMethodString info.HttpMethod ]
|
[ "System" ; "Net" ; "Http" ; "HttpMethod" ; httpMethodString info.HttpMethod ]
|
||||||
))
|
))
|
||||||
SynExpr.equals (SynExpr.CreateIdentString "RequestUri") requestUri
|
SynExpr.equals (SynExpr.CreateIdentString "RequestUri") (SynExpr.CreateIdentString "uri")
|
||||||
]
|
]
|
||||||
|> SynExpr.CreateParenedTuple
|
|> SynExpr.CreateParenedTuple
|
||||||
|
|
||||||
@@ -337,6 +333,7 @@ module internal HttpClientGenerator =
|
|||||||
let implementation =
|
let implementation =
|
||||||
[
|
[
|
||||||
yield LetBang ("ct", SynExpr.CreateLongIdent (SynLongIdent.Create [ "Async" ; "CancellationToken" ]))
|
yield LetBang ("ct", SynExpr.CreateLongIdent (SynLongIdent.Create [ "Async" ; "CancellationToken" ]))
|
||||||
|
yield Let ("uri", requestUri)
|
||||||
yield
|
yield
|
||||||
Use (
|
Use (
|
||||||
"httpMessage",
|
"httpMessage",
|
||||||
|
Reference in New Issue
Block a user