From b136097e183d91e6fee5ad3c9a67c6f94591c7b9 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Thu, 1 Oct 2026 12:12:21 +0200 Subject: [PATCH] :bug: Validate the enclosing root when instantiating a nested copy generate-instantiate-component validated the new copy on its own. When the copy is created inside another component it is a nested copy, but the validator starts with a :not-component context and reported :nested-copy-not-allowed, a false error that broke 34 common tests on JS. When the new copy is not an instance root, validate the instance roots that hold its parent instead. The validator then walks the copy with the right context, and also checks the parents that may change (e.g. layouts). AI-assisted-by: claude-opus-5-5 --- common/src/app/common/logic/libraries.cljc | 12 ++++-- .../logic/comp_creation_test.cljc | 38 ++++++++++++++++++- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/common/src/app/common/logic/libraries.cljc b/common/src/app/common/logic/libraries.cljc index b4d01e7a0d..de45c2efad 100644 --- a/common/src/app/common/logic/libraries.cljc +++ b/common/src/app/common/logic/libraries.cljc @@ -322,9 +322,15 @@ changes (rest new-shapes)) - ids-to-validate (cond-> [(:id first-shape)] - grid-parent? - (conj (:parent-id first-shape))) + ;; A copy nested inside another component can't be validated on + ;; its own, as the validator needs the context of its ancestors. + ;; Validate the root of the enclosing instance instead, which also + ;; checks the parents that may change (e.g. layouts) + ids-to-validate (if (ctk/instance-root? first-shape) + (cond-> [(:id first-shape)] + grid-parent? + (conj (:parent-id first-shape))) + (ctn/get-all-instance-roots objects [(:parent-id first-shape)])) changes (if (seq ids-to-validate) (pcb/validate-shapes changes diff --git a/common/test/common_tests/logic/comp_creation_test.cljc b/common/test/common_tests/logic/comp_creation_test.cljc index 7cd5acc67c..3c80dccec9 100644 --- a/common/test/common_tests/logic/comp_creation_test.cljc +++ b/common/test/common_tests/logic/comp_creation_test.cljc @@ -501,7 +501,43 @@ (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/is (ctst/parent-of? copy1-root' copy1-child')) + (t/is (thf/validates-shapes-last? changes (:id page) [(:id new-shape)])))) + +(t/deftest test-instantiate-component-inside-main-validates-root + ;; A copy nested in a main can't be validated on its own: the root of the + ;; main is validated instead + (let [;; ==== Setup + file (-> (thf/sample-file :file1) + (tho/add-simple-component :component1 :main1-root :main1-child) + (tho/add-simple-component :component2 :main2-root :main2-child)) + + page (thf/current-page file) + component (thc/get-component file :component1) + main2-id (thi/id :main2-root) + + ;; ==== 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} + nil + main2-id + main2-id + {}) + + file' (thf/apply-changes file changes) + copy1' (ths/get-shape-by-id file' (:id new-shape))] + + ;; ==== Check + (t/is (= main2-id (:parent-id copy1'))) + (t/is (not (ctk/instance-root? copy1'))) + (t/is (thf/validates-shapes-last? changes (:id page) [main2-id])))) (t/deftest test-instantiate-component-from-lib (let [;; ==== Setup