From 418a060ce401b62b1d4c92f9792e90f635d005e1 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 23 Oct 2026 09:23:09 +0200 Subject: [PATCH] :bug: Find the user duplicate after component propagation Duplicating a nested copy in a main also adds subtrees to that main's copies. The frontend result lookup counted all of them and threw instead of returning the user's duplicate. Exclude roots inside component copies. The regression checks the lookup after the sync cascade creates three subtrees. Focused common suites pass: 66 tests, 11263 assertions. AI-assisted-by: GPT-6 --- .../common/test_helpers/composable/comp/nodes.cljc | 8 +++++--- .../common_tests/logic/composable_runner_test.cljc | 13 +++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/common/src/app/common/test_helpers/composable/comp/nodes.cljc b/common/src/app/common/test_helpers/composable/comp/nodes.cljc index b0c5258015..b0dd95b813 100644 --- a/common/src/app/common/test_helpers/composable/comp/nodes.cljc +++ b/common/src/app/common/test_helpers/composable/comp/nodes.cljc @@ -965,13 +965,15 @@ (defn- new-subtree-head "The id of the shape in `page-after` that is not in `page-before` but whose - parent is: the head of the one subtree added between them. Throws when - there is not exactly one, as when the sync also added children to copies." + parent is, outside component copies. Sync can add matching subtrees in + copies too; only the user's new subtree identifies the duplicate." [page-before page-after] (let [before (:objects page-before) heads (->> (vals (:objects page-after)) (filter #(and (not (contains? before (:id %))) - (contains? before (:parent-id %)))) + (contains? before (:parent-id %)) + (empty? (ctn/get-parent-copy-heads (:objects page-after) + (get-in page-after [:objects (:parent-id %)]))))) (map :id))] (when-not (= 1 (count heads)) (throw (ex-info (str "Expected one new subtree, found " (count heads)) diff --git a/common/test/common_tests/logic/composable_runner_test.cljc b/common/test/common_tests/logic/composable_runner_test.cljc index 0a9d447014..f035c58420 100644 --- a/common/test/common_tests/logic/composable_runner_test.cljc +++ b/common/test/common_tests/logic/composable_runner_test.cljc @@ -569,3 +569,16 @@ (t/is false) (reset! counted @made)))) (t/is (= 2 @counted)))) + +(t/deftest duplicate-result-finds-the-user-subtree-after-propagation + (let [before (r/run-variant + {:setup setup/empty-situation + :operation (tm/in-sequence [(n/create-component "a" original :size 100) + (n/make-nested-component "a" 1) + (n/instantiate-copy "a") + (n/instantiate-copy "a")])}) + duplicate (n/duplicate (n/nested-head-of "a" 0)) + after (r/settle (r/step before duplicate)) + result (n/applied-result duplicate (tm/file before) (tm/file after)) + new-head (tm/shape-by-id after (:new-head result))] + (t/is (= ((n/main-head-of "a") before) (:parent-id new-head)))))