Skip to content

Commit d4386c9

Browse files
[feat]: Added tests and utility functions for Optimistic helper type based on PR feedback.
what changed?: added tests for Optimistic helper type; Also added utility functions for Optimistic helper type why?: from pr feedback effect?: better tested library
1 parent b4fd825 commit d4386c9

2 files changed

Lines changed: 110 additions & 1 deletion

File tree

src/SAFE.Client/SAFE.fs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,3 +208,45 @@ type Optimistic<'T> = {
208208
Value = this.Prev
209209
Prev = None
210210
}
211+
212+
/// Maps the underlying optimistic value, when it exists, into another shape.
213+
member this.Map (f: 'T -> 'U) =
214+
{
215+
Value = Option.map f this.Value
216+
Prev = Option.map f this.Prev
217+
}
218+
219+
/// Binds both current and previous values using the provided function
220+
member this.Bind (f: 'T -> Optimistic<'U>) =
221+
match this.Value with
222+
| Some v -> f v // Just use the result directly
223+
| None -> { Value = None; Prev = None }
224+
225+
/// Returns the current value as an option
226+
member this.AsOption = this.Value
227+
228+
/// Module containing functions for working with Optimistic type
229+
module Optimistic =
230+
/// Creates a new Optimistic value with no history
231+
let create value = { Value = Some value; Prev = None }
232+
233+
/// Creates an empty Optimistic value
234+
let empty = { Value = None; Prev = None }
235+
236+
/// Updates the current value, shifting existing value to previous
237+
let update value (optimistic: Optimistic<'T>) = optimistic.Update value
238+
239+
/// Rolls back to the previous value
240+
let rollback (optimistic: Optimistic<'T>) = optimistic.Rollback()
241+
242+
/// Maps both current and previous values
243+
let map f (optimistic: Optimistic<'T>) = optimistic.Map f
244+
245+
/// Binds both current and previous values
246+
let bind f (optimistic: Optimistic<'T>) = optimistic.Bind f
247+
248+
/// Returns the current value as an option
249+
let asOption (optimistic: Optimistic<'T>) = optimistic.AsOption
250+
251+
/// Returns the previous value as an option
252+
let asPrevOption optimistic = optimistic.Prev

test/SAFE.Client.Tests/Program.fs

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,5 +125,72 @@ let remoteData =
125125
| RemoteDataCase.Loaded -> Loading (Some true))
126126
]
127127

128+
let optimistic =
129+
testList "Optimistic" [
130+
testList "create" [
131+
testCase "creates new value with no history" <| fun _ ->
132+
let opt = Optimistic.create 42
133+
Expect.equal opt.Value (Some 42) "Current value should be set"
134+
Expect.equal opt.Prev None "Previous value should be None"
135+
]
136+
137+
testList "empty" [
138+
testCase "creates empty optimistic value" <| fun _ ->
139+
let opt = Optimistic.empty
140+
Expect.equal opt.Value None "Current value should be None"
141+
Expect.equal opt.Prev None "Previous value should be None"
142+
]
143+
144+
testList "update" [
145+
testCase "updates value and shifts previous" <| fun _ ->
146+
let opt = Optimistic.create 42
147+
let updated = opt.Update 84
148+
Expect.equal updated.Value (Some 84) "Current value should be updated"
149+
Expect.equal updated.Prev (Some 42) "Previous value should be old current"
150+
]
151+
152+
testList "rollback" [
153+
testCase "rolls back to previous value" <| fun _ ->
154+
let opt = Optimistic.create 42 |> Optimistic.update 84
155+
let rolled = opt.Rollback()
156+
Expect.equal rolled.Value (Some 42) "Current value should be previous"
157+
Expect.equal rolled.Prev None "Previous value should be cleared"
158+
]
159+
160+
testList "map" [
161+
testCase "maps both values" <| fun _ ->
162+
let opt = { Value = Some 42; Prev = Some 21 }
163+
let mapped = opt.Map string
164+
Expect.equal mapped.Value (Some "42") "Current value should be mapped"
165+
Expect.equal mapped.Prev (Some "21") "Previous value should be mapped"
166+
]
167+
168+
testList "bind" [
169+
testCase "binds value with history" <| fun _ ->
170+
let opt = { Value = Some 42; Prev = Some 21 }
171+
let bound = opt.Bind (fun x -> { Value = Some (string x); Prev = None})
172+
Expect.equal bound.Value (Some "42") "Current value should be bound"
173+
Expect.equal bound.Prev (None) "Previous value should be bound"
174+
]
175+
176+
testList "asOption" [
177+
testCase "returns current value as option" <| fun _ ->
178+
let opt = Optimistic.create 42
179+
Expect.equal (Optimistic.asOption opt) (Some 42) "Should return current value"
180+
]
181+
182+
testList "asPrevOption" [
183+
testCase "returns previous value as option" <| fun _ ->
184+
let opt = Optimistic.create 42 |> Optimistic.update 84
185+
Expect.equal (Optimistic.asPrevOption opt) (Some 42) "Should return previous value"
186+
]
187+
]
188+
189+
let allTests =
190+
testList "All Tests" [
191+
remoteData
192+
optimistic
193+
]
194+
128195
[<EntryPoint>]
129-
let main _ = Mocha.runTests remoteData
196+
let main _ = Mocha.runTests allTests

0 commit comments

Comments
 (0)