257 lines
8 KiB
Clojure
257 lines
8 KiB
Clojure
(ns failjure.test-core
|
|
(:require #?@(:clj [[clojure.test :refer :all]
|
|
[failjure.core :as f]]
|
|
:cljs [[cljs.test :refer-macros [deftest testing is]]
|
|
[failjure.core :as f :include-macros true]])))
|
|
|
|
(deftest failjure-core-test
|
|
(testing "attempt"
|
|
(let [handle-error #(str "Error: " (f/message %))]
|
|
(is (= "Ok" (f/attempt handle-error "Ok")))
|
|
(is (= "Error: failed" (f/attempt handle-error (f/fail "failed"))))))
|
|
|
|
(testing "attempt-all"
|
|
(testing "basically works"
|
|
(is (= "Ok"
|
|
(f/attempt-all [x "O"
|
|
y "k"]
|
|
(str x y)))))
|
|
|
|
; Fails
|
|
(testing "Returns/short-circuits on failures"
|
|
(is (= (f/fail "k")
|
|
(f/attempt-all [x "O"
|
|
y (f/fail "k")
|
|
_ (is false "Did not short-circuit")
|
|
]
|
|
(str x y)))))
|
|
|
|
(testing "Returns the exception for try*"
|
|
(let [result (f/attempt-all [x "O"
|
|
y (f/try* #?(:clj (Integer/parseInt "k")
|
|
:cljs (throw (js/Error. "Fails."))))
|
|
z (is false "Did not short-circuit")]
|
|
(str x y z))]
|
|
(is (f/failed? result))
|
|
#?(:clj (is (instance? NumberFormatException result))
|
|
:cljs (is (instance? js/Error result)))))
|
|
|
|
(testing "Runs when-failed"
|
|
; Runs when-failed
|
|
(is (= "Fail"
|
|
(f/attempt-all [x "O"
|
|
y (f/fail "Fail")
|
|
z "!"]
|
|
(str x y z)
|
|
(f/when-failed [e]
|
|
(f/message e))))))
|
|
|
|
(testing "Runs if-failed (which is DEPRECATED but still supported)"
|
|
; Runs if-failed
|
|
(is (= "Fail"
|
|
(f/attempt-all [x "O"
|
|
y (f/fail "Fail")
|
|
z "!"]
|
|
(str x y z)
|
|
(f/if-failed [e]
|
|
(f/message e))))))
|
|
|
|
#?(:clj
|
|
(testing "attempt-all does not catch exceptions automatically"
|
|
(is (= "Caught"
|
|
(try
|
|
(f/attempt-all [x "O"
|
|
y (Integer/parseInt "k")]
|
|
"Ok"
|
|
"Failed")
|
|
(catch NumberFormatException e "Caught")))))
|
|
:cljs
|
|
(testing "attempt-all does not catch exceptions automatically"
|
|
(is (= "Caught"
|
|
(try
|
|
(f/attempt-all [x "O"
|
|
y (throw (js/Error. "Some error"))]
|
|
"Ok"
|
|
"Failed")
|
|
(catch :default e "Caught"))))))
|
|
|
|
(testing "Destructuring in fail cases should return the failure"
|
|
(is (= (f/fail "Fail")
|
|
(f/attempt-all [x "1"
|
|
{:keys [y]} (f/fail "Fail")]
|
|
y))))
|
|
|
|
(testing "try-all safely catches an exception in the bindings"
|
|
(is (f/failed? (f/try-all [x #?(:clj (/ 4 0) :cljs (throw (js/Error. "Error")))
|
|
y (+ 3 4)]
|
|
(+ x y)))))
|
|
|
|
(testing "try-all safely catches an exception in the bindings with else clause"
|
|
(is (= "Divide by zero"
|
|
(f/try-all [x #?(:clj (/ 4 0) :cljs (throw (js/Error. "Divide by zero")))
|
|
y (+ 3 4)]
|
|
(+ x y)
|
|
(f/when-failed [err] (f/message err))))))
|
|
)
|
|
|
|
; Test ok-> (and therefore attempt->)
|
|
(testing "ok->"
|
|
(is (= "Ok!"
|
|
(f/ok->
|
|
""
|
|
(str "O")
|
|
(str "k")
|
|
(str "!"))))
|
|
|
|
(is (= (f/fail "Not OK!")
|
|
(f/ok->
|
|
""
|
|
(str "Not OK!")
|
|
(f/fail)
|
|
(str "kay-O!")
|
|
(reverse))))
|
|
|
|
; Ensure the double-eval bug goes away
|
|
(let [a (atom 0)]
|
|
(is (= 2
|
|
(f/ok->
|
|
(swap! a inc)
|
|
inc)))
|
|
(is (= 3
|
|
(f/ok->>
|
|
(swap! a inc)
|
|
inc)))))
|
|
|
|
(testing "as-ok->"
|
|
(is (= "Ok!"
|
|
(f/as-ok-> "k" a
|
|
(str a "!")
|
|
(str "O" a))))
|
|
(is (= "foo"
|
|
(let [func (constantly (f/fail "foo"))
|
|
result (f/as-ok-> "k" a
|
|
(str a "!")
|
|
(func a)
|
|
(str "O" a))]
|
|
(f/message result))))
|
|
(is (= "foo"
|
|
(let [func (constantly (f/fail "foo"))
|
|
result (f/as-ok-> "k" a
|
|
(str a "!")
|
|
(str "O" a)
|
|
(func a))]
|
|
(f/message result)))))
|
|
|
|
; Test attempt->>
|
|
(testing "ok->>"
|
|
(is (= "Ok"
|
|
(f/ok->>
|
|
""
|
|
(str "k")
|
|
(str "O"))))
|
|
|
|
(is (= (f/fail "Not OK!")
|
|
(f/ok->>
|
|
""
|
|
(str "Not OK!")
|
|
(f/fail)
|
|
(str "O")
|
|
(reverse)))))
|
|
|
|
(testing "failed?"
|
|
(testing "failed? is valid on nullable"
|
|
(is (false? (f/failed? nil)))
|
|
(is (= "nil" (f/message nil))))
|
|
|
|
(testing "failed? is valid on exception"
|
|
(is (true? (f/failed? #?(:clj (Exception. "Failed")
|
|
:cljs (js/Error. "Failed")))))
|
|
(is (= "My Message" (f/message #?(:clj (Exception. "My Message")
|
|
:cljs (js/Error. "My Message"))))))
|
|
|
|
(testing "failed? is valid on failure"
|
|
(is (true? (f/failed? (f/fail "You failed."))))
|
|
(is (= "You failed." (f/message (f/fail "You failed."))))))
|
|
|
|
(testing "if-let-ok?"
|
|
|
|
(is (= "Hello"
|
|
(f/if-let-ok? [v "Hello"] v)))
|
|
|
|
(is (f/failed?
|
|
(f/if-let-ok? [v (f/fail "FAIL")] "OK")))
|
|
|
|
(is (= "Hello"
|
|
(f/if-let-ok? [v :ok] "Hello" "Goodbye")))
|
|
|
|
(is (= "Goodbye"
|
|
(f/if-let-ok? [v (f/fail "Hello")] "Hello" "Goodbye")))
|
|
|
|
(is (= (f/fail "Fail")
|
|
(f/if-let-failed? [{:keys [y]} (f/fail "Something went wrong!")]
|
|
(f/fail "Fail")))))
|
|
|
|
(testing "when-let-ok?"
|
|
(let [result (atom nil)]
|
|
(is (= "Hello"
|
|
(f/when-let-ok? [v "Hello"]
|
|
(reset! result :ok)
|
|
v)))
|
|
(is (= :ok @result)))
|
|
|
|
(let [result (atom nil)]
|
|
(is (f/failed?
|
|
(f/when-let-ok? [v (f/fail "FAIL")]
|
|
(reset! result :ok)
|
|
"OK")))
|
|
(is (nil? @result))
|
|
)
|
|
)
|
|
|
|
(testing "if-let-failed?"
|
|
|
|
(is (= "Hello"
|
|
(f/if-let-failed? [v "Hello"] "FAILED" v)))
|
|
|
|
(is (f/failed?
|
|
(f/if-let-failed? [v (f/fail "FAIL")] v)))
|
|
|
|
(is (f/ok?
|
|
(f/if-let-failed? [v "Didn't fail"] v)))
|
|
|
|
(is (= "Goodbye"
|
|
(f/if-let-failed? [v :ok] "Hello" "Goodbye")))
|
|
|
|
(is (= "Hello"
|
|
(f/if-let-failed? [v (f/fail "Hello")] "Hello" "Goodbye")))
|
|
)
|
|
|
|
(testing "when-let-failed?"
|
|
(let [result (atom nil)]
|
|
(is (= "Hello"
|
|
(f/when-let-failed?
|
|
[v "Hello"]
|
|
(reset! result :ok)
|
|
v)))
|
|
(is (nil? @result)))
|
|
|
|
(let [result (atom nil)]
|
|
(is (= "OK"
|
|
(f/when-let-failed?
|
|
[v (f/fail "FAIL")]
|
|
(reset! result :ok)
|
|
"OK")))
|
|
(is (= :ok @result))))
|
|
|
|
(testing "Assertions"
|
|
;; assert-some? basically covers everything
|
|
(testing "Assert some?"
|
|
(is (= (f/fail "msg") (f/assert-some? nil "msg")))
|
|
(is (= "it" (f/assert-some? "it" "msg"))))))
|
|
|
|
|
|
|
|
|
|
(comment
|
|
(run-tests)
|
|
)
|