From 563f1c588d1cdac31629da009a1c894133038d2d Mon Sep 17 00:00:00 2001 From: Icaro Motta Date: Tue, 5 Dec 2023 17:20:54 -0300 Subject: [PATCH] Improve test failure readability (#18049) Problem: failed equality checks as in "(is (= expected actual))" will give a single, long line of output that for anything but the simplest data structures is unreadable by humans, and the output doesn't give a useful diff. Solution: use library https://github.com/nubank/matcher-combinators and its test directive "match?" which will pinpoint where two data structures differ. Then, instead of "(is (= ...", use "(is (match? expected actual)". It works beautifully. The library offers other nice matchers, but the majority of the time match? is sufficient. Can we use another test runner like Kaocha? kaocha-cljs2 (https://github.com/lambdaisland/kaocha-cljs2) would be able to print better test errors out of the box, among other features, but I have no clue if it would work well or at all in our stack (in theory yes, but it's a larger piece of work). --- .clj-kondo/config.edn | 10 +- doc/new-guidelines.md | 20 + nix/deps/clojure/deps.json | 18 + nix/deps/clojure/deps.list | 2 + shadow-cljs.edn | 1 + .../contexts/add_new_contact/events_test.cljs | 11 +- .../composer/link_preview/events_test.cljs | 165 +++++---- .../communities/discover/events_test.cljs | 3 +- .../communities/overview/events_test.cljs | 18 +- .../shell/activity_center/events_test.cljs | 350 +++++++++--------- .../contexts/wallet/events_test.cljs | 14 +- 11 files changed, 335 insertions(+), 277 deletions(-) diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn index 498e119204..fa20942ef3 100644 --- a/.clj-kondo/config.edn +++ b/.clj-kondo/config.edn @@ -62,7 +62,15 @@ ;; https://github.com/borkdude/clj-kondo/issues/867 :unresolved-symbol {:exclude [PersistentPriorityMap.EMPTY number - status-im.test-helpers/restore-app-db]} + status-im.test-helpers/restore-app-db + + ;; When the namespace + ;; matcher-combinators.test is loaded, it + ;; extends cljs.test/is macro with + ;; directives `match?` and + ;; `thrown-match?`. + match? + thrown-match?]} :unresolved-var {:level :error} :unsorted-required-namespaces {:level :error} :unused-alias {:level :warning} diff --git a/doc/new-guidelines.md b/doc/new-guidelines.md index a1e8d0f517..469c98dd44 100644 --- a/doc/new-guidelines.md +++ b/doc/new-guidelines.md @@ -641,6 +641,26 @@ keywords and concatenating them into a single string. ``` ### Tests +#### Prefer `match?` over `=` when comparing data structures + +Prefer the `match?` directive over `=` when comparing data structures, otherwise +when the check fails the output can be too difficult to read. `match?` is +defined by library https://github.com/nubank/matcher-combinators. + +```clojure +;; bad +(deftest some-test + (let [expected {...} + actual {...}] + (is (= expected actual)))) + +;; good +(deftest some-test + (let [expected {...} + actual {...}] + (is (match? expected actual)))) +``` + #### Subscription tests Test [layer-3 subscriptions](https://day8.github.io/re-frame/subscriptions/) by diff --git a/nix/deps/clojure/deps.json b/nix/deps/clojure/deps.json index 628cd2bd2c..1935e5ed59 100644 --- a/nix/deps/clojure/deps.json +++ b/nix/deps/clojure/deps.json @@ -602,6 +602,15 @@ } }, + { + "path": "nubank/matcher-combinators/3.8.8/matcher-combinators-3.8.8", + "host": "https://repo.clojars.org", + "jar": { + "sha1": "4c94bd510f0c18a20191e46dd6becedebc640bbd", + "sha256": "0wpla2hx0s4mda58ndyd8938zmnz1gyhgfr6pzfphy27xfbvsssl" + } + }, + { "path": "org/apache/ant/ant/1.10.11/ant-1.10.11", "host": "https://repo1.maven.org/maven2", @@ -746,6 +755,15 @@ } }, + { + "path": "org/clojure/math.combinatorics/0.2.0/math.combinatorics-0.2.0", + "host": "https://repo1.maven.org/maven2", + "jar": { + "sha1": "aa95d25ea98bfe1152ea540f6e58a303c8cacc86", + "sha256": "0qvdsr5ryjmrpz622ivpyq5aayn42y4bk531vbasyj2yj7gcg35h" + } + }, + { "path": "org/clojure/spec.alpha/0.3.218/spec.alpha-0.3.218", "host": "https://repo1.maven.org/maven2", diff --git a/nix/deps/clojure/deps.list b/nix/deps/clojure/deps.list index 3e0fb09d30..6f05ea5b88 100644 --- a/nix/deps/clojure/deps.list +++ b/nix/deps/clojure/deps.list @@ -65,6 +65,7 @@ net/cgrand/macrovich/0.2.1/macrovich-0.2.1.jar net/java/dev/jna/jna/5.12.1/jna-5.12.1.jar nrepl/bencode/1.1.0/bencode-1.1.0.jar nrepl/nrepl/1.0.0/nrepl-1.0.0.jar +nubank/matcher-combinators/3.8.8/matcher-combinators-3.8.8.jar org/apache/ant/ant/1.10.11/ant-1.10.11.jar org/apache/ant/ant-launcher/1.10.11/ant-launcher-1.10.11.jar org/babashka/sci/0.7.38/sci-0.7.38.jar @@ -81,6 +82,7 @@ org/clojure/data.json/2.4.0/data.json-2.4.0.jar org/clojure/data.priority-map/1.1.0/data.priority-map-1.1.0.jar org/clojure/google-closure-library/0.0-20230227-c7c0a541/google-closure-library-0.0-20230227-c7c0a541.jar org/clojure/google-closure-library-third-party/0.0-20230227-c7c0a541/google-closure-library-third-party-0.0-20230227-c7c0a541.jar +org/clojure/math.combinatorics/0.2.0/math.combinatorics-0.2.0.jar org/clojure/spec.alpha/0.3.218/spec.alpha-0.3.218.jar org/clojure/test.check/1.1.1/test.check-1.1.1.jar org/clojure/tools.analyzer/1.1.0/tools.analyzer-1.1.0.jar diff --git a/shadow-cljs.edn b/shadow-cljs.edn index c414410724..3b35a401c3 100644 --- a/shadow-cljs.edn +++ b/shadow-cljs.edn @@ -17,6 +17,7 @@ [cider/piggieback "0.4.1"] [org.slf4j/slf4j-nop "2.0.9"] [re-frisk-remote "1.6.0"] + [nubank/matcher-combinators "3.8.8"] ;; Use the same version specified in the Nix dependency. [clj-kondo/clj-kondo "2023.09.07"] diff --git a/src/status_im2/contexts/add_new_contact/events_test.cljs b/src/status_im2/contexts/add_new_contact/events_test.cljs index 8ee2b402ea..fb79020cf4 100644 --- a/src/status_im2/contexts/add_new_contact/events_test.cljs +++ b/src/status_im2/contexts/add_new_contact/events_test.cljs @@ -1,6 +1,7 @@ (ns status-im2.contexts.add-new-contact.events-test (:require [cljs.test :refer-macros [deftest are]] + matcher-combinators.test [status-im2.contexts.add-new-contact.events :as events])) (def user-ukey @@ -18,10 +19,10 @@ ;;; unit tests (no app-db involved) (deftest validate-contact-test - (are [i e] (= (events/validate-contact (events/init-contact - {:user-public-key user-ukey - :input i})) - (events/init-contact e)) + (are [i e] (match? (events/validate-contact (events/init-contact + {:user-public-key user-ukey + :input i})) + (events/init-contact e)) "" {:user-public-key user-ukey :input "" @@ -90,7 +91,7 @@ (deftest set-new-identity-test (with-redefs [events/dispatcher (fn [& args] args)] - (are [i edb] (= (events/set-new-identity {:db db} i nil) edb) + (are [i edb] (match? (events/set-new-identity {:db db} i nil) edb) "" {:db db} diff --git a/src/status_im2/contexts/chat/composer/link_preview/events_test.cljs b/src/status_im2/contexts/chat/composer/link_preview/events_test.cljs index 0f7bf91a35..a45659649d 100644 --- a/src/status_im2/contexts/chat/composer/link_preview/events_test.cljs +++ b/src/status_im2/contexts/chat/composer/link_preview/events_test.cljs @@ -1,6 +1,7 @@ (ns status-im2.contexts.chat.composer.link-preview.events-test (:require [cljs.test :refer [deftest is testing]] + matcher-combinators.test [status-im2.contexts.chat.composer.link-preview.events :as events])) (def url-github "https://github.com") @@ -20,17 +21,17 @@ (let [cofx {:db {:chat/link-previews {:unfurled {} :cache {} :request-id "123"}}}] - (is (= {:db {:chat/link-previews {:cache {}}}} - (events/unfurl-urls cofx " "))))) + (is (match? {:db {:chat/link-previews {:cache {}}}} + (events/unfurl-urls cofx " "))))) (testing "fetches parsed URLs" (let [cofx {:db {:chat/link-previews {:unfurled {} :cache {} :request-id "123"}}}] - (is (= {:json-rpc/call [{:method "wakuext_getTextURLs" - :params [url-github]}]} - (remove-rpc-callbacks - (events/unfurl-urls cofx url-github))))))) + (is (match? {:json-rpc/call [{:method "wakuext_getTextURLs" + :params [url-github]}]} + (remove-rpc-callbacks + (events/unfurl-urls cofx url-github))))))) (deftest unfurl-parsed-urls-test (with-redefs [events/new-request-id (constantly request-id)] @@ -38,30 +39,30 @@ (let [cofx {:db {:chat/link-previews {:cache {} :unfurled []}}}] - (is (= {:db {:chat/link-previews - {:request-id request-id - :cache {} - :unfurled [{:url url-github :loading? true} - {:url url-gitlab :loading? true}]}} - :json-rpc/call [{:method "wakuext_unfurlURLs" - :params [[url-github url-gitlab]]}]} - (remove-rpc-callbacks - (events/unfurl-parsed-urls cofx [url-github url-gitlab])))))) + (is (match? {:db {:chat/link-previews + {:request-id request-id + :cache {} + :unfurled [{:url url-github :loading? true} + {:url url-gitlab :loading? true}]}} + :json-rpc/call [{:method "wakuext_unfurlURLs" + :params [[url-github url-gitlab]]}]} + (remove-rpc-callbacks + (events/unfurl-parsed-urls cofx [url-github url-gitlab])))))) (testing "nothing unfurled, 1 cached URL and the other stale" (let [cache {url-github preview-github} cofx {:db {:chat/link-previews {:cache cache :unfurled []}}}] - (is (= {:db {:chat/link-previews - {:request-id request-id - :cache cache - :unfurled [preview-github - {:url url-gitlab :loading? true}]}} - :json-rpc/call [{:method "wakuext_unfurlURLs" - :params [[url-gitlab]]}]} - (remove-rpc-callbacks - (events/unfurl-parsed-urls cofx [url-github url-gitlab])))))) + (is (match? {:db {:chat/link-previews + {:request-id request-id + :cache cache + :unfurled [preview-github + {:url url-gitlab :loading? true}]}} + :json-rpc/call [{:method "wakuext_unfurlURLs" + :params [[url-gitlab]]}]} + (remove-rpc-callbacks + (events/unfurl-parsed-urls cofx [url-github url-gitlab])))))) (testing "does nothing when the URLs are identical to the last cleared ones" (let [cofx {:db {:chat/link-previews @@ -75,24 +76,24 @@ cofx {:db {:chat/link-previews {:cache cache :unfurled [preview-github]}}}] - (is (= {:db {:chat/link-previews - {:request-id request-id - :cache cache - :unfurled []}}} - (remove-rpc-callbacks - (events/unfurl-parsed-urls cofx [])))))) + (is (match? {:db {:chat/link-previews + {:request-id request-id + :cache cache + :unfurled []}}} + (remove-rpc-callbacks + (events/unfurl-parsed-urls cofx [])))))) (testing "2 unfurled, 2 cached URLs" (let [cache {url-github preview-github url-gitlab preview-gitlab} cofx {:db {:chat/link-previews {:cache cache :unfurled [preview-github preview-gitlab]}}}] - (is (= {:db {:chat/link-previews - {:request-id request-id - :cache cache - :unfurled [preview-github preview-gitlab]}}} - (remove-rpc-callbacks - (events/unfurl-parsed-urls cofx [url-github url-gitlab])))))) + (is (match? {:db {:chat/link-previews + {:request-id request-id + :cache cache + :unfurled [preview-github preview-gitlab]}}} + (remove-rpc-callbacks + (events/unfurl-parsed-urls cofx [url-github url-gitlab])))))) (testing "1 unfurled, 1 successful in the cache, 1 failed in the cache" (let [cache {url-github preview-github @@ -100,25 +101,25 @@ cofx {:db {:chat/link-previews {:cache cache :unfurled [preview-github]}}}] - (is (= {:db {:chat/link-previews - {:request-id request-id - :cache cache - :unfurled [preview-github]}}} - (events/unfurl-parsed-urls cofx [url-github url-gitlab]))))) + (is (match? {:db {:chat/link-previews + {:request-id request-id + :cache cache + :unfurled [preview-github]}}} + (events/unfurl-parsed-urls cofx [url-github url-gitlab]))))) (testing "nothing unfurled, 1 failed in the cache" (let [cache {url-gitlab (assoc preview-gitlab :failed? true)} cofx {:db {:chat/link-previews {:cache cache :unfurled []}}}] - (is (= {:db {:chat/link-previews - {:request-id request-id - :cache cache - :unfurled [{:url url-github :loading? true}]}} - :json-rpc/call [{:method "wakuext_unfurlURLs" - :params [[url-github]]}]} - (remove-rpc-callbacks - (events/unfurl-parsed-urls cofx [url-github url-gitlab])))))) + (is (match? {:db {:chat/link-previews + {:request-id request-id + :cache cache + :unfurled [{:url url-github :loading? true}]}} + :json-rpc/call [{:method "wakuext_unfurlURLs" + :params [[url-github]]}]} + (remove-rpc-callbacks + (events/unfurl-parsed-urls cofx [url-github url-gitlab])))))) (testing "empties unfurled collection when there are no valid previews" (let [unknown-url "https://github.abcdef" @@ -127,12 +128,12 @@ cofx {:db {:chat/link-previews {:cache cache :unfurled [preview-github]}}}] - (is (= {:db {:chat/link-previews - {:request-id request-id - :cache cache - :unfurled []}}} - (remove-rpc-callbacks - (events/unfurl-parsed-urls cofx [unknown-url])))))))) + (is (match? {:db {:chat/link-previews + {:request-id request-id + :cache cache + :unfurled []}}} + (remove-rpc-callbacks + (events/unfurl-parsed-urls cofx [unknown-url])))))))) (deftest unfurl-parsed-urls-success-test (testing "does nothing if the success request-id is different than the current one" @@ -152,12 +153,12 @@ cofx request-id {:linkPreviews [preview-gitlab]})] - (is (= {:chat/link-previews - {:request-id request-id - :unfurled [preview-github preview-gitlab] - :cache {url-github preview-github - url-gitlab preview-gitlab}}} - db)))) + (is (match? {:chat/link-previews + {:request-id request-id + :unfurled [preview-github preview-gitlab] + :cache {url-github preview-github + url-gitlab preview-gitlab}}} + db)))) (testing "identify and write failed preview in the cache" (let [preview-youtube {:url "https://youtube.com" :thumbnail nil} @@ -172,13 +173,13 @@ request-id {:linkPreviews [preview-github preview-youtube]})] - (is (= {:chat/link-previews - {:request-id request-id - :unfurled [preview-github preview-youtube] - :cache {(:url preview-youtube) preview-youtube - url-github preview-github - url-gitlab {:url "https://gitlab.com" :failed? true}}}} - db))))) + (is (match? {:chat/link-previews + {:request-id request-id + :unfurled [preview-github preview-youtube] + :cache {(:url preview-youtube) preview-youtube + url-github preview-github + url-gitlab {:url "https://gitlab.com" :failed? true}}}} + db))))) (deftest clear-link-previews-test (let [cache {url-github preview-github} @@ -186,22 +187,22 @@ {:db {:chat/link-previews {:unfurled [preview-github] :request-id request-id :cache cache}}})] - (is (= {:db {:chat/link-previews {:cache cache - :cleared #{url-github}}}} - effects)))) + (is (match? {:db {:chat/link-previews {:cache cache + :cleared #{url-github}}}} + effects)))) (deftest reset-unfurled-test (let [cache {url-github preview-github}] - (is (= {:db {:chat/link-previews {:cache cache}}} - (events/reset-unfurled - {:db {:chat/link-previews {:unfurled [preview-github] - :request-id request-id - :cleared #{url-github} - :cache cache}}}))))) + (is (match? {:db {:chat/link-previews {:cache cache}}} + (events/reset-unfurled + {:db {:chat/link-previews {:unfurled [preview-github] + :request-id request-id + :cleared #{url-github} + :cache cache}}}))))) (deftest reset-all-test - (is (= {:db {:non-related-key :some-value}} - (events/reset-all - {:db {:non-related-key :some-value - :chat/link-previews {:request-id request-id - :any-other-key "farewell"}}})))) + (is (match? {:db {:non-related-key :some-value}} + (events/reset-all + {:db {:non-related-key :some-value + :chat/link-previews {:request-id request-id + :any-other-key "farewell"}}})))) diff --git a/src/status_im2/contexts/communities/discover/events_test.cljs b/src/status_im2/contexts/communities/discover/events_test.cljs index 83e454cede..db4f80f064 100644 --- a/src/status_im2/contexts/communities/discover/events_test.cljs +++ b/src/status_im2/contexts/communities/discover/events_test.cljs @@ -1,6 +1,7 @@ (ns status-im2.contexts.communities.discover.events-test (:require [cljs.test :refer-macros [deftest are]] + matcher-combinators.test [status-im2.contexts.communities.discover.events :as events])) (deftest rename-contract-community-key-test @@ -13,7 +14,7 @@ :3f9e77b8-97c7 "3f9e77b8-97c7")) (deftest rename-contract-community-keys-test - (are [i e] (= (events/rename-contract-community-keys i) e) + (are [i e] (match? (events/rename-contract-community-keys i) e) {:contractCommunities ["0x032aa2439b14eb2caaf724223951da89de1530fbfa5d5a639b93b82cd5341713fd" diff --git a/src/status_im2/contexts/communities/overview/events_test.cljs b/src/status_im2/contexts/communities/overview/events_test.cljs index f5f00ce5e2..70eefd757d 100644 --- a/src/status_im2/contexts/communities/overview/events_test.cljs +++ b/src/status_im2/contexts/communities/overview/events_test.cljs @@ -1,5 +1,6 @@ (ns status-im2.contexts.communities.overview.events-test (:require [cljs.test :refer [deftest is]] + matcher-combinators.test [native-module.core :as native-module] [status-im2.contexts.communities.overview.events :as sut])) @@ -14,10 +15,10 @@ :params [account-pub-key community-id []] :on-success [:communities/sign-data community-id password] :on-error [:communities/requested-to-join-error community-id]}]]]}] - (is (= expected - (sut/request-to-join cofx - [{:community-id community-id - :password password}]))))) + (is (match? expected + (sut/request-to-join cofx + [{:community-id community-id + :password password}]))))) (deftest sign-data-test (let [cofx {:db {}} @@ -32,8 +33,8 @@ :on-success [:communities/request-to-join-with-signatures community-id addresses-to-reveal] :on-error [:communities/requested-to-join-error community-id]}]]]}] - (is (= expected - (sut/sign-data cofx [community-id password sign-params]))))) + (is (match? expected + (sut/sign-data cofx [community-id password sign-params]))))) (deftest request-to-join-with-signatures-test (let [cofx {:db {}} @@ -49,5 +50,6 @@ :on-success [:communities/requested-to-join] :on-error [:communities/requested-to-join-error community-id]}]]]}] - (is (= expected - (sut/request-to-join-with-signatures cofx [community-id addresses-to-reveal signatures]))))) + (is (match? expected + (sut/request-to-join-with-signatures cofx + [community-id addresses-to-reveal signatures]))))) diff --git a/src/status_im2/contexts/shell/activity_center/events_test.cljs b/src/status_im2/contexts/shell/activity_center/events_test.cljs index ea78a49aa1..4fdc4ec1f4 100644 --- a/src/status_im2/contexts/shell/activity_center/events_test.cljs +++ b/src/status_im2/contexts/shell/activity_center/events_test.cljs @@ -1,6 +1,7 @@ (ns status-im2.contexts.shell.activity-center.events-test (:require [cljs.test :refer [deftest is testing]] + matcher-combinators.test [status-im2.constants :as constants] [status-im2.contexts.shell.activity-center.events :as events] [status-im2.contexts.shell.activity-center.notification-types :as types] @@ -14,18 +15,18 @@ (deftest open-activity-center-test (testing "opens the activity center with default filters" - (is (= {:db {} - :fx [[:dispatch [:open-modal :activity-center {}]] - [:dispatch-later [{:ms 1000 :dispatch [:activity-center/mark-as-seen]}]]]} - (events/open-activity-center {:db {}} [nil])))) + (is (match? {:db {} + :fx [[:dispatch [:open-modal :activity-center {}]] + [:dispatch-later [{:ms 1000 :dispatch [:activity-center/mark-as-seen]}]]]} + (events/open-activity-center {:db {}} [nil])))) (testing "opens the activity center with filters enabled" - (is (= {:db {:activity-center {:filter {:status :unread :type types/contact-request}}} - :fx [[:dispatch [:open-modal :activity-center {}]] - [:dispatch-later [{:ms 1000 :dispatch [:activity-center/mark-as-seen]}]]]} - (events/open-activity-center {:db {}} - [{:filter-type types/contact-request - :filter-status :unread}]))))) + (is (match? {:db {:activity-center {:filter {:status :unread :type types/contact-request}}} + :fx [[:dispatch [:open-modal :activity-center {}]] + [:dispatch-later [{:ms 1000 :dispatch [:activity-center/mark-as-seen]}]]]} + (events/open-activity-center {:db {}} + [{:filter-type types/contact-request + :filter-status :unread}]))))) (deftest process-notification-failure-test (testing "logs and returns nil" @@ -34,11 +35,11 @@ notification-id :some-action-name :some-error))) - (is (= {:args ["Failed to :some-action-name" - {:notification-id notification-id - :error :some-error}] - :level :warn} - (last @h/logs))))) + (is (match? {:args ["Failed to :some-action-name" + {:notification-id notification-id + :error :some-error}] + :level :warn} + (last @h/logs))))) ;;;; Mark as read/unread @@ -53,13 +54,13 @@ (testing "dispatches RPC call" (let [notif {:id "0x1" :read false :type types/one-to-one-chat} cofx {:db {:activity-center {:notifications [notif]}}}] - (is (= {:json-rpc/call - [{:method "wakuext_markActivityCenterNotificationsRead" - :params [[(:id notif)]] - :on-success [:activity-center.notifications/mark-as-read-success notif] - :on-error [:activity-center/process-notification-failure (:id notif) - :notification/mark-as-read]}]} - (events/mark-as-read cofx (:id notif))))))) + (is (match? {:json-rpc/call + [{:method "wakuext_markActivityCenterNotificationsRead" + :params [[(:id notif)]] + :on-success [:activity-center.notifications/mark-as-read-success notif] + :on-error [:activity-center/process-notification-failure (:id notif) + :notification/mark-as-read]}]} + (events/mark-as-read cofx (:id notif))))))) (deftest mark-as-read-success-test (let [f-args (atom []) @@ -70,8 +71,8 @@ (reset! f-args args) :result)] (is (= :result (events/mark-as-read-success cofx notif))) - (is (= [cofx [(assoc notif :read true)]] - @f-args))))) + (is (match? [cofx [(assoc notif :read true)]] + @f-args))))) (deftest mark-as-unread-test (testing "does nothing if the notification ID cannot be found in the app db" @@ -84,13 +85,13 @@ (testing "dispatches RPC call" (let [notif {:id "0x1" :read true :type types/one-to-one-chat} cofx {:db {:activity-center {:notifications [notif]}}}] - (is (= {:json-rpc/call - [{:method "wakuext_markActivityCenterNotificationsUnread" - :params [[(:id notif)]] - :on-success [:activity-center.notifications/mark-as-unread-success notif] - :on-error [:activity-center/process-notification-failure (:id notif) - :notification/mark-as-unread]}]} - (events/mark-as-unread cofx (:id notif))))))) + (is (match? {:json-rpc/call + [{:method "wakuext_markActivityCenterNotificationsUnread" + :params [[(:id notif)]] + :on-success [:activity-center.notifications/mark-as-unread-success notif] + :on-error [:activity-center/process-notification-failure (:id notif) + :notification/mark-as-unread]}]} + (events/mark-as-unread cofx (:id notif))))))) (deftest mark-as-unread-success-test (let [f-args (atom []) @@ -101,19 +102,19 @@ (reset! f-args args) :reconciliation-result)] (is (= :reconciliation-result (events/mark-as-unread-success cofx notif))) - (is (= [cofx [(assoc notif :read false)]] - @f-args))))) + (is (match? [cofx [(assoc notif :read false)]] + @f-args))))) ;;;; Acceptance/dismissal (deftest accept-notification-test - (is (= {:json-rpc/call - [{:method "wakuext_acceptActivityCenterNotifications" - :params [[notification-id]] - :on-success [:activity-center.notifications/accept-success notification-id] - :on-error [:activity-center/process-notification-failure notification-id - :notification/accept]}]} - (events/accept-notification {:db {}} notification-id)))) + (is (match? {:json-rpc/call + [{:method "wakuext_acceptActivityCenterNotifications" + :params [[notification-id]] + :on-success [:activity-center.notifications/accept-success notification-id] + :on-error [:activity-center/process-notification-failure notification-id + :notification/accept]}]} + (events/accept-notification {:db {}} notification-id)))) (deftest accept-notification-success-test (testing "does nothing if the notification ID cannot be found in the app db" @@ -129,18 +130,18 @@ notif-2-accepted (assoc notif-2 :accepted true :read true) cofx {:db {:activity-center {:filter {:type types/no-type :status :all} :notifications [notif-2 notif-1]}}}] - (is (= {:fx [[:dispatch [:chat/ensure-chats []]] - [:dispatch [:activity-center.notifications/reconcile [notif-2-accepted]]]]} - (events/accept-notification-success cofx [(:id notif-2) nil])))))) + (is (match? {:fx [[:dispatch [:chat/ensure-chats []]] + [:dispatch [:activity-center.notifications/reconcile [notif-2-accepted]]]]} + (events/accept-notification-success cofx [(:id notif-2) nil])))))) (deftest dismiss-notification-test - (is (= {:json-rpc/call - [{:method "wakuext_dismissActivityCenterNotifications" - :params [[notification-id]] - :on-success [:activity-center.notifications/dismiss-success notification-id] - :on-error [:activity-center/process-notification-failure notification-id - :notification/dismiss]}]} - (events/dismiss-notification {:db {}} notification-id)))) + (is (match? {:json-rpc/call + [{:method "wakuext_dismissActivityCenterNotifications" + :params [[notification-id]] + :on-success [:activity-center.notifications/dismiss-success notification-id] + :on-error [:activity-center/process-notification-failure notification-id + :notification/dismiss]}]} + (events/dismiss-notification {:db {}} notification-id)))) (deftest dismiss-notification-success-test (testing "does nothing if the notification ID cannot be found in the app db" @@ -156,11 +157,11 @@ notif-2-dismissed (assoc notif-2 :dismissed true :read true) cofx {:db {:activity-center {:filter {:type types/no-type :status :all} :notifications [notif-2 notif-1]}}}] - (is (= {:db {:activity-center {:filter {:type 0 :status :all} - :notifications [notif-2-dismissed notif-1]}} - :dispatch-n [[:activity-center.notifications/fetch-unread-count] - [:activity-center.notifications/fetch-pending-contact-requests]]} - (events/dismiss-notification-success cofx (:id notif-2))))))) + (is (match? {:db {:activity-center {:filter {:type 0 :status :all} + :notifications [notif-2-dismissed notif-1]}} + :dispatch-n [[:activity-center.notifications/fetch-unread-count] + [:activity-center.notifications/fetch-pending-contact-requests]]} + (events/dismiss-notification-success cofx (:id notif-2))))))) ;;;; Contact verification @@ -208,41 +209,41 @@ :type types/contact-verification}) (deftest contact-verification-decline-test - (is (= {:json-rpc/call - [{:method "wakuext_declineContactVerificationRequest" - :params [notification-id] - :on-success [:activity-center/reconcile-notifications-from-response] - :on-error [:activity-center/process-notification-failure notification-id - :contact-verification/decline]}]} - (events/contact-verification-decline {:db {}} notification-id)))) + (is (match? {:json-rpc/call + [{:method "wakuext_declineContactVerificationRequest" + :params [notification-id] + :on-success [:activity-center/reconcile-notifications-from-response] + :on-error [:activity-center/process-notification-failure notification-id + :contact-verification/decline]}]} + (events/contact-verification-decline {:db {}} notification-id)))) (deftest contact-verification-reply-test (let [reply "The answer is 42"] - (is (= {:json-rpc/call - [{:method "wakuext_acceptContactVerificationRequest" - :params [notification-id reply] - :on-success [:activity-center/reconcile-notifications-from-response] - :on-error [:activity-center/process-notification-failure notification-id - :contact-verification/reply]}]} - (events/contact-verification-reply {:db {}} notification-id reply))))) + (is (match? {:json-rpc/call + [{:method "wakuext_acceptContactVerificationRequest" + :params [notification-id reply] + :on-success [:activity-center/reconcile-notifications-from-response] + :on-error [:activity-center/process-notification-failure notification-id + :contact-verification/reply]}]} + (events/contact-verification-reply {:db {}} notification-id reply))))) (deftest contact-verification-mark-as-trusted-test - (is (= {:json-rpc/call - [{:method "wakuext_verifiedTrusted" - :params [{:id notification-id}] - :on-success [:activity-center/reconcile-notifications-from-response] - :on-error [:activity-center/process-notification-failure notification-id - :contact-verification/mark-as-trusted]}]} - (events/contact-verification-mark-as-trusted {:db {}} notification-id)))) + (is (match? {:json-rpc/call + [{:method "wakuext_verifiedTrusted" + :params [{:id notification-id}] + :on-success [:activity-center/reconcile-notifications-from-response] + :on-error [:activity-center/process-notification-failure notification-id + :contact-verification/mark-as-trusted]}]} + (events/contact-verification-mark-as-trusted {:db {}} notification-id)))) (deftest contact-verification-mark-as-untrustworthy-test - (is (= {:json-rpc/call - [{:method "wakuext_verifiedUntrustworthy" - :params [{:id notification-id}] - :on-success [:activity-center/reconcile-notifications-from-response] - :on-error [:activity-center/process-notification-failure notification-id - :contact-verification/mark-as-untrustworthy]}]} - (events/contact-verification-mark-as-untrustworthy {:db {}} notification-id)))) + (is (match? {:json-rpc/call + [{:method "wakuext_verifiedUntrustworthy" + :params [{:id notification-id}] + :on-success [:activity-center/reconcile-notifications-from-response] + :on-error [:activity-center/process-notification-failure notification-id + :contact-verification/mark-as-untrustworthy]}]} + (events/contact-verification-mark-as-untrustworthy {:db {}} notification-id)))) ;;;; Notification reconciliation @@ -256,17 +257,17 @@ cofx {:db {:activity-center {:filter {:type types/no-type :status :all} :notifications [notif-2 notif-1]}}}] - (is (= {:db {:activity-center - {:filter {:type types/no-type :status :all} - :notifications [new-notif-4 new-notif-3 new-notif-2]}} - :dispatch-n [[:activity-center.notifications/fetch-unread-count] - [:activity-center.notifications/fetch-pending-contact-requests]]} - (events/notifications-reconcile - cofx - [(assoc notif-1 :deleted true) ; will be removed - new-notif-2 - new-notif-3 - new-notif-4]))))) + (is (match? {:db {:activity-center + {:filter {:type types/no-type :status :all} + :notifications [new-notif-4 new-notif-3 new-notif-2]}} + :dispatch-n [[:activity-center.notifications/fetch-unread-count] + [:activity-center.notifications/fetch-pending-contact-requests]]} + (events/notifications-reconcile + cofx + [(assoc notif-1 :deleted true) ; will be removed + new-notif-2 + new-notif-3 + new-notif-4]))))) (testing "All tab + Unread filter" (let [notif-1 {:id "0x1" :read false :type types/one-to-one-chat} @@ -278,18 +279,18 @@ cofx {:db {:activity-center {:filter {:type types/no-type :status :unread} :notifications [notif-5 notif-2 notif-1]}}}] - (is (= {:db {:activity-center - {:filter {:type types/no-type :status :unread} - :notifications [new-notif-3 notif-1]}} - :dispatch-n [[:activity-center.notifications/fetch-unread-count] - [:activity-center.notifications/fetch-pending-contact-requests]]} - (events/notifications-reconcile - cofx - [new-notif-2 ; will be removed because it's read - new-notif-3 ; will be inserted - new-notif-4 ; will be ignored because it's read - (assoc notif-5 :deleted true) ; will be removed - ]))))) + (is (match? {:db {:activity-center + {:filter {:type types/no-type :status :unread} + :notifications [new-notif-3 notif-1]}} + :dispatch-n [[:activity-center.notifications/fetch-unread-count] + [:activity-center.notifications/fetch-pending-contact-requests]]} + (events/notifications-reconcile + cofx + [new-notif-2 ; will be removed because it's read + new-notif-3 ; will be inserted + new-notif-4 ; will be ignored because it's read + (assoc notif-5 :deleted true) ; will be removed + ]))))) (testing "Contact request tab + All filter" (let [notif-1 {:id "0x1" :read true :type types/contact-request} @@ -301,18 +302,18 @@ cofx {:db {:activity-center {:filter {:type types/contact-request :status :all} :notifications [notif-5 notif-2 notif-1]}}}] - (is (= {:db {:activity-center - {:filter {:type types/contact-request :status :all} - :notifications [new-notif-3 new-notif-2 notif-1]}} - :dispatch-n [[:activity-center.notifications/fetch-unread-count] - [:activity-center.notifications/fetch-pending-contact-requests]]} - (events/notifications-reconcile - cofx - [new-notif-2 ; will be updated - new-notif-3 ; will be inserted - new-notif-4 ; will be ignored because it's not a contact request - (assoc notif-5 :deleted true) ; will be removed - ]))))) + (is (match? {:db {:activity-center + {:filter {:type types/contact-request :status :all} + :notifications [new-notif-3 new-notif-2 notif-1]}} + :dispatch-n [[:activity-center.notifications/fetch-unread-count] + [:activity-center.notifications/fetch-pending-contact-requests]]} + (events/notifications-reconcile + cofx + [new-notif-2 ; will be updated + new-notif-3 ; will be inserted + new-notif-4 ; will be ignored because it's not a contact request + (assoc notif-5 :deleted true) ; will be removed + ]))))) (testing "Contact request tab + Unread filter" (let [notif-1 {:id "0x1" :read false :type types/contact-request} @@ -326,20 +327,20 @@ {:filter {:type types/contact-request :status :unread} :notifications [notif-6 notif-2 notif-1]}}}] - (is (= {:db {:activity-center - {:filter {:type types/contact-request - :status :unread} - :notifications [new-notif-3 notif-1]}} - :dispatch-n [[:activity-center.notifications/fetch-unread-count] - [:activity-center.notifications/fetch-pending-contact-requests]]} - (events/notifications-reconcile - cofx - [new-notif-2 ; will be removed because it's read - new-notif-3 ; will be inserted - new-notif-4 ; will be ignored because it's read - new-notif-5 ; will be ignored because it's not a contact request - (assoc notif-6 :deleted true) ; will be removed - ]))))) + (is (match? {:db {:activity-center + {:filter {:type types/contact-request + :status :unread} + :notifications [new-notif-3 notif-1]}} + :dispatch-n [[:activity-center.notifications/fetch-unread-count] + [:activity-center.notifications/fetch-pending-contact-requests]]} + (events/notifications-reconcile + cofx + [new-notif-2 ; will be removed because it's read + new-notif-3 ; will be inserted + new-notif-4 ; will be ignored because it's read + new-notif-5 ; will be ignored because it's not a contact request + (assoc notif-6 :deleted true) ; will be removed + ]))))) ;; Sorting by timestamp and ID is compatible with what the backend does when ;; returning paginated results. @@ -354,15 +355,15 @@ cofx {:db {:activity-center {:notifications [notif-1 notif-3 notif-4 notif-2 notif-5]}}}] - (is (= {:db {:activity-center - {:notifications [notif-5 - new-notif-4 - notif-3 - notif-2 - new-notif-1]}} - :dispatch-n [[:activity-center.notifications/fetch-unread-count] - [:activity-center.notifications/fetch-pending-contact-requests]]} - (events/notifications-reconcile cofx [new-notif-1 new-notif-4])))))) + (is (match? {:db {:activity-center + {:notifications [notif-5 + new-notif-4 + notif-3 + notif-2 + new-notif-1]}} + :dispatch-n [[:activity-center.notifications/fetch-unread-count] + [:activity-center.notifications/fetch-pending-contact-requests]]} + (events/notifications-reconcile cofx [new-notif-1 new-notif-4])))))) (deftest remove-pending-contact-request-test (testing "removes notification from all related filter types and status" @@ -376,26 +377,27 @@ notif-2 ; will be removed notif-1 ; will be ignored because it's not from the same author ]}}}] - (is (= {:db {:activity-center {:notifications [notif-3 notif-1]}}} - (events/notifications-remove-pending-contact-request cofx author)))))) + (is (match? {:db {:activity-center {:notifications [notif-3 notif-1]}}} + (events/notifications-remove-pending-contact-request cofx author)))))) ;;;; Notifications fetching and pagination (deftest notifications-fetch-first-page-test (testing "fetches first page" (let [cofx {:db {}}] - (is (= {:db {:activity-center {:filter {:type types/one-to-one-chat - :status :unread} - :loading? true}} - :json-rpc/call [{:method "wakuext_activityCenterNotifications" - :params [{:cursor "" - :limit (:notifications-per-page events/defaults) - :activityTypes [types/one-to-one-chat] - :readType events/read-type-unread}] - :on-success [:activity-center.notifications/fetch-success true] - :on-error [:activity-center.notifications/fetch-error - types/one-to-one-chat :unread]}]} - (events/notifications-fetch-first-page cofx {:filter-type types/one-to-one-chat})))))) + (is (match? {:db {:activity-center {:filter {:type types/one-to-one-chat + :status :unread} + :loading? true}} + :json-rpc/call [{:method "wakuext_activityCenterNotifications" + :params [{:cursor "" + :limit (:notifications-per-page + events/defaults) + :activityTypes [types/one-to-one-chat] + :readType events/read-type-unread}] + :on-success [:activity-center.notifications/fetch-success true] + :on-error [:activity-center.notifications/fetch-error + types/one-to-one-chat :unread]}]} + (events/notifications-fetch-first-page cofx {:filter-type types/one-to-one-chat})))))) (deftest notifications-fetch-next-next-page-test (testing "does not fetch next page when pagination cursor reached the end" @@ -413,12 +415,12 @@ (reset! f-args args) :result)] (is (= :result (events/notifications-fetch-next-page cofx))) - (is (= [cofx - {:cursor cursor - :filter-type types/one-to-one-chat - :filter-status :unread - :reset-data? false}] - @f-args)))))) + (is (match? [cofx + {:cursor cursor + :filter-type types/one-to-one-chat + :filter-status :unread + :reset-data? false}] + @f-args)))))) (deftest notifications-fetch-error-test (testing "resets loading state" @@ -427,23 +429,23 @@ :filter {:status :unread :type types/one-to-one-chat} :cursor ""}}}] - (is (= {:db {:activity-center {:filter {:status :unread - :type types/one-to-one-chat} - :cursor ""}}} - (events/notifications-fetch-error cofx :dummy-error)))))) + (is (match? {:db {:activity-center {:filter {:status :unread + :type types/one-to-one-chat} + :cursor ""}}} + (events/notifications-fetch-error cofx :dummy-error)))))) (deftest seen-state-test (testing "update seen state" - (is (= {:db {:activity-center {:seen? true}}} - (events/reconcile-seen-state {:db {}} true)))) + (is (match? {:db {:activity-center {:seen? true}}} + (events/reconcile-seen-state {:db {}} true)))) (testing "update seen state when the user is on other screen" - (is (= {:db {:view-id :chats-stack - :activity-center {:seen? false}}} - (events/reconcile-seen-state {:db {:view-id :chats-stack}} false)))) + (is (match? {:db {:view-id :chats-stack + :activity-center {:seen? false}}} + (events/reconcile-seen-state {:db {:view-id :chats-stack}} false)))) (testing "update seen state when the user is on activity center" - (is (= {:db {:view-id :activity-center - :activity-center {:seen? false}} - :dispatch [:activity-center/mark-as-seen]} - (events/reconcile-seen-state {:db {:view-id :activity-center}} false))))) + (is (match? {:db {:view-id :activity-center + :activity-center {:seen? false}} + :dispatch [:activity-center/mark-as-seen]} + (events/reconcile-seen-state {:db {:view-id :activity-center}} false))))) diff --git a/src/status_im2/contexts/wallet/events_test.cljs b/src/status_im2/contexts/wallet/events_test.cljs index 88f7831e79..212982d550 100644 --- a/src/status_im2/contexts/wallet/events_test.cljs +++ b/src/status_im2/contexts/wallet/events_test.cljs @@ -1,6 +1,7 @@ (ns status-im2.contexts.wallet.events-test (:require [cljs.test :refer-macros [deftest is testing]] + matcher-combinators.test [status-im2.contexts.wallet.events :as events])) (def address "0x2f88d65f3cb52605a54a833ae118fb1363acccd2") @@ -11,7 +12,7 @@ (let [expected-db {:wallet/scanned-address address} effects (events/scan-address-success {:db db} address) result-db (:db effects)] - (is (= result-db expected-db)))))) + (is (match? result-db expected-db)))))) (deftest clean-scanned-address (let [db {:wallet/scanned-address address}] @@ -19,7 +20,7 @@ (let [expected-db {} effects (events/clean-scanned-address {:db db}) result-db (:db effects)] - (is (= result-db expected-db)))))) + (is (match? result-db expected-db)))))) (deftest store-collectibles (testing "(displayable-collectible?) helper function" @@ -34,7 +35,8 @@ [false {:collectible-data {:image-url nil :animation-url ""}}] [false {:collectible-data {:image-url "" :animation-url ""}}]]] (doseq [[result collection] expected-results] - (is (= result (events/displayable-collectible? collection)))))) + (is (match? result (events/displayable-collectible? collection)))))) + (testing "save-collectibles-request-details" (let [db {:wallet {}} collectibles [{:collectible-data {:image-url "https://..." :animation-url "https://..."}} @@ -46,7 +48,7 @@ {:image-url "" :animation-url "https://..."}}]}} effects (events/store-collectibles {:db db} [collectibles]) result-db (:db effects)] - (is (= result-db expected-db))))) + (is (match? result-db expected-db))))) (deftest clear-stored-collectibles (let [db {:wallet {:collectibles [{:id 1} {:id 2}]}}] @@ -54,7 +56,7 @@ (let [expected-db {:wallet {}} effects (events/clear-stored-collectibles {:db db}) result-db (:db effects)] - (is (= result-db expected-db)))))) + (is (match? result-db expected-db)))))) (deftest store-last-collectible-details (testing "store-last-collectible-details" @@ -65,4 +67,4 @@ :image-url "https://..."}}} effects (events/store-last-collectible-details {:db db} [last-collectible]) result-db (:db effects)] - (is (= result-db expected-db))))) + (is (match? result-db expected-db)))))