Skip to content

Commit 4b44f72

Browse files
authored
Merge pull request #89 from fossa-app/split-client-result-helpers
Add ergonomic helpers for client results
2 parents f23d269 + 2791a6f commit 4b44f72

3 files changed

Lines changed: 94 additions & 15 deletions

File tree

src/Bridge/Models/Helpers/ClientResultHelpers.fs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,49 @@ module ClientResultHelpers =
99
let problem<'T when 'T: not struct and 'T: not null> (problem: ProblemDetailsModel) : ClientResult<'T> =
1010
ClientResult.Failure problem
1111

12-
let matchClientResult<'T, 'TResult when 'T: not struct and 'T: not null>
12+
let mapClientResult<'T, 'U when 'T: not struct and 'T: not null and 'U: not struct and 'U: not null>
13+
(result: ClientResult<'T>)
14+
(mapSuccess: 'T -> 'U)
15+
: ClientResult<'U> =
16+
match result with
17+
| ClientResult.Success value -> ClientResult.Success(mapSuccess value)
18+
| ClientResult.Failure problem -> ClientResult.Failure problem
19+
20+
let foldClientResult<'T, 'TResult when 'T: not struct and 'T: not null>
1321
(result: ClientResult<'T>)
1422
(onSuccess: 'T -> 'TResult)
1523
(onFailure: ProblemDetailsModel -> 'TResult)
1624
: 'TResult =
17-
result.Match(onSuccess, onFailure)
25+
match result with
26+
| ClientResult.Success value -> onSuccess value
27+
| ClientResult.Failure problem -> onFailure problem
1828

19-
let matchClientUnitResult<'TResult>
29+
let foldClientUnitResult<'TResult>
2030
(result: ClientUnitResult)
2131
(onSuccess: unit -> 'TResult)
2232
(onFailure: ProblemDetailsModel -> 'TResult)
2333
: 'TResult =
24-
result.Match(onSuccess, onFailure)
34+
match result with
35+
| ClientUnitResult.Success -> onSuccess ()
36+
| ClientUnitResult.Failure problem -> onFailure problem
37+
38+
let handleClientResult<'T when 'T: not struct and 'T: not null>
39+
(result: ClientResult<'T>)
40+
(onSuccess: 'T -> unit)
41+
(onFailure: ProblemDetailsModel -> unit)
42+
: unit =
43+
match result with
44+
| ClientResult.Success value -> onSuccess value
45+
| ClientResult.Failure problem -> onFailure problem
46+
47+
let handleClientUnitResult
48+
(result: ClientUnitResult)
49+
(onSuccess: unit -> unit)
50+
(onFailure: ProblemDetailsModel -> unit)
51+
: unit =
52+
match result with
53+
| ClientUnitResult.Success -> onSuccess ()
54+
| ClientUnitResult.Failure problem -> onFailure problem
2555

2656
let isClientSuccess (result: IClientResult) : bool = result.IsSuccess
2757

tests/Bridge.Tests/ClientResultTests.fs

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,23 @@ let tests =
3939
<| fun _ ->
4040
let result = ClientResultHelpers.success "bridge"
4141

42-
let matched = ClientResultHelpers.matchClientResult result id (fun _ -> "problem")
42+
let mapped =
43+
ClientResultHelpers.mapClientResult result (fun value -> value + "-mapped")
4344

44-
Expect.equal matched "bridge" "Match should return success value"
45+
let folded = ClientResultHelpers.foldClientResult result id (fun _ -> "problem")
46+
let mutable successHandled = false
47+
let mutable failureHandled = false
48+
49+
ClientResultHelpers.handleClientResult result (fun value -> successHandled <- value = "bridge") (fun _ ->
50+
failureHandled <- true)
51+
52+
match mapped with
53+
| ClientResult.Success value -> Expect.equal value "bridge-mapped" "Map should transform success value"
54+
| ClientResult.Failure _ -> failtest "Expected mapped success"
55+
56+
Expect.equal folded "bridge" "Fold should return success projection"
57+
Expect.isTrue successHandled "Handle should invoke success callback"
58+
Expect.isFalse failureHandled "Handle should not invoke failure callback"
4559
Expect.isTrue (ClientResultHelpers.isClientSuccess result) "Result should be success"
4660
Expect.isFalse (ClientResultHelpers.isClientFailure result) "Result should not be failure"
4761
Expect.equal (ClientResultHelpers.getClientValue result) (Some "bridge") "Value should be available"
@@ -51,11 +65,30 @@ let tests =
5165
testCase "ergonomic helpers expose failure result"
5266
<| fun _ ->
5367
let result: ClientResult<string> = ClientResultHelpers.problem problem
68+
let mutable mapCalled = false
69+
70+
let mapped =
71+
ClientResultHelpers.mapClientResult result (fun value ->
72+
mapCalled <- true
73+
value + "-mapped")
74+
75+
let folded =
76+
ClientResultHelpers.foldClientResult result id (fun actual -> string actual.title)
77+
78+
let mutable successHandled = false
79+
let mutable failureHandled = false
80+
81+
ClientResultHelpers.handleClientResult result (fun _ -> successHandled <- true) (fun actual ->
82+
failureHandled <- actual = problem)
5483

55-
let matched =
56-
ClientResultHelpers.matchClientResult result id (fun actual -> string actual.title)
84+
match mapped with
85+
| ClientResult.Success _ -> failtest "Expected mapped failure"
86+
| ClientResult.Failure actual -> Expect.equal actual problem "Map should preserve problem"
5787

58-
Expect.equal matched (string problem.title) "Match should return problem projection"
88+
Expect.isFalse mapCalled "Map should not invoke success mapper for failure"
89+
Expect.equal folded (string problem.title) "Fold should return problem projection"
90+
Expect.isFalse successHandled "Handle should not invoke success callback"
91+
Expect.isTrue failureHandled "Handle should invoke failure callback"
5992
Expect.isFalse (ClientResultHelpers.isClientSuccess result) "Result should not be success"
6093
Expect.isTrue (ClientResultHelpers.isClientFailure result) "Result should be failure"
6194
Expect.equal (ClientResultHelpers.getClientValue result) None "Value should not be available"

tests/Bridge.Tests/ClientUnitResultTests.fs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,18 @@ let tests =
3939
<| fun _ ->
4040
let result = ClientUnitResultHelpers.success
4141

42-
let matched =
43-
ClientResultHelpers.matchClientUnitResult result (fun () -> "ok") (fun _ -> "problem")
42+
let folded =
43+
ClientResultHelpers.foldClientUnitResult result (fun () -> "ok") (fun _ -> "problem")
4444

45-
Expect.equal matched "ok" "Match should return success projection"
45+
let mutable successHandled = false
46+
let mutable failureHandled = false
47+
48+
ClientResultHelpers.handleClientUnitResult result (fun () -> successHandled <- true) (fun _ ->
49+
failureHandled <- true)
50+
51+
Expect.equal folded "ok" "Fold should return success projection"
52+
Expect.isTrue successHandled "Handle should invoke success callback"
53+
Expect.isFalse failureHandled "Handle should not invoke failure callback"
4654
Expect.isTrue (ClientResultHelpers.isClientSuccess result) "Result should be success"
4755
Expect.isFalse (ClientResultHelpers.isClientFailure result) "Result should not be failure"
4856
Expect.equal (ClientResultHelpers.getClientProblem result) None "Problem should not be available"
@@ -52,10 +60,18 @@ let tests =
5260
<| fun _ ->
5361
let result = ClientUnitResultHelpers.problem problem
5462

55-
let matched =
56-
ClientResultHelpers.matchClientUnitResult result (fun () -> "ok") (fun actual -> string actual.title)
63+
let folded =
64+
ClientResultHelpers.foldClientUnitResult result (fun () -> "ok") (fun actual -> string actual.title)
65+
66+
let mutable successHandled = false
67+
let mutable failureHandled = false
68+
69+
ClientResultHelpers.handleClientUnitResult result (fun () -> successHandled <- true) (fun actual ->
70+
failureHandled <- actual = problem)
5771

58-
Expect.equal matched (string problem.title) "Match should return problem projection"
72+
Expect.equal folded (string problem.title) "Fold should return problem projection"
73+
Expect.isFalse successHandled "Handle should not invoke success callback"
74+
Expect.isTrue failureHandled "Handle should invoke failure callback"
5975
Expect.isFalse (ClientResultHelpers.isClientSuccess result) "Result should not be success"
6076
Expect.isTrue (ClientResultHelpers.isClientFailure result) "Result should be failure"
6177
Expect.equal (ClientResultHelpers.getClientProblem result) (Some problem) "Problem should be available"

0 commit comments

Comments
 (0)