mirror of
https://github.com/penpot/penpot.git
synced 2026-10-29 05:50:35 +00:00
🐛 Update canvas and keep local sets when switching tokens source (#12442)
Setting a library as tokens source did not update shapes that use tokens, because set-tokens-source never ran the token propagation that every other token operation runs. Run it after the commit. Going back to the local tokens, or unlinking the library that was the source, left no local set active: the file has a single tokens status, and switching to a library replaced it with the library's one. Keep the status of the file's own tokens lib aside in a new optional :own-tokens-status attribute while an external library is the source, and restore it when the file is its own source again. Exporting without libraries and absorbing a deleted source library restore it as well. Closes #12430 AI-assisted-by: claude-opus-5-5
This commit is contained in:
parent
6f185c624f
commit
86e01d56a2
@ -683,7 +683,8 @@
|
||||
"Make the file its own tokens source when its tokens source is not one
|
||||
of the given library-ids, as happens when the library was deleted. The
|
||||
tokens lib of the source is copied while the library still exists, even
|
||||
if deleted; otherwise the tokens source and status are removed."
|
||||
if deleted; otherwise the tokens source is removed and the file gets back
|
||||
the tokens status kept aside for its own tokens lib, if any."
|
||||
[cfg data library-ids]
|
||||
(let [source-id (cfo/get-tokens-source data)]
|
||||
(if (and (some? source-id)
|
||||
@ -692,7 +693,7 @@
|
||||
:include-deleted? true
|
||||
:throw-if-not-exists? false)]
|
||||
(cfo/absorb-tokens-lib data (:data library))
|
||||
(dissoc data :tokens-source :tokens-status))
|
||||
(cfo/detach-tokens-source data))
|
||||
data)))
|
||||
|
||||
(defn embed-assets
|
||||
|
||||
@ -407,6 +407,12 @@
|
||||
[:theme-ids [:set ::sm/uuid]]
|
||||
[:set-ids [:set ::sm/uuid]]]]
|
||||
|
||||
[:set-own-tokens-status
|
||||
[:map {:title "SetOwnTokensStatus"}
|
||||
[:type [:= :set-own-tokens-status]]
|
||||
[:theme-ids [:maybe [:set ::sm/uuid]]]
|
||||
[:set-ids [:maybe [:set ::sm/uuid]]]]]
|
||||
|
||||
[:rename-token-set-group
|
||||
[:map {:title "RenameTokenSetGroup"}
|
||||
[:type [:= :rename-token-set-group]]
|
||||
@ -1067,6 +1073,13 @@
|
||||
(-> (cfo/ensure-tokens-lib data)
|
||||
(cfo/update-tokens-status ctos/set-tokens-status theme-ids set-ids)))
|
||||
|
||||
(defmethod process-change :set-own-tokens-status
|
||||
[data {:keys [theme-ids set-ids]}]
|
||||
(cfo/set-own-tokens-status data
|
||||
(when (or (some? theme-ids) (some? set-ids))
|
||||
(ctos/make-tokens-status :active-theme-ids theme-ids
|
||||
:active-set-ids set-ids))))
|
||||
|
||||
(defmethod process-change :rename-token-set-group
|
||||
[data {:keys [set-group-path set-group-fname]}]
|
||||
(-> (cfo/ensure-tokens-lib data)
|
||||
|
||||
@ -1077,6 +1077,24 @@
|
||||
(update :undo-changes conj {:type :set-tokens-status :theme-ids prev-theme-ids :set-ids prev-set-ids})
|
||||
(apply-changes-local)))))
|
||||
|
||||
(defn set-own-tokens-status
|
||||
"Keep aside the tokens status of the file's own tokens-lib, or remove it
|
||||
when `tokens-status` is nil."
|
||||
[changes tokens-status]
|
||||
(assert-library! changes)
|
||||
(assert (or (ctos/tokens-status? tokens-status)
|
||||
(nil? tokens-status)))
|
||||
(let [library-data (::library-data (meta changes))
|
||||
prev-tokens-status (cfo/get-own-tokens-status library-data)
|
||||
->change (fn [tokens-status]
|
||||
{:type :set-own-tokens-status
|
||||
:theme-ids (some-> tokens-status ctos/get-active-theme-ids)
|
||||
:set-ids (some-> tokens-status ctos/get-active-set-ids)})]
|
||||
(-> changes
|
||||
(update :redo-changes conj (->change tokens-status))
|
||||
(update :undo-changes conj (->change prev-tokens-status))
|
||||
(apply-changes-local))))
|
||||
|
||||
(defn rename-token-set-group
|
||||
[changes set-group-path set-group-fname]
|
||||
(let [undo-path (ctob/replace-last-path-name set-group-path set-group-fname)
|
||||
|
||||
@ -549,6 +549,37 @@
|
||||
[file-data f & args]
|
||||
(d/update-when file-data :tokens-status #(apply f % args)))
|
||||
|
||||
(defn get-own-tokens-status
|
||||
"The tokens status of the file's own tokens-lib, kept aside while the
|
||||
tokens source is an external library."
|
||||
[file-data]
|
||||
(:own-tokens-status file-data))
|
||||
|
||||
(defn set-own-tokens-status
|
||||
"Keep aside the tokens status of the file's own tokens-lib. Setting it to
|
||||
nil removes the attribute."
|
||||
[file-data tokens-status]
|
||||
(assert (or (nil? tokens-status) (ctos/tokens-status? tokens-status))
|
||||
"expected nil or valid tokens-status")
|
||||
(if (nil? tokens-status)
|
||||
(dissoc file-data :own-tokens-status)
|
||||
(assoc file-data :own-tokens-status tokens-status)))
|
||||
|
||||
(defn detach-tokens-source
|
||||
"Make the file its own tokens source again, restoring the tokens status
|
||||
kept aside for its own tokens-lib. If none was kept, the tokens status
|
||||
is removed."
|
||||
[file-data]
|
||||
(let [own-tokens-status (get-own-tokens-status file-data)]
|
||||
(if (some? own-tokens-status)
|
||||
(-> file-data
|
||||
(set-tokens-source nil)
|
||||
(set-own-tokens-status nil)
|
||||
(assoc :tokens-status own-tokens-status))
|
||||
(-> file-data
|
||||
(set-tokens-source nil)
|
||||
(dissoc :tokens-status)))))
|
||||
|
||||
(defn absorb-tokens-lib
|
||||
"Copy the tokens-lib of the library into the file, replacing the
|
||||
previous one if any, and unset the tokens-source, so the file becomes
|
||||
@ -558,19 +589,26 @@
|
||||
one of the library is copied along with the tokens-lib.
|
||||
|
||||
If the library has no tokens-lib, only the tokens-source is unset, and
|
||||
the file keeps its own tokens-lib and tokens-status. If there is no
|
||||
library-data, there is nothing to absorb and the file is returned
|
||||
unchanged."
|
||||
the file keeps its own tokens-lib, with the tokens status kept aside for
|
||||
it if any. If there is no library-data, there is nothing to absorb and
|
||||
the file is returned unchanged."
|
||||
[file-data library-data]
|
||||
(if (nil? library-data)
|
||||
file-data
|
||||
(let [tokens-lib (get-tokens-lib library-data)]
|
||||
(if (nil? tokens-lib)
|
||||
(set-tokens-source file-data nil)
|
||||
(let [own-tokens-status (get-own-tokens-status file-data)]
|
||||
(cond-> (-> file-data
|
||||
(set-tokens-source nil)
|
||||
(set-own-tokens-status nil))
|
||||
(some? own-tokens-status)
|
||||
(assoc :tokens-status own-tokens-status)))
|
||||
(let [tokens-status (or (get-tokens-status file-data)
|
||||
(get-tokens-status library-data))]
|
||||
(cond-> (-> file-data
|
||||
(set-tokens-source nil)
|
||||
;; The kept status refers to the replaced tokens-lib
|
||||
(set-own-tokens-status nil)
|
||||
(assoc :tokens-lib tokens-lib))
|
||||
(some? tokens-status)
|
||||
(assoc :tokens-status tokens-status)))))))
|
||||
|
||||
@ -16,36 +16,58 @@
|
||||
;; Tokens source
|
||||
|
||||
(defn- own-tokens-status
|
||||
"The current tokens status of `file-data`, keeping only the themes and sets
|
||||
that exist in its own tokens lib."
|
||||
[file-data]
|
||||
(let [tokens-status (cfo/get-tokens-status file-data)
|
||||
tokens-lib (cfo/get-tokens-lib file-data)]
|
||||
"`tokens-status` keeping only the themes and sets that exist in the own
|
||||
tokens lib of `file-data`."
|
||||
[file-data tokens-status]
|
||||
(let [tokens-lib (cfo/get-tokens-lib file-data)]
|
||||
(if (and tokens-status tokens-lib)
|
||||
(cfo/sync-tokens-status-with-lib tokens-status tokens-lib)
|
||||
(ctos/make-tokens-status))))
|
||||
|
||||
(defn generate-set-tokens-source
|
||||
"Create changes for setting the tokens source of a file to `library`,
|
||||
copying the library's tokens status. If the library is the file itself,
|
||||
the themes and sets that don't exist in its own tokens lib are deactivated.
|
||||
If the library is nil, the tokens source is removed and the tokens status
|
||||
is cleared."
|
||||
copying the library's tokens status.
|
||||
|
||||
While an external library is the source, the tokens status of the file's
|
||||
own tokens lib is kept aside, and it is restored when the file goes back
|
||||
to being its own source (the library is the file itself, or nil). With
|
||||
nothing kept aside, going back to the file itself deactivates the themes
|
||||
and sets that don't exist in its own tokens lib, and a nil library clears
|
||||
the tokens status."
|
||||
[changes library]
|
||||
(let [library-id (:id library)
|
||||
file-data (pcb/get-library-data changes)
|
||||
library-tokens-status (cond
|
||||
(nil? library)
|
||||
(ctos/make-tokens-status)
|
||||
(let [file-data (pcb/get-library-data changes)
|
||||
file-id (:id file-data)
|
||||
library-id (:id library)
|
||||
to-own? (or (nil? library) (= library-id file-id))
|
||||
from-own? (cfo/effective-tokens-source? file-data file-id)
|
||||
current-status (cfo/get-tokens-status file-data)
|
||||
kept-status (cfo/get-own-tokens-status file-data)
|
||||
|
||||
(= library-id (:id file-data))
|
||||
(own-tokens-status file-data)
|
||||
tokens-status
|
||||
(cond
|
||||
(and to-own? (some? kept-status))
|
||||
(own-tokens-status file-data kept-status)
|
||||
|
||||
:else
|
||||
(-> library ctf/file-data cfo/get-tokens-status))]
|
||||
(-> changes
|
||||
(pcb/set-tokens-source library-id)
|
||||
(pcb/set-tokens-status library-tokens-status))))
|
||||
(nil? library)
|
||||
(ctos/make-tokens-status)
|
||||
|
||||
to-own?
|
||||
(own-tokens-status file-data current-status)
|
||||
|
||||
:else
|
||||
(-> library ctf/file-data cfo/get-tokens-status))
|
||||
|
||||
kept-status'
|
||||
(cond
|
||||
to-own? nil
|
||||
from-own? (own-tokens-status file-data current-status)
|
||||
:else kept-status)]
|
||||
|
||||
(cond-> (-> changes
|
||||
(pcb/set-tokens-source library-id)
|
||||
(pcb/set-tokens-status tokens-status))
|
||||
(not (identical? kept-status kept-status'))
|
||||
(pcb/set-own-tokens-status kept-status'))))
|
||||
|
||||
;; Tokens lib
|
||||
|
||||
|
||||
@ -30,6 +30,10 @@
|
||||
[file]
|
||||
(-> file (ctf/file-data) (cfo/get-tokens-status)))
|
||||
|
||||
(defn get-own-tokens-status
|
||||
[file]
|
||||
(-> file (ctf/file-data) (cfo/get-own-tokens-status)))
|
||||
|
||||
(defn add-tokens-lib
|
||||
"Ensure the file has a tokens-lib and a tokens-status in its data, creating empty ones if not"
|
||||
[file]
|
||||
|
||||
@ -90,7 +90,8 @@
|
||||
[:plugin-data {:optional true} schema:plugin-data]
|
||||
[:tokens-source {:optional true} ::sm/uuid] ;; The tokens-lib may be in this file or in an external library
|
||||
[:tokens-lib {:optional true} ctob/schema:tokens-lib]
|
||||
[:tokens-status {:optional true} ctos/schema:tokens-status]])
|
||||
[:tokens-status {:optional true} ctos/schema:tokens-status]
|
||||
[:own-tokens-status {:optional true} ctos/schema:tokens-status]]) ;; Kept aside while the tokens source is an external library
|
||||
|
||||
(def schema:file-metadata
|
||||
[:map {:title "Metadata"}
|
||||
@ -1242,7 +1243,7 @@
|
||||
|
||||
(cond-> (update-in file [:data :pages-index] detach-pages)
|
||||
(not (cfo/effective-tokens-source? (:data file) file-id))
|
||||
(update :data dissoc :tokens-source :tokens-status))))
|
||||
(update :data cfo/detach-tokens-source))))
|
||||
|
||||
;; Base font size
|
||||
|
||||
|
||||
@ -115,6 +115,54 @@
|
||||
(t/is (= (ctos/get-active-set-ids file-tokens-status)
|
||||
(ctos/get-active-set-ids undo-tokens-status)))))
|
||||
|
||||
(t/testing "the file's own tokens status is kept aside while a library is the source, and restored when going back"
|
||||
(let [own-set-id (uuid/next)
|
||||
lib-set-id (uuid/next)
|
||||
lib2-set-id (uuid/next)
|
||||
library-file (tht/sample-file-with-tokens
|
||||
:file-id :library
|
||||
:lib-fn #(ctob/add-set % (ctob/make-token-set :id lib-set-id :name "library set"))
|
||||
:status-fn #(ctos/set-tokens-status % #{} #{lib-set-id}))
|
||||
library2-file (tht/sample-file-with-tokens
|
||||
:file-id :library2
|
||||
:lib-fn #(ctob/add-set % (ctob/make-token-set :id lib2-set-id :name "library2 set"))
|
||||
:status-fn #(ctos/set-tokens-status % #{} #{lib2-set-id}))
|
||||
file (tht/sample-file-with-tokens
|
||||
:file-id :file1
|
||||
:lib-fn #(ctob/add-set % (ctob/make-token-set :id own-set-id :name "own set"))
|
||||
:status-fn #(ctos/set-tokens-status % #{} #{own-set-id}))
|
||||
set-source (fn [file library]
|
||||
(let [changes (-> (pcb/empty-changes)
|
||||
(pcb/with-library-data (ctf/file-data file))
|
||||
(clt/generate-set-tokens-source library))]
|
||||
[(thf/apply-changes file changes) changes]))
|
||||
active-sets #(some-> % ctos/get-active-set-ids)
|
||||
|
||||
[to-library to-library-changes] (set-source file library-file)
|
||||
[to-library2 _] (set-source to-library library2-file)
|
||||
[back-to-own back-changes] (set-source to-library2 to-library2)
|
||||
undo-to-library (thf/apply-undo-changes to-library to-library-changes)
|
||||
undo-back-to-own (thf/apply-undo-changes back-to-own back-changes)]
|
||||
|
||||
;; A library as source: its status is used and the own status is kept aside
|
||||
(t/is (= #{lib-set-id} (active-sets (tht/get-tokens-status to-library))))
|
||||
(t/is (= #{own-set-id} (active-sets (tht/get-own-tokens-status to-library))))
|
||||
|
||||
;; Another library as source: the own status is still kept aside
|
||||
(t/is (= #{lib2-set-id} (active-sets (tht/get-tokens-status to-library2))))
|
||||
(t/is (= #{own-set-id} (active-sets (tht/get-own-tokens-status to-library2))))
|
||||
|
||||
;; Back to the file itself: the own status is restored, nothing is kept aside
|
||||
(t/is (nil? (tht/get-tokens-source back-to-own)))
|
||||
(t/is (= #{own-set-id} (active-sets (tht/get-tokens-status back-to-own))))
|
||||
(t/is (nil? (tht/get-own-tokens-status back-to-own)))
|
||||
|
||||
;; Undo works both ways
|
||||
(t/is (= #{own-set-id} (active-sets (tht/get-tokens-status undo-to-library))))
|
||||
(t/is (nil? (tht/get-own-tokens-status undo-to-library)))
|
||||
(t/is (= #{lib2-set-id} (active-sets (tht/get-tokens-status undo-back-to-own))))
|
||||
(t/is (= #{own-set-id} (active-sets (tht/get-own-tokens-status undo-back-to-own))))))
|
||||
|
||||
(t/testing "if the library is nil, the tokens source is cleared and the tokens status is reset to empty"
|
||||
(let [set-id (uuid/next)
|
||||
file (tht/sample-file-with-tokens
|
||||
|
||||
@ -510,7 +510,8 @@
|
||||
(pcb/with-library-data data)
|
||||
(clo/generate-set-tokens-source library)
|
||||
(pcb/set-tokens-source library-id))]
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(dwtp/propagate-workspace-tokens))))))
|
||||
|
||||
(defn delete-token-set
|
||||
[id]
|
||||
|
||||
@ -97,6 +97,7 @@
|
||||
[frontend-tests.tokens.logic.token-actions-test]
|
||||
[frontend-tests.tokens.logic.token-data-test]
|
||||
[frontend-tests.tokens.logic.token-remapping-test]
|
||||
[frontend-tests.tokens.logic.tokens-source-test]
|
||||
[frontend-tests.tokens.logic.tokens-status-test]
|
||||
[frontend-tests.tokens.style-dictionary-test]
|
||||
[frontend-tests.tokens.token-errors-test]
|
||||
@ -246,6 +247,7 @@
|
||||
'frontend-tests.tokens.style-dictionary-test
|
||||
'frontend-tests.tokens.token-errors-test
|
||||
'frontend-tests.tokens.token-path-test
|
||||
'frontend-tests.tokens.logic.tokens-source-test
|
||||
'frontend-tests.tokens.logic.tokens-status-test
|
||||
'frontend-tests.tokens.workspace-tokens-remap-test
|
||||
'frontend-tests.ui.check-updates-test
|
||||
|
||||
@ -0,0 +1,136 @@
|
||||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS SUBSIDIARY SL
|
||||
|
||||
(ns frontend-tests.tokens.logic.tokens-source-test
|
||||
(:require
|
||||
[app.common.test-helpers.compositions :as ctho]
|
||||
[app.common.test-helpers.ids-map :as cthi]
|
||||
[app.common.test-helpers.shapes :as cths]
|
||||
[app.common.test-helpers.tokens :as ctht]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.common.types.tokens-status :as ctos]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.tokens.library-edit :as dwtl]
|
||||
[app.main.repo :as rp]
|
||||
[beicon.v2.core :as rx]
|
||||
[cljs.test :as t :include-macros true]
|
||||
[frontend-tests.helpers.async :as async]
|
||||
[frontend-tests.helpers.mock :as mock]
|
||||
[frontend-tests.helpers.pages :as thp]
|
||||
[frontend-tests.helpers.state :as ths]
|
||||
[frontend-tests.helpers.wasm :as thw]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
(t/use-fixtures :each
|
||||
{:before (fn []
|
||||
(thp/reset-idmap!)
|
||||
(thw/setup-wasm-mocks!))
|
||||
:after thw/teardown-wasm-mocks!})
|
||||
|
||||
(defn- setup-library
|
||||
"A library whose active set defines `red` as green."
|
||||
[]
|
||||
(ctht/sample-file-with-tokens
|
||||
:file-id :library
|
||||
:lib-fn #(-> %
|
||||
(ctob/add-set (ctob/make-token-set :id (cthi/new-id! :library-set)
|
||||
:name "library-set"))
|
||||
(ctob/add-token (cthi/id :library-set)
|
||||
(ctob/make-token :id (cthi/new-id! :library-red)
|
||||
:name "red"
|
||||
:type :color
|
||||
:value "#00ff00")))
|
||||
:status-fn #(ctos/set-tokens-status % #{} #{(cthi/id :library-set)})))
|
||||
|
||||
(defn- setup-file
|
||||
"A file whose own active set defines `red` as dark red, applied to the
|
||||
fill of a rectangle."
|
||||
[]
|
||||
(-> (ctht/sample-file-with-tokens
|
||||
:file-id :local
|
||||
:lib-fn #(-> %
|
||||
(ctob/add-set (ctob/make-token-set :id (cthi/new-id! :local-set)
|
||||
:name "local-set"))
|
||||
(ctob/add-token (cthi/id :local-set)
|
||||
(ctob/make-token :id (cthi/new-id! :local-red)
|
||||
:name "red"
|
||||
:type :color
|
||||
:value "rgb(123, 34, 34)")))
|
||||
:status-fn #(ctos/set-tokens-status % #{} #{(cthi/id :local-set)}))
|
||||
(ctho/add-rect :rect1)
|
||||
(ctht/apply-token-to-shape :rect1 "red" [:fill] [:fill] "#7b2222")))
|
||||
|
||||
(defn- fill-color
|
||||
[store]
|
||||
(let [file (ths/get-file-from-state @store)]
|
||||
(-> (cths/get-shape file :rect1) :fills first :fill-color)))
|
||||
|
||||
(defn- active-set-ids
|
||||
[store]
|
||||
(-> (ths/get-file-from-state @store) ctht/get-tokens-status ctos/get-active-set-ids))
|
||||
|
||||
(defn- tokens-source
|
||||
[store]
|
||||
(-> (ths/get-file-from-state @store) ctht/get-tokens-source))
|
||||
|
||||
(defn- ^:async use-library-tokens
|
||||
"Set `library` as tokens source and wait for the canvas to use it."
|
||||
[store library]
|
||||
(ptk/emit! store (dwtl/set-tokens-source (:id library)))
|
||||
(await (async/wait-for #(= "#00ff00" (fill-color store))
|
||||
"the fill uses the library value of `red`"
|
||||
{:max-ticks 200})))
|
||||
|
||||
(t/deftest ^:async switching-tokens-source-updates-the-canvas
|
||||
(let [library (setup-library)
|
||||
file (setup-file)
|
||||
store (ths/setup-store file {:libraries [library]})]
|
||||
|
||||
(t/is (= "#7b2222" (fill-color store)))
|
||||
|
||||
(ptk/emit! store (dwtl/set-tokens-source (:id library)))
|
||||
(await (async/wait-for #(= "#00ff00" (fill-color store))
|
||||
"the fill uses the library value of `red`"
|
||||
{:max-ticks 200}))
|
||||
(t/is (= "#00ff00" (fill-color store))
|
||||
"Setting the library as tokens source resolves `red` from the library")
|
||||
|
||||
(ptk/emit! store (dwtl/set-tokens-source (:id file)))
|
||||
(await (async/settle))
|
||||
(t/is (contains? (active-set-ids store) (cthi/id :local-set))
|
||||
"Going back to the local tokens keeps the local set active")
|
||||
(await (async/wait-for #(= "#7b2222" (fill-color store))
|
||||
"the fill uses the local value of `red` again"
|
||||
{:max-ticks 200}))
|
||||
(t/is (= "#7b2222" (fill-color store))
|
||||
"Going back to the local tokens resolves `red` from the file again")
|
||||
|
||||
(rx/dispose! store)))
|
||||
|
||||
(t/deftest ^:async unlinking-the-tokens-source-library-restores-the-local-tokens
|
||||
(let [library (setup-library)
|
||||
file (setup-file)
|
||||
store (ths/setup-store file {:libraries [library]})]
|
||||
(await (use-library-tokens store library))
|
||||
|
||||
(await
|
||||
(mock/with-mocks*
|
||||
{rp/cmd! (mock/stub (fn [_ _] (rx/observe-on :async (rx/of []))))}
|
||||
;; The same events the libraries dialog emits on unlink
|
||||
(ptk/emit! store
|
||||
(dwl/unlink-file-from-library (:id file) (:id library))
|
||||
(dwtl/set-tokens-source (:id file)))
|
||||
(await (async/wait-for #(= "#7b2222" (fill-color store))
|
||||
"the fill uses the local value of `red` again"
|
||||
{:max-ticks 200}))))
|
||||
|
||||
(t/is (nil? (tokens-source store)))
|
||||
(t/is (contains? (active-set-ids store) (cthi/id :local-set))
|
||||
"Unlinking the library keeps the local set active")
|
||||
(t/is (= "#7b2222" (fill-color store)))
|
||||
|
||||
(rx/dispose! store)))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user