diff --git a/common/src/app/common/logic/variants.cljc b/common/src/app/common/logic/variants.cljc index 5e13da1241..5947d4dc95 100644 --- a/common/src/app/common/logic/variants.cljc +++ b/common/src/app/common/logic/variants.cljc @@ -482,3 +482,21 @@ (cfh/components-nesting-loop? (cfh/get-children-with-self (:objects page) (:id root)) (cfh/get-parents-with-self objects (:parent-id shape))))))) + +(defn generate-rename-variant + "Rename the variant `variant-id` to `name`: its board, and each of its + components with its main. The changes must hold the objects of the page + of the variant and the data of its file." + [changes variant-id name] + (let [data (pcb/get-library-data changes) + objects (pcb/get-objects changes) + clean-name (cpn/clean-path name) + valid-name (cpn/clean-valid-name clean-name) + rename (fn [changes component] + (-> changes + (cll/generate-rename-component (:id component) valid-name data) + (pcb/update-shapes [(:main-instance-id component)] #(assoc % :name valid-name))))] + (cond-> (pcb/update-shapes changes [variant-id] #(assoc % :name clean-name)) + (some? valid-name) + (as-> changes (reduce rename changes (cfv/find-variant-components data objects variant-id)))))) + diff --git a/common/src/app/common/test_helpers/composable/comp/cases.cljc b/common/src/app/common/test_helpers/composable/comp/cases.cljc index c75c8c5f8b..9001f4d6b5 100644 --- a/common/src/app/common/test_helpers/composable/comp/cases.cljc +++ b/common/src/app/common/test_helpers/composable/comp/cases.cljc @@ -1421,18 +1421,6 @@ rename-copy (n/change-property nested :name "Mine") rename (n/rename-variant #(:id (n/member-root % vset "a")) "Renamed")] {:setup setup/empty-situation - ;; the rename's transaction keeps the undo group of its first commit, the - ;; container's, while the copies' sync takes the group of the main - ;; renames: one undo reverts only the sync - :undo-check {:known-failures [{:bug "F6" - :fails {:undo #{[:object :sync-vset-vcontainer :name] - [:object :sync-vset-v0-root :name] - [:object :sync-vset-v1-root :name] - [:component :sync-vset-v0-component :name] - [:component :sync-vset-v1-component :name]} - :undo-index #{[:undo-index 1]}} - :op rename - :runners #{:frontend}}]} :operation (tm/in-sequence [(n/create-component m base-color :size 100) (n/make-variant-container vset [["a" base-color] ["b" red]] :size 100) diff --git a/frontend/src/app/main/data/workspace/variants.cljs b/frontend/src/app/main/data/workspace/variants.cljs index 3908a2dafc..1e1ed2d76a 100644 --- a/frontend/src/app/main/data/workspace/variants.cljs +++ b/frontend/src/app/main/data/workspace/variants.cljs @@ -14,7 +14,6 @@ [app.common.geom.rect :as grc] [app.common.logic.variant-properties :as clvp] [app.common.logic.variants :as clv] - [app.common.path-names :as cpn] [app.common.types.component :as ctc] [app.common.types.components-list :as ctkl] [app.common.types.shape.layout :as ctsl] @@ -25,7 +24,6 @@ [app.main.data.helpers :as dsh] [app.main.data.workspace.libraries :as dwl] [app.main.data.workspace.selection :as dws] - [app.main.data.workspace.shapes :as dwsh] [app.main.data.workspace.transforms :as dwt] [app.main.data.workspace.undo :as dwu] [app.util.dom :as dom] @@ -290,8 +288,14 @@ (not (ctc/is-variant? first-shape)) (ctc/main-instance? first-shape)) add-new-variant? (every? ctc/is-variant? selected-shapes) + variant-container? (and single? (ctc/is-variant-container? first-shape)) undo-id (js/Symbol)] (cond + variant-container? + (rx/of + (ev/event {::ev/name "add-new-variant" ::ev/origin "workspace:shortcut-create-component"}) + (add-new-variant (:id first-shape))) + transform-in-variant? (rx/of (ev/event {::ev/name "transform-in-variant" ::ev/origin "workspace:shortcut"}) @@ -336,27 +340,14 @@ (rx/empty)))))) (defn rename-variant - "Rename the variant container and all components belonging to this variant" + "Rename the variant container and all components belonging to this variant + (`clv/generate-rename-variant`), in one commit." [variant-id name] (ptk/reify ::rename-variant - ptk/WatchEvent - (watch [_ state _] - (let [page-id (:current-page-id state) - data (dsh/lookup-file-data state) - objects (-> (dsh/get-page data page-id) - (get :objects)) - variant-components (cfv/find-variant-components data objects variant-id) - clean-name (cpn/clean-path name) - undo-id (js/Symbol)] - - (rx/concat - (rx/of (dwu/start-undo-transaction undo-id) - (dwsh/update-shapes [variant-id] #(assoc % :name clean-name))) - (rx/from (map - #(dwl/rename-component-and-main-instance (:id %) clean-name) - variant-components)) - (rx/of (dwu/commit-undo-transaction undo-id))))))) + (watch [it state _] + (rx/of (dch/commit-changes (-> (variant-changes it state) + (clv/generate-rename-variant variant-id name))))))) (defn rename-comp-or-variant-and-main "If the component is in a variant, rename the variant. diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs index dc1b566385..ec80e1df06 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs @@ -177,18 +177,29 @@ :title (tr "workspace.assets.components.num-variants" num-variants)} [:> icon* {:icon-id i/variant :size "s"}]])])])) -(defn- count-leaves - "Counts the total number of leaf elements in a nested map structure. - A leaf element is considered any element inside a vector." +(defn- leaves + "The leaf elements of a nested map structure: the elements of each vector + in it." [m] (reduce-kv (fn [acc _ v] (cond - (map? v) (+ acc (count-leaves v)) - (vector? v) (+ acc (count v)) - :else acc)) - 0 + (map? v) (into acc (leaves v)) + (vector? v) (into acc v) + :else acc)) + [] m)) +(defn can-combine-group? + "Whether the components of a group of the assets panel, `groups` (its + subgroups by name, its own components under \"\"), nested ones included, + can be combined as variants: two or more, none a variant, all with their + main on one page." + [groups] + (let [components (leaves groups)] + (and (> (count components) 1) + (not-any? ctc/is-variant? components) + (apply = (map :main-instance-page components))))) + (mf/defc components-group* [{:keys [file-id prefix groups open-groups is-force-open renaming is-listing-thumbs selected on-asset-click on-drag-start do-rename cancel-rename on-rename-group on-group on-ungroup on-delete-group on-context-menu @@ -207,11 +218,8 @@ selected-full)) components (not-empty (get groups "" [])) - can-combine? (mf/with-memo [is-local groups components] - (and is-local - (> (count-leaves groups) 1) - (not-any? ctc/is-variant? components) - (apply = (map :main-instance-page components)))) + can-combine? (mf/with-memo [is-local groups] + (and is-local (can-combine-group? groups))) on-drag-enter (mf/use-fn (mf/deps dragging* prefix selected-paths is-local drag-data*) diff --git a/frontend/src/app/plugins/library.cljs b/frontend/src/app/plugins/library.cljs index e8362106ee..871c48e15e 100644 --- a/frontend/src/app/plugins/library.cljs +++ b/frontend/src/app/plugins/library.cljs @@ -696,6 +696,16 @@ [file-id variant-id] (cfv/find-variant-components (-> file-id u/locate-file :data) variant-id)) +(defn- on-current-page? + "Whether the main of `component`, of the file `file-id`, is on the page the + workspace shows: the variant events build their changes there." + [file-id component] + (and (= file-id (:current-file-id @st/state)) + (u/page-active? (:main-instance-page component)))) + +(def ^:private not-on-current-page + "The variant is not on the current page") + (declare lib-component-proxy) (defn variant-proxy @@ -742,6 +752,9 @@ (not (r/check-permission plugin-id "library:write")) (u/not-valid plugin-id :addVariant "Plugin doesn't have 'library:write' permission") + (not (on-current-page? file-id (first (get-variant-components file-id id)))) + (u/not-valid plugin-id :addVariant not-on-current-page) + :else (st/emit! (se/event plugin-id "add-new-variant") @@ -753,6 +766,9 @@ (not (r/check-permission plugin-id "library:write")) (u/not-valid plugin-id :addProperty "Plugin doesn't have 'library:write' permission") + (not (on-current-page? file-id (first (get-variant-components file-id id)))) + (u/not-valid plugin-id :addProperty not-on-current-page) + :else (st/emit! (se/event plugin-id "add-new-property") @@ -772,6 +788,9 @@ (not (ctv/can-remove-property? properties)) (u/not-valid plugin-id :removeProperty "A variant must keep at least one property") + (not (on-current-page? file-id (first (get-variant-components file-id id)))) + (u/not-valid plugin-id :removeProperty not-on-current-page) + :else (st/emit! (se/event plugin-id "remove-property") @@ -790,6 +809,9 @@ (not (r/check-permission plugin-id "library:write")) (u/not-valid plugin-id :renameProperty "Plugin doesn't have 'library:write' permission") + (not (on-current-page? file-id (first (get-variant-components file-id id)))) + (u/not-valid plugin-id :renameProperty not-on-current-page) + :else (st/emit! (dwv/update-property-name id pos (ctv/normalize-property-text name) @@ -1101,6 +1123,9 @@ (not (r/check-permission plugin-id "library:write")) (u/not-valid plugin-id :setVariantProperty "Plugin doesn't have 'library:write' permission") + (not (on-current-page? file-id (u/locate-library-component file-id id))) + (u/not-valid plugin-id :setVariantProperty not-on-current-page) + :else (st/emit! (se/event plugin-id "variant-edit-property-value") diff --git a/frontend/src/app/plugins/shape.cljs b/frontend/src/app/plugins/shape.cljs index 705ea9ad77..2610a61878 100644 --- a/frontend/src/app/plugins/shape.cljs +++ b/frontend/src/app/plugins/shape.cljs @@ -336,6 +336,13 @@ [shape] (and (ctk/instance-head? shape) (ctk/in-component-copy? shape))) +(defn swap-keeps-touched? + "Whether a swap of a copy of `component` for `target` keeps the copy's + overrides: only a switch between variants of one set does, as in the UI." + [component target] + (and (ctk/is-variant? component) + (= (:variant-id component) (:variant-id target)))) + (defn shape-proxy? [p] (obj/type-of? p "ShapeProxy")) @@ -1569,7 +1576,11 @@ valid-component? (obj/type-of? component "LibraryComponentProxy") target-file (when valid-component? (obj/get component "$file")) target-id (when valid-component? (obj/get component "$id")) - target-data (some-> target-file u/locate-file :data)] + target-data (some-> target-file u/locate-file :data) + component (when (copy-head? shape) + (u/locate-library-component (:component-file shape) (:component-id shape))) + target (when target-data + (dm/get-in target-data [:components target-id]))] (cond (not (r/check-permission plugin-id "content:write")) (u/not-valid plugin-id :swapComponent "Plugin doesn't have 'content:write' permission") @@ -1590,7 +1601,7 @@ (st/emit! (dwl/component-swap shape target-file target-id - true))))) + (swap-keeps-touched? component target)))))) :updateMain (fn [] @@ -1860,9 +1871,10 @@ :isVariantHead (fn [] - (let [shape (u/locate-shape file-id page-id id) - component (u/locate-library-component file-id (:component-id shape))] - (and (ctk/instance-head? shape) (ctk/is-variant? component)))) + (let [shape (u/locate-shape file-id page-id id)] + (and (ctk/instance-head? shape) + (ctk/is-variant? (u/locate-library-component (:component-file shape) + (:component-id shape)))))) :isVariantContainer (fn [] diff --git a/frontend/test/frontend_tests/composable_tests/golden_master.edn b/frontend/test/frontend_tests/composable_tests/golden_master.edn index 1f771c117d..7b4feb9103 100644 --- a/frontend/test/frontend_tests/composable_tests/golden_master.edn +++ b/frontend/test/frontend_tests/composable_tests/golden_master.edn @@ -67,8 +67,8 @@ [{:transcript " {:component \"first\", :id sync-first-component}\n {:component \"second\", :id sync-second-component}\n {:component \"first\", :copy sync-first-copyhead-0}\n {:component \"second\", :copy sync-second-copyhead-0}\n {:target #fn, :property :fills, :value \"#00ff00\"}\n {:action :combine, :params {:targets [#fn #fn], :selected? nil}}\n \n {:target #fn, :value #fn, :pos 0}", :states ["61c776d9e973c9dd" "0f68af4cace0f325" "97651ebcd2334fe5" "47fc4c7f440fdc13"]} {:transcript " {:component \"first\", :id sync-first-component}\n {:component \"second\", :id sync-second-component}\n {:component \"first\", :copy sync-first-copyhead-0}\n {:component \"second\", :copy sync-second-copyhead-0}\n {:target #fn, :property :fills, :value \"#00ff00\"}\n {:action :combine, :params {:targets [#fn #fn], :selected? true}}\n \n {:target #fn, :value #fn, :pos 0}", :states ["61c776d9e973c9dd" "0f68af4cace0f325" "97651ebcd2334fe5" "47fc4c7f440fdc13"]}] :case-av-variant-rename-reaches-copy-names - [{:transcript " {:component \"main\", :id sync-main-component}\n {:variant-set \"vset\", :variant-id sync-vset-vcontainer, :count 2}\n {:component \"main\", :level 0, :outer sync-main-outercomp-0}\n {:component \"main\", :copy sync-main-copyhead-0}\n {:target #fn, :property :name, :value \"Mine\"}\n {:action :rename, :params {:target #fn, :name \"Renamed\"}}", :states ["c6e889ca261596ce" "940f36855f4f991d" "d7a54338ab53a791"]} - {:transcript " {:component \"main\", :id sync-main-component}\n {:variant-set \"vset\", :variant-id sync-vset-vcontainer, :count 2}\n {:component \"main\", :level 0, :outer sync-main-outercomp-0}\n {:component \"main\", :copy sync-main-copyhead-0}\n one-of -> \n {:action :rename, :params {:target #fn, :name \"Renamed\"}}", :states ["5eb544d7e28709d7" "5e6794a9b313112e"]}] + [{:transcript " {:component \"main\", :id sync-main-component}\n {:variant-set \"vset\", :variant-id sync-vset-vcontainer, :count 2}\n {:component \"main\", :level 0, :outer sync-main-outercomp-0}\n {:component \"main\", :copy sync-main-copyhead-0}\n {:target #fn, :property :name, :value \"Mine\"}\n {:action :rename, :params {:target #fn, :name \"Renamed\"}}", :states ["c6e889ca261596ce" "940f36855f4f991d" "92ebbb582ece2af2"]} + {:transcript " {:component \"main\", :id sync-main-component}\n {:variant-set \"vset\", :variant-id sync-vset-vcontainer, :count 2}\n {:component \"main\", :level 0, :outer sync-main-outercomp-0}\n {:component \"main\", :copy sync-main-copyhead-0}\n one-of -> \n {:action :rename, :params {:target #fn, :name \"Renamed\"}}", :states ["5eb544d7e28709d7" "e76ffcfb4eccd16d"]}] :case-aw-variant-layer-rename-and-cleanup [{:transcript " {:component \"main\", :id sync-main-component}\n {:variant-set \"vset\", :variant-id sync-vset-vcontainer, :count 2}\n {:component \"main\", :level 0, :outer sync-main-outercomp-0}\n {:component \"main\", :copy sync-main-copyhead-0}\n {:target #fn, :property :fills, :value \"#00ff00\"}\n {:set-name \"vset\", :edit :rename-in-layers, :params {:member \"a\", :name \"Property 1=a2, Size=S\"}}\n \n {:set-name \"vset\", :edit :add, :params {:property-name \"Empty\"}}\n {:set-name \"vset\", :edit :remove-empty, :params {}}\n \n {:set-name \"vset\", :edit :rename-in-layers, :params {:member \"a\", :name \"Property 1=a2\"}}\n \n {:set-name \"vset\", :edit :error, :params {:member \"b\", :value \"Duplicated\"}}\n \n {:set-name \"vset\", :edit :error, :params {:member \"b\", :value nil}}\n \n {:target #fn, :value \"b\", :pos 0}", :states ["df9a042b9d59d699" "4b53486972986d97" "8553f89a9ebbcf54" "4b53486972986d97" "d65ad905aa97d661" "6daf5f692c6595f1" "d65ad905aa97d661" "cc7d2dfd618fc8cb" "6390b4d83995b629"]}] :case-ax-variant-shortcuts-add-members diff --git a/frontend/test/frontend_tests/data/workspace_variants_test.cljs b/frontend/test/frontend_tests/data/workspace_variants_test.cljs index c8c92054ce..3a9cb0f278 100644 --- a/frontend/test/frontend_tests/data/workspace_variants_test.cljs +++ b/frontend/test/frontend_tests/data/workspace_variants_test.cljs @@ -27,6 +27,7 @@ [app.main.data.workspace.selection :as dws] [app.main.data.workspace.undo :as dwu] [app.main.data.workspace.variants :as dwv] + [app.util.dom :as dom] [beicon.v2.core :as rx] [cljs.test :as t :include-macros true] [frontend-tests.helpers.mock :as mock] @@ -195,6 +196,22 @@ (run-selected done (file-with-a-rect) [:rect] (dwv/add-component-or-variant) #(t/is (= 1 (count (ctkl/components-seq (:data %)))))))) +(t/deftest create-component-shortcut-on-a-variant-container + ;; the shortcut the container's "Add variant" menu entry shows; the new + ;; variant focuses its first property 250 ms later, which finds no DOM here + (t/async + done + (mock/with-mocks + {dom/get-element (constantly nil)} + (fn [inner-done] + (let [file (-> (cthf/sample-file :file1) + (cthv/add-variant :v01 :c01 :m01 :c02 :m02))] + (run-selected #(js/setTimeout inner-done 300) file [:v01] (dwv/add-component-or-variant) + (fn [file'] + (t/is (= 3 (count (filter #(= (cthi/id :v01) (:variant-id %)) + (ctkl/components-seq (:data file')))))))))) + done))) + (t/deftest rename-of-a-plain-component (t/async done diff --git a/frontend/test/frontend_tests/plugins/library_test.cljs b/frontend/test/frontend_tests/plugins/library_test.cljs index 9180376715..3a3d004401 100644 --- a/frontend/test/frontend_tests/plugins/library_test.cljs +++ b/frontend/test/frontend_tests/plugins/library_test.cljs @@ -388,6 +388,47 @@ (t/is (= [plugin-id :setVariantProperty "Plugin doesn't have 'library:write' permission"] (first @errors))))))) +(defn- variant-edit-errors + "The errors and emitted events of `call` on a variant edit of the file + `file-id`, with its main on the page `page-id`, while the workspace shows + the current file `current-file` and page `current-page`." + [{:keys [file-id page-id current-file current-page]} call] + (let [errors (atom []) + emitted (atom [])] + (with-redefs [r/check-permission (constantly true) + u/not-valid (mock/stub (fn [_ prop msg] (swap! errors conj [prop msg]))) + u/locate-library-component (constantly {:main-instance-page page-id + :variant-properties [{:name "color" :value "red"} + {:name "size" :value "s"}]}) + library/get-variant-components (constantly [{:main-instance-page page-id + :variant-properties [{:name "color" :value "red"} + {:name "size" :value "s"}]}]) + st/state (atom {:current-file-id current-file :current-page-id current-page}) + st/emit! (fn ([_] (swap! emitted conj :emitted)) + ([_ & _] (swap! emitted conj :emitted)))] + (call (library/variant-proxy "test-plugin" file-id (uuid/next)) + (library/lib-component-proxy "test-plugin" file-id (uuid/next)))) + {:errors @errors :emitted @emitted})) + +(t/deftest variant-edits-need-the-variant-on-the-current-page + (let [file-id (uuid/next) + page-id (uuid/next) + edits {:addVariant #(.addVariant ^js %1) + :addProperty #(.addProperty ^js %1) + :removeProperty #(.removeProperty ^js %1 0) + :renameProperty #(.renameProperty ^js %1 0 "shade") + :setVariantProperty #(.setVariantProperty ^js %2 0 "blue")}] + (doseq [[prop call] edits] + (t/testing (name prop) + (let [here (variant-edit-errors {:file-id file-id :page-id page-id + :current-file file-id :current-page page-id} call) + there (variant-edit-errors {:file-id file-id :page-id page-id + :current-file file-id :current-page (uuid/next)} call)] + (t/is (empty? (:errors here))) + (t/is (seq (:emitted here))) + (t/is (= [[prop "The variant is not on the current page"]] (:errors there))) + (t/is (empty? (:emitted there)))))))) + ;; --------------------------------------------------------------------------- ;; connectLibrary ;; --------------------------------------------------------------------------- diff --git a/frontend/test/frontend_tests/plugins/shape_bugfixes_test.cljs b/frontend/test/frontend_tests/plugins/shape_bugfixes_test.cljs index 59c688a3b4..6fb988e250 100644 --- a/frontend/test/frontend_tests/plugins/shape_bugfixes_test.cljs +++ b/frontend/test/frontend_tests/plugins/shape_bugfixes_test.cljs @@ -466,6 +466,31 @@ (t/is (= [[:detach "Only a copy that is not inside another copy can be detached"]] errors)) (t/is (empty? emitted)))) +(t/deftest swap-component-keeps-overrides-only-within-a-variant-set + (let [set-a (uuid/next) + set-b (uuid/next) + variant #(hash-map :id (uuid/next) :variant-id %)] + (t/is (true? (shape/swap-keeps-touched? (variant set-a) (variant set-a)))) + (t/is (false? (shape/swap-keeps-touched? (variant set-a) (variant set-b)))) + (t/is (not (shape/swap-keeps-touched? {:id (uuid/next)} {:id (uuid/next)}))) + (t/is (not (shape/swap-keeps-touched? (variant set-a) {:id (uuid/next)}))))) + +(t/deftest is-variant-head-reads-the-component-file-of-the-shape + ;; a copy, in this file, of a variant of a library + (let [library-id (uuid/next) + copy-id (uuid/next) + rect-id (uuid/next) + objects {copy-id {:id copy-id :type :frame :component-id (uuid/next) + :component-file library-id :component-root true :shape-ref (uuid/next)} + rect-id {:id rect-id :type :rect}} + head? (fn [id] + (with-redefs [u/locate-shape (fn [_ _ id] (get objects id)) + u/locate-library-component + (fn [file-id _] (when (= file-id library-id) {:variant-id (uuid/next)}))] + (.isVariantHead ^js (shape/shape-proxy "test-plugin" (uuid/next) (uuid/next) id))))] + (t/is (true? (head? copy-id))) + (t/is (false? (head? rect-id))))) + (t/deftest swap-component-rejects-a-value-that-is-no-component (let [{:keys [objects head]} (nested-copy-objects) {:keys [errors emitted]} (plugin-errors-of objects head #(.swapComponent ^js % #js {}))] diff --git a/frontend/test/frontend_tests/runner.cljs b/frontend/test/frontend_tests/runner.cljs index 8c87826de0..3c358fce29 100644 --- a/frontend/test/frontend_tests/runner.cljs +++ b/frontend/test/frontend_tests/runner.cljs @@ -125,6 +125,7 @@ [frontend-tests.tokens.token-path-test] [frontend-tests.tokens.tokenscript-test] [frontend-tests.tokens.workspace-tokens-remap-test] + [frontend-tests.ui.assets-components-test] [frontend-tests.ui.check-updates-test] [frontend-tests.ui.color-token-position-test] [frontend-tests.ui.colorpicker-token-set-order-test] @@ -302,6 +303,7 @@ 'frontend-tests.tokens.logic.tokens-source-test 'frontend-tests.tokens.logic.tokens-status-test 'frontend-tests.tokens.workspace-tokens-remap-test + 'frontend-tests.ui.assets-components-test 'frontend-tests.ui.check-updates-test 'frontend-tests.ui.color-token-position-test 'frontend-tests.ui.colorpicker-token-set-order-test diff --git a/frontend/test/frontend_tests/ui/assets_components_test.cljs b/frontend/test/frontend_tests/ui/assets_components_test.cljs new file mode 100644 index 0000000000..50e8abf368 --- /dev/null +++ b/frontend/test/frontend_tests/ui/assets_components_test.cljs @@ -0,0 +1,31 @@ +;; 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 frontend-tests.ui.assets-components-test + "The check that offers to combine a group of the assets panel as variants." + (:require + [app.common.uuid :as uuid] + [app.main.ui.workspace.sidebar.assets.components :as assets] + [cljs.test :as t :include-macros true])) + +(def ^:private page-1 (uuid/next)) +(def ^:private page-2 (uuid/next)) + +(defn- component + [& {:as attrs}] + (merge {:id (uuid/next) :main-instance-page page-1} attrs)) + +(t/deftest combine-a-group-reads-its-nested-components + (t/testing "components only in subgroups" + (t/is (assets/can-combine-group? {"" [] "sub" {"" [(component) (component)]}}))) + (t/testing "a variant in a subgroup" + (t/is (not (assets/can-combine-group? {"" [(component)] + "sub" {"" [(component :variant-id (uuid/next))]}})))) + (t/testing "a subgroup with its main on another page" + (t/is (not (assets/can-combine-group? {"" [(component)] + "sub" {"" [(component :main-instance-page page-2)]}})))) + (t/testing "a single component" + (t/is (not (assets/can-combine-group? {"" [(component)]})))))