tests for contacts events

This commit is contained in:
Andrey Shovkoplyas 2017-08-04 18:27:34 +03:00 committed by Roman Volosovskyi
parent c378098d3b
commit 6d62a21af7
3 changed files with 250 additions and 137 deletions

View File

@ -12,6 +12,7 @@
[cljs.reader :refer [read-string]] [cljs.reader :refer [read-string]]
[status-im.utils.js-resources :as js-res] [status-im.utils.js-resources :as js-res]
[status-im.react-native.js-dependencies :as rn-dependencies] [status-im.react-native.js-dependencies :as rn-dependencies]
[status-im.js-dependencies :as dependencies]
[status-im.utils.identicon :refer [identicon]] [status-im.utils.identicon :refer [identicon]]
[status-im.utils.gfycat.core :refer [generate-gfy]] [status-im.utils.gfycat.core :refer [generate-gfy]]
[status-im.i18n :refer [label]] [status-im.i18n :refer [label]]
@ -174,29 +175,17 @@
{:db (update-in db [:contacts/contacts whisper-identity] merge contact) {:db (update-in db [:contacts/contacts whisper-identity] merge contact)
::save-contact contact}))) ::save-contact contact})))
(register-handler-fx
:load-contacts
[(inject-cofx ::get-all-contacts)]
(fn [{:keys [db all-contacts]} _]
(let [contacts-list (map #(vector (:whisper-identity %) %) all-contacts)
global-commands (->> contacts-list
(filter (fn [[_ c]] (:global-command c)))
(map (fn [[id {:keys [global-command]}]]
[(keyword id) (-> global-command
(update :params (comp vec vals))
(assoc :bot id
:type :command))]))
(into {}))
contacts (into {} contacts-list)]
{:db (assoc db :contacts/contacts contacts
:global-commands global-commands)
:dispatch-n (mapv (fn [_ contact] [:watch-contact contact]) contacts)})))
(register-handler-fx (register-handler-fx
:sync-contacts :sync-contacts
(fn [_ _] (fn [_ _]
{::fetch-contacts-from-phone! nil})) {::fetch-contacts-from-phone! nil}))
(defn- update-pending-status [old-contacts {:keys [whisper-identity pending?] :as contact}]
(let [{old-pending :pending?
:as old-contact} (get old-contacts whisper-identity)
pending?' (if old-contact (and old-pending pending?) pending?)]
(assoc contact :pending? (boolean pending?'))))
(defn- public-key->address [public-key] (defn- public-key->address [public-key]
(let [length (count public-key) (let [length (count public-key)
normalized-key (case length normalized-key (case length
@ -205,7 +194,7 @@
128 public-key 128 public-key
nil)] nil)]
(when normalized-key (when normalized-key
(subs (.sha3 js/Web3.prototype normalized-key #js {:encoding "hex"}) 26)))) (subs (.sha3 dependencies/Web3.prototype normalized-key #js {:encoding "hex"}) 26))))
(defn- prepare-default-groups-events [groups default-groups] (defn- prepare-default-groups-events [groups default-groups]
[[:add-contact-groups [[:add-contact-groups
@ -264,26 +253,31 @@
:load-default-contacts! :load-default-contacts!
[(inject-cofx ::get-default-contacts-and-groups)] [(inject-cofx ::get-default-contacts-and-groups)]
(fn [{:keys [db default-contacts default-groups]} _] (fn [{:keys [db default-contacts default-groups]} _]
(let [{:keys [groups] :contacts/keys [contacts]} db] (let [{:contacts/keys [contacts] :group/keys [contact-groups]} db]
{:dispatch-n (concat {:dispatch-n (concat
(prepare-default-groups-events groups default-groups) (prepare-default-groups-events contact-groups default-groups)
(prepare-default-contacts-events contacts default-contacts) (prepare-default-contacts-events contacts default-contacts)
(prepare-add-chat-events contacts default-contacts) (prepare-add-chat-events contacts default-contacts)
(prepare-bot-commands-events contacts default-contacts) (prepare-bot-commands-events contacts default-contacts)
(prepare-add-contacts-to-groups-events contacts default-contacts))}))) (prepare-add-contacts-to-groups-events contacts default-contacts))})))
(register-handler-db (register-handler-fx
:remove-contacts-click-handler :load-contacts
(fn [db _] [(inject-cofx ::get-all-contacts)]
(dissoc db (fn [{:keys [db all-contacts]} _]
:contacts/click-handler (let [contacts-list (map #(vector (:whisper-identity %) %) all-contacts)
:contacts/click-action))) global-commands (->> contacts-list
(filter (fn [[_ c]] (:global-command c)))
(defn- update-pending-status [old-contacts {:keys [whisper-identity pending?] :as contact}] (map (fn [[id {:keys [global-command]}]]
(let [{old-pending :pending? [(keyword id) (-> global-command
:as old-contact} (get old-contacts whisper-identity) (update :params (comp vec vals))
pending?' (if old-contact (and old-pending pending?) pending?)] (assoc :bot id
(assoc contact :pending? (boolean pending?')))) :type :command))]))
(into {}))
contacts (into {} contacts-list)]
{:db (assoc db :contacts/contacts contacts
:global-commands global-commands)
:dispatch-n (mapv (fn [_ contact] [:watch-contact contact]) contacts)})))
(register-handler-fx (register-handler-fx
:add-contacts :add-contacts
@ -301,12 +295,18 @@
[(keyword n) (assoc global-command [(keyword n) (assoc global-command
:type :command :type :command
:bot n)]))) :bot n)])))
(into {})) (into {}))]
new-contacts-vals (vals new-contacts')]
{:db (-> db {:db (-> db
(update :global-commands merge global-commands) (update :global-commands merge global-commands)
(update :contacts/contacts merge new-contacts')) (update :contacts/contacts merge new-contacts'))
::save-contacts! new-contacts-vals}))) ::save-contacts! (vals new-contacts')})))
(register-handler-db
:remove-contacts-click-handler
(fn [db _]
(dissoc db
:contacts/click-handler
:contacts/click-action)))
(register-handler-fx (register-handler-fx
::send-contact-request ::send-contact-request
@ -337,16 +337,16 @@
(register-handler-fx (register-handler-fx
:add-pending-contact :add-pending-contact
(fn [{:keys [db]} [_ chat-id]] (fn [{:keys [db]} [_ chat-or-whisper-id]]
(let [{:keys [chats] :contacts/keys [contacts]} db (let [{:keys [chats] :contacts/keys [contacts]} db
contact (if-let [contact-info (get-in chats [chat-id :contact-info])] contact (if-let [contact-info (get-in chats [chat-or-whisper-id :contact-info])]
(read-string contact-info) (read-string contact-info)
(get contacts chat-id)) (get contacts chat-or-whisper-id))
contact' (assoc contact :address (public-key->address chat-id) contact' (assoc contact :address (public-key->address chat-or-whisper-id)
:pending? false)] :pending? false)]
{:dispatch-n [[::add-new-contact contact'] {:dispatch-n [[::add-new-contact contact']
[:watch-contact contact'] [:watch-contact contact']
[:discoveries-send-portions chat-id]]}))) [:discoveries-send-portions chat-or-whisper-id]]})))
(register-handler-db (register-handler-db
:set-contact-identity-from-qr :set-contact-identity-from-qr
@ -416,6 +416,7 @@
group' (update (contact-groups group-id) :contacts (remove-contact-from-group whisper-identity))] group' (update (contact-groups group-id) :contacts (remove-contact-from-group whisper-identity))]
{:dispatch [:update-contact-group group']}))) {:dispatch [:update-contact-group group']})))
;;used only by status-dev-cli
(register-handler-fx (register-handler-fx
:remove-contact :remove-contact
(fn [{:keys [db]} [_ whisper-identity pred]] (fn [{:keys [db]} [_ whisper-identity pred]]

View File

@ -1,6 +1,6 @@
(ns status-im.utils.handlers (ns status-im.utils.handlers
(:require [re-frame.core :refer [reg-event-db reg-event-fx]] (:require [re-frame.core :refer [reg-event-db reg-event-fx]]
[re-frame.interceptor :refer [->interceptor get-coeffect]] [re-frame.interceptor :refer [->interceptor get-coeffect get-effect]]
[clojure.string :as str] [clojure.string :as str]
[taoensso.timbre :as log] [taoensso.timbre :as log]
[cljs.spec.alpha :as s]) [cljs.spec.alpha :as s])
@ -29,9 +29,9 @@
:after :after
(fn check-handler (fn check-handler
[context] [context]
(let [new-db (get-coeffect context :db) (let [new-db (get-effect context :db)
v (get-coeffect context :event)] v (get-coeffect context :event)]
(when-not (s/valid? :status-im.specs/db new-db) (when (and new-db (not (s/valid? :status-im.specs/db new-db)))
(throw (ex-info (str "spec check failed on: " (first v) "\n " (s/explain-str :status-im.specs/db new-db)) {}))) (throw (ex-info (str "spec check failed on: " (first v) "\n " (s/explain-str :status-im.specs/db new-db)) {})))
context)))) context))))

View File

@ -1,13 +1,16 @@
(ns status-im.test.contacts.handlers (ns status-im.test.contacts.handlers
(:require [cljs.test :refer-macros [deftest is]] (:require [cljs.test :refer-macros [deftest is testing]]
reagent.core reagent.core
[re-frame.core :as rf] [re-frame.core :as rf]
[day8.re-frame.test :refer-macros [run-test-sync]] [day8.re-frame.test :refer-macros [run-test-sync]]
status-im.specs status-im.specs
status-im.db status-im.db
[status-im.contacts.events :as e] [status-im.contacts.events :as contacts-events]
[status-im.handlers :as h] [status-im.group.events :as group-events]
status-im.subs)) [status-im.handlers :as handlers]
status-im.subs
[status-im.utils.js-resources :as js-res]
[status-im.utils.datetime :as datetime]))
(def browse-contact-from-realm-db (def browse-contact-from-realm-db
{:last-updated 0 {:last-updated 0
@ -91,97 +94,87 @@
:fullscreen true :fullscreen true
:suggestions-trigger "on-change"}}) :suggestions-trigger "on-change"}})
#_{:registered-only true (def dapps-contact-group
:has-handler false {:group-id "dapps"
:fullscreen true :name "ÐApps"
:hidden? nil} :order 0
:timestamp 0
:contacts [{:identity "wallet"}
{:identity "oaken-water-meter"}
{:identity "melonport"}
{:identity "bchat"}
{:identity "Dentacoin"}
{:identity "Augur"}
{:identity "Ethlance"}
{:identity "Commiteth"}]
:pending? false})
(def browse-contatcs (def wallet-contact
{ {:address nil
"browse" :name "Wallet"
{ :global-command nil
:last-updated 0 :dapp-url "https://status.im/dapps/wallet/"
:address nil
:name "Browse"
:global-command
{
:description "Launch the browser"
:sequential-params false
:color "#ffa500"
:name "global"
:params
{
:0
{
:name "url"
:type "text"
:placeholder "URL"}}
:icon nil
:title "Browser"
:has-handler false
:fullscreen true
:suggestions-trigger "on-change"}
:commands-loaded? true
:dapp-url nil
:dapp-hash nil :dapp-hash nil
:subscriptions {} :photo-path "icon_wallet_avatar"
:bot-url nil
:commands
{
:location
{
:description "Share your location"
:bot "mailman"
:sequential-params true
:hide-send-button true
:name "location"
:params
[
{
:name "address"
:placeholder "address"
:type "text"}]
:type :command
:title "Location"
:has-handler false
:hidden? nil
:owner-id "mailman"}}}
:photo-path nil
:debug? false
:status nil
:bot-url "local://browse-bot"
:responses {}
:pending? false :pending? false
:whisper-identity "browse" :whisper-identity "wallet"
:last-online 0
:dapp? true :dapp? true
:unremovable? true :unremovable? true
:private-key nil
:public-key nil}) :public-key nil})
(defn test-fixtures (def contacts-browse-wallet
[] {"browse" browse-contact-from-realm-db
"wallet" wallet-contact})
(defn test-fixtures []
(rf/reg-fx ::handlers/init-store #())
(rf/reg-fx ::contacts-events/save-contacts! #())
(rf/reg-fx ::contacts-events/save-contact #())
(rf/reg-fx ::contacts-events/watch-contact #())
(rf/reg-fx ::contacts-events/stop-watching-contact #())
(rf/reg-fx ::contacts-events/send-contact-request-fx #())
(rf/reg-fx ::group-events/save-contact-groups #())
(rf/reg-fx ::group-events/add-contacts-to-contact-group #())
(rf/reg-cofx (rf/reg-cofx
::e/get-all-contacts ::contacts-events/get-all-contacts
(fn [coeffects _] (fn [coeffects _]
(assoc coeffects :all-contacts [browse-contact-from-realm-db]))) (assoc coeffects :all-contacts [browse-contact-from-realm-db])))
(rf/reg-fx
::h/init-store
(fn []
nil)))
(deftest basic-sync ;;TODO implement tests later for :add-chat? and :bot-url
(rf/reg-cofx
::contacts-events/get-default-contacts-and-groups
(fn [coeffects _]
(assoc coeffects :default-contacts (update (select-keys js-res/default-contacts [:wallet])
:wallet
dissoc :add-chat? :bot-url)
:default-groups (select-keys js-res/default-contact-groups [:dapps])))))
(deftest contacts-events
"load-contacts
load-default-contacts (add-contact-groups, add-contacts, add-contacts-to-group ;TODO add-chat, load-commands!)
add-contact-handler (add-new-contact-and-open-chat, status-im.contacts.events/add-new-contact,
status-im.contacts.events/send-contact-request ;TODO start-chat)
contact-request-received (update-contact, watch-contact ;TODO :update-chat!)
contact-update-received (update-contact ;TODO :update-chat!)
hide-contact (update-contact ;TODO :account-update-keys)
add-contact-handler (add-pending-contact, status-im.contacts.events/add-new-contact
status-im.contacts.events/send-contact-request ;TODO :discoveries-send-portions)"
(run-test-sync (run-test-sync
(test-fixtures) (test-fixtures)
(rf/dispatch [:initialize-db]) (rf/dispatch [:initialize-db])
(let [contacts (rf/subscribe [:get-contacts]) (let [contacts (rf/subscribe [:get-contacts])
global-commands (rf/subscribe [:get :global-commands])] global-commands (rf/subscribe [:get :global-commands])
contact-groups (rf/subscribe [:get-contact-groups])]
(testing ":load-contacts event"
;;Assert the initial state ;;Assert the initial state
(is (and (map? @contacts) (empty? @contacts))) (is (and (map? @contacts) (empty? @contacts)))
@ -190,4 +183,123 @@
(rf/dispatch [:load-contacts]) (rf/dispatch [:load-contacts])
(is (= {"browse" browse-contact-from-realm-db} @contacts)) (is (= {"browse" browse-contact-from-realm-db} @contacts))
(is (= browse-global-commands @global-commands))))) (is (= browse-global-commands @global-commands)))
(testing ":load-default-contacts! event"
;;Assert the initial state
(is (and (map? @contact-groups) (empty? @contact-groups)))
;; :load-default-contacts! event dispatches next 5 events
;;
;; :add-contact-groups
;; :add-contacts
;; :add-contacts-to-group
;;TODO :add-chat
;;TODO :load-commands!
(rf/dispatch [:load-default-contacts!])
(is (= {"dapps" dapps-contact-group} (update @contact-groups "dapps" assoc :timestamp 0)))
(is (= contacts-browse-wallet
@contacts)))
(let [new-contact-public-key "0x048f7d5d4bda298447bbb5b021a34832509bd1a8dbe4e06f9b7223d00a59b6dc14f6e142b21d3220ceb3155a6d8f40ec115cd96394d3cc7c55055b433a1758dc74"
new-contact-address "5392ccb49f2e9fef8b8068b3e3b5ba6c020a9aca"
new-contact {:name ""
:photo-path ""
:whisper-identity new-contact-public-key
:address new-contact-address}
contact (rf/subscribe [:contact-by-identity new-contact-public-key])]
(testing ":add-contact-handler event - new contact"
;; :add-contact-handler event dispatches next 4 events for new contact
;;
;; :add-new-contact-and-open-chat
;; :status-im.contacts.events/add-new-contact
;; :status-im.contacts.events/send-contact-request
;;TODO :start-chat
(rf/reg-event-db :start-chat (fn [db _] db))
(rf/dispatch [:add-contact-handler new-contact-public-key])
(is (= new-contact (assoc @contact :photo-path "" :name "")))
(is (= (assoc contacts-browse-wallet new-contact-public-key new-contact)
(update @contacts new-contact-public-key assoc :photo-path "" :name ""))))
(testing ":contact-request-received event"
;; :contact-request-received event dispatches next 3 events
;;
;; :update-contact!
;; :watch-contact
;;TODO :update-chat!
(rf/reg-event-db :update-chat! (fn [db _] db))
(let [recieved-contact {:name "test"
:profile-image ""
:address new-contact-address
:status "test status"}
recieved-contact' (merge new-contact
(dissoc recieved-contact :profile-image)
{:public-key "" :private-key ""})]
(rf/dispatch [:contact-request-received {:from new-contact-public-key
:payload {:contact recieved-contact
:keypair {:public ""
:private ""}}}])
(is (= (assoc contacts-browse-wallet new-contact-public-key recieved-contact')
@contacts))
(testing ":contact-update-received event"
;; :contact-update-received event dispatches next 2 events
;;
;; :update-contact!
;;TODO :update-chat!
(let [timestamp (datetime/now-ms)
recieved-contact'' (assoc recieved-contact' :last-updated timestamp
:status "new status"
:name "new name")]
(rf/dispatch [:contact-update-received {:from new-contact-public-key
:payload {:content {:profile {:profile-image ""
:status "new status"
:name "new name"}}
:timestamp timestamp}}])
(is (= (assoc contacts-browse-wallet new-contact-public-key recieved-contact'')
@contacts))
(testing ":hide-contact event"
;; :hide-contact event dispatches next 2 events
;;
;; :update-contact!
;;TODO :account-update-keys
(rf/reg-event-db :account-update-keys (fn [db _] db))
(rf/dispatch [:hide-contact @contact])
(is (= (assoc contacts-browse-wallet new-contact-public-key (assoc recieved-contact''
:pending? true))
@contacts)))
(testing ":add-contact-handler event - :add-pending-contact"
;; :add-contact-handler event dispatches next 4 events
;;
;; :add-pending-contact
;; :status-im.contacts.events/add-new-contact
;; :status-im.contacts.events/send-contact-request
;;TODO :discoveries-send-portions
(rf/reg-event-db :discoveries-send-portions (fn [db _] db))
(rf/dispatch [:add-contact-handler new-contact-public-key])
(is (= (assoc contacts-browse-wallet new-contact-public-key (assoc recieved-contact''
:pending? false))
@contacts)))))))))))