(ns horizon.controls.widgets.tree.hierarchy-helpers-test (:require [cljs.test :refer-macros [deftest testing is use-fixtures async]] [horizon.controls.widgets.tree.hierarchy-helpers :as sut] [horizon.test-helpers.async-test-tools :as async-test-tools] [greenpowermonitor.test-doubles :as td] [cljs.core.async :as core.async] [horizon.common.logging :as log] [om.core :as om])) (deftest selecting-node-classes (is (= "tree-node level-0" (sut/select-node-classes #{} 1 0 3))) (is (= "tree-node level-1" (sut/select-node-classes #{} 1 1 3))) (is (= "tree-node selected level-0" (sut/select-node-classes #{{:id 1}} 1 0 3))) (is (= "tree-node level-0" (sut/select-node-classes #{{:id 1}} 5 0 3))) (is (= "tree-node level-1 clickable" (sut/select-node-classes #{{:id 1}} 5 1 0)))) ;: Handling branch-channel messages ;;---------------------------------- (deftest branch-channel-expanding-nodes-message (let [msg {:type :expand-node :value :some-value} channel (core.async/chan)] (async done (async-test-tools/expect-async-message channel :expected-message msg :done-fn done) (sut/handle-branch-channel-messages channel msg)))) (deftest branch-channel-selecting-alerts-message (let [msg {:type :select-alert} channel (core.async/chan)] (async done (async-test-tools/expect-async-message channel :expected-message msg :done-fn done) (sut/handle-branch-channel-messages channel msg)))) (deftest branch-channel-selecting-nodes-message (let [msg {:type :select-nodes :value :some-value} channel (core.async/chan)] (async done (async-test-tools/expect-async-message channel :expected-message msg :done-fn done) (sut/handle-branch-channel-messages channel msg)))) (deftest branch-channel-any-other-type-of-message-logs-an-error (td/with-doubles :spying [log/log-unknown-message-type] (let [msg {:type :any-other-type} channel :not-used-channel] (sut/handle-branch-channel-messages channel msg) (is (= [[::sut/handle-branch-channel-messages msg]] (td/calls-to log/log-unknown-message-type)))))) (deftest branch-channel-any-other-type-of-message-produces-no-messages-in-the-channel (let [msg {:type :any-other-type} channel (core.async/chan)] (async done (async-test-tools/expect-no-messages channel :done-fn done) (sut/handle-branch-channel-messages channel msg)))) ;: Handling tree-channel-handler messages ;;---------------------------------- (deftest tree-channel-expanding-nodes-message (let [owner :some-owner msg {:type :expand-node :value :some-value} channel (core.async/chan)] (async done (async-test-tools/expect-async-message channel :expected-message msg :done-fn done) (sut/handle-tree-channel-messages owner channel msg)))) (deftest tree-channel-selecting-alerts-message (let [owner :some-owner msg {:type :select-alert} channel (core.async/chan)] (async done (async-test-tools/expect-async-message channel :expected-message msg :done-fn done) (sut/handle-tree-channel-messages owner channel msg)))) (deftest tree-channel-selecting-nodes-message (let [owner :some-owner msg {:type :select-nodes :value :some-value} channel :not-used-channel] (td/with-doubles :spying [sut/select-node-handler] (sut/handle-tree-channel-messages owner channel msg) (is (= [[owner :some-value channel]] (td/calls-to sut/select-node-handler)))))) (deftest tree-channel-any-other-type-of-message-logs-an-error (td/with-doubles :spying [log/log-unknown-message-type] (let [msg {:type :any-other-type} owner :some-owner channel :not-used-channel] (sut/handle-tree-channel-messages owner channel msg) (is (= [[::sut/handle-tree-channel-messages msg]] (td/calls-to log/log-unknown-message-type)))))) (deftest tree-channel-any-other-type-of-message-produces-no-messages-in-the-channel (let [msg {:type :any-other-type} owner :some-owner channel (core.async/chan)] (async done (async-test-tools/expect-no-messages channel :done-fn done) (sut/handle-tree-channel-messages owner channel msg)))) (deftest selecting-a-node-handler (let [owner :some-owner channel :a-channel node :a-node] (testing "when shift is pressed" (let [pressed-keys #{:control :shift}] (td/with-doubles :stubbing [om/get-state :maps {[owner :pressed-keys] pressed-keys}] :spying [sut/handle-control-selection] (sut/select-node-handler owner node channel) (is (= [[channel owner node true]] (td/calls-to sut/handle-control-selection)))))) (testing "when control but not shift is pressed" (let [pressed-keys #{:shift}] (td/with-doubles :stubbing [om/get-state :maps {[owner :pressed-keys] pressed-keys}] :spying [sut/handle-shift-selection] (sut/select-node-handler owner node channel) (is (= [[node channel owner false]] (td/calls-to sut/handle-shift-selection)))))) (testing "if any other keys are pressed" (let [pressed-keys #{}] (td/with-doubles :stubbing [om/get-state :maps {[owner :pressed-keys] pressed-keys}] :spying [sut/handle-control-selection] (sut/select-node-handler owner node channel) (is (= [[channel owner node false]] (td/calls-to sut/handle-control-selection)))))))) (deftest handling-control-selection (let [owner :some-owner channel :some-channel clicked-node {:id 1 :name "koko"} a-selected-node {:id 2 :name "moko"}] (testing "when selection is additive and clicked node is already in selected nodes" (let [additive true selected-nodes #{clicked-node a-selected-node} expected-nodes-to-select #{a-selected-node}] (td/with-doubles :stubbing [om/get-state :maps {[owner :selected] selected-nodes}] :spying [sut/update-state-global-and-local!] (sut/handle-control-selection channel owner clicked-node additive) (is (= [[expected-nodes-to-select channel owner nil]] (td/calls-to sut/update-state-global-and-local!)))))) (testing "when selection is additive and clicked node is not in selected nodes" (let [additive true selected-nodes #{a-selected-node} expected-nodes-to-select #{clicked-node a-selected-node}] (td/with-doubles :stubbing [om/get-state :maps {[owner :selected] selected-nodes}] :spying [sut/update-state-global-and-local!] (sut/handle-control-selection channel owner clicked-node additive) (is (= [[expected-nodes-to-select channel owner nil]] (td/calls-to sut/update-state-global-and-local!)))))) (testing "when selection is not additive and clicked node is not in selected nodes" (let [additive false selected-nodes #{a-selected-node} expected-nodes-to-select #{clicked-node}] (td/with-doubles :stubbing [om/get-state :maps {[owner :selected] selected-nodes}] :spying [sut/update-state-global-and-local!] (sut/handle-control-selection channel owner clicked-node additive) (is (= [[expected-nodes-to-select channel owner clicked-node]] (td/calls-to sut/update-state-global-and-local!)))))) (testing "when selection is not additive and clicked node is already in selected nodes" (let [additive false selected-nodes #{clicked-node a-selected-node} expected-nodes-to-select #{}] (td/with-doubles :stubbing [om/get-state :maps {[owner :selected] selected-nodes}] :spying [sut/update-state-global-and-local!] (sut/handle-control-selection channel owner clicked-node additive) (is (= [[expected-nodes-to-select channel owner nil]] (td/calls-to sut/update-state-global-and-local!)))))))) (deftest handling-shift-selection (let [owner :some-owner channel :some-channel] (testing "when there're no shift selected node" (let [shift-selected-node nil additive :any-boolean clicked-node {:id 1 :name "k"}] (td/with-doubles :stubbing [om/get-state :maps {[owner :shift-selection] shift-selected-node}] :spying [om/set-state!] (sut/handle-shift-selection clicked-node channel owner additive) (is (= [[:some-owner :shift-selection clicked-node]] (td/calls-to om/set-state!)))))) (testing "when there are a shift selected node" (let [shift-selected-node {:id 3 :name "k"} currently-selected-node :any-node expanded-nodes-from-dom [{:id 1 :name "k"} {:id 2 :name "o"} {:id 3 :name "k"} {:id 4 :name "o"}] nodes-from-shift-selected-one-to-clicked-one #{{:id 1 :name "k"} {:id 2 :name "o"} {:id 3 :name "k"}} clicked-node {:id 1 :name "k"}] (testing "when selection is additive" (let [additive true expected-nodes-to-select (conj nodes-from-shift-selected-one-to-clicked-one currently-selected-node)] (td/with-doubles :stubbing [om/get-state :maps {[owner :shift-selection] shift-selected-node [owner :selected] currently-selected-node} sut/get-expanded-nodes-from-dom :returns [expanded-nodes-from-dom]] :spying [sut/update-state-global-and-local!] (sut/handle-shift-selection clicked-node channel owner additive) (is (= [[expected-nodes-to-select :some-channel :some-owner shift-selected-node]] (td/calls-to sut/update-state-global-and-local!)))))) (testing "when selection is not additive" (let [additive false expected-nodes-to-select nodes-from-shift-selected-one-to-clicked-one] (td/with-doubles :stubbing [om/get-state :maps {[owner :shift-selection] shift-selected-node [owner :selected] currently-selected-node} sut/get-expanded-nodes-from-dom :returns [expanded-nodes-from-dom]] :spying [sut/update-state-global-and-local!] (sut/handle-shift-selection clicked-node channel owner additive) (is (= [[expected-nodes-to-select :some-channel :some-owner shift-selected-node]] (td/calls-to sut/update-state-global-and-local!)))))))))) (deftest updating-global-and-local-state (let [selected :some-selected-nodes channel :some-channel owner :some-owner node :some-node] (td/with-doubles :spying [om/set-state! sut/notify-selected-nodes!] (sut/update-state-global-and-local! selected channel owner node) (is (= [[owner :shift-selection node] [owner :selected selected]] (td/calls-to om/set-state!))) (is (= [[channel selected]] (td/calls-to sut/notify-selected-nodes!)))))) (deftest notifying-selected-nodes (let [selected :some-nodes channel (core.async/chan)] (async done (async-test-tools/expect-async-message channel :expected-message {:type :select-nodes :value selected} :done-fn done) (sut/notify-selected-nodes! channel selected))))