diff --git a/common/test/common_tests/helpers/compositions.cljc b/common/test/common_tests/helpers/compositions.cljc index d8b9cbe8b..50e367afd 100644 --- a/common/test/common_tests/helpers/compositions.cljc +++ b/common/test/common_tests/helpers/compositions.cljc @@ -11,6 +11,8 @@ (defn add-rect [file rect-label & {:keys [] :as params}] + ;; Generated shape tree: + ;; :rect-label [:type :rect :name: Rect1] (thf/add-sample-shape file rect-label (merge {:type :rect :name "Rect1"} @@ -18,6 +20,8 @@ (defn add-frame [file frame-label & {:keys [] :as params}] + ;; Generated shape tree: + ;; :frame-label [:type :frame :name: Frame1] (thf/add-sample-shape file frame-label (merge {:type :frame :name "Frame1"} @@ -25,6 +29,9 @@ (defn add-frame-with-child [file frame-label child-label & {:keys [frame-params child-params]}] + ;; Generated shape tree: + ;; :frame-label [:name: Frame1] + ;; :child-label [:name: Rect1] (-> file (add-frame frame-label frame-params) (thf/add-sample-shape child-label @@ -36,6 +43,9 @@ (defn add-simple-component [file component-label root-label child-label & {:keys [component-params root-params child-params]}] + ;; Generated shape tree: + ;; {:root-label} [:name: Frame1] # [Component :component-label] + ;; :child-label [:name: Rect1] (-> file (add-frame-with-child root-label child-label :frame-params root-params :child-params child-params) (thf/make-component component-label root-label component-params))) @@ -43,6 +53,12 @@ (defn add-simple-component-with-copy [file component-label main-root-label main-child-label copy-root-label & {:keys [component-params main-root-params main-child-params copy-root-params]}] + ;; Generated shape tree: + ;; {:main-root-label} [:name: Frame1] # [Component :component-label] + ;; :main-child-label [:name: Rect1] + ;; + ;; :copy-root-label [:name: Frame1] #--> [Component :component-label] :main-root-label + ;; [:name: Rect1] ---> :main-child-label (-> file (add-simple-component component-label main-root-label @@ -55,27 +71,98 @@ (defn add-component-with-many-children [file component-label root-label child-labels & {:keys [component-params root-params child-params-list]}] + ;; Generated shape tree: + ;; {:root-label} [:name: Frame1] # [Component :component-label] + ;; :child1-label [:name: Rect1] + ;; :child2-label [:name: Rect2] + ;; :child3-label [:name: Rect3] (as-> file $ (add-frame $ root-label root-params) - (reduce (fn [file [label params]] + (reduce (fn [file [index [label params]]] (thf/add-sample-shape file label (merge {:type :rect - :name "Rect1" + :name (str "Rect" (inc index)) :parent-label root-label} params))) $ - (d/zip-all child-labels child-params-list)) + (d/enumerate (d/zip-all child-labels child-params-list))) (thf/make-component $ component-label root-label component-params))) (defn add-component-with-many-children-and-copy - [file component-label root-label child-labels copy-root-label - & {:keys [component-params root-params child-params-list copy-root-params]}] + [file component-label main-root-label main-child-labels copy-root-label + & {:keys [component-params main-root-params main-child-params-list copy-root-params]}] + ;; Generated shape tree: + ;; {:root-label} [:name: Frame1] # [Component :component-label] + ;; :child1-label [:name: Rect1] + ;; :child2-label [:name: Rect2] + ;; :child3-label [:name: Rect3] + ;; + ;; :copy-root-label [:name: Frame1] #--> [Component :component-label] :root-label + ;; [:name: Rect1] ---> :child1-label + ;; [:name: Rect2] ---> :child2-label + ;; [:name: Rect3] ---> :child3-label (-> file (add-component-with-many-children component-label - root-label - child-labels + main-root-label + main-child-labels :component-params component-params - :root-params root-params - :child-params-list child-params-list) + :root-params main-root-params + :child-params-list main-child-params-list) (thf/instantiate-component component-label copy-root-label copy-root-params))) + +(defn add-nested-component + [file component1-label main1-root-label main1-child-label component2-label main2-root-label nested-head-label + & {:keys [component1-params root1-params main1-child-params component2-params main2-root-params nested-head-params]}] + ;; Generated shape tree: + ;; {:main1-root-label} [:name: Frame1] # [Component :component1-label] + ;; :main1-child-label [:name: Rect1] + ;; + ;; {:main2-root-label} [:name: Frame2] # [Component :component2-label] + ;; :nested-head-label [:name: Frame1] @--> [Component :component1-label] :main1-root-label + ;; [:name: Rect1] ---> :main1-child-label + (-> file + (add-simple-component component1-label + main1-root-label + main1-child-label + :component-params component1-params + :root-params root1-params + :child-params main1-child-params) + (add-frame main2-root-label (merge {:name "Frame2"} + main2-root-params)) + (thf/instantiate-component component1-label + nested-head-label + (assoc nested-head-params + :parent-label main2-root-label)) + (thf/make-component component2-label + main2-root-label + component2-params))) + +(defn add-nested-component-with-copy + [file component1-label main1-root-label main1-child-label component2-label main2-root-label nested-head-label copy2-label + & {:keys [component1-params root1-params main1-child-params component2-params main2-root-params nested-head-params copy2-params]}] + ;; Generated shape tree: + ;; {:main1-root-label} [:name: Frame1] # [Component :component1-label] + ;; :main1-child-label [:name: Rect1] + ;; + ;; {:main2-root-label} [:name: Frame2] # [Component :component2-label] + ;; :nested-head-label [:name: Frame1] @--> [Component :component1-label] :main1-root-label + ;; [:name: Rect1] ---> :main1-child-label + ;; + ;; :copy2-label [:name: Frame2] #--> [Component :component2-label] :main2-root-label + ;; [:name: Frame1] @--> [Component :component1-label] :nested-head-label + ;; [:name: Rect1] ---> + (-> file + (add-nested-component component1-label + main1-root-label + main1-child-label + component2-label + main2-root-label + nested-head-label + :component1-params component1-params + :root1-params root1-params + :main1-child-params main1-child-params + :component2-params component2-params + :main2-root-params main2-root-params + :nested-head-params nested-head-params) + (thf/instantiate-component component2-label copy2-label copy2-params))) \ No newline at end of file diff --git a/common/test/common_tests/helpers/debug.cljc b/common/test/common_tests/helpers/debug.cljc index 984e47159..5ecdcdb71 100644 --- a/common/test/common_tests/helpers/debug.cljc +++ b/common/test/common_tests/helpers/debug.cljc @@ -1,7 +1,9 @@ (ns common-tests.helpers.debug (:require + [app.common.data :as d] [app.common.uuid :as uuid] - [common-tests.helpers.ids-map :as thi])) + [common-tests.helpers.ids-map :as thi] + [cuerdas.core :as str])) (defn dump-shape "Dumps a shape, with each attribute in a line" @@ -15,19 +17,37 @@ (defn- stringify-keys [m keys] (apply str (interpose ", " (map #(str % ": " (get m %)) keys)))) +(defn- dump-page-shape + [shape keys padding] + (println (str/pad (str padding + (when (:main-instance shape) "{") + (or (thi/label (:id shape)) "") + (when (:main-instance shape) "}") + (when keys + (str " [" (stringify-keys shape keys) "]"))) + {:length 40 :type :right}) + (if (nil? (:shape-ref shape)) + (if (:component-root shape) + (str "# [Component " (or (thi/label (:component-id shape)) "") "]") + "") + (str/format "%s--> %s%s" + (cond (:component-root shape) "#" + (:component-id shape) "@" + :else "-") + (if (:component-root shape) + (str "[Component " (or (thi/label (:component-id shape)) "") "] ") + "") + (or (thi/label (:shape-ref shape)) ""))))) + (defn dump-page "Dumps the layer tree of the page. Prints the label of each shape, and the specified keys. Example: (thd/dump-page (thf/current-page file) [:id :touched])" ([page keys] (dump-page page uuid/zero "" keys)) - ([page id padding keys] - (let [objects (vals (:objects page)) - root-objects (filter #(and - (= (:parent-id %) id) - (not= (:id %) id)) - objects)] - (doseq [val root-objects] - (println padding (thi/label (:id val)) - (when keys - (str "[" (stringify-keys val keys) "]"))) - (dump-page page (:id val) (str padding " ") keys))))) + ([page root-id padding keys] + (let [lookupf (d/getf (:objects page)) + root-shape (lookupf root-id) + shapes (map lookupf (:shapes root-shape))] + (doseq [shape shapes] + (dump-page-shape shape keys padding) + (dump-page page (:id shape) (str padding " ") keys))))) diff --git a/common/test/common_tests/logic/components_touched_test.cljc b/common/test/common_tests/logic/components_touched_test.cljc index 0aa14ca29..e20827c1e 100644 --- a/common/test/common_tests/logic/components_touched_test.cljc +++ b/common/test/common_tests/logic/components_touched_test.cljc @@ -7,7 +7,6 @@ (ns common-tests.logic.components-touched-test (:require [app.common.files.changes-builder :as pcb] - [app.common.logic.libraries :as cll] [app.common.logic.shapes :as cls] [clojure.test :as t] [common-tests.helpers.compositions :as tho] @@ -151,3 +150,81 @@ ;; Check (t/is (= (:touched copy-root') nil)) (t/is (= (:touched copy-child') nil)))) + +(t/deftest test-touched-when-changing-upper + (let [;; Setup + file (-> (thf/sample-file :file1) + (tho/add-nested-component-with-copy :component1 + :main1-root + :main1-child + :component2 + :main2-root + :main2-nested-head + :copy2-root + :root2-params {:fills (thf/sample-fills-color + :fill-color "#abcdef")})) + page (thf/current-page file) + copy2-root (thf/get-shape file :copy2-root) + + ;; Action + update-fn (fn [shape] + (assoc shape :fills (thf/sample-fills-color :fill-color "#fabada"))) + + changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page)) + #{(:id copy2-root)} + update-fn + (:objects page) + {}) + + file' (thf/apply-changes file changes) + + ;; Get + copy2-root' (thf/get-shape file' :copy2-root) + fills' (:fills copy2-root') + fill' (first fills')] + + ;; Check + (t/is (= (count fills') 1)) + (t/is (= (:fill-color fill') "#fabada")) + (t/is (= (:fill-opacity fill') 1)) + (t/is (= (:touched copy2-root') #{:fill-group})))) + +(t/deftest test-touched-when-changing-lower + (let [;; Setup + file (-> (thf/sample-file :file1) + (tho/add-nested-component-with-copy :component1 + :main1-root + :main1-child + :component2 + :main2-root + :main2-nested-head + :copy2-root + :nested-head-params {:fills (thf/sample-fills-color + :fill-color "#abcdef")})) + page (thf/current-page file) + copy2-root (thf/get-shape file :copy2-root) + + ;; Action + update-fn (fn [shape] + (assoc shape :fills (thf/sample-fills-color :fill-color "#fabada"))) + + changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page)) + (:shapes copy2-root) + update-fn + (:objects page) + {}) + + file' (thf/apply-changes file changes) + + ;; Get + copy2-root' (thf/get-shape file' :copy2-root) + copy2-child' (thf/get-shape-by-id file' (first (:shapes copy2-root'))) + fills' (:fills copy2-child') + fill' (first fills')] + + ;; Check + (t/is (= (count fills') 1)) + (t/is (= (:fill-color fill') "#fabada")) + (t/is (= (:fill-opacity fill') 1)) + (t/is (= (:touched copy2-root') nil)) + (t/is (= (:touched copy2-child') #{:fill-group})))) \ No newline at end of file diff --git a/frontend/test/frontend_tests/state_components_sync_test.cljs b/frontend/test/frontend_tests/state_components_sync_test.cljs index 8ae88562a..7907f4ddd 100644 --- a/frontend/test/frontend_tests/state_components_sync_test.cljs +++ b/frontend/test/frontend_tests/state_components_sync_test.cljs @@ -21,337 +21,6 @@ (t/use-fixtures :each {:before thp/reset-idmap!}) -;; === Test touched ====================== - -(t/deftest test-touched-from-lib - (t/async - done - (let [state (-> thp/initial-state - (thp/sample-page) - (thp/sample-shape :shape1 :rect - {:name "Rect 1" - :fill-color clr/white - :fill-opacity 1}) - (thp/make-component :main1 :component1 - [(thp/id :shape1)]) - (thp/move-to-library :lib1 "Library 1") - (thp/sample-page) - (thp/instantiate-component :instance1 - (thp/id :component1) - (thp/id :lib1))) - - [_group1 shape1'] - (thl/resolve-instance state (thp/id :instance1)) - - store (the/prepare-store state done - (fn [new-state] - ;; Expected shape tree: - ;; - ;; [Page] - ;; Root Frame - ;; Rect 1 #--> Rect 1 - ;; Rect 1* ---> Rect 1 - ;; #{:fill-group} - ;; - (let [[[group shape1] [c-group c-shape1] _component] - (thl/resolve-instance-and-main - new-state - (thp/id :instance1))] - - (t/is (= (:name group) "Rect 1")) - (t/is (= (:touched group) nil)) - (t/is (= (:name shape1) "Rect 1")) - (t/is (= (:touched shape1) #{:fill-group})) - (t/is (= (:fill-color shape1) clr/test)) - (t/is (= (:fill-opacity shape1) 0.5)) - - (t/is (= (:name c-group) "Rect 1")) - (t/is (= (:touched c-group) nil)) - (t/is (= (:name c-shape1) "Rect 1")) - (t/is (= (:touched c-shape1) nil)) - (t/is (= (:fill-color c-shape1) clr/white)) - (t/is (= (:fill-opacity c-shape1) 1)))))] - - (ptk/emit! - store - (dch/update-shapes [(:id shape1')] - (fn [shape] - (merge shape {:fill-color clr/test - :fill-opacity 0.5}))) - :the/end)))) - -(t/deftest test-touched-nested-upper - (t/async - done - (let [state (-> thp/initial-state - (thp/sample-page) - (thp/sample-shape :shape1 :rect - {:name "Rect 1" - :fill-color clr/white - :fill-opacity 1}) - (thp/make-component :main1 :component1 - [(thp/id :shape1)]) - (thp/instantiate-component :instance1 - (thp/id :component1)) - (thp/sample-shape :shape2 :circle - {:name "Circle 1" - :fill-color clr/black - :fill-opacity 0}) - (thp/frame-shapes :frame1 - [(thp/id :instance1) - (thp/id :shape2)]) - (thp/make-component :main2 :component2 - [(thp/id :frame1)]) - (thp/instantiate-component :instance2 - (thp/id :component2))) - - [_instance2 _instance1 shape1' _shape2'] - (thl/resolve-instance state (thp/id :instance2)) - - store (the/prepare-store state done - (fn [new-state] - ;; Expected shape tree: - ;; - ;; [Page] - ;; Root Frame - ;; Rect 1 - ;; Rect 1 - ;; Group - ;; Rect 1 #--> Rect 1 - ;; Rect 1 ---> Rect 1 - ;; Circle 1 - ;; Group #--> Group - ;; Rect 1 @--> Rect 1 - ;; Rect 1 ---> Rect 1 - ;; Circle 1* ---> Circle 1 - ;; #{:fill-group} - ;; - ;; [Rect 1] - ;; page1 / Rect 1 - ;; - ;; [Group] - ;; page1 / Group - ;; - (let [[[instance2 instance1 shape1 shape2] - [c-instance2 c-instance1 c-shape1 c-shape2] _component] - (thl/resolve-instance-and-main - new-state - (thp/id :instance2))] - - (t/is (= (:name instance2) "Board")) - (t/is (= (:touched instance2) nil)) - (t/is (= (:name instance1) "Rect 1")) - (t/is (= (:touched instance1) nil)) - (t/is (= (:name shape1) "Circle 1")) - (t/is (= (:touched shape1) #{:fill-group})) - (t/is (= (:fill-color shape1) clr/test)) - (t/is (= (:fill-opacity shape1) 0.5)) - (t/is (= (:name shape2) "Rect 1")) - (t/is (= (:touched shape2) nil)) - (t/is (= (:fill-color shape2) clr/white)) - (t/is (= (:fill-opacity shape2) 1)) - - (t/is (= (:name c-instance2) "Board")) - (t/is (= (:touched c-instance2) nil)) - (t/is (= (:name c-instance1) "Rect 1")) - (t/is (= (:touched c-instance1) nil)) - (t/is (= (:name c-shape1) "Circle 1")) - (t/is (= (:touched c-shape1) nil)) - (t/is (= (:fill-color c-shape1) clr/black)) - (t/is (= (:fill-opacity c-shape1) 0)) - (t/is (= (:name c-shape2) "Rect 1")) - (t/is (= (:touched c-shape2) nil)) - (t/is (= (:fill-color c-shape2) clr/white)) - (t/is (= (:fill-opacity c-shape2) 1)))))] - - (ptk/emit! - store - (dch/update-shapes [(:id shape1')] - (fn [shape] - (merge shape {:fill-color clr/test - :fill-opacity 0.5}))) - :the/end)))) - -(t/deftest test-touched-nested-lower-near - (t/async done - (let [state (-> thp/initial-state - (thp/sample-page) - (thp/sample-shape :shape1 :rect - {:name "Rect 1" - :fill-color clr/white - :fill-opacity 1}) - (thp/make-component :main1 :component1 - [(thp/id :shape1)]) - (thp/instantiate-component :instance1 - (thp/id :component1)) - (thp/sample-shape :shape2 :circle - {:name "Circle 1" - :fill-color clr/black - :fill-opacity 0}) - (thp/frame-shapes :frame1 - [(thp/id :instance1) - (thp/id :shape2)]) - (thp/make-component :instance2 :component2 - [(thp/id :frame1)]) - (thp/instantiate-component :instance2 - (thp/id :component2))) - - [_instance2 _instance1 _shape1' shape2'] - (thl/resolve-instance state (thp/id :instance2)) - - store (the/prepare-store state done - (fn [new-state] - ;; Expected shape tree: - ;; - ;; [Page] - ;; Root Frame - ;; Rect 1 - ;; Rect 1 - ;; Group - ;; Rect 1 #--> Rect 1 - ;; Rect 1 ---> Rect 1 - ;; Circle 1 - ;; Group #--> Group - ;; Rect 1 @--> Rect 1 - ;; Rect 1* ---> Rect 1 - ;; #{:fill-group} - ;; Circle 1 ---> Circle 1 - ;; - ;; [Rect 1] - ;; page1 / Rect 1 - ;; - ;; [Group] - ;; page1 / Group - ;; - (let [[[instance2 instance1 shape1 shape2] - [c-instance2 c-instance1 c-shape1 c-shape2] _component] - (thl/resolve-instance-and-main - new-state - (thp/id :instance2))] - - (t/is (= (:name instance2) "Board")) - (t/is (= (:touched instance2) nil)) - (t/is (= (:name instance1) "Rect 1")) - (t/is (= (:touched instance1) nil)) - (t/is (= (:name shape1) "Circle 1")) - (t/is (= (:touched shape1) nil)) - (t/is (= (:fill-color shape1) clr/black)) - (t/is (= (:fill-opacity shape1) 0)) - (t/is (= (:name shape2) "Rect 1")) - (t/is (= (:touched shape2) #{:fill-group})) - (t/is (= (:fill-color shape2) clr/test)) - (t/is (= (:fill-opacity shape2) 0.5)) - - (t/is (= (:name c-instance2) "Board")) - (t/is (= (:touched c-instance2) nil)) - (t/is (= (:name c-instance1) "Rect 1")) - (t/is (= (:touched c-instance1) nil)) - (t/is (= (:name c-shape1) "Circle 1")) - (t/is (= (:touched c-shape1) nil)) - (t/is (= (:fill-color c-shape1) clr/black)) - (t/is (= (:fill-opacity c-shape1) 0)) - (t/is (= (:name c-shape2) "Rect 1")) - (t/is (= (:touched c-shape2) nil)) - (t/is (= (:fill-color c-shape2) clr/white)) - (t/is (= (:fill-opacity c-shape2) 1)))))] - - (ptk/emit! - store - (dch/update-shapes [(:id shape2')] - (fn [shape] - (merge shape {:fill-color clr/test - :fill-opacity 0.5}))) - :the/end)))) - -(t/deftest test-touched-nested-lower-remote - (t/async done - (let [state (-> thp/initial-state - (thp/sample-page) - (thp/sample-shape :shape1 :rect - {:name "Rect 1" - :fill-color clr/white - :fill-opacity 1}) - (thp/make-component :main1 :component1 - [(thp/id :shape1)]) - (thp/instantiate-component :instance1 - (thp/id :component1)) - (thp/sample-shape :shape2 :circle - {:name "Circle 1" - :fill-color clr/black - :fill-opacity 0}) - (thp/frame-shapes :frame1 - [(thp/id :instance1) - (thp/id :shape2)]) - (thp/make-component :instance2 :component2 - [(thp/id :frame1)]) - (thp/instantiate-component :instance2 - (thp/id :component2))) - - [instance2 _instance1 _shape1' shape2'] - (thl/resolve-instance state (thp/id :instance2)) - - store (the/prepare-store state done - (fn [new-state] - ;; Expected shape tree: - ;; - ;; [Page] - ;; Root Frame - ;; Rect 1 - ;; Rect 1 - ;; Group - ;; Rect 1 #--> Rect 1 - ;; Rect 1* ---> Rect 1 - ;; #{:fill-group} - ;; Circle 1 - ;; Group #--> Group - ;; Rect 1 @--> Rect 1 - ;; Rect 1 ---> Rect 1 - ;; Circle 1 ---> Circle 1 - ;; - ;; [Rect 1] - ;; page1 / Rect 1 - ;; - ;; [Group] - ;; page1 / Group - ;; - (let [[[instance2 instance1 shape1 shape2] - [c-instance2 c-instance1 c-shape1 c-shape2] _component] - (thl/resolve-instance-and-main - new-state - (thp/id :instance2))] - - (t/is (= (:name instance2) "Board")) - (t/is (= (:touched instance2) nil)) - (t/is (= (:name instance1) "Rect 1")) - (t/is (= (:touched instance1) nil)) - (t/is (= (:name shape1) "Circle 1")) - (t/is (= (:touched shape1) nil)) - (t/is (= (:fill-color shape1) clr/black)) - (t/is (= (:fill-opacity shape1) 0)) - (t/is (= (:name shape2) "Rect 1")) - (t/is (= (:touched shape2) #{:fill-group})) - (t/is (= (:fill-color shape2) clr/test)) - (t/is (= (:fill-opacity shape2) 0.5)) - (t/is (= (:name c-instance2) "Board")) - (t/is (= (:touched c-instance2) nil)) - (t/is (= (:name c-instance1) "Rect 1")) - (t/is (= (:touched c-instance1) nil)) - (t/is (= (:name c-shape1) "Circle 1")) - (t/is (= (:touched c-shape1) nil)) - (t/is (= (:fill-color c-shape1) clr/black)) - (t/is (= (:fill-opacity c-shape1) 0)) - (t/is (= (:name c-shape2) "Rect 1")) - (t/is (= (:touched c-shape2) #{:fill-group})))))] - - (ptk/emit! - store - (dch/update-shapes [(:id shape2')] - (fn [shape] - (merge shape {:fill-color clr/test - :fill-opacity 0.5}))) - (dwl/update-component (:id instance2)) - :the/end)))) - ;; === Test reset changes ====================== (t/deftest test-reset-changes