mirror of
https://github.com/penpot/penpot.git
synced 2026-04-26 11:48:28 +00:00
* 🔧 Validate only after propagation in tests * 💄 Enhance some component sync traces * 🔧 Add fake uuid generator for debugging * 🐛 Remove old feature of advancing references when reset changes Since long time ago, we only allow to reset changes in the top copy shape. In this case the near and the remote shapes are the same, so the advance-ref has no effect. * 🐛 Fix some bugs and add validations, repair and migrations Also added several utilities to debug and to create scripts that processes files * 🐛 Fix misplaced parenthesis passing propagate-fn to wrong function The :propagate-fn keyword argument was incorrectly placed inside the ths/get-shape call instead of being passed to tho/reset-overrides. This caused reset-overrides to never propagate component changes, making the test not validate what it intended. * 🐛 Accept and forward :include-deleted? in find-near-match Callers were passing :include-deleted? true but the parameter was not in the destructuring, so it was silently ignored and the function always hardcoded true. This made the API misleading and would cause incorrect behavior if called with :include-deleted? false. * 💄 Use set/union alias instead of fully-qualified clojure.set/union The namespace already requires [clojure.set :as set], so use the alias for consistency. * 🐛 Add tests for reset-overrides with and without propagate-fn Add two focused tests to comp_reset_test to cover the propagate-fn path in reset-overrides: - test-reset-with-propagation-updates-copies: verifies that resetting an override on a nested copy inside a main and supplying propagate-fn causes the canonical color to appear in all downstream copies. - test-reset-without-propagation-does-not-update-copies: regression guard for the misplaced-parenthesis bug; confirms that omitting propagate-fn leaves copies with the overridden value because the component sync never runs. --------- Co-authored-by: Andrey Antukh <niwi@niwi.nz>
2686 lines
124 KiB
Clojure
2686 lines
124 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 INC
|
|
|
|
(ns common-tests.logic.variants-switch-test
|
|
(:require
|
|
[app.common.files.changes-builder :as pcb]
|
|
[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.test-helpers.variants :as thv]
|
|
[clojure.test :as t]))
|
|
|
|
(t/use-fixtures :each thi/test-fixture)
|
|
|
|
;; ============================================================
|
|
;; BASIC SWITCH TESTS (no overrides)
|
|
;; ============================================================
|
|
|
|
(t/deftest test-basic-switch
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant
|
|
:v01 :c01 :m01 :c02 :m02
|
|
{:variant1-params {:width 5}
|
|
:variant2-params {:width 15}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01))
|
|
copy01 (ths/get-shape file :copy01)
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
copy01' (ths/get-shape file' :copy02)]
|
|
(thf/dump-file file :keys [:width])
|
|
;; The copy had width 5 before the switch
|
|
(t/is (= (:width copy01) 5))
|
|
;; The rect has width 15 after the switch
|
|
(t/is (= (:width copy01') 15))))
|
|
|
|
(t/deftest test-simple-switch
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 5}
|
|
:child2-params {:width 15}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
;; The rect had width 5 before the switch
|
|
(t/is (= (:width rect01) 5))
|
|
;; The rect has width 15 after the switch
|
|
(t/is (= (:width rect02') 15))))
|
|
|
|
;; ============================================================
|
|
;; SIMPLE ATTRIBUTE OVERRIDES (identical variants)
|
|
;; ============================================================
|
|
|
|
(t/deftest test-basic-switch-override
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant
|
|
:v01 :c01 :m01 :c02 :m02
|
|
{:variant1-params {:width 5}
|
|
:variant2-params {:width 5}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01))
|
|
copy01 (ths/get-shape file :copy01)
|
|
|
|
;; Change width of copy
|
|
page (thf/current-page file)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id copy01)}
|
|
(fn [shape]
|
|
(assoc shape :width 25))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
copy01 (ths/get-shape file :copy01)
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
copy01' (ths/get-shape file' :copy02)]
|
|
(thf/dump-file file :keys [:width])
|
|
;; The copy had width 25 before the switch
|
|
(t/is (= (:width copy01) 25))
|
|
;; The override is keept: The copy still has width 25 after the switch
|
|
(t/is (= (:width copy01') 25))))
|
|
|
|
(t/deftest test-switch-with-override
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 5}
|
|
:child2-params {:width 5}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(assoc shape :width 25))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had width 25 before the switch
|
|
(t/is (= (:width rect01) 25))
|
|
;; The override is keept: The rect still has width 25 after the switch
|
|
(t/is (= (:width rect02') 25))))
|
|
|
|
;; ============================================================
|
|
;; SIMPLE ATTRIBUTE OVERRIDES (different variants)
|
|
;; ============================================================
|
|
|
|
(t/deftest test-switch-with-no-override
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 5}
|
|
:child2-params {:width 15}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(assoc shape :width 25))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had width 25 before the switch
|
|
(t/is (= (:width rect01) 25))
|
|
;; The override isn't keept, because the property is different in the mains
|
|
;; The rect has width 15 after the switch
|
|
(t/is (= (:width rect02') 15))))
|
|
|
|
;; ============================================================
|
|
;; TEXT OVERRIDES (identical variants)
|
|
;; ============================================================
|
|
|
|
(def font-size-path-paragraph [:content :children 0 :children 0 :font-size])
|
|
(def font-size-path-0 [:content :children 0 :children 0 :children 0 :font-size])
|
|
(def font-size-path-1 [:content :children 0 :children 0 :children 1 :font-size])
|
|
|
|
(def text-path-0 [:content :children 0 :children 0 :children 0 :text])
|
|
(def text-path-1 [:content :children 0 :children 0 :children 1 :text])
|
|
(def text-lines-path [:content :children 0 :children 0 :children])
|
|
|
|
(defn- update-attr
|
|
[file label path value]
|
|
(let [page (thf/current-page file)
|
|
shape (ths/get-shape file label)
|
|
changes (cls/generate-update-shapes
|
|
(pcb/empty-changes nil (:id page))
|
|
#{(:id shape)}
|
|
(fn [shape]
|
|
(cond-> (assoc-in shape path value)
|
|
(or (= path font-size-path-0) (= path font-size-path-1))
|
|
(assoc-in font-size-path-paragraph value)))
|
|
(:objects page)
|
|
{})]
|
|
(thf/apply-changes file changes)))
|
|
|
|
(defn- change-structure
|
|
[file label]
|
|
(let [page (thf/current-page file)
|
|
shape (ths/get-shape file label)
|
|
line1 (-> (get-in shape text-lines-path)
|
|
first
|
|
(assoc :text "new line 1"))
|
|
line2 (assoc line1 :text "new line 2")
|
|
changes (cls/generate-update-shapes
|
|
(pcb/empty-changes nil (:id page))
|
|
#{(:id shape)}
|
|
(fn [shape]
|
|
(assoc-in shape text-lines-path [line1 line2]))
|
|
(:objects page)
|
|
{})]
|
|
(thf/apply-changes file changes)))
|
|
|
|
(t/deftest test-switch-with-identical-text-override
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
;; Both components are identical: have the same text and props
|
|
(thv/add-variant-with-text
|
|
:v01 :c01 :m01 :c02 :m02 :t01 :t02 "hello world" "hello world")
|
|
(thc/instantiate-component :c01
|
|
:copy-clean
|
|
:children-labels [:copy-clean-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-font-size
|
|
:children-labels [:copy-font-size-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-text
|
|
:children-labels [:copy-text-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-both
|
|
:children-labels [:copy-both-t]))
|
|
|
|
|
|
;; The copy clean has no overrides
|
|
copy-clean-t (ths/get-shape file :copy-clean-t)
|
|
|
|
;; Override font size on copy-font-size
|
|
file (update-attr file :copy-font-size-t font-size-path-0 "25")
|
|
copy-font-size-t (ths/get-shape file :copy-font-size-t)
|
|
|
|
;; Override text on copy-text
|
|
file (update-attr file :copy-text-t text-path-0 "text overriden")
|
|
copy-text-t (ths/get-shape file :copy-text-t)
|
|
|
|
;; Override both on copy-both
|
|
file (update-attr file :copy-both-t font-size-path-0 "25")
|
|
file (update-attr file :copy-both-t text-path-0 "text overriden")
|
|
copy-both-t (ths/get-shape file :copy-both-t)
|
|
|
|
|
|
;; ==== Action: Switch all the copies
|
|
|
|
|
|
file' (-> file
|
|
(tho/swap-component-in-shape :copy-clean :c02 {:new-shape-label :copy-clean-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-font-size :c02 {:new-shape-label :copy-font-size-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-text :c02 {:new-shape-label :copy-text-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-both :c02 {:new-shape-label :copy-both-2 :keep-touched? true}))
|
|
page' (thf/current-page file')
|
|
copy-clean' (ths/get-shape file' :copy-clean-2)
|
|
copy-clean-t' (get-in page' [:objects (-> copy-clean' :shapes first)])
|
|
|
|
copy-font-size' (ths/get-shape file' :copy-font-size-2)
|
|
copy-font-size-t' (get-in page' [:objects (-> copy-font-size' :shapes first)])
|
|
|
|
copy-text' (ths/get-shape file' :copy-text-2)
|
|
copy-text-t' (get-in page' [:objects (-> copy-text' :shapes first)])
|
|
|
|
copy-both' (ths/get-shape file' :copy-both-2)
|
|
copy-both-t' (get-in page' [:objects (-> copy-both' :shapes first)])]
|
|
|
|
(thf/dump-file file' {:keys [:name #_:content]})
|
|
|
|
|
|
;;;;;;;;;;; Clean copy
|
|
;; Before the switch:
|
|
;; * font size 14
|
|
;; * text "hello world"
|
|
|
|
|
|
(t/is (= (get-in copy-clean-t font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-clean-t text-path-0) "hello world"))
|
|
|
|
;; After the switch:
|
|
;; * font size 25 (value of c02, because there was no override)
|
|
;; * text "hello world" (value of c02, because there was no override)
|
|
(t/is (= (get-in copy-clean-t' font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-clean-t' text-path-0) "hello world"))
|
|
|
|
|
|
;;;;;;;;;;; Font size copy
|
|
;; Before the switch:
|
|
;; * font size 25
|
|
;; * text "hello world"
|
|
|
|
|
|
(t/is (= (get-in copy-font-size-t font-size-path-0) "25"))
|
|
(t/is (= (get-in copy-font-size-t text-path-0) "hello world"))
|
|
|
|
;; After the switch:
|
|
;; * font size 25 (the override is preserved)
|
|
;; * text "hello world" (value of c02, because there was no override)
|
|
(t/is (= (get-in copy-font-size-t' font-size-path-0) "25"))
|
|
(t/is (= (get-in copy-font-size-t' text-path-0) "hello world"))
|
|
|
|
;;;;;;;;;;; Text copy
|
|
;; Before the switch:
|
|
;; * font size 14
|
|
;; * text "text overriden"
|
|
(t/is (= (get-in copy-text-t font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-text-t text-path-0) "text overriden"))
|
|
|
|
;; After the switch:
|
|
;; * font size 14 (value of c02, because there was no override)
|
|
;; * text "text overriden" (the override is preserved)
|
|
(t/is (= (get-in copy-text-t' font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-text-t' text-path-0) "text overriden"))
|
|
|
|
;;;;;;;;;;; Both copy
|
|
;; Before the switch:
|
|
;; * font size 25
|
|
;; * text "text overriden"
|
|
(t/is (= (get-in copy-both-t font-size-path-0) "25"))
|
|
(t/is (= (get-in copy-both-t text-path-0) "text overriden"))
|
|
|
|
;; After the switch:
|
|
;; * font size 25 (the override is preserved)
|
|
;; * text "text overriden" (the override is preserved)
|
|
(t/is (= (get-in copy-both-t' font-size-path-0) "25"))
|
|
(t/is (= (get-in copy-both-t' text-path-0) "text overriden"))))
|
|
|
|
;; ============================================================
|
|
;; TEXT OVERRIDES (different property)
|
|
;; ============================================================
|
|
|
|
(t/deftest test-switch-with-different-prop-text-override
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
;; The second component has a different prop
|
|
(thv/add-variant-with-text
|
|
:v01 :c01 :m01 :c02 :m02 :t01 :t02 "hello world" "hello world")
|
|
(update-attr :t02 font-size-path-0 "50")
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy-clean
|
|
:children-labels [:copy-clean-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-font-size
|
|
:children-labels [:copy-font-size-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-text
|
|
:children-labels [:copy-text-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-both
|
|
:children-labels [:copy-both-t]))
|
|
|
|
|
|
;; The copy clean has no overrides
|
|
copy-clean-t (ths/get-shape file :copy-clean-t)
|
|
|
|
;; Override font size on copy-font-size
|
|
file (update-attr file :copy-font-size-t font-size-path-0 "25")
|
|
copy-font-size-t (ths/get-shape file :copy-font-size-t)
|
|
|
|
;; Override text on copy-text
|
|
file (update-attr file :copy-text-t text-path-0 "text overriden")
|
|
copy-text-t (ths/get-shape file :copy-text-t)
|
|
|
|
;; Override both on copy-both
|
|
file (update-attr file :copy-both-t font-size-path-0 "25")
|
|
file (update-attr file :copy-both-t text-path-0 "text overriden")
|
|
copy-both-t (ths/get-shape file :copy-both-t)
|
|
|
|
|
|
;; ==== Action: Switch all the copies
|
|
|
|
|
|
file' (-> file
|
|
(tho/swap-component-in-shape :copy-clean :c02 {:new-shape-label :copy-clean-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-font-size :c02 {:new-shape-label :copy-font-size-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-text :c02 {:new-shape-label :copy-text-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-both :c02 {:new-shape-label :copy-both-2 :keep-touched? true}))
|
|
page' (thf/current-page file')
|
|
copy-clean' (ths/get-shape file' :copy-clean-2)
|
|
copy-clean-t' (get-in page' [:objects (-> copy-clean' :shapes first)])
|
|
|
|
copy-font-size' (ths/get-shape file' :copy-font-size-2)
|
|
copy-font-size-t' (get-in page' [:objects (-> copy-font-size' :shapes first)])
|
|
|
|
copy-text' (ths/get-shape file' :copy-text-2)
|
|
copy-text-t' (get-in page' [:objects (-> copy-text' :shapes first)])
|
|
|
|
copy-both' (ths/get-shape file' :copy-both-2)
|
|
copy-both-t' (get-in page' [:objects (-> copy-both' :shapes first)])]
|
|
|
|
(thf/dump-file file' {:keys [:name #_:content]})
|
|
|
|
|
|
;;;;;;;;;;; Clean copy
|
|
;; Before the switch:
|
|
;; * font size 14
|
|
;; * text "hello world"
|
|
|
|
|
|
(t/is (= (get-in copy-clean-t font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-clean-t text-path-0) "hello world"))
|
|
|
|
;; After the switch:
|
|
;; * font size 50 (value of c02, because there was no override)
|
|
;; * text "hello world" (value of c02, because there was no override)
|
|
(t/is (= (get-in copy-clean-t' font-size-path-0) "50"))
|
|
(t/is (= (get-in copy-clean-t' text-path-0) "hello world"))
|
|
|
|
|
|
;;;;;;;;;;; Font size copy
|
|
;; Before the switch:
|
|
;; * font size 25
|
|
;; * text "hello world"
|
|
|
|
|
|
(t/is (= (get-in copy-font-size-t font-size-path-0) "25"))
|
|
(t/is (= (get-in copy-font-size-t text-path-0) "hello world"))
|
|
|
|
;; After the switch:
|
|
;; * font size 50 (value of c02: the override is not preserved)
|
|
;; * text "hello world" (value of c02, because there was no override)
|
|
(t/is (= (get-in copy-font-size-t' font-size-path-0) "50"))
|
|
(t/is (= (get-in copy-font-size-t' text-path-0) "hello world"))
|
|
|
|
;;;;;;;;;;; Text copy
|
|
;; Before the switch:
|
|
;; * font size 14
|
|
;; * text "text overriden"
|
|
(t/is (= (get-in copy-text-t font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-text-t text-path-0) "text overriden"))
|
|
|
|
;; After the switch:
|
|
;; * font size 50 (value of c02, because there was no override)
|
|
;; * text "text overriden" (the override is preserved)
|
|
(t/is (= (get-in copy-text-t' font-size-path-0) "50"))
|
|
(t/is (= (get-in copy-text-t' text-path-0) "text overriden"))
|
|
|
|
;;;;;;;;;;; Both copy
|
|
;; Before the switch:
|
|
;; * font size 25
|
|
;; * text "text overriden"
|
|
(t/is (= (get-in copy-both-t font-size-path-0) "25"))
|
|
(t/is (= (get-in copy-both-t text-path-0) "text overriden"))
|
|
|
|
;; After the switch:
|
|
;; * font size 50 (value of c02: the override is not preserved)
|
|
;; * text "text overriden" (the override is preserved)
|
|
(t/is (= (get-in copy-both-t' font-size-path-0) "50"))
|
|
(t/is (= (get-in copy-both-t' text-path-0) "text overriden"))))
|
|
|
|
;; ============================================================
|
|
;; TEXT OVERRIDES (different text)
|
|
;; ============================================================
|
|
|
|
(t/deftest test-switch-with-different-text-text-override
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
;; Second comp has different text
|
|
(thv/add-variant-with-text
|
|
:v01 :c01 :m01 :c02 :m02 :t01 :t02 "hello world" "bye")
|
|
(thc/instantiate-component :c01
|
|
:copy-clean
|
|
:children-labels [:copy-clean-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-font-size
|
|
:children-labels [:copy-font-size-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-text
|
|
:children-labels [:copy-text-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-both
|
|
:children-labels [:copy-both-t]))
|
|
|
|
|
|
;; The copy clean has no overrides
|
|
copy-clean-t (ths/get-shape file :copy-clean-t)
|
|
|
|
;; Override font size on copy-font-size
|
|
file (update-attr file :copy-font-size-t font-size-path-0 "25")
|
|
copy-font-size-t (ths/get-shape file :copy-font-size-t)
|
|
|
|
;; Override text on copy-text
|
|
file (update-attr file :copy-text-t text-path-0 "text overriden")
|
|
copy-text-t (ths/get-shape file :copy-text-t)
|
|
|
|
;; Override both on copy-both
|
|
file (update-attr file :copy-both-t font-size-path-0 "25")
|
|
file (update-attr file :copy-both-t text-path-0 "text overriden")
|
|
copy-both-t (ths/get-shape file :copy-both-t)
|
|
|
|
|
|
;; ==== Action: Switch all the copies
|
|
|
|
|
|
file' (-> file
|
|
(tho/swap-component-in-shape :copy-clean :c02 {:new-shape-label :copy-clean-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-font-size :c02 {:new-shape-label :copy-font-size-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-text :c02 {:new-shape-label :copy-text-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-both :c02 {:new-shape-label :copy-both-2 :keep-touched? true}))
|
|
page' (thf/current-page file')
|
|
copy-clean' (ths/get-shape file' :copy-clean-2)
|
|
copy-clean-t' (get-in page' [:objects (-> copy-clean' :shapes first)])
|
|
|
|
copy-font-size' (ths/get-shape file' :copy-font-size-2)
|
|
copy-font-size-t' (get-in page' [:objects (-> copy-font-size' :shapes first)])
|
|
|
|
copy-text' (ths/get-shape file' :copy-text-2)
|
|
copy-text-t' (get-in page' [:objects (-> copy-text' :shapes first)])
|
|
|
|
copy-both' (ths/get-shape file' :copy-both-2)
|
|
copy-both-t' (get-in page' [:objects (-> copy-both' :shapes first)])]
|
|
|
|
(thf/dump-file file' {:keys [:name #_:content]})
|
|
|
|
|
|
;;;;;;;;;;; Clean copy
|
|
;; Before the switch:
|
|
;; * font size 14
|
|
;; * text "hello world"
|
|
|
|
|
|
(t/is (= (get-in copy-clean-t font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-clean-t text-path-0) "hello world"))
|
|
|
|
;; After the switch:
|
|
;; * font size 25 (value of c02, because there was no override)
|
|
;; * text "bye" (value of c02, because there was no override)
|
|
(t/is (= (get-in copy-clean-t' font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-clean-t' text-path-0) "bye"))
|
|
|
|
|
|
;;;;;;;;;;; Font size copy
|
|
;; Before the switch:
|
|
;; * font size 25
|
|
;; * text "hello world"
|
|
|
|
|
|
(t/is (= (get-in copy-font-size-t font-size-path-0) "25"))
|
|
(t/is (= (get-in copy-font-size-t text-path-0) "hello world"))
|
|
|
|
;; After the switch:
|
|
;; * font size 25 (the override is preserved)
|
|
;; * text "bye" (value of c02, because there was no override)
|
|
(t/is (= (get-in copy-font-size-t' font-size-path-0) "25"))
|
|
(t/is (= (get-in copy-font-size-t' text-path-0) "bye"))
|
|
|
|
;;;;;;;;;;; Text copy
|
|
;; Before the switch:
|
|
;; * font size 14
|
|
;; * text "text overriden"
|
|
(t/is (= (get-in copy-text-t font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-text-t text-path-0) "text overriden"))
|
|
|
|
;; After the switch:
|
|
;; * font size 14 (value of c02, because there was no override)
|
|
;; * text "text overriden" (value of c02: the override is not preserved)
|
|
(t/is (= (get-in copy-text-t' font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-text-t' text-path-0) "bye"))
|
|
|
|
;;;;;;;;;;; Both copy
|
|
;; Before the switch:
|
|
;; * font size 25
|
|
;; * text "text overriden"
|
|
(t/is (= (get-in copy-both-t font-size-path-0) "25"))
|
|
(t/is (= (get-in copy-both-t text-path-0) "text overriden"))
|
|
|
|
;; After the switch:
|
|
;; * font size 25 (the override is preserved)
|
|
;; * text "text overriden" (value of c02: the override is not preserved)
|
|
(t/is (= (get-in copy-both-t' font-size-path-0) "25"))
|
|
(t/is (= (get-in copy-both-t' text-path-0) "bye"))))
|
|
|
|
;; ============================================================
|
|
;; TEXT OVERRIDES (different text AND property)
|
|
;; ============================================================
|
|
|
|
(t/deftest test-switch-with-different-text-and-prop-text-override
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
;; The second component has a different text and prop
|
|
(thv/add-variant-with-text
|
|
:v01 :c01 :m01 :c02 :m02 :t01 :t02 "hello world" "bye")
|
|
(update-attr :t02 font-size-path-0 "50")
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy-clean
|
|
:children-labels [:copy-clean-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-font-size
|
|
:children-labels [:copy-font-size-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-text
|
|
:children-labels [:copy-text-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-both
|
|
:children-labels [:copy-both-t]))
|
|
|
|
|
|
;; The copy clean has no overrides
|
|
copy-clean-t (ths/get-shape file :copy-clean-t)
|
|
|
|
;; Override font size on copy-font-size
|
|
file (update-attr file :copy-font-size-t font-size-path-0 "25")
|
|
copy-font-size-t (ths/get-shape file :copy-font-size-t)
|
|
|
|
;; Override text on copy-text
|
|
file (update-attr file :copy-text-t text-path-0 "text overriden")
|
|
copy-text-t (ths/get-shape file :copy-text-t)
|
|
|
|
;; Override both on copy-both
|
|
file (update-attr file :copy-both-t font-size-path-0 "25")
|
|
file (update-attr file :copy-both-t text-path-0 "text overriden")
|
|
copy-both-t (ths/get-shape file :copy-both-t)
|
|
|
|
|
|
;; ==== Action: Switch all the copies
|
|
|
|
|
|
file' (-> file
|
|
(tho/swap-component-in-shape :copy-clean :c02 {:new-shape-label :copy-clean-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-font-size :c02 {:new-shape-label :copy-font-size-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-text :c02 {:new-shape-label :copy-text-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-both :c02 {:new-shape-label :copy-both-2 :keep-touched? true}))
|
|
page' (thf/current-page file')
|
|
copy-clean' (ths/get-shape file' :copy-clean-2)
|
|
copy-clean-t' (get-in page' [:objects (-> copy-clean' :shapes first)])
|
|
|
|
copy-font-size' (ths/get-shape file' :copy-font-size-2)
|
|
copy-font-size-t' (get-in page' [:objects (-> copy-font-size' :shapes first)])
|
|
|
|
copy-text' (ths/get-shape file' :copy-text-2)
|
|
copy-text-t' (get-in page' [:objects (-> copy-text' :shapes first)])
|
|
|
|
copy-both' (ths/get-shape file' :copy-both-2)
|
|
copy-both-t' (get-in page' [:objects (-> copy-both' :shapes first)])]
|
|
|
|
(thf/dump-file file' {:keys [:name #_:content]})
|
|
|
|
|
|
;;;;;;;;;;; Clean copy
|
|
;; Before the switch:
|
|
;; * font size 14
|
|
;; * text "hello world"
|
|
|
|
|
|
(t/is (= (get-in copy-clean-t font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-clean-t text-path-0) "hello world"))
|
|
|
|
;; After the switch:
|
|
;; * font size 50 (value of c02, because there was no override)
|
|
;; * text "bye" (value of c02, because there was no override)
|
|
(t/is (= (get-in copy-clean-t' font-size-path-0) "50"))
|
|
(t/is (= (get-in copy-clean-t' text-path-0) "bye"))
|
|
|
|
|
|
;;;;;;;;;;; Font size copy
|
|
;; Before the switch:
|
|
;; * font size 25
|
|
;; * text "hello world"
|
|
|
|
|
|
(t/is (= (get-in copy-font-size-t font-size-path-0) "25"))
|
|
(t/is (= (get-in copy-font-size-t text-path-0) "hello world"))
|
|
|
|
;; After the switch:
|
|
;; * font size 50 (value of c02: the override is not preserved)
|
|
;; * text "bye" (value of c02, because there was no override)
|
|
(t/is (= (get-in copy-font-size-t' font-size-path-0) "50"))
|
|
(t/is (= (get-in copy-font-size-t' text-path-0) "bye"))
|
|
|
|
;;;;;;;;;;; Text copy
|
|
;; Before the switch:
|
|
;; * font size 14
|
|
;; * text "text overriden"
|
|
(t/is (= (get-in copy-text-t font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-text-t text-path-0) "text overriden"))
|
|
|
|
;; After the switch:
|
|
;; * font size 50 (value of c02, because there was no override)
|
|
;; * text "bye" (value of c02: the override is not preserved)
|
|
(t/is (= (get-in copy-text-t' font-size-path-0) "50"))
|
|
(t/is (= (get-in copy-text-t' text-path-0) "bye"))
|
|
|
|
;;;;;;;;;;; Both copy
|
|
;; Before the switch:
|
|
;; * font size 25
|
|
;; * text "text overriden"
|
|
(t/is (= (get-in copy-both-t font-size-path-0) "25"))
|
|
(t/is (= (get-in copy-both-t text-path-0) "text overriden"))
|
|
|
|
;; After the switch:
|
|
;; * font size 50 (value of c02: the override is not preserved)
|
|
;; * text "bye" (value of c02: the override is not preserved)
|
|
(t/is (= (get-in copy-both-t' font-size-path-0) "50"))
|
|
(t/is (= (get-in copy-both-t' text-path-0) "bye"))))
|
|
|
|
;; ============================================================
|
|
;; TEXT STRUCTURE OVERRIDES (identical variants)
|
|
;; ============================================================
|
|
|
|
(t/deftest test-switch-with-identical-structure-text-override
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
;; Both components are identical: have the same text and props
|
|
(thv/add-variant-with-text
|
|
:v01 :c01 :m01 :c02 :m02 :t01 :t02 "hello world" "hello world")
|
|
(thc/instantiate-component :c01
|
|
:copy-structure-clean
|
|
:children-labels [:copy-structure-clean-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-structure-unif
|
|
:children-labels [:copy-structure-unif-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-structure-mixed
|
|
:children-labels [:copy-structure-mixed-t]))
|
|
|
|
|
|
|
|
;; Duplicate a text line in copy-structure-clean
|
|
|
|
|
|
file (change-structure file :copy-structure-clean-t)
|
|
copy-structure-clean-t (ths/get-shape file :copy-structure-clean-t)
|
|
|
|
;; Duplicate a text line in copy-structure-clean, updating
|
|
;; both lines with the same attrs
|
|
file (-> (update-attr file :copy-structure-unif-t font-size-path-0 "25")
|
|
(change-structure :copy-structure-unif-t))
|
|
copy-structure-unif-t (ths/get-shape file :copy-structure-unif-t)
|
|
|
|
;; Duplicate a text line in copy-structure-clean, updating
|
|
;; each line with a different attr
|
|
file (-> (change-structure file :copy-structure-mixed-t)
|
|
(update-attr :copy-structure-mixed-t font-size-path-0 "35")
|
|
(update-attr :copy-structure-mixed-t font-size-path-1 "40"))
|
|
copy-structure-mixed-t (ths/get-shape file :copy-structure-mixed-t)
|
|
|
|
|
|
;; ==== Action: Switch all the copies
|
|
|
|
|
|
file' (-> file
|
|
(tho/swap-component-in-shape :copy-structure-clean :c02 {:new-shape-label :copy-structure-clean-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-structure-unif :c02 {:new-shape-label :copy-structure-unif-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-structure-mixed :c02 {:new-shape-label :copy-structure-mixed-2 :keep-touched? true}))
|
|
page' (thf/current-page file')
|
|
copy-structure-clean' (ths/get-shape file' :copy-structure-clean-2)
|
|
copy-structure-clean-t' (get-in page' [:objects (-> copy-structure-clean' :shapes first)])
|
|
|
|
copy-structure-unif' (ths/get-shape file' :copy-structure-unif-2)
|
|
copy-structure-unif-t' (get-in page' [:objects (-> copy-structure-unif' :shapes first)])
|
|
|
|
copy-structure-mixed' (ths/get-shape file' :copy-structure-mixed-2)
|
|
copy-structure-mixed-t' (get-in page' [:objects (-> copy-structure-mixed' :shapes first)])]
|
|
|
|
(thf/dump-file file' {:keys [:name #_:content]})
|
|
|
|
;;;;;;;;;;; Copy structure clean
|
|
;; Before the switch, first line:
|
|
;; * font size 14
|
|
;; * text "new line 1"
|
|
;; Second line:
|
|
;; * font size 14
|
|
;; * text "new line 2"
|
|
(t/is (= (get-in copy-structure-clean-t font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-structure-clean-t text-path-0) "new line 1"))
|
|
(t/is (= (get-in copy-structure-clean-t font-size-path-1) "14"))
|
|
(t/is (= (get-in copy-structure-clean-t text-path-1) "new line 2"))
|
|
|
|
;; After the switch, first line:
|
|
;; * font size 14 (value of c02, because there was no override)
|
|
;; * text "new line 1" (the override is preserved)
|
|
;; Second line:
|
|
;; * font size 14 (value of c02, because there was no override)
|
|
;; * text "new line 2" (the override is preserved)
|
|
(t/is (= (get-in copy-structure-clean-t' font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-structure-clean-t' text-path-0) "new line 1"))
|
|
(t/is (= (get-in copy-structure-clean-t' font-size-path-1) "14"))
|
|
(t/is (= (get-in copy-structure-clean-t' text-path-1) "new line 2"))
|
|
|
|
;;;;;;;;;;; Copy structure unif
|
|
;; Before the switch, first line:
|
|
;; * font size 25
|
|
;; * text "new line 1"
|
|
;; Second line:
|
|
;; * font size 25
|
|
;; * text "new line 2"
|
|
(t/is (= (get-in copy-structure-unif-t font-size-path-0) "25"))
|
|
(t/is (= (get-in copy-structure-unif-t text-path-0) "new line 1"))
|
|
(t/is (= (get-in copy-structure-unif-t font-size-path-1) "25"))
|
|
(t/is (= (get-in copy-structure-unif-t text-path-1) "new line 2"))
|
|
|
|
;; After the switch, first line:
|
|
;; * font size 25 (the override is preserved)
|
|
;; * text "new line 1" (the override is preserved)
|
|
;; Second line:
|
|
;; * font size 25 (the override is preserved)
|
|
;; * text "new line 2" (the override is preserved)
|
|
(t/is (= (get-in copy-structure-unif-t' font-size-path-0) "25"))
|
|
(t/is (= (get-in copy-structure-unif-t' text-path-0) "new line 1"))
|
|
(t/is (= (get-in copy-structure-unif-t' font-size-path-1) "25"))
|
|
(t/is (= (get-in copy-structure-unif-t' text-path-1) "new line 2"))
|
|
|
|
;;;;;;;;;;; Copy structure mixed
|
|
;; Before the switch, first line:
|
|
;; * font size 35
|
|
;; * text "new line 1"
|
|
;; Before the switch, second line:
|
|
;; * font size 40
|
|
;; * text "new line 2"
|
|
(t/is (= (get-in copy-structure-mixed-t font-size-path-0) "35"))
|
|
(t/is (= (get-in copy-structure-mixed-t text-path-0) "new line 1"))
|
|
(t/is (= (get-in copy-structure-mixed-t font-size-path-1) "40"))
|
|
(t/is (= (get-in copy-structure-mixed-t text-path-1) "new line 2"))
|
|
|
|
;; After the switch, first line:
|
|
;; * font size 35 (the override is preserved)
|
|
;; * text "new line 1" (the override is preserved)
|
|
;; Second line:
|
|
;; * font size 40 (the override is preserved)
|
|
;; * text "new line 2" (the override is preserved)
|
|
(t/is (= (get-in copy-structure-mixed-t' font-size-path-0) "35"))
|
|
(t/is (= (get-in copy-structure-mixed-t' text-path-0) "new line 1"))
|
|
(t/is (= (get-in copy-structure-mixed-t' font-size-path-1) "40"))
|
|
(t/is (= (get-in copy-structure-mixed-t' text-path-1) "new line 2"))))
|
|
|
|
;; ============================================================
|
|
;; TEXT STRUCTURE OVERRIDES (different property)
|
|
;; ============================================================
|
|
|
|
(t/deftest test-switch-with-different-prop-structure-text-override
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
;; The second component has a different prop
|
|
(thv/add-variant-with-text
|
|
:v01 :c01 :m01 :c02 :m02 :t01 :t02 "hello world" "hello world")
|
|
(update-attr :t02 font-size-path-0 "50")
|
|
(thc/instantiate-component :c01
|
|
:copy-structure-clean
|
|
:children-labels [:copy-structure-clean-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-structure-unif
|
|
:children-labels [:copy-structure-unif-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-structure-mixed
|
|
:children-labels [:copy-structure-mixed-t]))
|
|
|
|
|
|
|
|
;; Duplicate a text line in copy-structure-clean
|
|
|
|
|
|
file (change-structure file :copy-structure-clean-t)
|
|
copy-structure-clean-t (ths/get-shape file :copy-structure-clean-t)
|
|
|
|
;; Duplicate a text line in copy-structure-clean, updating
|
|
;; both lines with the same attrs
|
|
file (-> (update-attr file :copy-structure-unif-t font-size-path-0 "25")
|
|
(change-structure :copy-structure-unif-t))
|
|
copy-structure-unif-t (ths/get-shape file :copy-structure-unif-t)
|
|
|
|
;; Duplicate a text line in copy-structure-clean, updating
|
|
;; each line with a different attr
|
|
file (-> (change-structure file :copy-structure-mixed-t)
|
|
(update-attr :copy-structure-mixed-t font-size-path-0 "35")
|
|
(update-attr :copy-structure-mixed-t font-size-path-1 "40"))
|
|
copy-structure-mixed-t (ths/get-shape file :copy-structure-mixed-t)
|
|
|
|
|
|
;; ==== Action: Switch all the copies
|
|
|
|
|
|
file' (-> file
|
|
(tho/swap-component-in-shape :copy-structure-clean :c02 {:new-shape-label :copy-structure-clean-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-structure-unif :c02 {:new-shape-label :copy-structure-unif-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-structure-mixed :c02 {:new-shape-label :copy-structure-mixed-2 :keep-touched? true}))
|
|
page' (thf/current-page file')
|
|
copy-structure-clean' (ths/get-shape file' :copy-structure-clean-2)
|
|
copy-structure-clean-t' (get-in page' [:objects (-> copy-structure-clean' :shapes first)])
|
|
|
|
copy-structure-unif' (ths/get-shape file' :copy-structure-unif-2)
|
|
copy-structure-unif-t' (get-in page' [:objects (-> copy-structure-unif' :shapes first)])
|
|
|
|
copy-structure-mixed' (ths/get-shape file' :copy-structure-mixed-2)
|
|
copy-structure-mixed-t' (get-in page' [:objects (-> copy-structure-mixed' :shapes first)])]
|
|
|
|
(thf/dump-file file' {:keys [:name #_:content]})
|
|
|
|
;;;;;;;;;;; Copy structure clean
|
|
;; Before the switch, first line:
|
|
;; * font size 14
|
|
;; * text "new line 1"
|
|
;; Second line:
|
|
;; * font size 14
|
|
;; * text "new line 2"
|
|
(t/is (= (get-in copy-structure-clean-t font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-structure-clean-t text-path-0) "new line 1"))
|
|
(t/is (= (get-in copy-structure-clean-t font-size-path-1) "14"))
|
|
(t/is (= (get-in copy-structure-clean-t text-path-1) "new line 2"))
|
|
|
|
;; After the switch, first line:
|
|
;; * font size 50 (value of c02, because there was no override)
|
|
;; * text "new line 1" (the override is preserved)
|
|
;; Second line:
|
|
;; * font size 50 (value of c02, because there was no override)
|
|
;; * text "new line 2" (the override is preserved)
|
|
(t/is (= (get-in copy-structure-clean-t' font-size-path-0) "50"))
|
|
(t/is (= (get-in copy-structure-clean-t' text-path-0) "new line 1"))
|
|
(t/is (= (get-in copy-structure-clean-t' font-size-path-1) "50"))
|
|
(t/is (= (get-in copy-structure-clean-t' text-path-1) "new line 2"))
|
|
|
|
;;;;;;;;;;; Copy structure unif
|
|
;; Before the switch, first line:
|
|
;; * font size 25
|
|
;; * text "new line 1"
|
|
;; Second line:
|
|
;; * font size 25
|
|
;; * text "new line 2"
|
|
(t/is (= (get-in copy-structure-unif-t font-size-path-0) "25"))
|
|
(t/is (= (get-in copy-structure-unif-t text-path-0) "new line 1"))
|
|
(t/is (= (get-in copy-structure-unif-t font-size-path-1) "25"))
|
|
(t/is (= (get-in copy-structure-unif-t text-path-1) "new line 2"))
|
|
|
|
;; After the switch, first line:
|
|
;; * font size 50 (the override is not preserved)
|
|
;; * text "new line 1" (the override is preserved)
|
|
;; Second line:
|
|
;; * font size 50 (the override is not preserved)
|
|
;; * text "new line 2" (the override is preserved)
|
|
(t/is (= (get-in copy-structure-unif-t' font-size-path-0) "50"))
|
|
(t/is (= (get-in copy-structure-unif-t' text-path-0) "new line 1"))
|
|
(t/is (= (get-in copy-structure-unif-t' font-size-path-1) "50"))
|
|
(t/is (= (get-in copy-structure-unif-t' text-path-1) "new line 2"))
|
|
|
|
;;;;;;;;;;; Copy structure mixed
|
|
;; Before the switch, first line:
|
|
;; * font size 35
|
|
;; * text "new line 1"
|
|
;; Before the switch, second line:
|
|
;; * font size 40
|
|
;; * text "new line 2"
|
|
(t/is (= (get-in copy-structure-mixed-t font-size-path-0) "35"))
|
|
(t/is (= (get-in copy-structure-mixed-t text-path-0) "new line 1"))
|
|
(t/is (= (get-in copy-structure-mixed-t font-size-path-1) "40"))
|
|
(t/is (= (get-in copy-structure-mixed-t text-path-1) "new line 2"))
|
|
|
|
;; After the switch, first line:
|
|
;; * font size 50 (the override is not preserved)
|
|
;; * text "hello world" (the override is not preserved)
|
|
;; No second line
|
|
(t/is (= (get-in copy-structure-mixed-t' font-size-path-0) "50"))
|
|
(t/is (= (get-in copy-structure-mixed-t' text-path-0) "hello world"))
|
|
(t/is (nil? (get-in copy-structure-mixed-t' font-size-path-1)))))
|
|
|
|
;; ============================================================
|
|
;; TEXT STRUCTURE OVERRIDES (different text)
|
|
;; ============================================================
|
|
|
|
(t/deftest test-switch-with-different-text-structure-text-override
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
;; Second comp has different text
|
|
(thv/add-variant-with-text
|
|
:v01 :c01 :m01 :c02 :m02 :t01 :t02 "hello world" "bye")
|
|
(thc/instantiate-component :c01
|
|
:copy-structure-clean
|
|
:children-labels [:copy-structure-clean-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-structure-unif
|
|
:children-labels [:copy-structure-unif-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-structure-mixed
|
|
:children-labels [:copy-structure-mixed-t]))
|
|
|
|
|
|
|
|
;; Duplicate a text line in copy-structure-clean
|
|
|
|
|
|
file (change-structure file :copy-structure-clean-t)
|
|
copy-structure-clean-t (ths/get-shape file :copy-structure-clean-t)
|
|
|
|
;; Duplicate a text line in copy-structure-clean, updating
|
|
;; both lines with the same attrs
|
|
file (-> (update-attr file :copy-structure-unif-t font-size-path-0 "25")
|
|
(change-structure :copy-structure-unif-t))
|
|
copy-structure-unif-t (ths/get-shape file :copy-structure-unif-t)
|
|
|
|
;; Duplicate a text line in copy-structure-clean, updating
|
|
;; each line with a different attr
|
|
file (-> (change-structure file :copy-structure-mixed-t)
|
|
(update-attr :copy-structure-mixed-t font-size-path-0 "35")
|
|
(update-attr :copy-structure-mixed-t font-size-path-1 "40"))
|
|
copy-structure-mixed-t (ths/get-shape file :copy-structure-mixed-t)
|
|
|
|
|
|
;; ==== Action: Switch all the copies
|
|
|
|
|
|
file' (-> file
|
|
(tho/swap-component-in-shape :copy-structure-clean :c02 {:new-shape-label :copy-structure-clean-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-structure-unif :c02 {:new-shape-label :copy-structure-unif-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-structure-mixed :c02 {:new-shape-label :copy-structure-mixed-2 :keep-touched? true}))
|
|
page' (thf/current-page file')
|
|
copy-structure-clean' (ths/get-shape file' :copy-structure-clean-2)
|
|
copy-structure-clean-t' (get-in page' [:objects (-> copy-structure-clean' :shapes first)])
|
|
|
|
copy-structure-unif' (ths/get-shape file' :copy-structure-unif-2)
|
|
copy-structure-unif-t' (get-in page' [:objects (-> copy-structure-unif' :shapes first)])
|
|
|
|
copy-structure-mixed' (ths/get-shape file' :copy-structure-mixed-2)
|
|
copy-structure-mixed-t' (get-in page' [:objects (-> copy-structure-mixed' :shapes first)])]
|
|
|
|
(thf/dump-file file' {:keys [:name #_:content]})
|
|
|
|
;;;;;;;;;;; Copy structure clean
|
|
;; Before the switch, first line:
|
|
;; * font size 14
|
|
;; * text "new line 1"
|
|
;; Second line:
|
|
;; * font size 14
|
|
;; * text "new line 2"
|
|
(t/is (= (get-in copy-structure-clean-t font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-structure-clean-t text-path-0) "new line 1"))
|
|
(t/is (= (get-in copy-structure-clean-t font-size-path-1) "14"))
|
|
(t/is (= (get-in copy-structure-clean-t text-path-1) "new line 2"))
|
|
|
|
;; After the switch, first line:
|
|
;; * font size 14 (value of c02, because there was no override)
|
|
;; * text "bye" (the override is not preserved)
|
|
;; No second line
|
|
(t/is (= (get-in copy-structure-clean-t' font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-structure-clean-t' text-path-0) "bye"))
|
|
(t/is (nil? (get-in copy-structure-clean-t' font-size-path-1)))
|
|
|
|
|
|
;;;;;;;;;;; Copy structure unif
|
|
;; Before the switch, first line:
|
|
;; * font size 25
|
|
;; * text "new line 1"
|
|
;; Second line:
|
|
;; * font size 25
|
|
;; * text "new line 2"
|
|
|
|
|
|
(t/is (= (get-in copy-structure-unif-t font-size-path-0) "25"))
|
|
(t/is (= (get-in copy-structure-unif-t text-path-0) "new line 1"))
|
|
(t/is (= (get-in copy-structure-unif-t font-size-path-1) "25"))
|
|
(t/is (= (get-in copy-structure-unif-t text-path-1) "new line 2"))
|
|
|
|
;; After the switch, first line:
|
|
;; * font size 25 (the override is preserved)
|
|
;; * text "bye" (the override is not preserved)
|
|
;; No second line
|
|
(t/is (= (get-in copy-structure-unif-t' font-size-path-0) "25"))
|
|
(t/is (= (get-in copy-structure-unif-t' text-path-0) "bye"))
|
|
(t/is (nil? (get-in copy-structure-unif-t' font-size-path-1)))
|
|
|
|
|
|
;;;;;;;;;;; Copy structure mixed
|
|
;; Before the switch, first line:
|
|
;; * font size 35
|
|
;; * text "new line 1"
|
|
;; Before the switch, second line:
|
|
;; * font size 40
|
|
;; * text "new line 2"
|
|
|
|
|
|
(t/is (= (get-in copy-structure-mixed-t font-size-path-0) "35"))
|
|
(t/is (= (get-in copy-structure-mixed-t text-path-0) "new line 1"))
|
|
(t/is (= (get-in copy-structure-mixed-t font-size-path-1) "40"))
|
|
(t/is (= (get-in copy-structure-mixed-t text-path-1) "new line 2"))
|
|
|
|
;; After the switch, first line:
|
|
;; * font size 14 (the override is not preserved)
|
|
;; * text "bye" (the override is not preserved)
|
|
;; No second line
|
|
(t/is (= (get-in copy-structure-mixed-t' font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-structure-mixed-t' text-path-0) "bye"))
|
|
(t/is (nil? (get-in copy-structure-mixed-t' font-size-path-1)))))
|
|
|
|
;; ============================================================
|
|
;; TEXT STRUCTURE OVERRIDES (different text AND property)
|
|
;; ============================================================
|
|
|
|
(t/deftest test-switch-with-different-text-and-prop-structure-text-override
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
;; The second component has a different text and prop
|
|
(thv/add-variant-with-text
|
|
:v01 :c01 :m01 :c02 :m02 :t01 :t02 "hello world" "bye")
|
|
(update-attr :t02 font-size-path-0 "50")
|
|
(thc/instantiate-component :c01
|
|
:copy-structure-clean
|
|
:children-labels [:copy-structure-clean-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-structure-unif
|
|
:children-labels [:copy-structure-unif-t])
|
|
(thc/instantiate-component :c01
|
|
:copy-structure-mixed
|
|
:children-labels [:copy-structure-mixed-t]))
|
|
|
|
|
|
|
|
;; Duplicate a text line in copy-structure-clean
|
|
|
|
|
|
file (change-structure file :copy-structure-clean-t)
|
|
copy-structure-clean-t (ths/get-shape file :copy-structure-clean-t)
|
|
|
|
;; Duplicate a text line in copy-structure-clean, updating
|
|
;; both lines with the same attrs
|
|
file (-> (update-attr file :copy-structure-unif-t font-size-path-0 "25")
|
|
(change-structure :copy-structure-unif-t))
|
|
copy-structure-unif-t (ths/get-shape file :copy-structure-unif-t)
|
|
|
|
;; Duplicate a text line in copy-structure-clean, updating
|
|
;; each line with a different attr
|
|
file (-> (change-structure file :copy-structure-mixed-t)
|
|
(update-attr :copy-structure-mixed-t font-size-path-0 "35")
|
|
(update-attr :copy-structure-mixed-t font-size-path-1 "40"))
|
|
copy-structure-mixed-t (ths/get-shape file :copy-structure-mixed-t)
|
|
|
|
|
|
;; ==== Action: Switch all the copies
|
|
|
|
|
|
file' (-> file
|
|
(tho/swap-component-in-shape :copy-structure-clean :c02 {:new-shape-label :copy-structure-clean-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-structure-unif :c02 {:new-shape-label :copy-structure-unif-2 :keep-touched? true})
|
|
(tho/swap-component-in-shape :copy-structure-mixed :c02 {:new-shape-label :copy-structure-mixed-2 :keep-touched? true}))
|
|
page' (thf/current-page file')
|
|
copy-structure-clean' (ths/get-shape file' :copy-structure-clean-2)
|
|
copy-structure-clean-t' (get-in page' [:objects (-> copy-structure-clean' :shapes first)])
|
|
|
|
copy-structure-unif' (ths/get-shape file' :copy-structure-unif-2)
|
|
copy-structure-unif-t' (get-in page' [:objects (-> copy-structure-unif' :shapes first)])
|
|
|
|
copy-structure-mixed' (ths/get-shape file' :copy-structure-mixed-2)
|
|
copy-structure-mixed-t' (get-in page' [:objects (-> copy-structure-mixed' :shapes first)])]
|
|
|
|
(thf/dump-file file' {:keys [:name #_:content]})
|
|
|
|
;;;;;;;;;;; Copy structure clean
|
|
;; Before the switch, first line:
|
|
;; * font size 14
|
|
;; * text "new line 1"
|
|
;; Second line:
|
|
;; * font size 14
|
|
;; * text "new line 2"
|
|
(t/is (= (get-in copy-structure-clean-t font-size-path-0) "14"))
|
|
(t/is (= (get-in copy-structure-clean-t text-path-0) "new line 1"))
|
|
(t/is (= (get-in copy-structure-clean-t font-size-path-1) "14"))
|
|
(t/is (= (get-in copy-structure-clean-t text-path-1) "new line 2"))
|
|
|
|
;; After the switch, first line:
|
|
;; * font size 50 (value of c02, because there was no override)
|
|
;; * text "bye" (the override is not preserved)
|
|
;; No second line
|
|
(t/is (= (get-in copy-structure-clean-t' font-size-path-0) "50"))
|
|
(t/is (= (get-in copy-structure-clean-t' text-path-0) "bye"))
|
|
(t/is (nil? (get-in copy-structure-clean-t' font-size-path-1)))
|
|
|
|
|
|
;;;;;;;;;;; Copy structure unif
|
|
;; Before the switch, first line:
|
|
;; * font size 25
|
|
;; * text "new line 1"
|
|
;; Second line:
|
|
;; * font size 25
|
|
;; * text "new line 2"
|
|
|
|
|
|
(t/is (= (get-in copy-structure-unif-t font-size-path-0) "25"))
|
|
(t/is (= (get-in copy-structure-unif-t text-path-0) "new line 1"))
|
|
(t/is (= (get-in copy-structure-unif-t font-size-path-1) "25"))
|
|
(t/is (= (get-in copy-structure-unif-t text-path-1) "new line 2"))
|
|
|
|
;; After the switch, first line:
|
|
;; * font size 50 (the override is not preserved)
|
|
;; * text "bye" (the override is not preserved)
|
|
;; No second line
|
|
(t/is (= (get-in copy-structure-unif-t' font-size-path-0) "50"))
|
|
(t/is (= (get-in copy-structure-unif-t' text-path-0) "bye"))
|
|
(t/is (nil? (get-in copy-structure-unif-t' font-size-path-1)))
|
|
|
|
|
|
;;;;;;;;;;; Copy structure mixed
|
|
;; Before the switch, first line:
|
|
;; * font size 35
|
|
;; * text "new line 1"
|
|
;; Before the switch, second line:
|
|
;; * font size 40
|
|
;; * text "new line 2"
|
|
|
|
|
|
(t/is (= (get-in copy-structure-mixed-t font-size-path-0) "35"))
|
|
(t/is (= (get-in copy-structure-mixed-t text-path-0) "new line 1"))
|
|
(t/is (= (get-in copy-structure-mixed-t font-size-path-1) "40"))
|
|
(t/is (= (get-in copy-structure-mixed-t text-path-1) "new line 2"))
|
|
|
|
;; After the switch, first line:
|
|
;; * font size 50 (the override is not preserved)
|
|
;; * text "bye" (the override is not preserved)
|
|
;; No second line
|
|
(t/is (= (get-in copy-structure-mixed-t' font-size-path-0) "50"))
|
|
(t/is (= (get-in copy-structure-mixed-t' text-path-0) "bye"))
|
|
(t/is (nil? (get-in copy-structure-mixed-t' font-size-path-1)))))
|
|
|
|
;; ============================================================
|
|
;; NESTED COMPONENTS (with same component in both variants)
|
|
;; ============================================================
|
|
|
|
(t/deftest test-switch-variant-for-other-with-same-nested-component
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(tho/add-simple-component :external01 :external01-root :external01-child)
|
|
(tho/add-simple-component :external02 :external02-root :external02-child)
|
|
(thv/add-variant-with-copy
|
|
:v01 :c01 :m01 :c02 :m02 :cp01 :cp02 :external01)
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-cp01]))
|
|
|
|
page (thf/current-page file)
|
|
copy-cp01 (ths/get-shape file :copy-cp01)
|
|
copy-cp01-rect-id (-> copy-cp01 :shapes first)
|
|
|
|
|
|
;; On :copy-cp01, change the width of the rect
|
|
|
|
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{copy-cp01-rect-id}
|
|
(fn [shape]
|
|
(assoc shape :width 25))
|
|
(:objects page)
|
|
{})
|
|
file (thf/apply-changes file changes)
|
|
copy-cp01-rect (ths/get-shape-by-id file copy-cp01-rect-id)
|
|
|
|
;; ==== Action
|
|
;; Switch :c01 for :c02
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
copy02 (ths/get-shape file' :copy02)
|
|
copy-cp02' (ths/get-shape-by-id file' (-> copy02 :shapes first))
|
|
copy-cp02-rect' (ths/get-shape-by-id file' (-> copy-cp02' :shapes first))]
|
|
|
|
;; The width of copy-cp01-rect was 25
|
|
(t/is (= (:width copy-cp01-rect) 25))
|
|
|
|
;; The width of copy-cp02-rect' is 25 (change is preserved)
|
|
(t/is (= (:width copy-cp02-rect') 25))))
|
|
|
|
;; ============================================================
|
|
;; SWAPPED COPIES (switching variants that contain swapped components)
|
|
;; ============================================================
|
|
|
|
(t/deftest test-switch-variant-that-has-swaped-copy
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(tho/add-simple-component :external01 :external01-root :external01-child)
|
|
(tho/add-simple-component :external02 :external02-root :external02-child)
|
|
(thv/add-variant-with-copy
|
|
:v01 :c01 :m01 :c02 :m02 :cp01 :cp02 :external01)
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-cp01]))
|
|
|
|
copy01 (ths/get-shape file :copy01)
|
|
external02 (thc/get-component file :external02)
|
|
|
|
;; On :c01, swap the copy of :external01 for a copy of :external02
|
|
file (-> file
|
|
(tho/swap-component-in-shape :copy-cp01 :external02 {:new-shape-label :copy-cp02 :keep-touched? false}))
|
|
copy-cp02 (ths/get-shape file :copy-cp02)
|
|
|
|
;; ==== Action
|
|
;; Switch :c01 for :c02
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
copy02' (ths/get-shape file' :copy02)
|
|
copy-cp02' (ths/get-shape file' :copy-cp02)]
|
|
(thf/dump-file file')
|
|
;;copy-cp02 is a copy of external02
|
|
(t/is (= (:component-id copy-cp02) (:id external02)))
|
|
;;copy-01 had copy-cp02 as child
|
|
(t/is (= (-> copy01 :shapes first) (:id copy-cp02)))
|
|
|
|
;;copy-cp02' is a copy of external02
|
|
(t/is (= (:component-id copy-cp02') (:id external02)))
|
|
;;copy-02' had copy-cp02' as child
|
|
(t/is (= (-> copy02' :shapes first) (:id copy-cp02')))))
|
|
|
|
(t/deftest test-switch-variant-that-has-swaped-copy-with-changed-attr
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(tho/add-simple-component :external01 :external01-root :external01-child)
|
|
(tho/add-simple-component :external02 :external02-root :external02-child)
|
|
(thv/add-variant-with-copy
|
|
:v01 :c01 :m01 :c02 :m02 :cp01 :cp02 :external01)
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-cp01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
external02 (thc/get-component file :external02)
|
|
|
|
;; On :c01, swap the copy of :external01 for a copy of :external02
|
|
file (-> file
|
|
(tho/swap-component-in-shape :copy-cp01 :external02 {:new-shape-label :copy-cp02 :keep-touched? false}))
|
|
copy-cp02 (ths/get-shape file :copy-cp02)
|
|
copy-cp02-rect-id (-> copy-cp02 :shapes first)
|
|
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{copy-cp02-rect-id}
|
|
(fn [shape]
|
|
(assoc shape :width 25))
|
|
(:objects page)
|
|
{})
|
|
file (thf/apply-changes file changes)
|
|
copy-cp02-rect (ths/get-shape-by-id file copy-cp02-rect-id)
|
|
|
|
;; ==== Action
|
|
;; Switch :c01 for :c02
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
copy02' (ths/get-shape file' :copy02)
|
|
copy-cp02' (ths/get-shape file' :copy-cp02)
|
|
copy-cp02-rect' (ths/get-shape-by-id file' (-> copy-cp02' :shapes first))]
|
|
(thf/dump-file file')
|
|
;;copy-cp02 is a copy of external02
|
|
(t/is (= (:component-id copy-cp02) (:id external02)))
|
|
;;copy-01 had copy-cp02 as child
|
|
(t/is (= (-> copy01 :shapes first) (:id copy-cp02)))
|
|
;; The width of copy-cp02-rect was 25
|
|
(t/is (= (:width copy-cp02-rect) 25))
|
|
|
|
;;copy-cp02' is a copy of external02
|
|
(t/is (= (:component-id copy-cp02') (:id external02)))
|
|
;;copy-02' had copy-cp02' as child
|
|
(t/is (= (-> copy02' :shapes first) (:id copy-cp02')))
|
|
;; The width of copy-cp02-rect' is 25 (change is preserved)
|
|
(t/is (= (:width copy-cp02-rect') 25))))
|
|
|
|
;; ============================================================
|
|
;; TOUCHED PARENT (switch without touched but with touched parent)
|
|
;; ============================================================
|
|
|
|
(t/deftest test-switch-variant-without-touched-but-touched-parent
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 5}
|
|
:child2-params {:width 5}})
|
|
(tho/add-simple-component :external01 :external01-root :external01-child)
|
|
|
|
(thc/instantiate-component :c01
|
|
:c01-in-root
|
|
:children-labels [:r01-in-c01-in-root]
|
|
:parent-label :external01-root))
|
|
|
|
;; Make a change on r01-in-c01-in-root so it is touched
|
|
page (thf/current-page file)
|
|
r01-in-c01-in-root (ths/get-shape file :r01-in-c01-in-root)
|
|
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id r01-in-c01-in-root)}
|
|
(fn [shape]
|
|
(assoc shape :width 25))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
|
|
|
|
;; Instantiate the component :external01
|
|
|
|
|
|
file (thc/instantiate-component file
|
|
:external01
|
|
:external-copy01
|
|
:children-labels [:external-copy01-rect :c01-in-copy])
|
|
page (thf/current-page file)
|
|
c01-in-copy (ths/get-shape file :c01-in-copy)
|
|
rect01 (get-in page [:objects (-> c01-in-copy :shapes first)])
|
|
|
|
|
|
;; ==== Action
|
|
|
|
|
|
file' (tho/swap-component-in-shape file :c01-in-copy :c02 {:new-shape-label :c02-in-copy :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
c02-in-copy' (ths/get-shape file' :c02-in-copy)
|
|
rect02' (get-in page' [:objects (-> c02-in-copy' :shapes first)])]
|
|
|
|
(thf/dump-file file :keys [:width :touched])
|
|
;; The rect had width 25 before the switch
|
|
(t/is (= (:width rect01) 25))
|
|
;; The rect still has width 25 after the switch
|
|
(t/is (= (:width rect02') 25))))
|
|
|
|
;; ============================================================
|
|
;; LAYOUT ITEM SIZING - HORIZONTAL (fix, auto, fill, none)
|
|
;; ============================================================
|
|
|
|
(t/deftest test-switch-with-layout-item-h-sizing-fix
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
;; Create a variant with a child that has layout-item-h-sizing :fix
|
|
;; When :fix is set, the width should NOT be preserved on switch
|
|
;; but should take the new component's width
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 100
|
|
:height 50
|
|
:layout-item-h-sizing :fix}
|
|
:child2-params {:width 200
|
|
:height 50
|
|
:layout-item-h-sizing :fix}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Change width of the child rect (creating an override)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(assoc shape :width 150))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had width 150 before the switch (with override)
|
|
(t/is (= (:width rect01) 150))
|
|
;; With layout-item-h-sizing :fix, the width should be taken from the new component
|
|
;; (not preserving the override), so it should be 200
|
|
(t/is (= (:width rect02') 200))
|
|
;; Verify layout-item-h-sizing is still :fix after switch
|
|
(t/is (= (:layout-item-h-sizing rect02') :fix))))
|
|
|
|
(t/deftest test-switch-with-layout-item-h-sizing-auto
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
;; Create a variant with a child that has layout-item-h-sizing :auto
|
|
;; When :auto is set, the width override SHOULD be preserved on switch
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 100
|
|
:height 50
|
|
:layout-item-h-sizing :auto}
|
|
:child2-params {:width 200
|
|
:height 50
|
|
:layout-item-h-sizing :auto}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Change width of the child rect (creating an override)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(assoc shape :width 150))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had width 150 before the switch (with override)
|
|
(t/is (= (:width rect01) 150))
|
|
;; With layout-item-h-sizing :auto, since the two variants have different widths (100 vs 200),
|
|
;; the override is not preserved and the new component's width (200) is used
|
|
(t/is (= (:width rect02') 200))
|
|
;; Verify layout-item-h-sizing is still :auto after switch
|
|
(t/is (= (:layout-item-h-sizing rect02') :auto))))
|
|
|
|
(t/deftest test-switch-with-layout-item-h-sizing-fill
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
;; Create a variant with a child that has layout-item-h-sizing :fill
|
|
;; When :fill is set, the width override SHOULD be preserved on switch
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 100
|
|
:height 50
|
|
:layout-item-h-sizing :fill}
|
|
:child2-params {:width 200
|
|
:height 50
|
|
:layout-item-h-sizing :fill}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Change width of the child rect (creating an override)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(assoc shape :width 150))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had width 150 before the switch (with override)
|
|
(t/is (= (:width rect01) 150))
|
|
;; With layout-item-h-sizing :fill, since the two variants have different widths (100 vs 200),
|
|
;; the override is not preserved and the new component's width (200) is used
|
|
(t/is (= (:width rect02') 200))
|
|
;; Verify layout-item-h-sizing is still :fill after switch
|
|
(t/is (= (:layout-item-h-sizing rect02') :fill))))
|
|
|
|
(t/deftest test-switch-without-layout-item-h-sizing
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
;; Create a variant with a child without layout-item-h-sizing
|
|
;; When not set, the width override SHOULD be preserved on switch
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 100
|
|
:height 50}
|
|
:child2-params {:width 200
|
|
:height 50}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Change width of the child rect (creating an override)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(assoc shape :width 150))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had width 150 before the switch (with override)
|
|
(t/is (= (:width rect01) 150))
|
|
;; Without layout-item-h-sizing, since the two variants have different widths (100 vs 200),
|
|
;; the override is not preserved and the new component's width (200) is used
|
|
(t/is (= (:width rect02') 200))
|
|
;; Verify layout-item-h-sizing is still nil after switch
|
|
(t/is (nil? (:layout-item-h-sizing rect02')))))
|
|
|
|
;; ============================================================
|
|
;; LAYOUT ITEM SIZING - VERTICAL (fix, auto, fill, none)
|
|
;; ============================================================
|
|
|
|
(t/deftest test-switch-with-layout-item-v-sizing-fix
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
;; Create a variant with a child that has layout-item-v-sizing :fix
|
|
;; When :fix is set, the height should NOT be preserved on switch
|
|
;; but should take the new component's height
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 50
|
|
:height 100
|
|
:layout-item-v-sizing :fix}
|
|
:child2-params {:width 50
|
|
:height 200
|
|
:layout-item-v-sizing :fix}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Change height of the child rect (creating an override)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(assoc shape :height 150))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had height 150 before the switch (with override)
|
|
(t/is (= (:height rect01) 150))
|
|
;; With layout-item-v-sizing :fix, the height should be taken from the new component
|
|
;; (not preserving the override), so it should be 200
|
|
(t/is (= (:height rect02') 200))
|
|
;; Verify layout-item-v-sizing is still :fix after switch
|
|
(t/is (= (:layout-item-v-sizing rect02') :fix))))
|
|
|
|
(t/deftest test-switch-with-layout-item-v-sizing-auto
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
;; Create a variant with a child that has layout-item-v-sizing :auto
|
|
;; When :auto is set, the height override SHOULD be preserved on switch
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 50
|
|
:height 100
|
|
:layout-item-v-sizing :auto}
|
|
:child2-params {:width 50
|
|
:height 200
|
|
:layout-item-v-sizing :auto}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Change height of the child rect (creating an override)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(assoc shape :height 150))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had height 150 before the switch (with override)
|
|
(t/is (= (:height rect01) 150))
|
|
;; With layout-item-v-sizing :auto, since the two variants have different heights (100 vs 200),
|
|
;; the override is not preserved and the new component's height (200) is used
|
|
(t/is (= (:height rect02') 200))
|
|
;; Verify layout-item-v-sizing is still :auto after switch
|
|
(t/is (= (:layout-item-v-sizing rect02') :auto))))
|
|
|
|
(t/deftest test-switch-with-layout-item-v-sizing-fill
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
;; Create a variant with a child that has layout-item-v-sizing :fill
|
|
;; When :fill is set, the height override SHOULD be preserved on switch
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 50
|
|
:height 100
|
|
:layout-item-v-sizing :fill}
|
|
:child2-params {:width 50
|
|
:height 200
|
|
:layout-item-v-sizing :fill}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Change height of the child rect (creating an override)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(assoc shape :height 150))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had height 150 before the switch (with override)
|
|
(t/is (= (:height rect01) 150))
|
|
;; With layout-item-v-sizing :fill, since the two variants have different heights (100 vs 200),
|
|
;; the override is not preserved and the new component's height (200) is used
|
|
(t/is (= (:height rect02') 200))
|
|
;; Verify layout-item-v-sizing is still :fill after switch
|
|
(t/is (= (:layout-item-v-sizing rect02') :fill))))
|
|
|
|
(t/deftest test-switch-without-layout-item-v-sizing
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
;; Create a variant with a child without layout-item-v-sizing
|
|
;; When not set, the height override SHOULD be preserved on switch
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 50
|
|
:height 100}
|
|
:child2-params {:width 50
|
|
:height 200}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Change height of the child rect (creating an override)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(assoc shape :height 150))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had height 150 before the switch (with override)
|
|
(t/is (= (:height rect01) 150))
|
|
;; Without layout-item-v-sizing, since the two variants have different heights (100 vs 200),
|
|
;; the override is not preserved and the new component's height (200) is used
|
|
(t/is (= (:height rect02') 200))
|
|
;; Verify layout-item-v-sizing is still nil after switch
|
|
(t/is (nil? (:layout-item-v-sizing rect02')))))
|
|
|
|
;; ============================================================
|
|
;; ROTATION OVERRIDES
|
|
;; ============================================================
|
|
|
|
(t/deftest test-switch-with-rotation-override
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 100
|
|
:height 100
|
|
:rotation 0}
|
|
:child2-params {:width 100
|
|
:height 100
|
|
:rotation 0}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Apply rotation to the child rect (creating an override)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(assoc shape :rotation 45))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had rotation 45 before the switch (with override)
|
|
(t/is (= (:rotation rect01) 45))
|
|
;; The rotation override should be preserved after switch since both variants have the same rotation
|
|
(t/is (= (:rotation rect02') 45))
|
|
;; The transform matrix should also be preserved
|
|
(t/is (some? (:transform rect02')))))
|
|
|
|
(t/deftest test-switch-with-rotation-different-variants
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 100
|
|
:height 100
|
|
:rotation 0}
|
|
:child2-params {:width 100
|
|
:height 100
|
|
:rotation 90}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Apply rotation to the child rect (creating an override)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(assoc shape :rotation 45))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had rotation 45 before the switch (with override)
|
|
(t/is (= (:rotation rect01) 45))
|
|
;; The override should NOT be preserved since the two variants have different rotations (0 vs 90)
|
|
;; The new rotation should be 90 (from c02)
|
|
(t/is (= (:rotation rect02') 90))))
|
|
|
|
;; ============================================================
|
|
;; SPECIAL CASES (auto-text, geometry, touched attributes, position data)
|
|
;; ============================================================
|
|
|
|
(t/deftest test-switch-with-auto-text-geometry-not-copied
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
;; Create variants with auto-text (grow-type :auto-width or :auto-height)
|
|
(thv/add-variant-with-text
|
|
:v01 :c01 :m01 :c02 :m02 :t01 :t02 "hello" "world"))
|
|
|
|
page (thf/current-page file)
|
|
;; Modify the first text shape to have grow-type :auto-width
|
|
t01 (ths/get-shape file :t01)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id t01)}
|
|
(fn [shape]
|
|
(assoc shape :grow-type :auto-width))
|
|
(:objects page)
|
|
{})
|
|
file (thf/apply-changes file changes)
|
|
|
|
;; Also modify t02
|
|
page (thf/current-page file)
|
|
t02 (ths/get-shape file :t02)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id t02)}
|
|
(fn [shape]
|
|
(assoc shape :grow-type :auto-width))
|
|
(:objects page)
|
|
{})
|
|
file (thf/apply-changes file changes)
|
|
|
|
;; Now create a copy and modify its width
|
|
file (thc/instantiate-component file :c01
|
|
:copy01
|
|
:children-labels [:copy-t01])
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
text01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Change width of the text (creating an override)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id text01)}
|
|
(fn [shape]
|
|
(assoc shape :width 200))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
text01 (get-in page [:objects (:id text01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
text02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The text had width 200 before the switch (with override)
|
|
(t/is (= (:width text01) 200))
|
|
;; For auto-text shapes, geometry attributes like width should NOT be copied on switch
|
|
;; So the width should be from the new component (t02's width)
|
|
(t/is (not= (:width text02') 200))
|
|
;; Verify grow-type is preserved
|
|
(t/is (= (:grow-type text02') :auto-width))))
|
|
|
|
(t/deftest test-switch-different-shape-types-content-not-copied
|
|
(let [;; ==== Setup - Create a variant with a rect in first component
|
|
;; This test is simplified to just test attributes, not changing shape types
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 100 :height 100 :type :rect}
|
|
:child2-params {:width 100 :height 100 :type :rect}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; ==== Action - Try to switch to a component with different shape type
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
child02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; Verify the shapes are still rects
|
|
(t/is (= (:type rect01) :rect))
|
|
(t/is (= (:type child02') :rect))
|
|
;; This test demonstrates that content with different types isn't copied
|
|
;; In practice this means proper attribute filtering
|
|
(t/is (= (:width child02') 100))))
|
|
|
|
(t/deftest test-switch-with-path-shape-geometry-override
|
|
(let [;; ==== Setup - Create variants with path shapes
|
|
;; Using rect shapes as path shapes are complex - the principle is the same
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 100 :height 100 :type :rect}
|
|
:child2-params {:width 200 :height 200 :type :rect}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-path01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
path01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Resize the path (creating an override by changing selrect)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id path01)}
|
|
(fn [shape]
|
|
(assoc shape :width 150))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
path01 (get-in page [:objects (:id path01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
path02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had width 150 before the switch
|
|
(t/is (= (:width path01) 150))
|
|
;; For shapes with geometry changes, the transformed geometry is applied
|
|
;; Since variants have different widths (100 vs 200), override is discarded
|
|
(t/is (= (:width path02') 200))
|
|
;; Verify it's still a rect type
|
|
(t/is (= (:type path02') :rect))))
|
|
|
|
(t/deftest test-switch-preserves-touched-attributes-only
|
|
(let [;; ==== Setup - Test that only touched attributes are copied
|
|
;; Use opacity since it's a simpler attribute than fill-color
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 100
|
|
:height 100
|
|
:opacity 1}
|
|
:child2-params {:width 200
|
|
:height 200
|
|
:opacity 1}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Change the opacity (creating a touched attribute)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(assoc shape :opacity 0.5))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had opacity 0.5 before the switch (touched)
|
|
(t/is (= (:opacity rect01) 0.5))
|
|
;; The rect had width 100 before the switch (not touched)
|
|
(t/is (= (:width rect01) 100))
|
|
|
|
;; After switch:
|
|
;; - opacity override SHOULD be preserved because:
|
|
;; 1. It was touched
|
|
;; 2. Both variants have same opacity (1)
|
|
(t/is (= (:opacity rect02') 0.5))
|
|
;; - width should NOT be preserved (it wasn't touched, and variants have different widths)
|
|
(t/is (= (:width rect02') 200))
|
|
;; - height should match the new variant
|
|
(t/is (= (:height rect02') 200))))
|
|
|
|
(t/deftest test-switch-with-equal-values-not-copied
|
|
(let [;; ==== Setup - Test that when previous-shape and current-shape have equal values,
|
|
;; no copy operation occurs (optimization in update-attrs-on-switch)
|
|
;; Both variants start with opacity 0.5
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 100
|
|
:height 100
|
|
:opacity 0.5}
|
|
:child2-params {:width 100
|
|
:height 100
|
|
:opacity 0.5}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had opacity 0.5 before the switch
|
|
(t/is (= (:opacity rect01) 0.5))
|
|
;; After switch, opacity should still be 0.5
|
|
;; This validates that the equality check works correctly
|
|
(t/is (= (:opacity rect02') 0.5))))
|
|
|
|
(t/deftest test-switch-with-position-data-reset
|
|
(let [;; ==== Setup - Test that position-data is reset when geometry-group is touched
|
|
file (-> (thf/sample-file :file1)
|
|
;; Create variants with text shapes
|
|
(thv/add-variant-with-text
|
|
:v01 :c01 :m01 :c02 :m02 :t01 :t02 "hello world" "hello world"))
|
|
|
|
page (thf/current-page file)
|
|
;; Modify the first text shape to have specific geometry
|
|
t01 (ths/get-shape file :t01)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id t01)}
|
|
(fn [shape]
|
|
(assoc shape :width 200))
|
|
(:objects page)
|
|
{})
|
|
file (thf/apply-changes file changes)
|
|
|
|
;; Create a copy and modify its geometry (touching geometry-group)
|
|
file (thc/instantiate-component file :c01
|
|
:copy01
|
|
:children-labels [:copy-t01])
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
text01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Change width of the text (touching geometry)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id text01)}
|
|
(fn [shape]
|
|
(assoc shape :width 300))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
text01 (get-in page [:objects (:id text01)])
|
|
old-position-data (:position-data text01)
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
text02' (get-in page' [:objects (-> copy02' :shapes first)])
|
|
new-position-data (:position-data text02')]
|
|
|
|
;; position-data should be reset (nil or different) when geometry group is touched
|
|
;; This allows the system to recalculate it based on the new geometry
|
|
;; Note: old-position-data may be nil initially, which is fine
|
|
;; After switch with geometry changes, if old data existed and was different,
|
|
;; or if it needs recalculation, the test validates the behavior
|
|
(t/is (or (nil? old-position-data)
|
|
(nil? new-position-data)
|
|
(not= old-position-data new-position-data)))))
|
|
|
|
;; ============================================================
|
|
;; SELRECT CONSISTENCY TESTS
|
|
;; These tests verify that after a variant switch, the composite
|
|
;; geometry attributes (:selrect, :points) stay consistent with
|
|
;; the scalar attributes (:width, :height) that are kept.
|
|
;; ============================================================
|
|
|
|
(t/deftest test-switch-selrect-consistent-no-sizing-different-widths
|
|
;; When no :fix sizing and variants have different widths,
|
|
;; :width is correctly skipped (stays at new component width),
|
|
;; but :selrect was being copied from the old shape, leaving
|
|
;; selrect.width inconsistent with :width. This test verifies the fix.
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 100 :height 50}
|
|
:child2-params {:width 200 :height 50}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Override width AND selrect consistently (simulating a real resize)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(let [new-width 150
|
|
sr (:selrect shape)
|
|
new-sr (-> sr
|
|
(assoc :width new-width)
|
|
(assoc :x2 (+ (:x1 sr) new-width)))]
|
|
(-> shape
|
|
(assoc :width new-width)
|
|
(assoc :selrect new-sr))))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had the width override before the switch
|
|
(t/is (= (:width rect01) 150))
|
|
(t/is (= (get-in rect01 [:selrect :width]) 150))
|
|
;; Since the variants have different widths (100 vs 200), the override is not preserved
|
|
(t/is (= (:width rect02') 200))
|
|
;; The selrect must be consistent with :width
|
|
(t/is (= (get-in rect02' [:selrect :width]) 200))))
|
|
|
|
(t/deftest test-switch-selrect-consistent-no-sizing-different-heights
|
|
;; Same as above but for height.
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 50 :height 100}
|
|
:child2-params {:width 50 :height 200}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Override height AND selrect consistently
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(let [new-height 150
|
|
sr (:selrect shape)
|
|
new-sr (-> sr
|
|
(assoc :height new-height)
|
|
(assoc :y2 (+ (:y1 sr) new-height)))]
|
|
(-> shape
|
|
(assoc :height new-height)
|
|
(assoc :selrect new-sr))))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had the height override before the switch
|
|
(t/is (= (:height rect01) 150))
|
|
(t/is (= (get-in rect01 [:selrect :height]) 150))
|
|
;; Since the variants have different heights (100 vs 200), the override is not preserved
|
|
(t/is (= (:height rect02') 200))
|
|
;; The selrect must be consistent with :height
|
|
(t/is (= (get-in rect02' [:selrect :height]) 200))))
|
|
|
|
(t/deftest test-switch-with-v-sizing-fix-selrect-consistent-different-widths
|
|
;; mixed-sizing scenario: v-sizing=:fix but variants differ in WIDTH.
|
|
;; switch-fixed-layout-geom-change-value is triggered (because v-sizing=:fix).
|
|
;; Without the fix, the function returned prev-width for the non-:fix dimension,
|
|
;; leaving selrect.width inconsistent with :width.
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 100 :height 50 :layout-item-v-sizing :fix}
|
|
:child2-params {:width 200 :height 50 :layout-item-v-sizing :fix}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Override width AND selrect consistently
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(let [new-width 150
|
|
sr (:selrect shape)
|
|
new-sr (-> sr
|
|
(assoc :width new-width)
|
|
(assoc :x2 (+ (:x1 sr) new-width)))]
|
|
(-> shape
|
|
(assoc :width new-width)
|
|
(assoc :selrect new-sr))))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had the width override before the switch
|
|
(t/is (= (:width rect01) 150))
|
|
(t/is (= (get-in rect01 [:selrect :width]) 150))
|
|
;; Since the variants have different widths (100 vs 200), the override is not preserved
|
|
;; (v-sizing=:fix does not affect the horizontal dimension)
|
|
(t/is (= (:width rect02') 200))
|
|
;; The selrect must be consistent with :width
|
|
(t/is (= (get-in rect02' [:selrect :width]) 200))
|
|
;; v-sizing is preserved
|
|
(t/is (= (:layout-item-v-sizing rect02') :fix))))
|
|
|
|
(t/deftest test-switch-with-h-sizing-fix-selrect-consistent-different-heights
|
|
;; mixed-sizing scenario: h-sizing=:fix but variants differ in HEIGHT.
|
|
;; switch-fixed-layout-geom-change-value is triggered (because h-sizing=:fix).
|
|
;; Without the fix, the function returned prev-height for the non-:fix dimension,
|
|
;; leaving selrect.height inconsistent with :height.
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 50 :height 100 :layout-item-h-sizing :fix}
|
|
:child2-params {:width 50 :height 200 :layout-item-h-sizing :fix}})
|
|
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Override height AND selrect consistently
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(let [new-height 150
|
|
sr (:selrect shape)
|
|
new-sr (-> sr
|
|
(assoc :height new-height)
|
|
(assoc :y2 (+ (:y1 sr) new-height)))]
|
|
(-> shape
|
|
(assoc :height new-height)
|
|
(assoc :selrect new-sr))))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had the height override before the switch
|
|
(t/is (= (:height rect01) 150))
|
|
(t/is (= (get-in rect01 [:selrect :height]) 150))
|
|
;; Since the variants have different heights (100 vs 200), the override is not preserved
|
|
;; (h-sizing=:fix does not affect the vertical dimension)
|
|
(t/is (= (:height rect02') 200))
|
|
;; The selrect must be consistent with :height
|
|
(t/is (= (get-in rect02' [:selrect :height]) 200))
|
|
;; h-sizing is preserved
|
|
(t/is (= (:layout-item-h-sizing rect02') :fix))))
|
|
|
|
;; ============================================================
|
|
;; FIXED-SIZING: "SAME-SIZE → PRESERVE OVERRIDE" PATH TESTS
|
|
;; These tests exercise the branch inside switch-fixed-layout-geom-change-value
|
|
;; where variants share the same value in the non-:fix dimension:
|
|
;; (if (= origin-dim current-dim) prev-dim current-dim)
|
|
;; When origin-dim == current-dim the user's override for that dimension
|
|
;; must be preserved after the switch.
|
|
;; ============================================================
|
|
|
|
(t/deftest test-switch-with-h-sizing-fix-same-height-override-preserved
|
|
;; h-sizing=:fix, variants have SAME height (non-:fix dim, same-size).
|
|
;; switch-fixed-layout-geom-change-value must return prev-height for the
|
|
;; non-:fix dimension because origin-height == current-height.
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 100 :height 50 :layout-item-h-sizing :fix}
|
|
:child2-params {:width 200 :height 50 :layout-item-h-sizing :fix}})
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Override height (the non-:fix dimension) and selrect consistently
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(let [new-height 75
|
|
sr (:selrect shape)
|
|
new-sr (-> sr
|
|
(assoc :height new-height)
|
|
(assoc :y2 (+ (:y1 sr) new-height)))]
|
|
(-> shape
|
|
(assoc :height new-height)
|
|
(assoc :selrect new-sr))))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had the height override 75 before the switch
|
|
(t/is (= (:height rect01) 75))
|
|
;; h-sizing=:fix means width always takes the new component's value
|
|
(t/is (= (:width rect02') 200))
|
|
;; Height (non-:fix dim) is preserved because both variants have same height (50)
|
|
(t/is (= (:height rect02') 75))
|
|
;; selrect must be consistent with the preserved height
|
|
(t/is (= (get-in rect02' [:selrect :height]) 75))
|
|
(t/is (= (get-in rect02' [:selrect :width]) 200))
|
|
;; h-sizing is preserved
|
|
(t/is (= (:layout-item-h-sizing rect02') :fix))))
|
|
|
|
(t/deftest test-switch-with-v-sizing-fix-same-width-override-preserved
|
|
;; v-sizing=:fix, variants have SAME width (non-:fix dim, same-size).
|
|
;; switch-fixed-layout-geom-change-value must return prev-width for the
|
|
;; non-:fix dimension because origin-width == current-width.
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 100 :height 50 :layout-item-v-sizing :fix}
|
|
:child2-params {:width 100 :height 100 :layout-item-v-sizing :fix}})
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Override width (the non-:fix dimension) and selrect consistently
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(let [new-width 150
|
|
sr (:selrect shape)
|
|
new-sr (-> sr
|
|
(assoc :width new-width)
|
|
(assoc :x2 (+ (:x1 sr) new-width)))]
|
|
(-> shape
|
|
(assoc :width new-width)
|
|
(assoc :selrect new-sr))))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had the width override 150 before the switch
|
|
(t/is (= (:width rect01) 150))
|
|
;; Width (non-:fix dim) is preserved because both variants have same width (100)
|
|
(t/is (= (:width rect02') 150))
|
|
;; selrect must be consistent with the preserved width
|
|
(t/is (= (get-in rect02' [:selrect :width]) 150))
|
|
;; v-sizing=:fix means height always takes the new component's value
|
|
(t/is (= (:height rect02') 100))
|
|
(t/is (= (get-in rect02' [:selrect :height]) 100))
|
|
;; v-sizing is preserved
|
|
(t/is (= (:layout-item-v-sizing rect02') :fix))))
|
|
|
|
(t/deftest test-switch-with-both-sizing-fix-overrides-discarded
|
|
;; When both h-sizing=:fix and v-sizing=:fix, switch-fixed-layout-geom-change-value
|
|
;; always uses current-width and current-height (the new component's values).
|
|
;; Both width and height overrides are discarded because :fix always
|
|
;; defers to the new component's dimension regardless of same-size or not.
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 100 :height 50
|
|
:layout-item-h-sizing :fix
|
|
:layout-item-v-sizing :fix}
|
|
:child2-params {:width 200 :height 100
|
|
:layout-item-h-sizing :fix
|
|
:layout-item-v-sizing :fix}})
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Override both width and height (and selrect) consistently
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(let [new-width 150
|
|
new-height 75
|
|
sr (:selrect shape)
|
|
new-sr (-> sr
|
|
(assoc :width new-width)
|
|
(assoc :height new-height)
|
|
(assoc :x2 (+ (:x1 sr) new-width))
|
|
(assoc :y2 (+ (:y1 sr) new-height)))]
|
|
(-> shape
|
|
(assoc :width new-width)
|
|
(assoc :height new-height)
|
|
(assoc :selrect new-sr))))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had both overrides before the switch
|
|
(t/is (= (:width rect01) 150))
|
|
(t/is (= (:height rect01) 75))
|
|
;; With both sizing :fix, both dimensions take the new component's values
|
|
(t/is (= (:width rect02') 200))
|
|
(t/is (= (:height rect02') 100))
|
|
;; selrect must be consistent
|
|
(t/is (= (get-in rect02' [:selrect :width]) 200))
|
|
(t/is (= (get-in rect02' [:selrect :height]) 100))
|
|
(t/is (= (:layout-item-h-sizing rect02') :fix))
|
|
(t/is (= (:layout-item-v-sizing rect02') :fix))))
|
|
|
|
(t/deftest test-switch-same-size-variants-geometry-override-preserved
|
|
;; When both variants have IDENTICAL dimensions (width=100, height=50),
|
|
;; the guard that skips :selrect/:points must NOT fire
|
|
;; (its condition `(or (not= origin.width current.width) ...)` is false).
|
|
;; A geometry override should therefore be carried through correctly.
|
|
(let [;; ==== Setup
|
|
file (-> (thf/sample-file :file1)
|
|
(thv/add-variant-with-child
|
|
:v01 :c01 :m01 :c02 :m02 :r01 :r02
|
|
{:child1-params {:width 100 :height 50}
|
|
:child2-params {:width 100 :height 50}}) ; same size!
|
|
(thc/instantiate-component :c01
|
|
:copy01
|
|
:children-labels [:copy-r01]))
|
|
|
|
page (thf/current-page file)
|
|
copy01 (ths/get-shape file :copy01)
|
|
rect01 (get-in page [:objects (-> copy01 :shapes first)])
|
|
|
|
;; Override width AND selrect consistently (simulating a real resize)
|
|
changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page))
|
|
#{(:id rect01)}
|
|
(fn [shape]
|
|
(let [new-width 150
|
|
sr (:selrect shape)
|
|
new-sr (-> sr
|
|
(assoc :width new-width)
|
|
(assoc :x2 (+ (:x1 sr) new-width)))]
|
|
(-> shape
|
|
(assoc :width new-width)
|
|
(assoc :selrect new-sr))))
|
|
(:objects page)
|
|
{})
|
|
|
|
file (thf/apply-changes file changes)
|
|
page (thf/current-page file)
|
|
rect01 (get-in page [:objects (:id rect01)])
|
|
|
|
;; ==== Action
|
|
file' (tho/swap-component-in-shape file :copy01 :c02 {:new-shape-label :copy02 :keep-touched? true})
|
|
|
|
page' (thf/current-page file')
|
|
copy02' (ths/get-shape file' :copy02)
|
|
rect02' (get-in page' [:objects (-> copy02' :shapes first)])]
|
|
|
|
;; The rect had the width override 150 before the switch
|
|
(t/is (= (:width rect01) 150))
|
|
(t/is (= (get-in rect01 [:selrect :width]) 150))
|
|
;; Both variants are identical in size (100x50), so the override IS preserved
|
|
(t/is (= (:width rect02') 150))
|
|
;; The guard must not have suppressed :selrect — it should be consistent
|
|
(t/is (= (get-in rect02' [:selrect :width]) 150)))) |