diff --git a/common/src/app/common/test_helpers/compositions.cljc b/common/src/app/common/test_helpers/compositions.cljc index 9de6aafa55..7a27224397 100644 --- a/common/src/app/common/test_helpers/compositions.cljc +++ b/common/src/app/common/test_helpers/compositions.cljc @@ -177,7 +177,7 @@ ;; ----- Getters -(defn- bottom-shape-by-id +(defn bottom-shape-by-id "Get the deepest descendant of a shape by id" [file id & {:keys [page-label]}] (let [shape (ths/get-shape-by-id file id :page-label page-label)] @@ -187,7 +187,7 @@ (bottom-shape-by-id file child-id :page-label page-label)) shape))) -(defn- bottom-shape +(defn bottom-shape "Get the deepest descendant of a shape by tag" [file tag & {:keys [page-label]}] (let [shape (ths/get-shape file tag :page-label page-label)] @@ -318,3 +318,19 @@ first) shape (ths/get-shape-by-id file first-child-id :page-label page-label)] (reset-overrides file shape :page-label page-label :propagate-fn propagate-fn))) + +(defn delete-shape [file shape-tag & {:keys [page-label propagate-fn]}] + (let [page (if page-label + (thf/get-page file page-label) + (thf/current-page file)) + [_ changes] (cls/generate-delete-shapes (pcb/empty-changes nil (:id page)) + file + page + (:objects page) + #{(-> (ths/get-shape file shape-tag :page-label page-label) + :id)} + {:components-v2 true}) + file' (thf/apply-changes file changes)] + (if propagate-fn + (propagate-fn file') + file'))) diff --git a/common/test/common_tests/logic/chained_propagation_test.cljc b/common/test/common_tests/logic/chained_propagation_test.cljc index dc9a5ac91c..dd3f07aa75 100644 --- a/common/test/common_tests/logic/chained_propagation_test.cljc +++ b/common/test/common_tests/logic/chained_propagation_test.cljc @@ -37,7 +37,7 @@ (letfn [(setup [] (-> (thf/sample-file :file1) (tho/add-frame :frame-comp-1) - (ths/add-sample-shape :rectangle :parent-label :frame-comp-1) + (ths/add-sample-shape :rectangle :parent-label :frame-comp-1 :fills (ths/sample-fills-color :fill-color "#2653d8")) (thc/make-component :comp-1 :frame-comp-1) (tho/add-frame :frame-comp-2) @@ -48,90 +48,39 @@ (thc/instantiate-component :comp-2 :copy-comp-2 :parent-label :frame-comp-3 :children-labels [:comp-1-comp-2]) (thc/make-component :comp-3 :frame-comp-3))) - (step-update-color-comp-2 [file] - (let [page (thf/current-page file) + (propagate-all-component-changes [file] + (-> file + (tho/propagate-component-changes :comp-1) + (tho/propagate-component-changes :comp-2))) - ;; Changes to update the color of the contained rectangle in component comp-2 - changes-update-color-comp-1 - (cls/generate-update-shapes (pcb/empty-changes nil (:id page)) - (:shapes (ths/get-shape file :copy-comp-1)) - (fn [shape] - (assoc shape :fills (ths/sample-fills-color :fill-color "#FF0000"))) - (:objects page) - {}) + (fill-colors [file] + [(tho/bottom-fill-color file :frame-comp-1) + (tho/bottom-fill-color file :frame-comp-2) + (tho/bottom-fill-color file :frame-comp-3)]) - file' (thf/apply-changes file changes-update-color-comp-1)] - - (t/is (= (first-child-fill-color file' :comp-1-comp-2) "#B1B2B5")) - file')) - - (step-propagate-comp-2 [file] - (let [page (thf/current-page file) - file-id (:id file) - - ;; Changes to propagate the color changes of component comp-1 - changes-sync-comp-1 (-> (pcb/empty-changes) - (cll/generate-sync-file-changes - nil - :components - file-id - (:id (thc/get-component file :comp-2)) - file-id - {file-id file} - file-id)) - - file' (thf/apply-changes file changes-sync-comp-1)] - - (t/is (= (first-fill-color file' :rect-comp-2) "#FF0000")) - (t/is (= (first-child-fill-color file' :comp-1-comp-2) "#FF0000")) - file')) - - (step-update-color-comp-3 [file] - (let [page (thf/current-page file) - page-id (:id page) - comp-1-comp-2 (ths/get-shape file :comp-1-comp-2) - rect-comp-3 (ths/get-shape-by-id file (first (:shapes comp-1-comp-2))) - ;; Changes to update the color of the contained rectangle in component comp-3 - changes-update-color-comp-3 - (cls/generate-update-shapes (pcb/empty-changes nil page-id) - [(:id rect-comp-3)] - (fn [shape] - (assoc shape :fills (ths/sample-fills-color :fill-color "#00FF00"))) - (:objects page) - {}) - - file' (thf/apply-changes file changes-update-color-comp-3)] - - (t/is (= (first-child-fill-color file' :comp-1-comp-2) "#00FF00")) - file')) - - (step-reset [file] - (let [page (thf/current-page file) - file-id (:id file) - comp-1-comp-2 (ths/get-shape file :comp-1-comp-2) - ;; Changes to reset the changes on comp-1 inside comp-3 - changes-reset (cll/generate-reset-component (pcb/empty-changes) - file - {file-id file} - (ctn/make-container page :page) - (:id comp-1-comp-2) - true) - file' (thf/apply-changes file changes-reset)] - - (t/is (= (first-child-fill-color file' :comp-1-comp-2) "#FF0000")) - file'))] + (validate [file validator] + (validator file) + file)] (-> (setup) - step-update-color-comp-2 - step-propagate-comp-2 - step-update-color-comp-3 - step-reset))) + ;; Change the color of Comp1 inside Comp2 to red. It will propagate to Comp1 inside Comp3 + (tho/update-bottom-color :frame-comp-2 "#FF0000" :propagate-fn propagate-all-component-changes) + (validate #(t/is (= (fill-colors %) ["#2653d8" "#FF0000" "#FF0000"]))) + + ;; Change the color of Comp1 inside Comp3 to green. + (tho/update-bottom-color :frame-comp-3 "#00FF00" :propagate-fn propagate-all-component-changes) + (validate #(t/is (= (fill-colors %) ["#2653d8" "#FF0000" "#00FF00"]))) + + ;; Select Comp1 inside Comp3, and do a ‘Reset override’ + ;; Desired result: Comp1 inside Comp3 change its color to red, like Comp1 inside Comp2. + (tho/reset-overrides-in-first-child :copy-comp-2) + (validate #(t/is (= (fill-colors %) ["#2653d8" "#FF0000" "#FF0000"])))))) (t/deftest test-propagation-with-deleted-component (letfn [(setup [] (-> (thf/sample-file :file1) (tho/add-frame :frame-comp-4) - (ths/add-sample-shape :rectangle :parent-label :frame-comp-4) + (ths/add-sample-shape :rectangle :parent-label :frame-comp-4 :fills (ths/sample-fills-color :fill-color "#b1b2b5")) (thc/make-component :comp-4 :frame-comp-4) (tho/add-frame :frame-comp-5) @@ -142,71 +91,26 @@ (thc/instantiate-component :comp-5 :copy-comp-5 :parent-label :frame-comp-6 :children-labels [:comp-4-comp-5]) (thc/make-component :comp-6 :frame-comp-6))) - (step-delete-comp-5 [file] - (let [page (thf/current-page file) - ;; Changes to delete comp-5 - [_ changes-delete] (cls/generate-delete-shapes (pcb/empty-changes nil (:id page)) - file - page - (:objects page) - #{(-> (ths/get-shape file :frame-comp-5) - :id)} - {:components-v2 true}) + (propagate-all-component-changes [file] + (-> file + (tho/propagate-component-changes :comp-4) + (tho/propagate-component-changes :comp-5))) - file' (thf/apply-changes file changes-delete)] - (t/is (= (first-child-fill-color file' :comp-4-comp-5) "#B1B2B5")) - file')) + (fill-colors [file] + [(tho/bottom-fill-color file :frame-comp-4) + (tho/bottom-fill-color file :frame-comp-5) + (tho/bottom-fill-color file :frame-comp-6)]) - (step-update-color-comp-4 [file] - (let [page (thf/current-page file) - ;; Changes to update the color of the contained rectangle in component comp-4 - changes-update-color-comp-4 - (cls/generate-update-shapes (pcb/empty-changes nil (:id page)) - [(-> (ths/get-shape file :rectangle) - :id)] - (fn [shape] - (assoc shape :fills (ths/sample-fills-color :fill-color "#FF0000"))) - (:objects page) - {}) - - file' (thf/apply-changes file changes-update-color-comp-4)] - (t/is (= (first-fill-color file' :rectangle) "#FF0000")) - file')) - - (step-propagate-comp-4 [file] - (let [file-id (:id file) - ;; Changes to propagate the color changes of component comp-4 - changes-sync-comp-4 (-> (pcb/empty-changes) - (cll/generate-sync-file-changes - nil - :components - file-id - (:id (thc/get-component file :comp-4)) - file-id - {file-id file} - file-id)) - - file' (thf/apply-changes file changes-sync-comp-4)] - file')) - - (step-propagate-comp-5 [file] - (let [file-id (:id file) - ;; Changes to propagate the color changes of component comp-5 - changes-sync-comp-5 (-> (pcb/empty-changes) - (cll/generate-sync-file-changes - nil - :components - file-id - (:id (thc/get-component file :comp-5)) - file-id - {file-id file} - file-id)) - file' (thf/apply-changes file changes-sync-comp-5)] - (t/is (= (first-child-fill-color file' :comp-4-comp-5) "#FF0000")) - file'))] + (validate [file validator] + (validator file) + file)] (-> (setup) - step-delete-comp-5 - step-update-color-comp-4 - step-propagate-comp-4 - step-propagate-comp-5))) + ;; Delete Comp5. + (tho/delete-shape :frame-comp-5) + (validate #(t/is (= (fill-colors %) ["#b1b2b5" nil "#b1b2b5"]))) + + ;; Change the color of Comp4 + ;; Desired result: Comp6 change color + (tho/update-bottom-color :frame-comp-4 "#FF0000" :propagate-fn propagate-all-component-changes) + (validate #(t/is (= (fill-colors %) ["#FF0000" nil "#FF0000"])))))) diff --git a/common/test/common_tests/logic/swap_and_reset_test.cljc b/common/test/common_tests/logic/swap_and_reset_test.cljc index c27a5b99e8..0bb3e95ba0 100644 --- a/common/test/common_tests/logic/swap_and_reset_test.cljc +++ b/common/test/common_tests/logic/swap_and_reset_test.cljc @@ -20,156 +20,65 @@ (t/use-fixtures :each thi/test-fixture) ;; Related .penpot file: common/test/cases/swap-and-reset.penpot -(t/deftest test-simple-swap - (let [;; ==== Setup - file (-> (thf/sample-file :file1) - (tho/add-simple-component-with-copy :component-1 - :component-1-main-root - :component-1-main-child - :component-1-copy-root) - (tho/add-simple-component :component-2 - :component-2-root - :component-2-child)) - - component-1-copy-root (ths/get-shape file :component-1-copy-root) - component-2 (thc/get-component file :component-2) - page (thf/current-page file) - - ;; ==== Action - [new-shape _all-parents changes] - (cll/generate-component-swap (pcb/empty-changes) - (:objects page) - component-1-copy-root - (:data file) - page - {(:id file) file} - (:id component-2) - 0 - nil - {}) - - file' (thf/apply-changes file changes) - - ;; ==== Get - swapped (ths/get-shape-by-id file' (:id new-shape))] - - ;; ==== Check - (t/is (not= (:component-id component-1-copy-root) (:component-id swapped))) - (t/is (= (:id component-2) (:component-id swapped))) - (t/is (= (:id file) (:component-file swapped))))) - -(t/deftest test-swap-nested - (let [;; ==== Setup - file - (-> (thf/sample-file :file1) - (tho/add-simple-component :component-1 :component-1-main-root :component-1-main-child) - (tho/add-frame :component-container) - (thc/instantiate-component :component-1 :component-1-copy-root :parent-label :component-container) - (thc/make-component :component-container-main :component-container) - (thc/instantiate-component :component-container-main :component-container-instance) - (tho/add-simple-component :component-2 :component-2-main-root :component-2-main-child)) - - page (thf/current-page file) - component-2 (thc/get-component file :component-2) - - copy - (->> - (ths/get-shape file :component-container-instance) - :shapes - first - (ths/get-shape-by-id file)) - - libraries {(:id file) file} - - ;; ==== Action - [new-shape _all-parents changes] - (cll/generate-component-swap (pcb/empty-changes) - (:objects page) - copy - (:data file) - page - libraries - (:id component-2) - 0 - nil - {}) - - file' (thf/apply-changes file changes) - libraries' {(:id file') file'} - page' (thf/current-page file') - - ;; ==== Get - swapped (ths/get-shape-by-id file' (:id new-shape)) - component-1-copy-root (ths/get-shape file' :component-1-copy-root) - slot (-> (ctf/find-swap-slot swapped - page' - file' - libraries') - (ctk/build-swap-slot-group))] - - ;; ==== Check - (t/is (not= (:component-id copy) (:component-id swapped))) - (t/is (= (:id component-2) (:component-id swapped))) - (t/is (= (:id file) (:component-file swapped))) - (t/is (contains? (:touched swapped) slot)) - (t/is (= (ctk/get-swap-slot swapped) (:id component-1-copy-root))))) - (t/deftest test-swap-and-reset-override - (let [;; ==== Setup - file - (-> (thf/sample-file :file1) - (tho/add-simple-component :component-1 :component-1-main-root :component-1-main-child) - (tho/add-frame :component-container) - (thc/instantiate-component :component-1 :component-1-copy-root :parent-label :component-container) - (thc/make-component :component-container-main :component-container) - (thc/instantiate-component :component-container-main :component-container-instance) - (tho/add-simple-component :component-2 :component-2-main-root :component-2-main-child)) + (letfn [(setup [] + (-> (thf/sample-file :file1) - page (thf/current-page file) - component-1 (thc/get-component file :component-1) - component-2 (thc/get-component file :component-2) + (tho/add-frame :frame-rectangle) + (ths/add-sample-shape :rectangle-shape :parent-label :frame-rectangle :type :rect) + (thc/make-component :rectangle :frame-rectangle) - copy - (->> - (ths/get-shape file :component-container-instance) - :shapes - first - (ths/get-shape-by-id file)) + (tho/add-frame :frame-circle) + (ths/add-sample-shape :circle :parent-label :frame-circle :type :circle) + (thc/make-component :circle :frame-circle) - ;; ==== Action - [new-shape _all-parents changes-swap] - (cll/generate-component-swap (pcb/empty-changes) - (:objects page) - copy - (:data file) - page - {(:id file) file} - (:id component-2) - 0 - nil - {}) + (tho/add-frame :frame-main) + (thc/instantiate-component :rectangle :copy-rectangle :parent-label :frame-main :children-labels [:copy-rectangle-shape]) + (thc/make-component :main :frame-main) - file-swap (thf/apply-changes file changes-swap) - page-swap (thf/current-page file-swap) + (thc/instantiate-component :main :copy :children-labels [:copy-copy-rectangle]))) - changes - (cll/generate-reset-component (pcb/empty-changes) - file-swap - {(:id file-swap) file-swap} - page-swap - (:id new-shape) - true) + (copy-type [file] + (:type (tho/bottom-shape file :copy))) - file' (thf/apply-changes file changes) + (nested-component-id [file] + (->> + (ths/get-shape file :copy) + :shapes + first + (ths/get-shape-by-id file) + (:component-id))) - ;; ==== Get - reset - (->> - (ths/get-shape file' :component-container-instance) - :shapes - first - (ths/get-shape-by-id file'))] + (nested-swap-slot [file] + (->> + (ths/get-shape file :copy) + :shapes + first + (ths/get-shape-by-id file) + (ctk/get-swap-slot))) - ;; ==== Check - (t/is (= (:id component-1) (:component-id reset))) - (t/is (nil? (ctk/get-swap-slot reset))))) + (circle-component-id [file] + (:id (thc/get-component file :circle))) + + (rectangle-component-id [file] + (:id (thc/get-component file :rectangle))) + + (copy-rectangle-id [file] + (:id (ths/get-shape file :copy-rectangle))) + + (validate [file validator] + (validator file) + file)] + + (-> (setup) + ;; Select the Rectangle inside Copy and swap it for an Ellipse + (tho/swap-component-in-shape :copy-copy-rectangle :circle) + (validate #(t/is (= (copy-type %) :circle))) + (validate #(t/is (= (nested-component-id %) (circle-component-id %)))) + (validate #(t/is (= (copy-rectangle-id %) (nested-swap-slot %)))) + + ;; Do a "Reset override" on the newly created Ellipse. It should swap for a Rectangle + (tho/reset-overrides-in-first-child :copy) + (validate #(t/is (= (copy-type %) :rect))) + (validate #(t/is (= (nested-component-id %) (rectangle-component-id %)))) + (validate #(t/is (nil? (nested-swap-slot %)))))))