mirror of
https://github.com/penpot/penpot.git
synced 2026-11-01 23:50:38 +00:00
* 🐛 Ensure normalized names in components and variants We have a rule of that shape names that include / separator should have it normalized, with one space before and one after. But this rule is being enforced only in the UI and the plugins API. There may be other ways of creating shapes that does not follow it. For normal shapes this is not really a problem. But for main instances it may cause that the name of the shape does not match the joined path+name of the component, and this may generate some problems. We have decided to add a migration to fix this in all main instances and variant containers and enforce it in the future with integrity validations (normal shapes may be left as is). * 🐛 Fix bad variant-id in the component and the main instance * 🔧 Fix some issues detected in PR review * 🐛 Add nil guard
665 lines
26 KiB
Clojure
665 lines
26 KiB
Clojure
;; 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 SUBSIDIARY SL
|
|
|
|
(ns common-tests.logic.comp-creation-test
|
|
(:require
|
|
[app.common.data :as d]
|
|
[app.common.files.changes-builder :as pcb]
|
|
[app.common.files.shapes-helpers :as cfsh]
|
|
[app.common.geom.point :as gpt]
|
|
[app.common.logic.libraries :as cll]
|
|
[app.common.logic.shapes :as cls]
|
|
[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]
|
|
[app.common.types.components-list :as ctkl]
|
|
[app.common.types.file :as ctf]
|
|
[app.common.types.shape-tree :as ctst]
|
|
[app.common.uuid :as uuid]
|
|
[clojure.test :as t]))
|
|
|
|
(t/use-fixtures :each thi/test-fixture)
|
|
|
|
(t/deftest test-add-component-from-single-frame
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(ths/add-sample-shape :frame1 :type :frame))
|
|
|
|
page (thf/current-page file)
|
|
frame1 (ths/get-shape file :frame1)
|
|
|
|
;; ==== Action
|
|
[_ component-id changes]
|
|
(cll/generate-add-component (pcb/empty-changes)
|
|
[frame1]
|
|
(:objects page)
|
|
(:id page)
|
|
(:id file)
|
|
nil)
|
|
|
|
file' (thf/apply-changes file changes)
|
|
|
|
;; ==== Get
|
|
component (thc/get-component-by-id file' component-id)
|
|
root (ths/get-shape-by-id file' (:main-instance-id component))
|
|
frame1' (ths/get-shape file' :frame1)]
|
|
|
|
;; ==== Check
|
|
(t/is (some? component))
|
|
(t/is (some? root))
|
|
(t/is (some? frame1'))
|
|
(t/is (= (:id root) (:id frame1')))
|
|
(t/is (ctk/main-instance? root))
|
|
(t/is (ctk/main-instance-of? (:id root) (:id page) component))))
|
|
|
|
(t/deftest test-add-component-from-single-shape
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(ths/add-sample-shape :shape1 :type :rect))
|
|
|
|
page (thf/current-page file)
|
|
shape1 (ths/get-shape file :shape1)
|
|
|
|
;; ==== Action
|
|
[_ component-id changes]
|
|
(cll/generate-add-component (pcb/empty-changes)
|
|
[shape1]
|
|
(:objects page)
|
|
(:id page)
|
|
(:id file)
|
|
cfsh/prepare-create-artboard-from-selection)
|
|
|
|
file' (thf/apply-changes file changes)
|
|
|
|
;; ==== Get
|
|
component (thc/get-component-by-id file' component-id)
|
|
root (ths/get-shape-by-id file' (:main-instance-id component))
|
|
shape1' (ths/get-shape file' :shape1)]
|
|
|
|
;; ==== Check
|
|
(t/is (some? component))
|
|
(t/is (some? root))
|
|
(t/is (some? shape1'))
|
|
(t/is (ctst/parent-of? root shape1'))
|
|
(t/is (= (:type root) :frame))
|
|
(t/is (ctk/main-instance? root))
|
|
(t/is (ctk/main-instance-of? (:id root) (:id page) component))))
|
|
|
|
(t/deftest test-add-component-from-several-shapes
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(ths/add-sample-shape :shape1 :type :rect)
|
|
(ths/add-sample-shape :shape2 :type :rect))
|
|
|
|
page (thf/current-page file)
|
|
shape1 (ths/get-shape file :shape1)
|
|
shape2 (ths/get-shape file :shape2)
|
|
|
|
;; ==== Action
|
|
[_ component-id changes]
|
|
(cll/generate-add-component (pcb/empty-changes)
|
|
[shape1 shape2]
|
|
(:objects page)
|
|
(:id page)
|
|
(:id file)
|
|
cfsh/prepare-create-artboard-from-selection)
|
|
|
|
file' (thf/apply-changes file changes)
|
|
|
|
;; ==== Get
|
|
component (thc/get-component-by-id file' component-id)
|
|
root (ths/get-shape-by-id file' (:main-instance-id component))
|
|
shape1' (ths/get-shape file' :shape1)
|
|
shape2' (ths/get-shape file' :shape2)]
|
|
|
|
;; ==== Check
|
|
(t/is (some? component))
|
|
(t/is (some? root))
|
|
(t/is (some? shape1'))
|
|
(t/is (some? shape2'))
|
|
(t/is (ctst/parent-of? root shape1'))
|
|
(t/is (ctst/parent-of? root shape2'))
|
|
(t/is (= (:type root) :frame))
|
|
(t/is (ctk/main-instance? root))
|
|
(t/is (ctk/main-instance-of? (:id root) (:id page) component))))
|
|
|
|
(t/deftest test-add-component-from-several-frames
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(ths/add-sample-shape :frame1 :type :frame)
|
|
(ths/add-sample-shape :frame2 :type :frame))
|
|
|
|
page (thf/current-page file)
|
|
frame1 (ths/get-shape file :frame1)
|
|
frame2 (ths/get-shape file :frame2)
|
|
|
|
;; ==== Action
|
|
[_ component-id changes]
|
|
(cll/generate-add-component (pcb/empty-changes)
|
|
[frame1 frame2]
|
|
(:objects page)
|
|
(:id page)
|
|
(:id file)
|
|
cfsh/prepare-create-artboard-from-selection)
|
|
|
|
file' (thf/apply-changes file changes)
|
|
|
|
;; ==== Get
|
|
component (thc/get-component-by-id file' component-id)
|
|
root (ths/get-shape-by-id file' (:main-instance-id component))
|
|
frame1' (ths/get-shape file' :frame1)
|
|
frame2' (ths/get-shape file' :frame2)]
|
|
|
|
;; ==== Check
|
|
(t/is (some? component))
|
|
(t/is (some? root))
|
|
(t/is (some? frame1'))
|
|
(t/is (some? frame2'))
|
|
(t/is (ctst/parent-of? root frame1'))
|
|
(t/is (ctst/parent-of? root frame2'))
|
|
(t/is (= (:type root) :frame))
|
|
(t/is (ctk/main-instance? root))
|
|
(t/is (ctk/main-instance-of? (:id root) (:id page) component))))
|
|
|
|
(t/deftest test-add-component-from-frame-with-children
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(ths/add-sample-shape :frame1 :type :frame)
|
|
(ths/add-sample-shape :shape1 :type :rect :parent-label :frame1)
|
|
(ths/add-sample-shape :shape2 :type :rect :parent-label :frame1))
|
|
|
|
page (thf/current-page file)
|
|
frame1 (ths/get-shape file :frame1)
|
|
|
|
;; ==== Action
|
|
[_ component-id changes]
|
|
(cll/generate-add-component (pcb/empty-changes)
|
|
[frame1]
|
|
(:objects page)
|
|
(:id page)
|
|
(:id file)
|
|
nil)
|
|
|
|
file' (thf/apply-changes file changes)
|
|
|
|
;; ==== Get
|
|
component (thc/get-component-by-id file' component-id)
|
|
root (ths/get-shape-by-id file' (:main-instance-id component))
|
|
frame1' (ths/get-shape file' :frame1)
|
|
shape1' (ths/get-shape file' :shape1)
|
|
shape2' (ths/get-shape file' :shape2)]
|
|
|
|
;; ==== Check
|
|
(t/is (some? component))
|
|
(t/is (some? root))
|
|
(t/is (some? frame1'))
|
|
(t/is (= (:id root) (:id frame1')))
|
|
(t/is (ctst/parent-of? frame1' shape1'))
|
|
(t/is (ctst/parent-of? frame1' shape2'))
|
|
(t/is (ctk/main-instance? root))
|
|
(t/is (ctk/main-instance-of? (:id root) (:id page) component))))
|
|
|
|
(t/deftest test-add-component-from-copy
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(tho/add-simple-component-with-copy :component1
|
|
:main1-root
|
|
:main1-child
|
|
:copy1-root))
|
|
|
|
page (thf/current-page file)
|
|
copy1-root (ths/get-shape file :copy1-root)
|
|
|
|
;; ==== Action
|
|
[_ component2-id changes]
|
|
(cll/generate-add-component (pcb/empty-changes)
|
|
[copy1-root]
|
|
(:objects page)
|
|
(:id page)
|
|
(:id file)
|
|
cfsh/prepare-create-artboard-from-selection)
|
|
|
|
file' (thf/apply-changes file changes)
|
|
|
|
;; ==== Get
|
|
component2' (thc/get-component-by-id file' component2-id)
|
|
root2' (ths/get-shape-by-id file' (:main-instance-id component2'))
|
|
copy1-root' (ths/get-shape file' :copy1-root)]
|
|
|
|
;; ==== Check
|
|
(t/is (some? component2'))
|
|
(t/is (some? root2'))
|
|
(t/is (some? copy1-root'))
|
|
(t/is (ctst/parent-of? root2' copy1-root'))
|
|
(t/is (ctk/main-instance? root2'))
|
|
(t/is (ctk/main-instance-of? (:id root2') (:id page) component2'))))
|
|
|
|
(t/deftest test-rename-component
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(tho/add-simple-component :component1
|
|
:main1-root
|
|
:main1-child
|
|
:name "Test component before"))
|
|
|
|
component (thc/get-component file :component1)
|
|
|
|
;; ==== Action
|
|
changes (-> (pcb/empty-changes nil (thf/current-page-id file))
|
|
(pcb/with-file-data (ctf/file-data file))
|
|
(cll/generate-rename-component
|
|
(:id component)
|
|
"Test component after"
|
|
(:data file))
|
|
(pcb/update-shapes
|
|
[(thi/id :main1-root)]
|
|
#(assoc % :name "Test component after")))
|
|
|
|
file' (thf/apply-changes file changes)
|
|
|
|
;; ==== Get
|
|
component' (thc/get-component file' :component1)
|
|
main1-root' (ths/get-shape file' :main1-root)]
|
|
|
|
;; ==== Check
|
|
(t/is (= (:name component') "Test component after"))
|
|
(t/is (= (:name main1-root') "Test component after"))))
|
|
|
|
(t/deftest test-duplicate-component
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(tho/add-simple-component :component1
|
|
:main1-root
|
|
:main1-child))
|
|
|
|
component (thc/get-component file :component1)
|
|
|
|
;; ==== Action
|
|
[_ changes]
|
|
(cll/generate-duplicate-component (pcb/empty-changes)
|
|
file
|
|
(:id component)
|
|
(uuid/next)
|
|
true)
|
|
|
|
file' (thf/apply-changes file changes)
|
|
|
|
;; ==== Get
|
|
components' (ctkl/components-seq (:data file'))
|
|
component1' (d/seek #(= (:id %) (thi/id :component1)) components')
|
|
component2' (d/seek #(not= (:id %) (thi/id :component1)) components')
|
|
root1' (ths/get-shape-by-id file' (:main-instance-id component1'))
|
|
root2' (ths/get-shape-by-id file' (:main-instance-id component2'))
|
|
child1' (ths/get-shape-by-id file' (first (:shapes root1')))
|
|
child2' (ths/get-shape-by-id file' (first (:shapes root2')))]
|
|
|
|
;; ==== Check
|
|
(t/is (= 2 (count components')))
|
|
(t/is (some? component1'))
|
|
(t/is (some? component2'))
|
|
(t/is (some? root1'))
|
|
(t/is (some? root2'))
|
|
(t/is (= (thi/id :main1-root) (:id root1')))
|
|
(t/is (not= (thi/id :main1-root) (:id root2')))
|
|
(t/is (some? child1'))
|
|
(t/is (some? child2'))
|
|
(t/is (= (thi/id :main1-child) (:id child1')))
|
|
(t/is (not= (thi/id :main1-child) (:id child2')))))
|
|
|
|
(t/deftest test-duplicate-component-rewrites-component-file-to-destination
|
|
;; Regression test for Issue #8144. When a component is duplicated
|
|
;; into a different file via `:apply-changes-local-library? true`
|
|
;; and `:new-component-file` is provided, the returned main-instance
|
|
;; shape must carry `:component-file` equal to the destination file
|
|
;; id so the referential-integrity validator
|
|
;; (:component-main-external) is satisfied.
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(tho/add-simple-component :component1
|
|
:main1-root
|
|
:main1-child))
|
|
|
|
component (thc/get-component file :component1)
|
|
new-component-file (uuid/next)
|
|
|
|
;; ==== Action
|
|
[new-shape _]
|
|
(cll/generate-duplicate-component (pcb/empty-changes)
|
|
file
|
|
(:id component)
|
|
(uuid/next)
|
|
{:apply-changes-local-library? true
|
|
:new-component-file new-component-file})]
|
|
|
|
;; ==== Check
|
|
(t/is (some? new-shape))
|
|
(t/is (ctk/main-instance? new-shape))
|
|
(t/is (= new-component-file (:component-file new-shape)))))
|
|
|
|
(t/deftest test-duplicate-component-keeps-component-file-without-dest
|
|
;; Baseline: when no `:new-component-file` is passed (same-file
|
|
;; duplication), the main-instance's `:component-file` is left
|
|
;; untouched, matching pre-existing behavior.
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(tho/add-simple-component :component1
|
|
:main1-root
|
|
:main1-child))
|
|
|
|
component (thc/get-component file :component1)
|
|
original-source (:component-file
|
|
(ths/get-shape-by-id file (:main-instance-id component)))
|
|
|
|
;; ==== Action
|
|
[new-shape _]
|
|
(cll/generate-duplicate-component (pcb/empty-changes)
|
|
file
|
|
(:id component)
|
|
(uuid/next)
|
|
{:apply-changes-local-library? true})]
|
|
|
|
;; ==== Check
|
|
(t/is (some? new-shape))
|
|
(t/is (= original-source (:component-file new-shape)))))
|
|
|
|
(t/deftest test-delete-component
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(tho/add-simple-component-with-copy :component1
|
|
:main1-root
|
|
:main1-child
|
|
:copy1-root))
|
|
|
|
page (thf/current-page file)
|
|
root (ths/get-shape file :main1-root)
|
|
|
|
;; ==== Action
|
|
[_ changes]
|
|
(cls/generate-delete-shapes (pcb/empty-changes)
|
|
file
|
|
page
|
|
(:objects page)
|
|
#{(:id root)}
|
|
{:components-v2 true})
|
|
|
|
file' (thf/apply-changes file changes)
|
|
|
|
;; ==== Get
|
|
component1' (thc/get-component file' :component1 :include-deleted? true)
|
|
copy1-root' (ths/get-shape file' :copy1-root)
|
|
|
|
main1-root' (ths/get-shape file' :main1-root)
|
|
main1-child' (ths/get-shape file' :main1-child)
|
|
|
|
saved-objects (:objects component1')
|
|
saved-main1-root' (get saved-objects (thi/id :main1-root))
|
|
saved-main1-child' (get saved-objects (thi/id :main1-child))]
|
|
|
|
;; ==== Check
|
|
(t/is (true? (:deleted component1')))
|
|
(t/is (some? copy1-root'))
|
|
(t/is (nil? main1-root'))
|
|
(t/is (nil? main1-child'))
|
|
(t/is (some? saved-main1-root'))
|
|
(t/is (some? saved-main1-child'))))
|
|
|
|
(t/deftest test-restore-component
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(tho/add-simple-component-with-copy :component1
|
|
:main1-root
|
|
:main1-child
|
|
:copy1-root))
|
|
|
|
page (thf/current-page file)
|
|
root (ths/get-shape file :main1-root)
|
|
|
|
;; ==== Action
|
|
[_ changes]
|
|
(cls/generate-delete-shapes (pcb/empty-changes)
|
|
file
|
|
page
|
|
(:objects page)
|
|
#{(:id root)}
|
|
{:components-v2 true})
|
|
|
|
file-deleted (thf/apply-changes file changes)
|
|
page-deleted (thf/current-page file-deleted)
|
|
|
|
changes (cll/generate-restore-component (pcb/empty-changes)
|
|
(:data file-deleted)
|
|
(thi/id :component1)
|
|
(:id file-deleted)
|
|
page-deleted
|
|
(:objects page-deleted))
|
|
|
|
file' (thf/apply-changes file changes)
|
|
|
|
;; ==== Get
|
|
component1' (thc/get-component file' :component1 :include-deleted? false)
|
|
copy1-root' (ths/get-shape file' :copy1-root)
|
|
|
|
main1-root' (ths/get-shape file' :main1-root)
|
|
main1-child' (ths/get-shape file' :main1-child)
|
|
|
|
saved-objects' (:objects component1')]
|
|
|
|
;; ==== Check
|
|
(t/is (nil? (:deleted component1')))
|
|
(t/is (some? copy1-root'))
|
|
(t/is (some? main1-root'))
|
|
(t/is (some? main1-child'))
|
|
(t/is (ctk/main-instance? main1-root'))
|
|
(t/is (ctk/main-instance-of? (:id main1-root') (:id page) component1'))
|
|
(t/is (nil? saved-objects'))))
|
|
|
|
(t/deftest test-instantiate-component
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(tho/add-simple-component :component1
|
|
:main1-root
|
|
:main1-child))
|
|
|
|
page (thf/current-page file)
|
|
component (thc/get-component file :component1)
|
|
|
|
;; ==== Action
|
|
[new-shape changes]
|
|
(cll/generate-instantiate-component (-> (pcb/empty-changes nil (:id page)) ;; This may not be moved to generate
|
|
(pcb/with-objects (:objects page))) ;; because in some cases the objects
|
|
(:objects page) ;; not the same as those on the page
|
|
(:id file)
|
|
(:id component)
|
|
(gpt/point 1000 1000)
|
|
page
|
|
{(:id file) file})
|
|
|
|
file' (thf/apply-changes file changes)
|
|
|
|
;; ==== Get
|
|
component' (thc/get-component file' :component1)
|
|
main1-root' (ths/get-shape file' :main1-root)
|
|
main1-child' (ths/get-shape file' :main1-child)
|
|
copy1-root' (ths/get-shape-by-id file' (:id new-shape))
|
|
copy1-child' (ths/get-shape-by-id file' (first (:shapes copy1-root')))]
|
|
|
|
;; ==== Check
|
|
(t/is (some? main1-root'))
|
|
(t/is (some? main1-child'))
|
|
(t/is (some? copy1-root'))
|
|
(t/is (some? copy1-child'))
|
|
(t/is (ctk/instance-root? copy1-root'))
|
|
(t/is (ctk/instance-of? copy1-root' (:id file') (:id component')))
|
|
(t/is (ctk/is-main-of? main1-root' copy1-root'))
|
|
(t/is (ctk/is-main-of? main1-child' copy1-child'))
|
|
(t/is (ctst/parent-of? copy1-root' copy1-child'))))
|
|
|
|
(t/deftest test-instantiate-component-from-lib
|
|
(let [;; ==== Setup
|
|
library (-> (thf/sample-file :library1)
|
|
(tho/add-simple-component :component1
|
|
:main1-root
|
|
:main1-child))
|
|
|
|
file (thf/sample-file :file1)
|
|
|
|
page (thf/current-page file)
|
|
component (thc/get-component library :component1)
|
|
|
|
;; ==== Action
|
|
[new-shape changes]
|
|
(cll/generate-instantiate-component (-> (pcb/empty-changes nil (:id page))
|
|
(pcb/with-objects (:objects page)))
|
|
(:objects page)
|
|
(:id library)
|
|
(:id component)
|
|
(gpt/point 1000 1000)
|
|
page
|
|
{(:id file) file
|
|
(:id library) library})
|
|
|
|
file' (thf/apply-changes file changes)
|
|
|
|
;; ==== Get
|
|
component' (thc/get-component library :component1)
|
|
main1-root' (ths/get-shape library :main1-root)
|
|
main1-child' (ths/get-shape library :main1-child)
|
|
copy1-root' (ths/get-shape-by-id file' (:id new-shape))
|
|
copy1-child' (ths/get-shape-by-id file' (first (:shapes copy1-root')))]
|
|
|
|
;; ==== Check
|
|
(t/is (some? main1-root'))
|
|
(t/is (some? main1-child'))
|
|
(t/is (some? copy1-root'))
|
|
(t/is (some? copy1-child'))
|
|
(t/is (ctk/instance-root? copy1-root'))
|
|
(t/is (ctk/instance-of? copy1-root' (:id library) (:id component')))
|
|
(t/is (ctk/is-main-of? main1-root' copy1-root'))
|
|
(t/is (ctk/is-main-of? main1-child' copy1-child'))
|
|
(t/is (ctst/parent-of? copy1-root' copy1-child'))))
|
|
|
|
(t/deftest test-instantiate-nested-component
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(tho/add-nested-component :component1
|
|
:main1-root
|
|
:main1-child
|
|
:component2
|
|
:main2-root
|
|
:main2-nested-head))
|
|
|
|
page (thf/current-page file)
|
|
component (thc/get-component file :component1)
|
|
|
|
;; ==== Action
|
|
[new-shape changes]
|
|
(cll/generate-instantiate-component (-> (pcb/empty-changes nil (:id page))
|
|
(pcb/with-objects (:objects page)))
|
|
(:objects page)
|
|
(:id file)
|
|
(:id component)
|
|
(gpt/point 1000 1000)
|
|
page
|
|
{(:id file) file})
|
|
|
|
file' (thf/apply-changes file changes)
|
|
|
|
;; ==== Get
|
|
component' (thc/get-component file' :component1)
|
|
main1-root' (ths/get-shape file' :main1-root)
|
|
main1-child' (ths/get-shape file' :main1-child)
|
|
copy1-root' (ths/get-shape-by-id file' (:id new-shape))
|
|
copy1-child' (ths/get-shape-by-id file' (first (:shapes copy1-root')))]
|
|
|
|
;; ==== Check
|
|
(t/is (some? main1-root'))
|
|
(t/is (some? main1-child'))
|
|
(t/is (some? copy1-root'))
|
|
(t/is (some? copy1-child'))
|
|
(t/is (ctk/instance-root? copy1-root'))
|
|
(t/is (ctk/instance-of? copy1-root' (:id file') (:id component')))
|
|
(t/is (ctk/is-main-of? main1-root' copy1-root'))
|
|
(t/is (ctk/is-main-of? main1-child' copy1-child'))
|
|
(t/is (ctst/parent-of? copy1-root' copy1-child'))))
|
|
|
|
(t/deftest test-instantiate-nested-component-from-lib
|
|
(let [;; ==== Setup
|
|
library (-> (thf/sample-file :file1)
|
|
(tho/add-nested-component :component1
|
|
:main1-root
|
|
:main1-child
|
|
:component2
|
|
:main2-root
|
|
:main2-nested-head))
|
|
|
|
file (thf/sample-file :file1)
|
|
|
|
page (thf/current-page file)
|
|
component (thc/get-component library :component1)
|
|
|
|
;; ==== Action
|
|
[new-shape changes]
|
|
(cll/generate-instantiate-component (-> (pcb/empty-changes nil (:id page))
|
|
(pcb/with-objects (:objects page)))
|
|
(:objects page)
|
|
(:id library)
|
|
(:id component)
|
|
(gpt/point 1000 1000)
|
|
page
|
|
{(:id file) file
|
|
(:id library) library})
|
|
|
|
file' (thf/apply-changes file changes)
|
|
|
|
;; ==== Get
|
|
component' (thc/get-component library :component1)
|
|
main1-root' (ths/get-shape library :main1-root)
|
|
main1-child' (ths/get-shape library :main1-child)
|
|
copy1-root' (ths/get-shape-by-id file' (:id new-shape))
|
|
copy1-child' (ths/get-shape-by-id file' (first (:shapes copy1-root')))]
|
|
|
|
;; ==== Check
|
|
(t/is (some? main1-root'))
|
|
(t/is (some? main1-child'))
|
|
(t/is (some? copy1-root'))
|
|
(t/is (some? copy1-child'))
|
|
(t/is (ctk/instance-root? copy1-root'))
|
|
(t/is (ctk/instance-of? copy1-root' (:id library) (:id component')))
|
|
(t/is (ctk/is-main-of? main1-root' copy1-root'))
|
|
(t/is (ctk/is-main-of? main1-child' copy1-child'))
|
|
(t/is (ctst/parent-of? copy1-root' copy1-child'))))
|
|
|
|
(t/deftest test-detach-copy
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(tho/add-simple-component-with-copy :component1
|
|
:main1-root
|
|
:main1-child
|
|
:copy1-root))
|
|
|
|
page (thf/current-page file)
|
|
copy1-root (ths/get-shape file :copy1-root)
|
|
|
|
;; ==== Action
|
|
changes (cll/generate-detach-component (pcb/empty-changes)
|
|
(:id copy1-root)
|
|
(:data file)
|
|
(:id page)
|
|
{(:id file) file})
|
|
|
|
file' (thf/apply-changes file changes)
|
|
|
|
;; ==== Get
|
|
copy1-root' (ths/get-shape file' :copy1-root)]
|
|
|
|
;; ==== Check
|
|
(t/is (some? copy1-root'))
|
|
(t/is (not (ctk/instance-head? copy1-root')))
|
|
(t/is (not (ctk/in-component-copy? copy1-root')))))
|