-
Notifications
You must be signed in to change notification settings - Fork 15
/
state_test.clj
87 lines (76 loc) · 3.48 KB
/
state_test.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
(ns state-flow.state-test
(:require [cats.core :as m]
[cats.monad.exception :as e]
[clojure.test :as t :refer [deftest is testing]]
[state-flow.state :as state]))
(deftest primitives
(testing "all primitives are flows"
(is (state/state? (state/get)))
(is (state/state? (state/gets inc)))
(is (state/state? (state/modify inc)))
(is (state/state? (state/put {:count 0})))
(is (state/state? (state/return 37)))
(is (state/state? (state/invoke (constantly "hello")))))
(testing "primitives returns correct values"
(is (= [2 2] (state/run (state/get) 2)))
(is (= [3 2] (state/run (state/gets inc) 2)))
(is (= [2 3] (state/run (state/modify inc) 2)))
(is (= [2 3] (state/run (state/put 3) 2)))
(is (= [37 2] (state/run (state/return 37) 2)))
(is (= ["hello" 2] (state/run (state/invoke (constantly "hello")) 2)))))
(deftest exception-handling
(let [double-state (state/modify * 2)]
(testing "state with an exception returns a failure as the left value"
(let [[res state] (state/run (m/>> double-state
double-state
(state/modify (fn [s] (throw (Exception. "My exception"))))
double-state) 2)]
(is (e/failure? res))
(is (= 8 state))))
(testing "also handles exceptions with fmap"
(let [[res state] (state/run
(m/fmap inc (m/>> double-state
double-state
(state/modify (fn [s] (throw (Exception. "My exception"))))
double-state)) 2)]
(is (e/failure? res))
(is (= 8 state)))
(let [[res state] (state/run
(m/>> double-state
double-state
(state/modify (fn [s] (throw (Exception. "My exception"))))
double-state) 2)]
(is (e/failure? res))
(is (= 8 state)))
(let [[res state] (state/run
(m/>> (m/fmap (fn [s] (throw (Exception. "My exception")))
(m/>> double-state
double-state))
double-state) 2)]
(is (e/failure? res))
(is (= 8 state)))))
(testing "exceptions in primitives are returned as the result"
(is (e/failure? (first (state/run (state/gets #(/ 2 %)) 0))))
(is (e/failure? (first (state/run (state/modify #(/ 2 %)) 0))))))
(deftest get-and-put
(let [increment-state (m/mlet [x (state/get)
_ (state/put (inc x))]
(m/return x))]
(testing "modify state with get and put"
(is (= [2 3]
(state/run increment-state 2))))))
(deftest modify
(testing "supports single function or varargs"
(is (= [{:count 0} {:count 1}]
(state/run (state/modify #(update % :count inc)) {:count 0})
(state/run (state/modify update :count inc) {:count 0})))))
(deftest gets
(testing "supports single function or varargs"
(is (= [{:count 1} {:count 0}]
(state/run (state/gets #(update % :count inc)) {:count 0})
(state/run (state/gets update :count inc) {:count 0})))))
(deftest fmap
(is (= 1
(first (state/run
(state/fmap (comp inc :count) (state/get))
{:count 0})))))