From 1dd20b0a0ca053305aa759d011c119be11b43a50 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sat, 13 Feb 2021 10:48:59 +0100 Subject: [PATCH] Add failjure to libtests --- deps.edn | 3 +- .../lib_tests/babashka/run_all_libtests.clj | 2 + .../lib_tests/failjure/test_core.cljc | 257 ++++++++++++++++++ 3 files changed, 261 insertions(+), 1 deletion(-) create mode 100644 test-resources/lib_tests/failjure/test_core.cljc diff --git a/deps.edn b/deps.edn index be01e738..d9ed180b 100644 --- a/deps.edn +++ b/deps.edn @@ -71,7 +71,8 @@ minimallist/minimallist {:mvn/version "0.0.6"} circleci/bond {:mvn/version "0.4.0"} version-clj/version-clj {:mvn/version "0.1.2"} - gaka/gaka {:mvn/version "0.3.0"}}} + gaka/gaka {:mvn/version "0.3.0"} + failjure/failjure {:mvn/version "2.1.1"}}} :clj-nvd {:extra-deps {clj-nvd/clj-nvd {:git/url "https://github.com/miikka/clj-nvd.git" :sha "f2ec98699e057a379baf170cb49cf7ad76874a70"}} diff --git a/test-resources/lib_tests/babashka/run_all_libtests.clj b/test-resources/lib_tests/babashka/run_all_libtests.clj index f125d1df..2bc95639 100644 --- a/test-resources/lib_tests/babashka/run_all_libtests.clj +++ b/test-resources/lib_tests/babashka/run_all_libtests.clj @@ -178,6 +178,8 @@ (test-namespaces 'gaka.core-test) +(test-namespaces 'failjure.test-core) + ;;;; final exit code (let [{:keys [:test :fail :error] :as m} @status] diff --git a/test-resources/lib_tests/failjure/test_core.cljc b/test-resources/lib_tests/failjure/test_core.cljc new file mode 100644 index 00000000..d5992aec --- /dev/null +++ b/test-resources/lib_tests/failjure/test_core.cljc @@ -0,0 +1,257 @@ +(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) + )