From 419e84db0848e5a9a800ceee0a153536604b9266 Mon Sep 17 00:00:00 2001 From: Icaro Motta Date: Mon, 24 Jun 2024 15:56:55 -0300 Subject: [PATCH] chore(tests)_: Make bignumber instances test friendly (#20535) Solves a problem encountered in unit tests, where instances of BigNumber (used in the utils.money namespace) can't be compared with = or match? If you try the following code you will always get false because they're different instances in memory. (= (money/bignumber 0) (money/bignumber 0)) We now extend BigNumber (from lib bignumber.js) so that their instances are comparable (e.g. necessary to sort) and understand equality. We also extend BigNumber to work with the match? directive. For example, this is the output of comparing a nested map containing bignumbers (colored in the terminal): (match? {:a {:b {:c (money/bignumber 42)}}} {:a {:b {:c (money/bignumber 43)}}}) FAIL in (equivalence-test) (at cljs$test$run_block (status-mobile/target/test/cljs-runtime/cljs.test.js:366:13) expected: (match? {:a {:b {:c (money/bignumber 42)}}} {:a {:b {:c (money/bignumber 43)}}}) actual: {:a {:b {:c (mismatch (expected "42") (actual "43"))}}} --- shadow-cljs.edn | 3 ++- src/status_im/setup/test_preload.cljs | 18 ++++++++++++++++++ src/utils/money.cljs | 17 ++++++++++++++++- src/utils/money_test.cljs | 22 ++++++++++++++++++++++ 4 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 src/status_im/setup/test_preload.cljs diff --git a/shadow-cljs.edn b/shadow-cljs.edn index 425f58f3fa..d9f226b1b8 100644 --- a/shadow-cljs.edn +++ b/shadow-cljs.edn @@ -131,7 +131,8 @@ :output-dir "target/test" :optimizations :simple :target :node-test - :dev {:devtools {:preloads [status-im.setup.schema-preload]}} + :dev {:devtools {:preloads [status-im.setup.schema-preload + status-im.setup.test-preload]}} ;; Uncomment line below to `make test-watch` a specific file :ns-regexp #shadow/env "SHADOW_NS_REGEXP" :main legacy.status-im.test-runner/main diff --git a/src/status_im/setup/test_preload.cljs b/src/status_im/setup/test_preload.cljs new file mode 100644 index 0000000000..2db545851c --- /dev/null +++ b/src/status_im/setup/test_preload.cljs @@ -0,0 +1,18 @@ +(ns status-im.setup.test-preload + (:require + ["bignumber.js" :as BigNumber] + [matcher-combinators.core :as matcher-combinators] + [matcher-combinators.model :as matcher.model])) + +;; We must implement Matcher in order for tests to work with the `match?` +;; directive. +(extend-type BigNumber + matcher-combinators/Matcher + (-matcher-for [this] this) + (-base-name [_] 'bignumber) + (-match [this actual] + (if (-equiv this actual) + {:matcher-combinators.result/type :match + :matcher-combinators.result/value actual} + {:matcher-combinators.result/type :mismatch + :matcher-combinators.result/value (matcher.model/->Mismatch this actual)}))) diff --git a/src/utils/money.cljs b/src/utils/money.cljs index cd5e6f0e35..cf41537e60 100644 --- a/src/utils/money.cljs +++ b/src/utils/money.cljs @@ -50,10 +50,26 @@ [bn1 bn2] (.greaterThan ^js bn1 bn2)) +(defn less-than + [bn1 bn2] + (.lessThan ^js bn1 bn2)) + (defn equal-to [bn1 bn2] (.eq ^js bn1 bn2)) +(extend-type BigNumber + IEquiv + (-equiv [this other] + (equal-to this other)) + + IComparable + (-compare [this other] + (cond + (less-than this other) -1 + (greater-than this other) 1 + :else 0))) + (defn sub [bn1 bn2] (.sub ^js bn1 bn2)) @@ -260,4 +276,3 @@ (schema/=> format-amount [:=> [:cat [:maybe :int]] [:maybe :string]]) - diff --git a/src/utils/money_test.cljs b/src/utils/money_test.cljs index ca034d8a8b..97e2cf68d3 100644 --- a/src/utils/money_test.cljs +++ b/src/utils/money_test.cljs @@ -3,6 +3,28 @@ [cljs.test :refer-macros [deftest testing is are]] [utils.money :as money])) +(deftest comparable-test + (is (= [(money/bignumber -4) + (money/bignumber 0) + (money/bignumber 1) + (money/bignumber 1.1) + (money/bignumber 2.1)] + (sort [(money/bignumber 0) + (money/bignumber 2.1) + (money/bignumber -4) + (money/bignumber 1.1) + (money/bignumber 1)])))) + +(deftest equivalence-test + (is (= (money/bignumber 0) + (money/bignumber 0))) + (is (= (money/bignumber -1) + (money/bignumber -1))) + (is (not (= (money/bignumber 10) + (money/bignumber -10)))) + (is (match? {:a {:b {:c (money/bignumber 42)}}} + {:a {:b {:c (money/bignumber 42)}}}))) + (deftest wei->ether-test (testing "Numeric input, 15 significant digits" (is (= (str (money/wei->ether 111122223333444000))