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"))}}}
This commit is contained in:
Icaro Motta 2024-06-24 15:56:55 -03:00 committed by GitHub
parent 66785d01ec
commit 419e84db08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 58 additions and 2 deletions

View File

@ -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

View File

@ -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)})))

View File

@ -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]])

View File

@ -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))