From d2212414511090c14620c85c857342318f78bf9c Mon Sep 17 00:00:00 2001 From: Pablo Alba <pablo.alba@kaleidos.net> Date: Mon, 13 May 2024 18:02:21 +0200 Subject: [PATCH] :white_check_mark: Components refactor: Add tests for remove swap slot on copy-paste --- .../frontend_tests/basic_shapes_test.cljs | 2 - .../test/frontend_tests/helpers/pages.cljs | 85 ++ .../test/frontend_tests/helpers/state.cljs | 5 + .../logic/comp_remove_swap_slots_test.cljs | 815 ++++++++++++++++++ 4 files changed, 905 insertions(+), 2 deletions(-) create mode 100644 frontend/test/frontend_tests/logic/comp_remove_swap_slots_test.cljs diff --git a/frontend/test/frontend_tests/basic_shapes_test.cljs b/frontend/test/frontend_tests/basic_shapes_test.cljs index 7f3188620..9204ab29a 100644 --- a/frontend/test/frontend_tests/basic_shapes_test.cljs +++ b/frontend/test/frontend_tests/basic_shapes_test.cljs @@ -40,8 +40,6 @@ fills' (:fills shape1') fill' (first fills')] - (cthf/dump-shape shape1') - ;; ==== Check (t/is (some? shape1')) (t/is (= (count fills') 1)) diff --git a/frontend/test/frontend_tests/helpers/pages.cljs b/frontend/test/frontend_tests/helpers/pages.cljs index 939d06a07..74ad1c9f9 100644 --- a/frontend/test/frontend_tests/helpers/pages.cljs +++ b/frontend/test/frontend_tests/helpers/pages.cljs @@ -6,13 +6,19 @@ (ns frontend-tests.helpers.pages (:require + [app.common.data :as d] [app.common.files.changes :as cp] [app.common.files.changes-builder :as pcb] [app.common.files.helpers :as cfh] [app.common.files.shapes-helpers :as cfsh] [app.common.geom.point :as gpt] + [app.common.geom.shapes :as gsh] [app.common.logic.libraries :as cll] + [app.common.types.component :as ctk] + [app.common.types.container :as ctn] + [app.common.types.file :as ctf] [app.common.types.shape :as cts] + [app.common.types.shape-tree :as ctst] [app.common.uuid :as uuid] [app.main.data.workspace.groups :as dwg] [app.main.data.workspace.layout :as layout] @@ -186,3 +192,82 @@ :components (:components data)}}) (update :workspace-data assoc :components {} :pages [] :pages-index {})))) + + +(defn simulate-copy-shape + [selected objects libraries page file features version] + (letfn [(sort-selected [data] + (let [;; Narrow the objects map so it contains only relevant data for + ;; selected and its parents + objects (cfh/selected-subtree objects selected) + selected (->> (ctst/sort-z-index objects selected) + (reverse) + (into (d/ordered-set)))] + + (assoc data :selected selected))) + + ;; Prepare the shape object. + (prepare-object [objects parent-frame-id obj] + (maybe-translate obj objects parent-frame-id)) + + ;; Collects all the items together and split images into a + ;; separated data structure for a more easy paste process. + (collect-data [result {:keys [id ::images] :as item}] + (cond-> result + :always + (update :objects assoc id (dissoc item ::images)) + + (some? images) + (update :images into images))) + + (maybe-translate [shape objects parent-frame-id] + (if (= parent-frame-id uuid/zero) + shape + (let [frame (get objects parent-frame-id)] + (gsh/translate-to-frame shape frame)))) + + ;; When copying an instance that is nested inside another one, we need to + ;; advance the shape refs to one or more levels of remote mains. + (advance-copies [data] + (let [heads (mapcat #(ctn/get-child-heads (:objects data) %) selected)] + (update data :objects + #(reduce (partial advance-copy file libraries page) + % + heads)))) + + (advance-copy [file libraries page objects shape] + (if (and (ctk/instance-head? shape) (not (ctk/main-instance? shape))) + (let [level-delta (ctn/get-nesting-level-delta (:objects page) shape uuid/zero)] + (if (pos? level-delta) + (reduce (partial advance-shape file libraries page level-delta) + objects + (cfh/get-children-with-self objects (:id shape))) + objects)) + objects)) + + (advance-shape [file libraries page level-delta objects shape] + (let [new-shape-ref (ctf/advance-shape-ref file page libraries shape level-delta {:include-deleted? true})] + (cond-> objects + (and (some? new-shape-ref) (not= new-shape-ref (:shape-ref shape))) + (assoc-in [(:id shape) :shape-ref] new-shape-ref))))] + + (let [file-id (:id file) + frame-id (cfh/common-parent-frame objects selected) + + initial {:type :copied-shapes + :features features + :version version + :file-id file-id + :selected selected + :objects {} + :images #{} + :in-viewport false} + + shapes (->> (cfh/selected-with-children objects selected) + (keep (d/getf objects)))] + + (->> shapes + (map (partial prepare-object objects frame-id)) + (reduce collect-data initial) + sort-selected + advance-copies)))) diff --git a/frontend/test/frontend_tests/helpers/state.cljs b/frontend/test/frontend_tests/helpers/state.cljs index 3b5fd501f..6c3c7cb2c 100644 --- a/frontend/test/frontend_tests/helpers/state.cljs +++ b/frontend/test/frontend_tests/helpers/state.cljs @@ -54,3 +54,8 @@ (doall (for [event events] (ptk/emit! store event))) (ptk/emit! store :the/end))) + +(defn get-file-from-store + [store] + (-> (:workspace-file store) + (assoc :data (:workspace-data store)))) diff --git a/frontend/test/frontend_tests/logic/comp_remove_swap_slots_test.cljs b/frontend/test/frontend_tests/logic/comp_remove_swap_slots_test.cljs new file mode 100644 index 000000000..87ec95532 --- /dev/null +++ b/frontend/test/frontend_tests/logic/comp_remove_swap_slots_test.cljs @@ -0,0 +1,815 @@ +;; 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 frontend-tests.logic.comp-remove-swap-slots-test + (:require + [app.common.test-helpers.components :as cthc] + [app.common.test-helpers.compositions :as ctho] + [app.common.test-helpers.files :as cthf] + [app.common.test-helpers.ids-map :as cthi] + [app.common.test-helpers.shapes :as cths] + [app.common.types.component :as ctk] + [app.common.uuid :as uuid] + [app.main.data.workspace :as dw] + [app.main.data.workspace.selection :as dws] + [cljs.test :as t :include-macros true] + [cuerdas.core :as str] + [frontend-tests.helpers.pages :as thp] + [frontend-tests.helpers.state :as ths])) + +;; Related .penpot file: common/test/cases/remove-swap-slots.penpot +(defn- setup-file + [] + ;; {:frame-red} [:name Frame1] # [Component :red] + ;; {:frame-blue} [:name Frame1] # [Component :blue] + ;; {:frame-green} [:name Frame1] # [Component :green] + ;; :red-copy-green [:name Frame1] @--> :frame-red + ;; {:frame-b1} [:name Frame1] # [Component :b1] + ;; :blue1 [:name Frame1, :swap-slot-label :red-copy] @--> :frame-blue + ;; :frame-yellow [:name Frame1] + ;; :green-copy [:name Frame1] @--> :frame-green + ;; :blue-copy-in-green-copy [:name Frame1, :swap-slot-label :red-copy-green] @--> :frame-blue + ;; {:frame-b2} [:name Frame1] # [Component :b2] + (-> (cthf/sample-file :file1) + (ctho/add-frame :frame-red) + (cthc/make-component :red :frame-red) + (ctho/add-frame :frame-blue :name "frame-blue") + (cthc/make-component :blue :frame-blue) + (ctho/add-frame :frame-green :name "frame-green") + (cthc/make-component :green :frame-green) + (cthc/instantiate-component :red :red-copy-green :parent-label :frame-green) + (ctho/add-frame :frame-b1) + (cthc/make-component :b1 :frame-b1) + (ctho/add-frame :frame-yellow :parent-label :frame-b1 :name "frame-yellow") + (cthc/instantiate-component :red :red-copy :parent-label :frame-b1) + (cthc/component-swap :red-copy :blue :blue1) + (cthc/instantiate-component :green :green-copy :parent-label :frame-b1 :children-labels [:red-copy-in-green-copy]) + (cthc/component-swap :red-copy-in-green-copy :blue :blue-copy-in-green-copy) + (ctho/add-frame :frame-b2) + (cthc/make-component :b2 :frame-b2))) + + +(defn- setup-file-blue1-in-yellow + [] + ;; {:frame-red} [:name Frame1] # [Component :red] + ;; {:frame-blue} [:name Frame1] # [Component :blue] + ;; {:frame-green} [:name Frame1] # [Component :green] + ;; :red-copy-green [:name Frame1] @--> :frame-red + ;; {:frame-b1} [:name Frame1] # [Component :b1] + ;; :frame-yellow [:name Frame1] + ;; :blue1 [:name Frame1, :swap-slot-label :red-copy] @--> :frame-blue + ;; :green-copy [:name Frame1] @--> :frame-green + ;; :blue-copy-in-green-copy [:name Frame1, :swap-slot-label :red-copy-green] @--> :frame-blue + ;; {:frame-b2} [:name Frame1] # [Component :b2] + (-> (cthf/sample-file :file1) + (ctho/add-frame :frame-red) + (cthc/make-component :red :frame-red) + (ctho/add-frame :frame-blue :name "frame-blue") + (cthc/make-component :blue :frame-blue) + (ctho/add-frame :frame-green) + (cthc/make-component :green :frame-green) + (cthc/instantiate-component :red :red-copy-green :parent-label :frame-green) + (ctho/add-frame :frame-b1) + (cthc/make-component :b1 :frame-b1) + (ctho/add-frame :frame-yellow :parent-label :frame-b1 :name "frame-yellow") + (cthc/instantiate-component :red :red-copy :parent-label :frame-yellow) + (cthc/component-swap :red-copy :blue :blue1) + (cthc/instantiate-component :green :green-copy :parent-label :frame-b1 :children-labels [:red-copy-in-green-copy]) + (cthc/component-swap :red-copy-in-green-copy :blue :blue-copy-in-green-copy) + (ctho/add-frame :frame-b2) + (cthc/make-component :b2 :frame-b2))) + +(defn- find-copied-shape + [original-shape page parent-id] + ;; copied shape has the same name, is in the specified parent, and doesn't have a label + (->> (vals (:objects page)) + (filter #(and (= (:name %) (:name original-shape)) + (= (:parent-id %) parent-id) + (str/starts-with? (cthi/label (:id %)) "<no-label"))) + first)) + +(t/deftest test-remove-swap-slot-copy-paste-blue1-to-root + (t/async + done + (let [;; ==== Setup + file (setup-file) + store (ths/setup-store file) + + ;; ==== Action + page (cthf/current-page file) + blue1 (cths/get-shape file :blue1) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id blue1)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape uuid/zero) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + blue1' (cths/get-shape file' :blue1) + copied-blue1' (find-copied-shape blue1' page' uuid/zero)] + + ;; ==== Check + + ;; blue1 has swap-id + (t/is (some? (ctk/get-swap-slot blue1'))) + + ;; copied-blue1 has not swap-id + (t/is (some? copied-blue1')) + (t/is (nil? (ctk/get-swap-slot copied-blue1'))))))))) + + +(t/deftest test-remove-swap-slot-copy-paste-blue1-to-b1 + (t/async + done + (let [;; ==== Setup + file (setup-file) + store (ths/setup-store file) + + ;; ==== Action + page (cthf/current-page file) + b1 (cths/get-shape file :frame-b1) + blue1 (cths/get-shape file :blue1) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id blue1)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape (:id b1)) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + b1' (cths/get-shape file' :frame-b1) + blue1' (cths/get-shape file' :blue1) + copied-blue1' (find-copied-shape blue1' page' (:id b1'))] + + ;; ==== Check + ;; blue1 has swap-id + (t/is (some? (ctk/get-swap-slot blue1'))) + + ;; copied-blue1 has not swap-id + (t/is (some? copied-blue1')) + (t/is (nil? (ctk/get-swap-slot copied-blue1'))))))))) + +(t/deftest test-remove-swap-slot-copy-paste-blue1-to-yellow + (t/async + done + (let [;; ==== Setup + file (setup-file) + store (ths/setup-store file) + + ;; ==== Action + page (cthf/current-page file) + yellow (cths/get-shape file :frame-yellow) + blue1 (cths/get-shape file :blue1) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id blue1)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape (:id yellow)) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + yellow' (cths/get-shape file' :frame-yellow) + blue1' (cths/get-shape file' :blue1) + copied-blue1' (find-copied-shape blue1' page' (:id yellow'))] + + ;; ==== Check + ;; blue1 has swap-id + (t/is (some? (ctk/get-swap-slot blue1'))) + + ;; copied-blue1 has not swap-id + (t/is (some? copied-blue1')) + (t/is (nil? (ctk/get-swap-slot copied-blue1'))))))))) + + +(t/deftest test-remove-swap-slot-copy-paste-blue1-to-b2 + (t/async + done + (let [;; ==== Setup + file (setup-file) + store (ths/setup-store file) + + ;; ==== Action + page (cthf/current-page file) + b2 (cths/get-shape file :frame-b2) + blue1 (cths/get-shape file :blue1) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id blue1)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape (:id b2)) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + b2' (cths/get-shape file' :frame-b2) + blue1' (cths/get-shape file' :blue1) + copied-blue1' (find-copied-shape blue1' page' (:id b2'))] + + ;; ==== Check + ;; blue1 has swap-id + (t/is (some? (ctk/get-swap-slot blue1'))) + + ;; copied-blue1 has not swap-id + (t/is (some? copied-blue1')) + (t/is (nil? (ctk/get-swap-slot copied-blue1'))))))))) + + +(t/deftest test-remove-swap-slot-cut-paste-blue1-to-root + (t/async + done + (let [;; ==== Setup + file (setup-file) + store (ths/setup-store file) + + ;; ==== Action + page (cthf/current-page file) + blue1 (cths/get-shape file :blue1) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id blue1)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape (:id blue1)) + (dw/delete-selected) + (dws/select-shape uuid/zero) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + copied-blue1' (find-copied-shape blue1 page' uuid/zero)] + + ;; ==== Check + ;; copied-blue1 has not swap-id + (t/is (some? copied-blue1')) + (t/is (nil? (ctk/get-swap-slot copied-blue1'))))))))) + + + +(t/deftest test-remove-swap-slot-cut-paste-blue1-to-yellow + (t/async + done + (let [;; ==== Setup + file (setup-file) + store (ths/setup-store file) + + ;; ==== Action + page (cthf/current-page file) + yellow (cths/get-shape file :frame-yellow) + blue1 (cths/get-shape file :blue1) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id blue1)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape (:id blue1)) + (dw/delete-selected) + (dws/select-shape (:id yellow)) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + yellow' (cths/get-shape file' :frame-yellow) + copied-blue1' (find-copied-shape blue1 page' (:id yellow'))] + + ;; ==== Check + ;; copied-blue1 has not swap-id + (t/is (some? copied-blue1')) + (t/is (nil? (ctk/get-swap-slot copied-blue1'))))))))) + + +(t/deftest test-remove-swap-slot-cut-paste-blue1-to-b2 + (t/async + done + (let [;; ==== Setup + file (setup-file) + store (ths/setup-store file) + + ;; ==== Action + page (cthf/current-page file) + b2 (cths/get-shape file :frame-b2) + blue1 (cths/get-shape file :blue1) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id blue1)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape (:id blue1)) + (dw/delete-selected) + (dws/select-shape (:id b2)) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + b2' (cths/get-shape file' :frame-b2) + copied-blue1' (find-copied-shape blue1 page' (:id b2'))] + + ;; ==== Check + ;; copied-blue1 has not swap-id + (t/is (some? copied-blue1')) + (t/is (nil? (ctk/get-swap-slot copied-blue1'))))))))) + + +(t/deftest test-remove-swap-slot-copy-paste-yellow-to-root + (t/async + done + (let [;; ==== Setup + file (setup-file-blue1-in-yellow) + store (ths/setup-store file) + + ;; ==== Action + page (cthf/current-page file) + yellow (cths/get-shape file :frame-yellow) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id yellow)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape uuid/zero) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + copied-yellow' (find-copied-shape yellow page' uuid/zero) + blue1' (cths/get-shape file' :blue1) + copied-blue1' (find-copied-shape blue1' page' (:id copied-yellow'))] + + ;; ==== Check + + ;; blue1 has swap-id + (t/is (some? (ctk/get-swap-slot blue1'))) + + ;; copied-blue1 has not swap-id + (t/is (some? copied-blue1')) + (t/is (nil? (ctk/get-swap-slot copied-blue1'))))))))) + +(t/deftest test-remove-swap-slot-copy-paste-yellow-to-b1 + (t/async + done + (let [;; ==== Setup + file (setup-file-blue1-in-yellow) + store (ths/setup-store file) + + ;; ==== Action + page (cthf/current-page file) + yellow (cths/get-shape file :frame-yellow) + b1 (cths/get-shape file :frame-b1) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id yellow)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape (:id b1)) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + b1' (cths/get-shape file' :frame-b1) + copied-yellow' (find-copied-shape yellow page' (:id b1')) + blue1' (cths/get-shape file' :blue1) + copied-blue1' (find-copied-shape blue1' page' (:id copied-yellow'))] + + ;; ==== Check + + ;; blue1 has swap-id + (t/is (some? (ctk/get-swap-slot blue1'))) + + ;; copied-blue1 has not swap-id + (t/is (some? copied-blue1')) + (t/is (nil? (ctk/get-swap-slot copied-blue1'))))))))) + +(t/deftest test-remove-swap-slot-copy-paste-yellow-to-b2 + (t/async + done + (let [;; ==== Setup + file (setup-file-blue1-in-yellow) + store (ths/setup-store file) + + ;; ==== Action + page (cthf/current-page file) + yellow (cths/get-shape file :frame-yellow) + b2 (cths/get-shape file :frame-b2) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id yellow)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape (:id b2)) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + b2' (cths/get-shape file' :frame-b2) + copied-yellow' (find-copied-shape yellow page' (:id b2')) + blue1' (cths/get-shape file' :blue1) + copied-blue1' (find-copied-shape blue1' page' (:id copied-yellow'))] + + ;; ==== Check + + ;; blue1 has swap-id + (t/is (some? (ctk/get-swap-slot blue1'))) + ;; copied-blue1 has not swap-id + (t/is (some? copied-blue1')) + (t/is (nil? (ctk/get-swap-slot copied-blue1'))))))))) + +(t/deftest test-remove-swap-slot-cut-paste-yellow-to-root + (t/async + done + (let [;; ==== Setup + file (setup-file-blue1-in-yellow) + store (ths/setup-store file) + blue1 (cths/get-shape file :blue1) + + ;; ==== Action + page (cthf/current-page file) + yellow (cths/get-shape file :frame-yellow) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id yellow)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape (:id yellow)) + (dw/delete-selected) + (dws/select-shape uuid/zero) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + copied-yellow' (find-copied-shape yellow page' uuid/zero) + copied-blue1' (find-copied-shape blue1 page' (:id copied-yellow'))] + + ;; ==== Check + ;; copied-blue1 has not swap-id + (t/is (some? copied-blue1')) + (t/is (nil? (ctk/get-swap-slot copied-blue1'))))))))) + +(t/deftest test-remove-swap-slot-cut-paste-yellow-to-b1 + (t/async + done + (let [;; ==== Setup + file (setup-file-blue1-in-yellow) + store (ths/setup-store file) + blue1 (cths/get-shape file :blue1) + + ;; ==== Action + page (cthf/current-page file) + yellow (cths/get-shape file :frame-yellow) + b1 (cths/get-shape file :frame-b1) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id yellow)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape (:id yellow)) + (dw/delete-selected) + (dws/select-shape (:id b1)) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + b1' (cths/get-shape file' :frame-b1) + copied-yellow' (find-copied-shape yellow page' (:id b1')) + copied-blue1' (find-copied-shape blue1 page' (:id copied-yellow'))] + + ;; ==== Check + ;; copied-blue1 has not swap-id + (t/is (some? copied-blue1')) + (t/is (nil? (ctk/get-swap-slot copied-blue1'))))))))) + +(t/deftest test-remove-swap-slot-cut-paste-yellow-to-b2 + (t/async + done + (let [;; ==== Setup + file (setup-file-blue1-in-yellow) + store (ths/setup-store file) + blue1 (cths/get-shape file :blue1) + + ;; ==== Action + page (cthf/current-page file) + yellow (cths/get-shape file :frame-yellow) + b2 (cths/get-shape file :frame-b2) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id yellow)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape (:id yellow)) + (dw/delete-selected) + (dws/select-shape (:id b2)) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + b2' (cths/get-shape file' :frame-b2) + copied-yellow' (find-copied-shape yellow page' (:id b2')) + copied-blue1' (find-copied-shape blue1 page' (:id copied-yellow'))] + + ;; ==== Check + ;; copied-blue1 has not swap-id + (t/is (some? copied-blue1')) + (t/is (nil? (ctk/get-swap-slot copied-blue1'))))))))) + +(t/deftest test-keep-swap-slot-copy-paste-green-copy-to-root + (t/async + done + (let [;; ==== Setup + file (setup-file) + store (ths/setup-store file) + + ;; ==== Action + page (cthf/current-page file) + green (cths/get-shape file :green-copy) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id green)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape uuid/zero) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + blue2' (cths/get-shape file' :blue-copy-in-green-copy) + copied-green' (find-copied-shape green page' uuid/zero) + copied-blue2' (find-copied-shape blue2' page' (:id copied-green'))] + + ;; ==== Check + + ;; blue2 has swap-id + (t/is (some? (ctk/get-swap-slot blue2'))) + + ;; copied-blue2 also has swap-id + (t/is (some? copied-blue2')) + (t/is (some? (ctk/get-swap-slot copied-blue2'))))))))) + +(t/deftest test-keep-swap-slot-copy-paste-green-copy-to-b1 + (t/async + done + (let [;; ==== Setup + file (setup-file) + store (ths/setup-store file) + + ;; ==== Action + page (cthf/current-page file) + b1 (cths/get-shape file :frame-b1) + green (cths/get-shape file :green-copy) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id green)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape (:id b1)) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + b1' (cths/get-shape file' :frame-b1) + blue2' (cths/get-shape file' :blue-copy-in-green-copy) + copied-green' (find-copied-shape green page' (:id b1')) + copied-blue2' (find-copied-shape blue2' page' (:id copied-green'))] + + ;; ==== Check + + ;; blue1 has swap-id + (t/is (some? (ctk/get-swap-slot blue2'))) + + ;; copied-blue1 also has swap-id + (t/is (some? copied-blue2')) + (t/is (some? (ctk/get-swap-slot copied-blue2'))))))))) + +(t/deftest test-keep-swap-slot-copy-paste-green-copy-to-b2 + (t/async + done + (let [;; ==== Setup + file (setup-file) + store (ths/setup-store file) + + ;; ==== Action + page (cthf/current-page file) + b2 (cths/get-shape file :frame-b2) + green (cths/get-shape file :green-copy) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id green)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape (:id b2)) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + b2' (cths/get-shape file' :frame-b2) + blue2' (cths/get-shape file' :blue-copy-in-green-copy) + copied-green' (find-copied-shape green page' (:id b2')) + copied-blue2' (find-copied-shape blue2' page' (:id copied-green'))] + + ;; ==== Check + + ;; blue2 has swap-id + (t/is (some? (ctk/get-swap-slot blue2'))) + + ;; copied-blue1 also has swap-id + (t/is (some? copied-blue2')) + (t/is (some? (ctk/get-swap-slot copied-blue2'))))))))) + + +(t/deftest test-keep-swap-slot-cut-paste-green-copy-to-root + (t/async + done + (let [;; ==== Setup + file (setup-file) + store (ths/setup-store file) + + ;; ==== Action + page (cthf/current-page file) + green (cths/get-shape file :green-copy) + blue2 (cths/get-shape file :blue-copy-in-green-copy) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id green)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape (:id green)) + (dw/delete-selected) + (dws/select-shape uuid/zero) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + copied-green' (find-copied-shape green page' uuid/zero) + copied-blue1' (find-copied-shape blue2 page' (:id copied-green'))] + + ;; ==== Check + ;; copied-blue1 has swap-id + (t/is (some? copied-blue1')) + (t/is (some? (ctk/get-swap-slot copied-blue1'))))))))) + +(t/deftest test-keep-swap-slot-cut-paste-green-copy-to-b1 + (t/async + done + (let [;; ==== Setup + file (setup-file) + store (ths/setup-store file) + + ;; ==== Action + page (cthf/current-page file) + b1 (cths/get-shape file :frame-b1) + green (cths/get-shape file :green-copy) + blue2 (cths/get-shape file :blue-copy-in-green-copy) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id green)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape (:id green)) + (dw/delete-selected) + (dws/select-shape (:id b1)) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + b1' (cths/get-shape file' :frame-b1) + copied-green' (find-copied-shape green page' (:id b1')) + copied-blue2' (find-copied-shape blue2 page' (:id copied-green'))] + + ;; ==== Check + ;; copied-blue1 has swap-id + (t/is (some? copied-blue2')) + (t/is (some? (ctk/get-swap-slot copied-blue2'))))))))) + +(t/deftest test-keep-swap-slot-cut-paste-green-copy-to-b2 + (t/async + done + (let [;; ==== Setup + file (setup-file) + store (ths/setup-store file) + + ;; ==== Action + page (cthf/current-page file) + b2 (cths/get-shape file :frame-b2) + blue2 (cths/get-shape file :blue-copy-in-green-copy) + green (cths/get-shape file :green-copy) + features #{"components/v2"} + version 46 + + pdata (thp/simulate-copy-shape #{(:id green)} (:objects page) {(:id file) file} page file features version) + + events + [(dws/select-shape (:id green)) + (dw/delete-selected) + (dws/select-shape (:id b2)) + (dw/paste-shapes pdata)]] + + (ths/run-store + store done events + (fn [new-state] + (let [;; ==== Get + file' (ths/get-file-from-store new-state) + page' (cthf/current-page file') + b2' (cths/get-shape file' :frame-b2) + copied-green' (find-copied-shape green page' (:id b2')) + copied-blue2' (find-copied-shape blue2 page' (:id copied-green'))] + + ;; ==== Check + ;; copied-blue1 has swap-id + (t/is (some? copied-blue2')) + (t/is (some? (ctk/get-swap-slot copied-blue2')))))))))