0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-04-01 17:41:50 -05:00

Add tests for detach with swapped copies

This commit is contained in:
Andrés Moya 2024-06-18 13:07:34 +02:00 committed by Andrey Antukh
parent 3e657874d7
commit d039df6b73
6 changed files with 238 additions and 14 deletions

View file

@ -6,6 +6,7 @@
(ns app.common.test-helpers.components
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.files.changes-builder :as pcb]
[app.common.files.helpers :as cfh]
@ -64,13 +65,12 @@
[file id]
(ctkl/get-component (:data file) id))
(defn set-child-label
[file shape-label child-idx label]
(let [id (-> (ths/get-shape file shape-label)
:shapes
(nth child-idx))]
(when id
(thi/set-id! label id))))
(defn- set-children-labels!
[file shape-label children-labels]
(doseq [[label id]
(d/zip children-labels (cfh/get-children-ids (-> (thf/current-page file) :objects)
(thi/id shape-label)))]
(thi/set-id! label id)))
(defn instantiate-component
[file component-label copy-root-label & {:keys [parent-label library children-labels] :as params}]
@ -103,6 +103,7 @@
(and (some? parent) (ctn/in-any-component? (:objects page) parent))
(dissoc :component-root))
file' (ctf/update-file-data
file
(fn [file-data]
@ -128,14 +129,14 @@
true)))
$
(remove #(= (:id %) (:id copy-root')) copy-shapes)))))]
(when children-labels
(dotimes [idx (count children-labels)]
(set-child-label file' copy-root-label idx (nth children-labels idx))))
(set-children-labels! file' copy-root-label children-labels))
file'))
(defn component-swap
[file shape-label new-component-label new-shape-label & {:keys [library] :as params}]
[file shape-label new-component-label new-shape-label & {:keys [library children-labels] :as params}]
(let [shape (ths/get-shape file shape-label)
library (or library file)
libraries {(:id library) library}
@ -147,10 +148,15 @@
;; Store the properties that need to be maintained when the component is swapped
keep-props-values (select-keys shape ctk/swap-keep-attrs)
[new_shape _ changes]
(-> (pcb/empty-changes nil (:id page))
(cll/generate-component-swap objects shape (:data file) page libraries id-new-component 0 nil keep-props-values))]
(cll/generate-component-swap objects shape (:data file) page libraries id-new-component 0 nil keep-props-values))
file' (thf/apply-changes file changes)]
(thi/set-id! new-shape-label (:id new_shape))
(thf/apply-changes file changes)))
(when children-labels
(set-children-labels! file' new-shape-label children-labels))
file'))

View file

@ -58,6 +58,28 @@
:parent-label frame-label}
child-params))))
(defn add-minimal-component
[file component-label root-label
& {:keys [component-params root-params]}]
;; Generated shape tree:
;; {:root-label} [:name Frame1] # [Component :component-label]
(-> file
(add-frame root-label root-params)
(thc/make-component component-label root-label component-params)))
(defn add-minimal-component-with-copy
[file component-label main-root-label copy-root-label
& {:keys [component-params main-root-params copy-root-params]}]
;; Generated shape tree:
;; {:main-root-label} [:name Frame1] # [Component :component-label]
;; :copy-root-label [:name Frame1] #--> [Component :component-label] :main-root-label
(-> file
(add-minimal-component component-label
main-root-label
:component-params component-params
:root-params main-root-params)
(thc/instantiate-component component-label copy-root-label copy-root-params)))
(defn add-simple-component
[file component-label root-label child-label
& {:keys [component-params root-params child-params]}]

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,197 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS INC
(ns common-tests.logic.comp-detach-with-swap-test
(:require
[app.common.files.changes-builder :as pcb]
[app.common.logic.libraries :as cll]
[app.common.test-helpers.components :as thc]
[app.common.test-helpers.compositions :as tho]
[app.common.test-helpers.files :as thf]
[app.common.test-helpers.ids-map :as thi]
[app.common.test-helpers.shapes :as ths]
[app.common.types.component :as ctk]
[clojure.test :as t]))
(t/use-fixtures :each thi/test-fixture)
;; Related .penpot file: common/test/cases/detach-with-swap.penpot
(defn- setup-file
[]
;; {:r-ellipse} [:name Ellipse, :type :frame] # [Component :c-ellipse]
;; :ellipse [:name Ellipse, :type :circle]
;; {:r-rectangle} [:name Rectangle, :type :frame] # [Component :c-rectangle]
;; :rectangle [:name rectangle, :type :rect]
;; {:board-with-ellipse} [:name Board with ellipse, :type :frame] # [Component :c-board-with-ellipse]
;; :nested-h-ellipse [:name Ellipse, :type :frame] @--> :r-ellipse
;; :nested-ellipse [:name Ellipse, :type :circle] ---> :ellipse
;; {:board-with-rectangle} [:name Board with rectangle, :type :frame] # [Component :c-board-with-rectangle]
;; :nested-h-rectangle [:name Rectangle, :type :frame] @--> :r-rectangle
;; :nested-rectangle [:name rectangle, :type :rect] ---> :rectangle
;; {:big-board} [:name Big Board, :type :frame] # [Component :c-big-board]
;; :h-board-with-ellipse [:name Board with ellipse, :type :frame] @--> :board-with-ellipse
;; :nested2-h-ellipse [:name Ellipse, :type :frame] @--> :nested-h-ellipse
;; :nested2-ellipse [:name Ellipse, :type :circle] ---> :nested-ellipse
(-> (thf/sample-file :file1)
(tho/add-simple-component :c-ellipse :r-ellipse :ellipse
:root-params {:name "Ellipse"}
:child-params {:name "Ellipse" :type :circle})
(tho/add-simple-component :c-rectangle :r-rectangle :rectangle
:root-params {:name "Rectangle"}
:child-params {:name "rectangle" :type :rect})
(tho/add-frame :board-with-ellipse :name "Board with ellipse")
(thc/instantiate-component :c-ellipse :nested-h-ellipse :parent-label :board-with-ellipse
:children-labels [:nested-ellipse])
(thc/make-component :c-board-with-ellipse :board-with-ellipse)
(tho/add-frame :board-with-rectangle :name "Board with rectangle")
(thc/instantiate-component :c-rectangle :nested-h-rectangle :parent-label :board-with-rectangle
:children-labels [:nested-rectangle])
(thc/make-component :c-board-with-rectangle :board-with-rectangle)
(tho/add-frame :big-board :name "Big Board")
(thc/instantiate-component :c-board-with-ellipse
:h-board-with-ellipse
:parent-label :big-board
:children-labels [:nested2-h-ellipse :nested2-ellipse])
(thc/make-component :c-big-board :big-board)))
(t/deftest test-advance-when-not-swapped
(let [;; ==== Setup
file (-> (setup-file)
(thc/instantiate-component :c-big-board
:copy-big-board
:children-labels [:copy-h-board-with-ellipse
:copy-nested-h-ellipse
:copy-nested-ellipse]))
page (thf/current-page file)
;; ==== Action
changes (cll/generate-detach-instance (-> (pcb/empty-changes nil)
(pcb/with-page page)
(pcb/with-objects (:objects page)))
page
{(:id file) file}
(thi/id :copy-big-board))
file' (thf/apply-changes file changes)
;; ==== Get
copy-h-board-with-ellipse (ths/get-shape file' :copy-h-board-with-ellipse)
copy-nested-h-ellipse (ths/get-shape file' :copy-nested-h-ellipse)
copy-nested-ellipse (ths/get-shape file' :copy-nested-ellipse)]
;; ==== Check
;; In the normal case, children's ref (that pointed to the near main inside big-board)
;; are advanced to point to the new near main inside board-with-ellipse.
(t/is (ctk/instance-root? copy-h-board-with-ellipse))
(t/is (= (:shape-ref copy-h-board-with-ellipse) (thi/id :board-with-ellipse)))
(t/is (nil? (ctk/get-swap-slot copy-h-board-with-ellipse)))
(t/is (ctk/instance-head? copy-nested-h-ellipse))
(t/is (= (:shape-ref copy-nested-h-ellipse) (thi/id :nested-h-ellipse)))
(t/is (nil? (ctk/get-swap-slot copy-nested-h-ellipse)))
(t/is (not (ctk/instance-head? copy-nested-ellipse)))
(t/is (= (:shape-ref copy-nested-ellipse) (thi/id :nested-ellipse)))
(t/is (nil? (ctk/get-swap-slot copy-nested-ellipse)))))
(t/deftest test-dont-advance-when-swapped-copy
(let [;; ==== Setup
file (-> (setup-file)
(thc/instantiate-component :c-big-board
:copy-big-board
:children-labels [:copy-h-board-with-ellipse
:copy-nested-h-ellipse
:copy-nested-ellipse])
(thc/component-swap :copy-h-board-with-ellipse
:c-board-with-rectangle
:copy-h-board-with-rectangle
:children-labels [:copy-nested-h-rectangle
:copy-nested-rectangle]))
page (thf/current-page file)
;; ==== Action
changes (cll/generate-detach-instance (-> (pcb/empty-changes nil)
(pcb/with-page page)
(pcb/with-objects (:objects page)))
page
{(:id file) file}
(thi/id :copy-big-board))
file' (thf/apply-changes file changes)
;; ==== Get
copy-h-board-with-rectangle (ths/get-shape file' :copy-h-board-with-rectangle)
copy-nested-h-rectangle (ths/get-shape file' :copy-nested-h-rectangle)
copy-nested-rectangle (ths/get-shape file' :copy-nested-rectangle)]
;; ==== Check
;; If the nested copy was swapped, there is no need to advance shape-refs,
;; as they already pointing to the near main inside board-with-rectangle.
(t/is (ctk/instance-root? copy-h-board-with-rectangle))
(t/is (= (:shape-ref copy-h-board-with-rectangle) (thi/id :board-with-rectangle)))
(t/is (nil? (ctk/get-swap-slot copy-h-board-with-rectangle)))
(t/is (ctk/instance-head? copy-nested-h-rectangle))
(t/is (= (:shape-ref copy-nested-h-rectangle) (thi/id :nested-h-rectangle)))
(t/is (nil? (ctk/get-swap-slot copy-nested-h-rectangle)))
(t/is (not (ctk/instance-head? copy-nested-rectangle)))
(t/is (= (:shape-ref copy-nested-rectangle) (thi/id :nested-rectangle)))
(t/is (nil? (ctk/get-swap-slot copy-nested-rectangle)))))
(t/deftest test-propagate-slot-when-swapped-main
(let [;; ==== Setup
file (-> (setup-file)
(thc/component-swap :nested2-h-ellipse
:c-rectangle
:nested2-h-rectangle
:children-labels [:nested2-rectangle])
(thc/instantiate-component :c-big-board
:copy-big-board
:children-labels [:copy-h-board-with-ellipse
:copy-nested-h-rectangle
:copy-nested-rectangle]))
page (thf/current-page file)
;; ==== Action
changes (cll/generate-detach-instance (-> (pcb/empty-changes nil)
(pcb/with-page page)
(pcb/with-objects (:objects page)))
page
{(:id file) file}
(thi/id :copy-big-board))
file' (thf/apply-changes file changes)
;; ==== Get
copy-h-board-with-ellipse (ths/get-shape file' :copy-h-board-with-ellipse)
copy-nested-h-rectangle (ths/get-shape file' :copy-nested-h-rectangle)
copy-nested-rectangle (ths/get-shape file' :copy-nested-rectangle)]
;; ==== Check
;; This one is advanced normally, as it has not been swapped.
(t/is (ctk/instance-root? copy-h-board-with-ellipse))
(t/is (= (:shape-ref copy-h-board-with-ellipse) (thi/id :board-with-ellipse)))
(t/is (nil? (ctk/get-swap-slot copy-h-board-with-ellipse)))
;; If the nested copy has been swapped in the main, it does advance,
;; but the swap slot of the near main is propagated to the copy.
(t/is (ctk/instance-head? copy-nested-h-rectangle))
(t/is (= (:shape-ref copy-nested-h-rectangle) (thi/id :r-rectangle)))
(t/is (= (ctk/get-swap-slot copy-nested-h-rectangle) (thi/id :nested-h-ellipse)))
(t/is (not (ctk/instance-head? copy-nested-rectangle)))
(t/is (= (:shape-ref copy-nested-rectangle) (thi/id :rectangle)))
(t/is (nil? (ctk/get-swap-slot copy-nested-rectangle)))))

View file

@ -758,7 +758,6 @@
(t/is (some? blue-copy1'))
(t/is (nil? (ctk/get-swap-slot blue-copy1')))))
(t/deftest test-remove-swap-slot-detach
(let [;; ==== Setup
file (setup-file)