🔧 Normalize status helper functions and access token sets by id

This commit is contained in:
Andrés Moya 2026-07-06 20:15:45 +02:00
parent 21a69d89cd
commit aab5741bcd
17 changed files with 1197 additions and 792 deletions

View File

@ -504,11 +504,13 @@
(defn get-active-themes (defn get-active-themes
"Return an ordered sequence of active themes" "Return an ordered sequence of active themes"
[tokens-status tokens-lib] [tokens-status tokens-lib]
(assert (ctos/tokens-status? tokens-status) "expected valid tokens-status")
(assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib")
(->> (ctob/get-themes tokens-lib) (->> (ctob/get-themes tokens-lib)
(filter #(ctos/theme-active? tokens-status (ctob/get-id %))))) (filter #(ctos/theme-active? tokens-status (ctob/get-id %)))))
(defn activate-theme (defn activate-theme
"Activate a theme and all its sets" "Activate a theme and all its sets. Deactivate any other theme in the same group."
[tokens-status tokens-lib id] [tokens-status tokens-lib id]
(assert (ctos/tokens-status? tokens-status) "expected valid tokens-status") (assert (ctos/tokens-status? tokens-status) "expected valid tokens-status")
(assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib") (assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib")
@ -543,69 +545,117 @@
(deactivate-theme tokens-status tokens-lib id) (deactivate-theme tokens-status tokens-lib id)
(activate-theme tokens-status tokens-lib id))) (activate-theme tokens-status tokens-lib id)))
(defn set-active-themes (defn set-theme-active
"Set the active themes and recalculate active sets." "Set a theme's active state and update active sets accordingly."
[tokens-status tokens-lib theme-ids] [tokens-status tokens-lib id active?]
(assert (ctos/tokens-status? tokens-status)) (if active?
(assert (ctob/tokens-lib? tokens-lib)) (activate-theme tokens-status tokens-lib id)
(assert (set? theme-ids)) (deactivate-theme tokens-status tokens-lib id)))
(let [active-set-ids (calculate-active-sets theme-ids tokens-lib)]
(ctos/set-tokens-status tokens-status theme-ids active-set-ids)))
(defn get-active-set-names (defn get-active-sets
"Return a set of active set names, resolved from TokensStatus + TokensLib." "Return a clojure set of the active sets, resolved from TokensStatus + TokensLib."
[tokens-status tokens-lib] [tokens-status tokens-lib]
(assert (ctos/tokens-status? tokens-status) "expected valid tokens-status")
(assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib")
(let [active-set-ids (ctos/get-active-set-ids tokens-status)] (let [active-set-ids (ctos/get-active-set-ids tokens-status)]
(into #{} (into #{}
(comp (filter #(contains? active-set-ids (ctob/get-id %))) (comp (map #(ctob/get-set tokens-lib %))
(map ctob/get-name)) (filter some?))
(ctob/get-sets tokens-lib)))) active-set-ids)))
(defn token-set-active? (defn set-set-active
"Check if a set (by name) is active." "Set directly a set's active state and deactivate all themes."
[tokens-status tokens-lib set-name] [tokens-status tokens-lib id active?]
(let [active-set-names (get-active-set-names tokens-status tokens-lib)] (assert (ctos/tokens-status? tokens-status) "expected valid tokens-status")
(contains? active-set-names set-name))) (assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib")
(assert (uuid? id) "expected valid set id")
(if (and (ctob/get-set tokens-lib id)
(not= active? (ctos/set-active? tokens-status id)))
(let [active-set-ids (ctos/get-active-set-ids tokens-status)
active-set-ids' (if active?
(conj active-set-ids id)
(disj active-set-ids id))]
(ctos/set-tokens-status tokens-status #{} active-set-ids'))
tokens-status))
(defn activate-set
"Activate directly a set, and deactivate all themes."
[tokens-status tokens-lib id]
(set-set-active tokens-status tokens-lib id true))
(defn deactivate-set
"Deactivate directly a set, and deactivate all themes."
[tokens-status tokens-lib id]
(set-set-active tokens-status tokens-lib id false))
(defn toggle-set-active
"Toggle a set's active state and deactivate all themes."
[tokens-status tokens-lib id]
(set-set-active tokens-status tokens-lib id (not (ctos/set-active? tokens-status id))))
(defn sets-at-path-all-active? (defn sets-at-path-all-active?
"Check active state of sets at a group path. "Check active state of sets at a group path.
Returns :none, :all, or :partial." Returns :none, :all, or :partial."
[tokens-status tokens-lib group-path] [tokens-status tokens-lib group-path]
(let [active-set-names (get-active-set-names tokens-status tokens-lib) (assert (ctos/tokens-status? tokens-status) "expected valid tokens-status")
path-sets (into #{} (assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib")
(map ctob/get-name) (assert (vector? group-path) "expected valid group path")
(ctob/get-sets-at-path tokens-lib group-path))] (let [active-set-ids (ctos/get-active-set-ids tokens-status)
(if (seq active-set-names) path-set-ids (into #{}
(let [difference (set/difference path-sets active-set-names)] (map ctob/get-id)
(ctob/get-sets-at-path tokens-lib group-path))]
(if (seq active-set-ids)
(let [difference (set/difference path-set-ids active-set-ids)]
(cond (cond
(empty? difference) :all (empty? difference) :all
(seq (set/intersection path-sets active-set-names)) :partial (seq (set/intersection path-set-ids active-set-ids)) :partial
:else :none)) :else :none))
:none))) :none)))
(defn toggle-set-group-active
"Toggle the active state of all sets at a group path, and deactivate all themes.
If all sets are active, deactivate all. If none or some are active, activate all."
[tokens-status tokens-lib group-path]
(let [all-active? (sets-at-path-all-active? tokens-status tokens-lib group-path)
sets-at-path (ctob/get-sets-at-path tokens-lib group-path)
set-ids-at-path (into #{} (map ctob/get-id) sets-at-path)
active-set-ids (ctos/get-active-set-ids tokens-status)
active-set-ids' (if (contains? #{:all :partial} all-active?)
(set/difference active-set-ids set-ids-at-path)
(set/union active-set-ids set-ids-at-path))]
(if (not= active-set-ids active-set-ids')
(ctos/set-tokens-status tokens-status #{} active-set-ids')
tokens-status)))
(defn get-tokens-in-active-sets (defn get-tokens-in-active-sets
"Get merged tokens from all active sets, in set order." "Get merged tokens from all active sets, in set order."
[tokens-status tokens-lib] [tokens-status tokens-lib]
(let [active-set-names (get-active-set-names tokens-status tokens-lib) (assert (ctos/tokens-status? tokens-status) "expected valid tokens-status")
all-set-names (ctob/get-set-names tokens-lib) (assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib")
ordered-active (filter active-set-names all-set-names)] (let [active-set-ids (ctos/get-active-set-ids tokens-status)
(reduce (fn [tokens set-name] all-set-ids (map ctob/get-id (ctob/get-sets tokens-lib))
(let [set (ctob/get-set-by-name tokens-lib set-name)] ordered-active (filter active-set-ids all-set-ids)]
(merge tokens (ctob/get-tokens- set)))) (reduce (fn [tokens set-id]
(merge tokens (ctob/get-tokens tokens-lib set-id)))
(d/ordered-map) (d/ordered-map)
ordered-active))) ordered-active)))
(defn get-tokens-in-active-sets-force (defn get-tokens-in-active-sets-force
"Same as get-tokens-in-active-sets but force-including a set by id." "Same as get-tokens-in-active-sets but force-including a set by id."
[tokens-status tokens-lib force-set-id] [tokens-status tokens-lib force-set-id]
(let [active-set-names (get-active-set-names tokens-status tokens-lib) (assert (ctos/tokens-status? tokens-status) "expected valid tokens-status")
all-set-names (ctob/get-set-names tokens-lib) (assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib")
force-set (ctob/get-set tokens-lib force-set-id) (assert (uuid? force-set-id) "expected valid set id")
ordered-active (cond-> (filter active-set-names all-set-names) (let [active-set-ids (ctos/get-active-set-ids tokens-status)
(some? force-set) all-set-ids (map ctob/get-id (ctob/get-sets tokens-lib))
(conj (ctob/get-name force-set)))] ordered-active (cond-> (filter active-set-ids all-set-ids)
(reduce (fn [tokens set-name] (some? force-set-id)
(let [set (ctob/get-set-by-name tokens-lib set-name)] (conj force-set-id))]
(reduce (fn [tokens set-id]
(let [set (ctob/get-set tokens-lib set-id)]
(merge tokens (ctob/get-tokens- set)))) (merge tokens (ctob/get-tokens- set))))
(d/ordered-map) (d/ordered-map)
ordered-active))) ordered-active)))
@ -614,6 +664,8 @@
"Synchronizes tokens status with the current tokens lib: "Synchronizes tokens status with the current tokens lib:
- Delete any theme or set that no longer exists in the lib." - Delete any theme or set that no longer exists in the lib."
[tokens-status tokens-lib] [tokens-status tokens-lib]
(assert (ctos/tokens-status? tokens-status) "expected valid tokens-status")
(assert (ctob/tokens-lib? tokens-lib) "expected valid tokens-lib")
(let [active-theme-ids (ctos/get-active-theme-ids tokens-status) (let [active-theme-ids (ctos/get-active-theme-ids tokens-status)
valid-theme-ids (into #{} valid-theme-ids (into #{}
(filter #(some? (ctob/get-theme tokens-lib %))) (filter #(some? (ctob/get-theme tokens-lib %)))

View File

@ -8,94 +8,11 @@
(:require (:require
[app.common.files.changes-builder :as pcb] [app.common.files.changes-builder :as pcb]
[app.common.files.tokens :as cfo] [app.common.files.tokens :as cfo]
[app.common.types.tokens-lib :as ctob] [app.common.types.tokens-lib :as ctob]))
[app.common.types.tokens-status :as ctos]
[clojure.set :as set]))
(defn- generate-update-active-sets ;; Tokens lib
"Update active set ids in tokens-status by applying update-fn to the
current active set ids. Also deactivate all themes since this is a manual
set activation. Returns updated changes."
[changes tokens-status _tokens-lib update-fn]
(let [current-set-ids (ctos/get-active-set-ids tokens-status)
new-set-ids (update-fn current-set-ids)
tokens-status' (ctos/set-tokens-status tokens-status #{} new-set-ids)]
(pcb/set-tokens-status changes tokens-status')))
(defn generate-set-enabled-token-set (defn- vec-starts-with? [v1 v2]
"Enable or disable a token set at `set-name` in `tokens-lib` without modifying a user theme."
[changes tokens-status tokens-lib set-name enabled?]
(let [set-id (ctob/get-id (ctob/get-set-by-name tokens-lib set-name))]
(if set-id
(if enabled?
(generate-update-active-sets changes tokens-status tokens-lib #(conj % set-id))
(generate-update-active-sets changes tokens-status tokens-lib #(disj % set-id)))
changes)))
(defn generate-toggle-token-set
"Toggle a token set at `set-name` in `tokens-lib` without modifying a user theme."
[changes tokens-status tokens-lib set-name]
(let [set-id (ctob/get-id (ctob/get-set-by-name tokens-lib set-name))]
(if set-id
(generate-update-active-sets changes tokens-status tokens-lib
#(if (contains? % set-id) (disj % set-id) (conj % set-id)))
changes)))
;; ================== nuevo
(defn generate-activate-theme
[changes tokens-status tokens-lib id]
(let [tokens-status' (cfo/activate-theme tokens-status tokens-lib id)]
(if (not= tokens-status tokens-status')
(pcb/set-tokens-status changes tokens-status')
changes)))
(defn generate-deactivate-theme
[changes tokens-status tokens-lib id]
(let [tokens-status' (cfo/deactivate-theme tokens-status tokens-lib id)]
(if (not= tokens-status tokens-status')
(pcb/set-tokens-status changes tokens-status')
changes)))
(defn generate-set-theme-status
[changes tokens-status tokens-lib id active?]
(if active?
(generate-activate-theme changes tokens-status tokens-lib id)
(generate-deactivate-theme changes tokens-status tokens-lib id)))
(defn generate-toggle-theme
[changes tokens-status tokens-lib id]
(let [active? (ctos/theme-active? tokens-status id)]
(if active?
(generate-deactivate-theme changes tokens-status tokens-lib id)
(generate-activate-theme changes tokens-status tokens-lib id))))
(defn generate-sync-tokens-status-with-lib
"Synchronizes tokens status with the current tokens lib"
[changes tokens-status tokens-lib]
(let [tokens-status' (cfo/sync-tokens-status-with-lib tokens-status tokens-lib)]
(if (not= tokens-status tokens-status')
(pcb/set-tokens-status changes tokens-status')
changes)))
;; ======= fin nuevo
(defn generate-toggle-token-set-group
"Toggle a token set group at `group-path` in `tokens-lib` without modifying a user theme."
[changes tokens-status tokens-lib group-path]
(let [sets-at-path (ctob/get-sets-at-path tokens-lib group-path)
set-ids (into #{} (map ctob/get-id) sets-at-path)
active? (cfo/sets-at-path-all-active? tokens-status tokens-lib group-path)]
(if (contains? #{:all :partial} active?)
;; Deactivate all sets at path
(generate-update-active-sets changes tokens-status tokens-lib
#(set/difference % set-ids))
;; Activate all sets at path
(generate-update-active-sets changes tokens-status tokens-lib
#(set/union % set-ids)))))
(defn vec-starts-with? [v1 v2]
(= (subvec v1 0 (min (count v1) (count v2))) v2)) (= (subvec v1 0 (min (count v1) (count v2))) v2))
(defn- calculate-move-token-set-or-set-group (defn- calculate-move-token-set-or-set-group
@ -191,3 +108,44 @@
(pcb/set-token-set changes (ctob/get-id set) nil)) (pcb/set-token-set changes (ctob/get-id set) nil))
changes changes
sets))) sets)))
;; Tokens Status
(defn- update-tokens-status
[changes tokens-status update-fn & args]
(let [tokens-status' (apply update-fn tokens-status args)]
(if (not= tokens-status tokens-status')
(pcb/set-tokens-status changes tokens-status')
changes)))
(defn generate-activate-theme
[changes tokens-status tokens-lib id]
(update-tokens-status changes tokens-status cfo/activate-theme tokens-lib id))
(defn generate-deactivate-theme
[changes tokens-status tokens-lib id]
(update-tokens-status changes tokens-status cfo/deactivate-theme tokens-lib id))
(defn generate-set-theme-status
[changes tokens-status tokens-lib id active?]
(update-tokens-status changes tokens-status cfo/set-theme-active tokens-lib id active?))
(defn generate-toggle-theme
[changes tokens-status tokens-lib id]
(update-tokens-status changes tokens-status cfo/toggle-theme-active tokens-lib id))
(defn generate-set-enabled-token-set
[changes tokens-status tokens-lib id enabled?]
(update-tokens-status changes tokens-status cfo/set-set-active tokens-lib id enabled?))
(defn generate-toggle-token-set
[changes tokens-status tokens-lib id]
(update-tokens-status changes tokens-status cfo/toggle-set-active tokens-lib id))
(defn generate-toggle-token-set-group
[changes tokens-status tokens-lib group-path]
(update-tokens-status changes tokens-status cfo/toggle-set-group-active tokens-lib group-path))
(defn generate-sync-tokens-status-with-lib
[changes tokens-status tokens-lib]
(update-tokens-status changes tokens-status cfo/sync-tokens-status-with-lib tokens-lib))

View File

@ -480,11 +480,6 @@
[path] [path]
(mapv add-set-path-group-prefix path)) (mapv add-set-path-group-prefix path))
(defn- set-group-path->set-group-prefixed-path-str
[path]
(-> (set-group-path->set-group-prefixed-path path)
(join-set-path)))
(defn add-set-group-prefix [group-path] (defn add-set-group-prefix [group-path]
(str set-group-prefix group-path)) (str set-group-prefix group-path))
@ -548,7 +543,7 @@
"Get an ordered sequence of all sets names in the library") "Get an ordered sequence of all sets names in the library")
(get-set-tree [_] (get-set-tree [_]
"Get a nested tree of all sets in the library") "Get a nested tree of all sets in the library")
(get-sets-at-path [_ path-str] (get-sets-at-path [_ path-vec]
"Get an ordered sequence of sets under `path` in the library")) "Get an ordered sequence of sets under `path` in the library"))
(def ^:private schema:token-set-node (def ^:private schema:token-set-node
@ -1108,8 +1103,8 @@
(->> (tree-seq d/ordered-map? vals sets) (->> (tree-seq d/ordered-map? vals sets)
(filter (partial instance? TokenSet)))) (filter (partial instance? TokenSet))))
(get-sets-at-path [_ path] (get-sets-at-path [_ path-vec]
(some->> (map add-set-path-group-prefix path) (some->> (map add-set-path-group-prefix path-vec)
(get-in sets) (get-in sets)
(tree-seq d/ordered-map? vals) (tree-seq d/ordered-map? vals)
(filter (partial instance? TokenSet)))) (filter (partial instance? TokenSet))))

View File

@ -14,8 +14,110 @@
[app.common.types.tokens-lib :as ctob] [app.common.types.tokens-lib :as ctob]
[app.common.types.tokens-status :as ctos] [app.common.types.tokens-status :as ctos]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[clojure.datafy :refer [datafy]]
[clojure.test :as t])) [clojure.test :as t]))
;; Helper functions
(t/deftest test-token-circular-reference?
(t/testing "returns nil when token has no references"
(let [tokens {"spacing" {:name "spacing" :value "16px"}}]
(t/is (nil? (cfo/token-circular-reference? tokens "spacing")))))
(t/testing "returns nil for a simple non-circular reference chain"
(let [tokens {"base" {:name "base" :value "10"}
"large" {:name "large" :value "{base}"}}]
(t/is (nil? (cfo/token-circular-reference? tokens "large")))))
(t/testing "detects direct self-reference"
(let [tokens {"self" {:name "self" :value "{self}"}}]
(t/is (= "self" (cfo/token-circular-reference? tokens "self")))))
(t/testing "detects indirect circular reference"
(let [tokens {"a" {:name "a" :value "{b}"}
"b" {:name "b" :value "{c}"}
"c" {:name "c" :value "{a}"}}]
(t/is (some? (cfo/token-circular-reference? tokens "a")))))
(t/testing "returns nil for diamond dependency (no cycle)"
(let [tokens {"base" {:name "base" :value "10"}
"left" {:name "left" :value "{base}"}
"right" {:name "right" :value "{base}"}
"combine" {:name "combine" :value "{left} {right}"}}]
(t/is (nil? (cfo/token-circular-reference? tokens "combine")))))
(t/testing "returns nil when token name does not exist in tokens map"
(let [tokens {"a" {:name "a" :value "10"}}]
(t/is (nil? (cfo/token-circular-reference? tokens "nonexistent")))))
(t/testing "detects circular reference in map-typed values (typography composite)"
(let [tokens {"family" {:name "family" :value "Arial"}
"size" {:name "size" :value "16px"}
"typog" {:name "typog" :value {:font-family {:reference "{family}"}
:font-size {:reference "{size}"}}}
"cycle" {:name "cycle" :value {:font-family {:reference "{typog}"}}}}]
;; typog references family and size (no cycle)
(t/is (nil? (cfo/token-circular-reference? tokens "typog"))))))
(t/deftest test-attributes-map
(t/testing "creates map from attributes to token name"
(t/is (= {:fill "primary" :stroke "primary"}
(cfo/attributes-map [:fill :stroke] {:name "primary"}))))
(t/testing "returns empty map for empty attributes"
(t/is (= {} (cfo/attributes-map [] {:name "primary"}))))
(t/testing "maps each attribute independently"
(t/is (= {:x "t" :y "t" :z "t"}
(cfo/attributes-map [:x :y :z] {:name "t"})))))
(t/deftest test-remove-attributes-for-token
(t/testing "removes entries matching both attribute set and token name"
(t/is (= {:stroke "other"}
(cfo/remove-attributes-for-token
[:fill :stroke] "primary"
{:fill "primary" :stroke "other"}))))
(t/testing "keeps entries with matching attribute but different token name"
(t/is (= {:fill "secondary" :stroke "other"}
(cfo/remove-attributes-for-token
[:fill :stroke] "primary"
{:fill "secondary" :stroke "other"}))))
(t/testing "keeps entries with matching token name but non-matching attribute"
(t/is (= {:opacity "primary"}
(cfo/remove-attributes-for-token
[:fill :stroke] "primary"
{:fill "primary" :opacity "primary"}))))
(t/testing "returns empty map when all entries match"
(t/is (= {}
(cfo/remove-attributes-for-token
[:fill] "primary"
{:fill "primary"}))))
(t/testing "returns empty map for empty applied-tokens"
(t/is (= {}
(cfo/remove-attributes-for-token [:fill] "primary" {})))))
(t/deftest test-color-token?
(t/testing "returns true for color type"
(t/is (true? (cfo/color-token? {:type :color}))))
(t/testing "returns false for non-color types"
(t/is (false? (cfo/color-token? {:type :spacing})))
(t/is (false? (cfo/color-token? {:type :border-radius})))
(t/is (false? (cfo/color-token? {})))))
(t/deftest test-is-reference?
(t/testing "returns truthy when value contains opening brace"
(t/is (cfo/is-reference? {:value "{foo}"}))
(t/is (cfo/is-reference? {:value "calc({bar} + 1)"})))
(t/testing "returns falsy when value has no brace"
(t/is (not (cfo/is-reference? {:value "16px"})))
(t/is (not (cfo/is-reference? {:value ""})))))
(t/deftest test-parse-token-value (t/deftest test-parse-token-value
(t/testing "parses double from a token value" (t/testing "parses double from a token value"
(t/is (= {:value 100.1 :unit nil} (cfo/parse-token-value "100.1"))) (t/is (= {:value 100.1 :unit nil} (cfo/parse-token-value "100.1")))
@ -100,7 +202,7 @@
{:applied-tokens {:x "a"}}] {:applied-tokens {:x "a"}}]
#{:y}))))) #{:y})))))
;; Tokens lib ;; Tokens lib in file data
(t/deftest test-ensure-tokens-lib (t/deftest test-ensure-tokens-lib
(t/testing "ensure-tokens-lib should add a tokens-lib and tokens-status to the file data if they are missing" (t/testing "ensure-tokens-lib should add a tokens-lib and tokens-status to the file data if they are missing"
@ -143,7 +245,7 @@
(t/is (not (contains? file-data' :tokens-lib))) (t/is (not (contains? file-data' :tokens-lib)))
(t/is (= tokens-file (:tokens-file file-data'))) (t/is (= tokens-file (:tokens-file file-data')))
(t/is (= tokens-status (:tokens-status file-data'))))) (t/is (= tokens-status (:tokens-status file-data')))))
(t/testing "ensure-tokens-lib should not add a tokens-lib if there is a tokens-file, but should add a tokens-status if it's missing" (t/testing "ensure-tokens-lib should not add a tokens-lib if there is a tokens-file, but should add a tokens-status if it's missing"
(let [tokens-file (uuid/next) (let [tokens-file (uuid/next)
file (-> (thf/sample-file :file1) file (-> (thf/sample-file :file1)
@ -155,6 +257,41 @@
(t/is (contains? file-data' :tokens-status)) (t/is (contains? file-data' :tokens-status))
(t/is (ctos/tokens-status? (:tokens-status file-data')))))) (t/is (ctos/tokens-status? (:tokens-status file-data'))))))
(t/deftest test-get-tokens-lib
(t/testing "returns tokens-lib from file data"
(let [tokens-lib (ctob/make-tokens-lib)
file-data {:tokens-lib tokens-lib}]
(t/is (= tokens-lib (cfo/get-tokens-lib file-data)))))
(t/testing "returns nil when no tokens-lib"
(t/is (nil? (cfo/get-tokens-lib {})))))
(t/deftest test-get-tokens-file
(t/testing "returns tokens-file from file data"
(let [file-id (thi/new-id! :tokens-file)
file-data {:tokens-file file-id}]
(t/is (= file-id (cfo/get-tokens-file file-data)))))
(t/testing "returns nil when no tokens-file"
(t/is (nil? (cfo/get-tokens-file {})))))
(t/deftest test-set-tokens-file
(t/testing "sets tokens-file on file data"
(let [file-id (thi/new-id! :tokens-file)
file-data {:other :data}
file-data' (cfo/set-tokens-file file-data file-id)]
(t/is (= file-id (:tokens-file file-data')))
(t/is (= :data (:other file-data'))))))
(t/deftest test-get-tokens-status
(t/testing "returns tokens-status from file data"
(let [tokens-status (ctos/make-tokens-status)
file-data {:tokens-status tokens-status}]
(t/is (= tokens-status (cfo/get-tokens-status file-data)))))
(t/testing "returns nil when no tokens-status"
(t/is (nil? (cfo/get-tokens-status {})))))
(t/deftest test-update-tokens-lib (t/deftest test-update-tokens-lib
(t/testing "update when there is no tokens-lib has no effect" (t/testing "update when there is no tokens-lib has no effect"
(let [file (thf/sample-file :file1) (let [file (thf/sample-file :file1)
@ -425,6 +562,409 @@
tokens-status' (cfo/deactivate-theme tokens-status tokens-lib (thi/new-id! :nonexistent))] tokens-status' (cfo/deactivate-theme tokens-status tokens-lib (thi/new-id! :nonexistent))]
(t/is (identical? tokens-status tokens-status'))))) (t/is (identical? tokens-status tokens-status')))))
(t/deftest test-toggle-theme-active
(t/testing "activates an inactive theme"
(let [tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-a) :name "set-a"))
(ctob/add-theme (ctob/make-token-theme :id (thi/new-id! :theme-1)
:name "theme-1"
:group ""
:sets #{"set-a"})))
tokens-status (ctos/make-tokens-status)
tokens-status' (cfo/toggle-theme-active tokens-status tokens-lib (thi/id :theme-1))]
(t/is (ctos/theme-active? tokens-status' (thi/id :theme-1)))))
(t/testing "deactivates an active theme"
(let [tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-a) :name "set-a"))
(ctob/add-theme (ctob/make-token-theme :id (thi/new-id! :theme-1)
:name "theme-1"
:group ""
:sets #{"set-a"})))
tokens-status (ctos/make-tokens-status :active-theme-ids #{(thi/id :theme-1)}
:active-set-ids #{(thi/id :set-a)})
tokens-status' (cfo/toggle-theme-active tokens-status tokens-lib (thi/id :theme-1))]
(t/is (not (ctos/theme-active? tokens-status' (thi/id :theme-1)))))))
(t/deftest test-set-theme-active
(t/testing "activates a theme when active? is true"
(let [tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-a) :name "set-a"))
(ctob/add-theme (ctob/make-token-theme :id (thi/new-id! :theme-1)
:name "theme-1"
:group ""
:sets #{"set-a"})))
tokens-status (ctos/make-tokens-status)
tokens-status' (cfo/set-theme-active tokens-status tokens-lib (thi/id :theme-1) true)]
(t/is (ctos/theme-active? tokens-status' (thi/id :theme-1)))))
(t/testing "deactivates a theme when active? is false"
(let [tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-a) :name "set-a"))
(ctob/add-theme (ctob/make-token-theme :id (thi/new-id! :theme-1)
:name "theme-1"
:group ""
:sets #{"set-a"})))
tokens-status (ctos/make-tokens-status :active-theme-ids #{(thi/id :theme-1)}
:active-set-ids #{(thi/id :set-a)})
tokens-status' (cfo/set-theme-active tokens-status tokens-lib (thi/id :theme-1) false)]
(t/is (not (ctos/theme-active? tokens-status' (thi/id :theme-1)))))))
(t/deftest test-get-active-sets
(t/testing "returns active sets resolved from status and lib"
(let [set-a-id (thi/new-id! :set-a)
set-b-id (thi/new-id! :set-b)
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "set-a"))
(ctob/add-set (ctob/make-token-set :id set-b-id :name "set-b")))
tokens-status (ctos/make-tokens-status :active-set-ids #{set-a-id})
active-sets (cfo/get-active-sets tokens-status tokens-lib)]
(t/is (= 1 (count active-sets)))
(t/is (= set-a-id (ctob/get-id (first active-sets))))))
(t/testing "returns empty set when no sets are active"
(let [tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-a) :name "set-a")))
tokens-status (ctos/make-tokens-status)
active-sets (cfo/get-active-sets tokens-status tokens-lib)]
(t/is (empty? active-sets)))))
(t/deftest test-set-set-active
(t/testing "activates a set and clears all themes"
(let [set-a-id (thi/new-id! :set-a)
theme-1-id (thi/new-id! :theme-1)
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "set-a"))
(ctob/add-theme (ctob/make-token-theme :id theme-1-id
:name "theme-1"
:group ""
:sets #{"set-a"})))
tokens-status (ctos/make-tokens-status :active-theme-ids #{theme-1-id}
:active-set-ids #{})
tokens-status' (cfo/set-set-active tokens-status tokens-lib set-a-id true)]
(t/is (ctos/set-active? tokens-status' set-a-id))
(t/is (= #{} (ctos/get-active-theme-ids tokens-status')))))
(t/testing "deactivates a set and clears all themes"
(let [set-a-id (thi/new-id! :set-a)
theme-1-id (thi/new-id! :theme-1)
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "set-a"))
(ctob/add-theme (ctob/make-token-theme :id theme-1-id
:name "theme-1"
:group ""
:sets #{"set-a"})))
tokens-status (ctos/make-tokens-status :active-theme-ids #{theme-1-id}
:active-set-ids #{set-a-id})
tokens-status' (cfo/set-set-active tokens-status tokens-lib set-a-id false)]
(t/is (not (ctos/set-active? tokens-status' set-a-id)))
(t/is (= #{} (ctos/get-active-theme-ids tokens-status')))))
(t/testing "returns same status when set is already in target state"
(let [set-a-id (thi/new-id! :set-a)
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "set-a")))
tokens-status (ctos/make-tokens-status :active-set-ids #{set-a-id})
tokens-status' (cfo/set-set-active tokens-status tokens-lib set-a-id true)]
(t/is (identical? tokens-status tokens-status'))))
(t/testing "returns same status for non-existent set"
(let [tokens-lib (ctob/make-tokens-lib)
tokens-status (ctos/make-tokens-status)
tokens-status' (cfo/set-set-active tokens-status tokens-lib (thi/new-id! :nonexistent) true)]
(t/is (identical? tokens-status tokens-status')))))
(t/deftest test-activate-set
(t/testing "delegates to set-set-active with true"
(let [set-a-id (thi/new-id! :set-a)
theme-1-id (thi/new-id! :theme-1)
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "set-a"))
(ctob/add-theme (ctob/make-token-theme :id theme-1-id
:name "theme-1"
:group ""
:sets #{"set-a"})))
tokens-status (ctos/make-tokens-status)
tokens-status' (cfo/activate-set tokens-status tokens-lib set-a-id)]
(t/is (ctos/set-active? tokens-status' set-a-id))
(t/is (= #{} (ctos/get-active-theme-ids tokens-status'))))))
(t/deftest test-deactivate-set
(t/testing "delegates to set-set-active with false"
(let [set-a-id (thi/new-id! :set-a)
theme-1-id (thi/new-id! :theme-1)
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "set-a"))
(ctob/add-theme (ctob/make-token-theme :id theme-1-id
:name "theme-1"
:group ""
:sets #{"set-a"})))
tokens-status (ctos/make-tokens-status :active-theme-ids #{theme-1-id}
:active-set-ids #{set-a-id})
tokens-status' (cfo/deactivate-set tokens-status tokens-lib set-a-id)]
(t/is (not (ctos/set-active? tokens-status' set-a-id)))
(t/is (= #{} (ctos/get-active-theme-ids tokens-status'))))))
(t/deftest test-toggle-set-active
(t/testing "activates an inactive set"
(let [set-a-id (thi/new-id! :set-a)
theme-1-id (thi/new-id! :theme-1)
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "set-a"))
(ctob/add-theme (ctob/make-token-theme :id theme-1-id
:name "theme-1"
:group ""
:sets #{})))
tokens-status (ctos/make-tokens-status :active-theme-ids #{theme-1-id}
:active-set-ids #{})
tokens-status' (cfo/toggle-set-active tokens-status tokens-lib set-a-id)]
(t/is (ctos/set-active? tokens-status' set-a-id))
(t/is (= #{} (ctos/get-active-theme-ids tokens-status')))))
(t/testing "deactivates an active set"
(let [set-a-id (thi/new-id! :set-a)
theme-1-id (thi/new-id! :theme-1)
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "set-a"))
(ctob/add-theme (ctob/make-token-theme :id theme-1-id
:name "theme-1"
:group ""
:sets #{"set-a"})))
tokens-status (ctos/make-tokens-status :active-theme-ids #{theme-1-id}
:active-set-ids #{set-a-id})
tokens-status' (cfo/toggle-set-active tokens-status tokens-lib set-a-id)]
(t/is (not (ctos/set-active? tokens-status' set-a-id)))
(t/is (= #{} (ctos/get-active-theme-ids tokens-status'))))))
(t/deftest test-sets-at-path-all-active?
(t/testing "returns :all when all sets at path are active"
(let [set-a-id (thi/new-id! :set-a)
set-b-id (thi/new-id! :set-b)
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "group/set-a"))
(ctob/add-set (ctob/make-token-set :id set-b-id :name "group/set-b")))
tokens-status (ctos/make-tokens-status :active-set-ids #{set-a-id set-b-id})]
(t/is (= :all (cfo/sets-at-path-all-active? tokens-status tokens-lib ["group"])))))
(t/testing "returns :none when no sets at path are active"
(let [set-a-id (thi/new-id! :set-a)
set-b-id (thi/new-id! :set-b)
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "group/set-a"))
(ctob/add-set (ctob/make-token-set :id set-b-id :name "group/set-b")))
tokens-status (ctos/make-tokens-status :active-set-ids #{})]
(t/is (= :none (cfo/sets-at-path-all-active? tokens-status tokens-lib ["group"])))))
(t/testing "returns :partial when some sets at path are active"
(let [set-a-id (thi/new-id! :set-a)
set-b-id (thi/new-id! :set-b)
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "group/set-a"))
(ctob/add-set (ctob/make-token-set :id set-b-id :name "group/set-b")))
tokens-status (ctos/make-tokens-status :active-set-ids #{set-a-id})]
(t/is (= :partial (cfo/sets-at-path-all-active? tokens-status tokens-lib ["group"])))))
(t/testing "returns :none for empty path when no sets exist at root"
(let [tokens-lib (ctob/make-tokens-lib)
tokens-status (ctos/make-tokens-status)]
(t/is (= :none (cfo/sets-at-path-all-active? tokens-status tokens-lib [])))))
(t/testing "several combinations with longer paths"
(let [baz-id (thi/new-id! :baz)
bam-id (thi/new-id! :bam)
none-id (thi/new-id! :none)
partial-id (thi/new-id! :partial)
all-id (thi/new-id! :all)
invalid-id (thi/new-id! :invalid)
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id baz-id :name "foo/bar/baz"))
(ctob/add-set (ctob/make-token-set :id bam-id :name "foo/bar/bam"))
(ctob/add-theme (ctob/make-token-theme :id none-id
:name "none"))
(ctob/add-theme (ctob/make-token-theme :id partial-id
:name "partial"
:sets #{"foo/bar/baz"}))
(ctob/add-theme (ctob/make-token-theme :id all-id
:name "all"
:sets #{"foo/bar/baz"
"foo/bar/bam"}))
(ctob/add-theme (ctob/make-token-theme :id invalid-id
:name "invalid"
:sets #{"foo/missing"})))
expected-none (-> (ctos/make-tokens-status {:active-theme-ids #{none-id}
:active-set-ids #{}})
(cfo/sets-at-path-all-active? tokens-lib ["foo"]))
expected-all (-> (ctos/make-tokens-status {:active-theme-ids #{all-id}
:active-set-ids #{baz-id bam-id}})
(cfo/sets-at-path-all-active? tokens-lib ["foo"]))
expected-partial (-> (ctos/make-tokens-status {:active-theme-ids #{partial-id}
:active-set-ids #{baz-id}})
(cfo/sets-at-path-all-active? tokens-lib ["foo"]))
expected-invalid-none (-> (ctos/make-tokens-status {:active-theme-ids #{invalid-id}
:active-set-ids #{}})
(cfo/sets-at-path-all-active? tokens-lib ["foo"]))]
(t/is (= :none expected-none))
(t/is (= :all expected-all))
(t/is (= :partial expected-partial))
(t/is (= :none expected-invalid-none)))))
(t/deftest test-toggle-set-group-active
(t/testing "activates all sets in group when none are active, and deactivate all themes"
(let [set-a-id (thi/new-id! :set-a)
set-b-id (thi/new-id! :set-b)
set-c-id (thi/new-id! :set-c)
theme-1-id (thi/new-id! :theme-1)
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "group/set-a"))
(ctob/add-set (ctob/make-token-set :id set-b-id :name "group/set-b"))
(ctob/add-set (ctob/make-token-set :id set-c-id :name "group/set-b/child"))
(ctob/add-theme (ctob/make-token-theme :id theme-1-id
:name "theme-1"
:group ""
:sets #{})))
tokens-status (ctos/make-tokens-status :active-theme-ids #{theme-1-id}
:active-set-ids #{})
tokens-status' (cfo/toggle-set-group-active tokens-status tokens-lib ["group"])]
(t/is (ctos/set-active? tokens-status' set-a-id))
(t/is (ctos/set-active? tokens-status' set-b-id))
(t/is (ctos/set-active? tokens-status' set-c-id))
(t/is (= #{} (ctos/get-active-theme-ids tokens-status')))))
(t/testing "deactivates all sets in group when all are active, and deactivate all themes"
(let [set-a-id (thi/new-id! :set-a)
set-b-id (thi/new-id! :set-b)
set-c-id (thi/new-id! :set-c)
theme-1-id (thi/new-id! :theme-1)
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "group/set-a"))
(ctob/add-set (ctob/make-token-set :id set-b-id :name "group/set-b"))
(ctob/add-set (ctob/make-token-set :id set-c-id :name "group/set-b/child"))
(ctob/add-theme (ctob/make-token-theme :id theme-1-id
:name "theme-1"
:group ""
:sets #{"group/set-a" "group/set-b" "group/set-b/child"})))
tokens-status (ctos/make-tokens-status :active-theme-ids #{theme-1-id}
:active-set-ids #{set-a-id set-b-id set-c-id})
tokens-status' (cfo/toggle-set-group-active tokens-status tokens-lib ["group"])]
(t/is (not (ctos/set-active? tokens-status' set-a-id)))
(t/is (not (ctos/set-active? tokens-status' set-b-id)))
(t/is (not (ctos/set-active? tokens-status' set-c-id)))
(t/is (= #{} (ctos/get-active-theme-ids tokens-status')))))
(t/testing "deactivates all sets in group when only some are active, and deactivate all themes"
(let [set-a-id (thi/new-id! :set-a)
set-b-id (thi/new-id! :set-b)
set-c-id (thi/new-id! :set-c)
theme-1-id (thi/new-id! :theme-1)
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "group/set-a"))
(ctob/add-set (ctob/make-token-set :id set-b-id :name "group/set-b"))
(ctob/add-set (ctob/make-token-set :id set-c-id :name "group/set-b/child"))
(ctob/add-theme (ctob/make-token-theme :id theme-1-id
:name "theme-1"
:group ""
:sets #{"set-a"})))
tokens-status (ctos/make-tokens-status :active-theme-ids #{theme-1-id}
:active-set-ids #{set-a-id})
tokens-status' (cfo/toggle-set-group-active tokens-status tokens-lib ["group"])]
(t/is (not (ctos/set-active? tokens-status' set-a-id)))
(t/is (not (ctos/set-active? tokens-status' set-b-id)))
(t/is (not (ctos/set-active? tokens-status' set-c-id)))
(t/is (= #{} (ctos/get-active-theme-ids tokens-status'))))))
(t/deftest test-get-tokens-in-active-sets
(t/testing "returns merged tokens from active sets in set order"
(let [set-a-id (thi/new-id! :set-a)
set-b-id (thi/new-id! :set-b)
tok-a (ctob/make-token :name "spacing" :type :spacing :value "8px")
tok-b (ctob/make-token :name "radius" :type :border-radius :value "4px")
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "set-a"))
(ctob/add-set (ctob/make-token-set :id set-b-id :name "set-b"))
(ctob/add-token set-a-id tok-a)
(ctob/add-token set-b-id tok-b))
tokens-status (ctos/make-tokens-status :active-set-ids #{set-a-id set-b-id})
tokens (cfo/get-tokens-in-active-sets tokens-status tokens-lib)]
(t/is (= 2 (count tokens)))
(t/is (contains? tokens "spacing"))
(t/is (contains? tokens "radius"))))
(t/testing "later active sets override earlier sets with same token name"
(let [set-a-id (thi/new-id! :set-a)
set-b-id (thi/new-id! :set-b)
tok-a (ctob/make-token :name "spacing" :type :spacing :value "8px")
tok-b (ctob/make-token :name "spacing" :type :spacing :value "16px")
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "set-a"))
(ctob/add-set (ctob/make-token-set :id set-b-id :name "set-b"))
(ctob/add-token set-a-id tok-a)
(ctob/add-token set-b-id tok-b))
tokens-status (ctos/make-tokens-status :active-set-ids #{set-a-id set-b-id})
tokens (cfo/get-tokens-in-active-sets tokens-status tokens-lib)]
(t/is (= 1 (count tokens)))
(t/is (= "16px" (:value (get tokens "spacing"))))))
(t/testing "tokens in inactive sets are not included"
(let [set-a-id (thi/new-id! :set-a)
set-b-id (thi/new-id! :set-b)
tok-a (ctob/make-token :name "spacing" :type :spacing :value "8px")
tok-b (ctob/make-token :name "spacing" :type :spacing :value "16px")
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "set-a"))
(ctob/add-set (ctob/make-token-set :id set-b-id :name "set-b"))
(ctob/add-token set-a-id tok-a)
(ctob/add-token set-b-id tok-b))
tokens-status (ctos/make-tokens-status :active-set-ids #{set-a-id})
tokens (cfo/get-tokens-in-active-sets tokens-status tokens-lib)]
(t/is (= 1 (count tokens)))
(t/is (= "8px" (:value (get tokens "spacing"))))))
(t/testing "returns empty map when no sets are active"
(let [tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-a) :name "set-a")))
tokens-status (ctos/make-tokens-status)
tokens (cfo/get-tokens-in-active-sets tokens-status tokens-lib)]
(t/is (empty? tokens))))
(t/testing "returns empty map when empty lib"
(let [tokens-lib (ctob/make-tokens-lib)
tokens-status (ctos/make-tokens-status)
tokens (cfo/get-tokens-in-active-sets tokens-status tokens-lib)]
(t/is (empty? tokens)))))
(t/deftest test-get-tokens-in-active-sets-force
(t/testing "includes force-set-id even when not in active sets"
(let [set-a-id (thi/new-id! :set-a)
set-b-id (thi/new-id! :set-b)
tok-a (ctob/make-token :name "spacing" :type :spacing :value "8px")
tok-b (ctob/make-token :name "radius" :type :border-radius :value "4px")
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "set-a"))
(ctob/add-set (ctob/make-token-set :id set-b-id :name "set-b"))
(ctob/add-token set-a-id tok-a)
(ctob/add-token set-b-id tok-b))
tokens-status (ctos/make-tokens-status :active-set-ids #{set-a-id})
tokens (cfo/get-tokens-in-active-sets-force tokens-status tokens-lib set-b-id)]
(t/is (= 2 (count tokens)))
(t/is (contains? tokens "spacing"))
(t/is (contains? tokens "radius"))))
(t/testing "active set tokens override force-set tokens with same name"
(let [set-a-id (thi/new-id! :set-a)
set-b-id (thi/new-id! :set-b)
tok-a (ctob/make-token :name "spacing" :type :spacing :value "8px")
tok-b (ctob/make-token :name "spacing" :type :spacing :value "32px")
tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id set-a-id :name "set-a"))
(ctob/add-set (ctob/make-token-set :id set-b-id :name "set-b"))
(ctob/add-token set-a-id tok-a)
(ctob/add-token set-b-id tok-b))
tokens-status (ctos/make-tokens-status :active-set-ids #{set-a-id})
tokens (cfo/get-tokens-in-active-sets-force tokens-status tokens-lib set-b-id)]
(t/is (= 1 (count tokens)))
(t/is (= "8px" (:value (get tokens "spacing")))))))
(t/deftest test-sync-tokens-status-with-lib (t/deftest test-sync-tokens-status-with-lib
(t/testing "removes theme ids that no longer exist in the lib" (t/testing "removes theme ids that no longer exist in the lib"
(let [theme-1-id (thi/new-id! :theme-1) (let [theme-1-id (thi/new-id! :theme-1)

View File

@ -8,7 +8,6 @@
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.files.changes-builder :as pcb] [app.common.files.changes-builder :as pcb]
[app.common.files.tokens :as cfo]
[app.common.logic.shapes :as cls] [app.common.logic.shapes :as cls]
[app.common.test-helpers.compositions :as tho] [app.common.test-helpers.compositions :as tho]
[app.common.test-helpers.files :as thf] [app.common.test-helpers.files :as thf]

View File

@ -18,363 +18,7 @@
(t/use-fixtures :each thi/test-fixture) (t/use-fixtures :each thi/test-fixture)
(t/deftest generate-toggle-token-set-test ;; Tokens lib
(t/testing "toggling an active set will deactivate it"
(let [theme-id (uuid/next)
set-id (thi/new-id! :foo-bar)
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-set (ctob/make-token-set :id set-id :name "foo/bar"))
(ctob/add-theme (ctob/make-token-theme :id theme-id
:name "theme"
:sets #{"foo/bar"})))
:status-fn #(ctos/set-tokens-status % #{theme-id} #{set-id}))
tokens-status (tht/get-tokens-status file)
tokens-lib (tht/get-tokens-lib file)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(clt/generate-toggle-token-set tokens-status tokens-lib "foo/bar"))
redo (thf/apply-changes file changes)
redo-status (tht/get-tokens-status redo)
undo (thf/apply-undo-changes redo changes)
undo-status (tht/get-tokens-status undo)]
;; Redo: set is deactivated, all themes deactivated
(t/is (not (ctos/set-active? redo-status set-id)))
(t/is (= #{} (ctos/get-active-theme-ids redo-status)))
;; Undo: set is active again, themes restored
(t/is (ctos/set-active? undo-status set-id))
(t/is (= #{theme-id} (ctos/get-active-theme-ids undo-status)))))
(t/testing "toggling an inactive set will activate it"
(let [theme-id (uuid/next)
set-id (thi/new-id! :foo-bar)
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-set (ctob/make-token-set :id set-id :name "foo/bar"))
(ctob/add-theme (ctob/make-token-theme :id theme-id
:name "theme"
:sets #{"foo/bar"})))
:status-fn #(ctos/set-tokens-status % #{theme-id} #{}))
tokens-status (tht/get-tokens-status file)
tokens-lib (tht/get-tokens-lib file)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(clt/generate-toggle-token-set tokens-status tokens-lib "foo/bar"))
redo (thf/apply-changes file changes)
redo-status (tht/get-tokens-status redo)
undo (thf/apply-undo-changes redo changes)
undo-status (tht/get-tokens-status undo)]
;; Redo: set is activated, all themes deactivated
(t/is (ctos/set-active? redo-status set-id))
(t/is (= #{} (ctos/get-active-theme-ids redo-status)))
;; Undo: set is inactive again, themes restored
(t/is (not (ctos/set-active? undo-status set-id)))
(t/is (= #{theme-id} (ctos/get-active-theme-ids undo-status)))))
(t/testing "toggling a set group toggles its sets in status"
(let [set-id (thi/new-id! :foo-bar)
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-set (ctob/make-token-set :id set-id :name "foo/bar"))))
tokens-status (tht/get-tokens-status file)
tokens-lib (tht/get-tokens-lib file)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(clt/generate-toggle-token-set-group tokens-status tokens-lib ["foo"]))
redo (thf/apply-changes file changes)
redo-status (tht/get-tokens-status redo)
undo (thf/apply-undo-changes redo changes)
undo-status (tht/get-tokens-status undo)]
;; Redo: set is activated
(t/is (ctos/set-active? redo-status set-id))
;; Undo: set is deactivated
(t/is (not (ctos/set-active? undo-status set-id))))))
(t/deftest set-token-theme-test
(t/testing "delete token theme"
(let [theme-id (uuid/next)
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-theme (ctob/make-token-theme :id theme-id
:name "foo"
:group "main"))))
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token-theme theme-id nil))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
;; Redo
(t/is (nil? (ctob/get-theme redo-lib theme-id)))
;; Undo
(t/is (some? (ctob/get-theme undo-lib theme-id)))))
(t/testing "add token theme"
(let [theme-id (uuid/next)
theme (ctob/make-token-theme :id theme-id
:name "foo"
:group "main")
file (tht/sample-file-with-tokens)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token-theme theme-id theme))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
;; Redo
(t/is (some? (ctob/get-theme redo-lib theme-id)))
;; Undo
(t/is (nil? (ctob/get-theme undo-lib theme-id)))))
(t/testing "update token theme"
(let [theme-id (uuid/next)
prev-theme-name "foo"
prev-theme (ctob/make-token-theme :id theme-id
:name prev-theme-name
:group "main")
file (tht/sample-file-with-tokens
:lib-fn #(ctob/add-theme % prev-theme))
new-theme-name "foo1"
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token-theme theme-id (ctob/rename prev-theme new-theme-name)))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
redo-theme (ctob/get-theme redo-lib theme-id)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)
undo-theme (ctob/get-theme undo-lib theme-id)]
;; Redo
(t/is (= new-theme-name (ctob/get-name redo-theme)))
;; Undo
(t/is (= prev-theme-name (ctob/get-name undo-theme)))))
(t/testing "toggling token theme updates using changes history"
(let [theme-id (uuid/next)
theme (ctob/make-token-theme :id theme-id
:name "foo-theme"
:group "main")
set-name "bar-set"
token-set (ctob/make-token-set :name set-name)
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-theme theme)
(ctob/add-set token-set)))
theme' (assoc theme :sets #{set-name})
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token-theme theme-id theme'))
changed-file (-> file
(thf/apply-changes changes)
(thf/apply-undo-changes changes)
(thf/apply-changes changes))
changed-lib (tht/get-tokens-lib changed-file)]
(t/is (= #{set-name}
(-> changed-lib (ctob/get-theme theme-id) :sets))))))
(t/deftest set-token-test
(t/testing "delete token"
(let [set-name "foo"
set-id (uuid/next)
token-id (uuid/next)
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-set (ctob/make-token-set :id set-id
:name set-name))
(ctob/add-token set-id (ctob/make-token {:name "to.delete.color.red"
:id token-id
:value "red"
:type :color}))))
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token set-id token-id nil))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
(t/is (nil? (ctob/get-token redo-lib set-id token-id)))
;; Undo
(t/is (some? (ctob/get-token undo-lib set-id token-id)))))
(t/testing "add token"
(let [set-name "foo"
set-id (uuid/next)
token (ctob/make-token {:name "to.add.color.red"
:value "red"
:type :color})
file (tht/sample-file-with-tokens
:lib-fn #(-> % (ctob/add-set (ctob/make-token-set :id set-id
:name set-name))))
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token set-id (:id token) token))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
(t/is (= token (ctob/get-token redo-lib set-id (:id token))))
;; Undo
(t/is (nil? (ctob/get-token undo-lib set-id (:id token))))))
(t/testing "update token"
(let [set-name "foo"
set-id (uuid/next)
prev-token (ctob/make-token {:name "to.update.color.red"
:value "red"
:type :color})
token (-> prev-token
(assoc :name "color.red.changed")
(assoc :value "blue"))
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-set (ctob/make-token-set :id set-id
:name set-name))
(ctob/add-token set-id prev-token)))
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token set-id (:id prev-token) token))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
(t/is (tht/token-data-eq? token (ctob/get-token redo-lib set-id (:id token))))
;; Undo
(t/is (tht/token-data-eq? prev-token (ctob/get-token undo-lib set-id (:id prev-token)))))))
(t/deftest set-token-set-test
(t/testing "delete token set"
(let [set-name "foo"
set-id (uuid/next)
file (tht/sample-file-with-tokens
:lib-fn #(ctob/add-set % (ctob/make-token-set :id set-id :name set-name)))
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token-set set-id nil))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
(t/is (not (ctob/set-path-exists? redo-lib [set-name])))
;; Undo
(t/is (ctob/set-path-exists? undo-lib [set-name]))))
(t/testing "add token set"
(let [set-name "foo"
set-id (uuid/next)
token-set (ctob/make-token-set :id set-id :name set-name)
file (tht/sample-file-with-tokens)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token-set set-id token-set))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
(t/is (not (ctob/set-path-exists? undo-lib [set-name])))
;; Undo
(t/is (ctob/set-path-exists? redo-lib [set-name]))))
(t/testing "update token set"
(let [set-name "foo"
set-id (uuid/next)
token-set (ctob/make-token-set :id set-id :name set-name)
file (tht/sample-file-with-tokens
:lib-fn #(-> (ctob/add-set % token-set)))
new-set-name "foo1"
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token-set set-id (ctob/rename token-set new-set-name)))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
redo-token-set (ctob/get-set redo-lib set-id)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)
undo-token-set (ctob/get-set undo-lib set-id)]
(t/is (= (ctob/get-name redo-token-set) new-set-name))
;; Undo
(t/is (= (ctob/get-name undo-token-set) set-name)))))
(t/deftest generate-toggle-token-set-group-test
(t/testing "toggling set group with no active sets inside will activate all child sets"
(let [set-bar-id (thi/new-id! :foo-bar)
set-baz-id (thi/new-id! :foo-bar-baz)
set-child-id (thi/new-id! :baz-child)
theme-id (uuid/next)
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-set (ctob/make-token-set :id set-bar-id :name "foo/bar"))
(ctob/add-set (ctob/make-token-set :id set-baz-id :name "foo/bar/baz"))
(ctob/add-set (ctob/make-token-set :id set-child-id :name "foo/bar/baz/baz-child"))
(ctob/add-theme (ctob/make-token-theme :id theme-id :name "theme")))
:status-fn #(ctos/set-tokens-status % #{theme-id} #{}))
tokens-status (tht/get-tokens-status file)
tokens-lib (tht/get-tokens-lib file)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(clt/generate-toggle-token-set-group tokens-status tokens-lib ["foo" "bar"]))
redo (thf/apply-changes file changes)
redo-status (tht/get-tokens-status redo)
undo (thf/apply-undo-changes redo changes)
undo-status (tht/get-tokens-status undo)]
;; Redo: all child sets activated, all themes deactivated
(t/is (ctos/set-active? redo-status set-baz-id))
(t/is (ctos/set-active? redo-status set-child-id))
(t/is (= #{} (ctos/get-active-theme-ids redo-status)))
;; Undo: child sets deactivated, themes restored
(t/is (not (ctos/set-active? undo-status set-baz-id)))
(t/is (not (ctos/set-active? undo-status set-child-id)))
(t/is (= #{theme-id} (ctos/get-active-theme-ids undo-status))))))
(t/testing "toggling set group with partially active sets inside will deactivate all child sets"
(let [set-bar-id (thi/new-id! :foo-bar)
set-baz-id (thi/new-id! :foo-bar-baz)
set-child-id (thi/new-id! :baz-child)
theme-id (uuid/next)
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-set (ctob/make-token-set :id set-bar-id :name "foo/bar"))
(ctob/add-set (ctob/make-token-set :id set-baz-id :name "foo/bar/baz"))
(ctob/add-set (ctob/make-token-set :id set-child-id :name "foo/bar/baz/baz-child"))
(ctob/add-theme (ctob/make-token-theme :id theme-id
:name "theme"
:sets #{"foo/bar/baz"})))
:status-fn #(ctos/set-tokens-status % #{theme-id} #{set-baz-id}))
tokens-status (tht/get-tokens-status file)
tokens-lib (tht/get-tokens-lib file)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(clt/generate-toggle-token-set-group tokens-status tokens-lib ["foo" "bar"]))
redo (thf/apply-changes file changes)
redo-status (tht/get-tokens-status redo)
undo (thf/apply-undo-changes redo changes)
undo-status (tht/get-tokens-status undo)]
;; Redo: all child sets deactivated, all themes deactivated
(t/is (not (ctos/set-active? redo-status set-baz-id)))
(t/is (not (ctos/set-active? redo-status set-child-id)))
(t/is (= #{} (ctos/get-active-theme-ids redo-status)))
;; Undo: restores previous state, themes restored
(t/is (ctos/set-active? undo-status set-baz-id))
(t/is (not (ctos/set-active? undo-status set-child-id)))
(t/is (= #{theme-id} (ctos/get-active-theme-ids undo-status)))))
(t/deftest generate-move-token-set-test (t/deftest generate-move-token-set-test
(t/testing "Ignore dropping set to the same position:" (t/testing "Ignore dropping set to the same position:"
@ -628,6 +272,283 @@
:position :bot}) :position :bot})
#"move token set error: parent-to-child")))))))) #"move token set error: parent-to-child"))))))))
(t/deftest generate-delete-token-set-group-test
(t/testing "deletes all sets under the given group path"
(let [set-a-id (thi/new-id! :set-a)
set-b-id (thi/new-id! :set-b)
set-c-id (thi/new-id! :set-c)
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-set (ctob/make-token-set :id set-a-id :name "group/set-a"))
(ctob/add-set (ctob/make-token-set :id set-b-id :name "group/set-b"))
(ctob/add-set (ctob/make-token-set :id set-c-id :name "other/set-c"))))
tokens-lib (tht/get-tokens-lib file)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(clt/generate-delete-token-set-group tokens-lib ["group"]))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
;; Redo: group sets deleted, other set remains
(t/is (not (ctob/set-path-exists? redo-lib ["group" "set-a"])))
(t/is (not (ctob/set-path-exists? redo-lib ["group" "set-b"])))
(t/is (ctob/set-path-exists? redo-lib ["other" "set-c"]))
;; Undo: group sets restored
(t/is (ctob/set-path-exists? undo-lib ["group" "set-a"]))
(t/is (ctob/set-path-exists? undo-lib ["group" "set-b"]))))
(t/testing "deleting a group with nested subgroups deletes all descendant sets"
(let [set-a-id (thi/new-id! :set-a)
set-b-id (thi/new-id! :set-b)
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-set (ctob/make-token-set :id set-a-id :name "group/sub/set-a"))
(ctob/add-set (ctob/make-token-set :id set-b-id :name "group/set-b"))))
tokens-lib (tht/get-tokens-lib file)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(clt/generate-delete-token-set-group tokens-lib ["group"]))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
;; Redo: all group sets deleted
(t/is (not (ctob/set-path-exists? redo-lib ["group" "sub" "set-a"])))
(t/is (not (ctob/set-path-exists? redo-lib ["group" "set-b"])))
;; Undo: all restored
(t/is (ctob/set-path-exists? undo-lib ["group" "sub" "set-a"]))
(t/is (ctob/set-path-exists? undo-lib ["group" "set-b"]))))
(t/testing "deleting an empty group produces no changes"
(let [file (tht/sample-file-with-tokens
:lib-fn #(ctob/add-set % (ctob/make-token-set :name "other/set-a")))
tokens-lib (tht/get-tokens-lib file)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(clt/generate-delete-token-set-group tokens-lib ["nonexistent"]))]
(t/is (= [] (:redo-changes changes))))))
(t/deftest set-token-theme-test
(t/testing "delete token theme"
(let [theme-id (uuid/next)
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-theme (ctob/make-token-theme :id theme-id
:name "foo"
:group "main"))))
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token-theme theme-id nil))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
;; Redo
(t/is (nil? (ctob/get-theme redo-lib theme-id)))
;; Undo
(t/is (some? (ctob/get-theme undo-lib theme-id)))))
(t/testing "add token theme"
(let [theme-id (uuid/next)
theme (ctob/make-token-theme :id theme-id
:name "foo"
:group "main")
file (tht/sample-file-with-tokens)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token-theme theme-id theme))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
;; Redo
(t/is (some? (ctob/get-theme redo-lib theme-id)))
;; Undo
(t/is (nil? (ctob/get-theme undo-lib theme-id)))))
(t/testing "update token theme"
(let [theme-id (uuid/next)
prev-theme-name "foo"
prev-theme (ctob/make-token-theme :id theme-id
:name prev-theme-name
:group "main")
file (tht/sample-file-with-tokens
:lib-fn #(ctob/add-theme % prev-theme))
new-theme-name "foo1"
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token-theme theme-id (ctob/rename prev-theme new-theme-name)))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
redo-theme (ctob/get-theme redo-lib theme-id)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)
undo-theme (ctob/get-theme undo-lib theme-id)]
;; Redo
(t/is (= new-theme-name (ctob/get-name redo-theme)))
;; Undo
(t/is (= prev-theme-name (ctob/get-name undo-theme)))))
(t/testing "toggling token theme updates using changes history"
(let [theme-id (uuid/next)
theme (ctob/make-token-theme :id theme-id
:name "foo-theme"
:group "main")
set-name "bar-set"
token-set (ctob/make-token-set :name set-name)
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-theme theme)
(ctob/add-set token-set)))
theme' (assoc theme :sets #{set-name})
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token-theme theme-id theme'))
changed-file (-> file
(thf/apply-changes changes)
(thf/apply-undo-changes changes)
(thf/apply-changes changes))
changed-lib (tht/get-tokens-lib changed-file)]
(t/is (= #{set-name}
(-> changed-lib (ctob/get-theme theme-id) :sets))))))
(t/deftest set-token-test
(t/testing "delete token"
(let [set-name "foo"
set-id (uuid/next)
token-id (uuid/next)
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-set (ctob/make-token-set :id set-id
:name set-name))
(ctob/add-token set-id (ctob/make-token {:name "to.delete.color.red"
:id token-id
:value "red"
:type :color}))))
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token set-id token-id nil))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
(t/is (nil? (ctob/get-token redo-lib set-id token-id)))
;; Undo
(t/is (some? (ctob/get-token undo-lib set-id token-id)))))
(t/testing "add token"
(let [set-name "foo"
set-id (uuid/next)
token (ctob/make-token {:name "to.add.color.red"
:value "red"
:type :color})
file (tht/sample-file-with-tokens
:lib-fn #(-> % (ctob/add-set (ctob/make-token-set :id set-id
:name set-name))))
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token set-id (:id token) token))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
(t/is (= token (ctob/get-token redo-lib set-id (:id token))))
;; Undo
(t/is (nil? (ctob/get-token undo-lib set-id (:id token))))))
(t/testing "update token"
(let [set-name "foo"
set-id (uuid/next)
prev-token (ctob/make-token {:name "to.update.color.red"
:value "red"
:type :color})
token (-> prev-token
(assoc :name "color.red.changed")
(assoc :value "blue"))
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-set (ctob/make-token-set :id set-id
:name set-name))
(ctob/add-token set-id prev-token)))
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token set-id (:id prev-token) token))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
(t/is (tht/token-data-eq? token (ctob/get-token redo-lib set-id (:id token))))
;; Undo
(t/is (tht/token-data-eq? prev-token (ctob/get-token undo-lib set-id (:id prev-token)))))))
(t/deftest set-token-set-test
(t/testing "delete token set"
(let [set-name "foo"
set-id (uuid/next)
file (tht/sample-file-with-tokens
:lib-fn #(ctob/add-set % (ctob/make-token-set :id set-id :name set-name)))
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token-set set-id nil))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
(t/is (not (ctob/set-path-exists? redo-lib [set-name])))
;; Undo
(t/is (ctob/set-path-exists? undo-lib [set-name]))))
(t/testing "add token set"
(let [set-name "foo"
set-id (uuid/next)
token-set (ctob/make-token-set :id set-id :name set-name)
file (tht/sample-file-with-tokens)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token-set set-id token-set))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
(t/is (not (ctob/set-path-exists? undo-lib [set-name])))
;; Undo
(t/is (ctob/set-path-exists? redo-lib [set-name]))))
(t/testing "update token set"
(let [set-name "foo"
set-id (uuid/next)
token-set (ctob/make-token-set :id set-id :name set-name)
file (tht/sample-file-with-tokens
:lib-fn #(-> (ctob/add-set % token-set)))
new-set-name "foo1"
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token-set set-id (ctob/rename token-set new-set-name)))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
redo-token-set (ctob/get-set redo-lib set-id)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)
undo-token-set (ctob/get-set undo-lib set-id)]
(t/is (= (ctob/get-name redo-token-set) new-set-name))
;; Undo
(t/is (= (ctob/get-name undo-token-set) set-name)))))
;; Tokens Status
(t/deftest generate-activate-theme-test (t/deftest generate-activate-theme-test
(t/testing "activating an inactive theme creates changes" (t/testing "activating an inactive theme creates changes"
(let [set-id (uuid/next) (let [set-id (uuid/next)
@ -668,17 +589,8 @@
changes (-> (pcb/empty-changes) changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file)) (pcb/with-library-data (:data file))
(clt/generate-activate-theme tokens-status tokens-lib theme-id))] (clt/generate-activate-theme tokens-status tokens-lib theme-id))]
(t/is (= [] (:redo-changes changes))))) (t/is (= [] (:redo-changes changes)))
(t/is (= [] (:undo-changes changes))))))
(t/testing "activating a non-existent theme returns same changes"
(let [non-existent-id (uuid/next)
file (tht/sample-file-with-tokens)
tokens-status (tht/get-tokens-status file)
tokens-lib (tht/get-tokens-lib file)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(clt/generate-activate-theme tokens-status tokens-lib non-existent-id))]
(t/is (= [] (:redo-changes changes))))))
(t/deftest generate-deactivate-theme-test (t/deftest generate-deactivate-theme-test
(t/testing "deactivating an active theme creates changes" (t/testing "deactivating an active theme creates changes"
@ -716,7 +628,8 @@
changes (-> (pcb/empty-changes) changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file)) (pcb/with-library-data (:data file))
(clt/generate-deactivate-theme tokens-status tokens-lib theme-id))] (clt/generate-deactivate-theme tokens-status tokens-lib theme-id))]
(t/is (= [] (:redo-changes changes)))))) (t/is (= [] (:redo-changes changes)))
(t/is (= [] (:undo-changes changes))))))
(t/deftest generate-set-theme-status-test (t/deftest generate-set-theme-status-test
(t/testing "setting active? to true activates the theme" (t/testing "setting active? to true activates the theme"
@ -732,25 +645,28 @@
(pcb/with-library-data (:data file)) (pcb/with-library-data (:data file))
(clt/generate-set-theme-status tokens-status tokens-lib theme-id true)) (clt/generate-set-theme-status tokens-status tokens-lib theme-id true))
file' (thf/apply-changes file changes) file' (thf/apply-changes file changes)
tokens-status' (tht/get-tokens-status file')] tokens-status' (tht/get-tokens-status file')
(t/is (ctos/theme-active? tokens-status' theme-id)))) file'' (thf/apply-undo-changes file changes)
tokens-status'' (tht/get-tokens-status file'')]
;; Redo: theme is active
(t/is (ctos/theme-active? tokens-status' theme-id))
;; Undo: theme is inactive
(t/is (not (ctos/theme-active? tokens-status'' theme-id)))))
(t/testing "setting active? to false deactivates the theme" (t/testing "setting active? to same state returns same changes"
(let [theme-id (uuid/next) (let [theme-id (uuid/next)
file (tht/sample-file-with-tokens file (tht/sample-file-with-tokens
:lib-fn #(-> % :lib-fn #(-> %
(ctob/add-theme (ctob/make-token-theme :id theme-id (ctob/add-theme (ctob/make-token-theme :id theme-id
:name "t1" :name "t1"
:sets #{}))) :sets #{}))))
:status-fn #(ctos/set-tokens-status % #{theme-id} #{}))
tokens-status (tht/get-tokens-status file) tokens-status (tht/get-tokens-status file)
tokens-lib (tht/get-tokens-lib file) tokens-lib (tht/get-tokens-lib file)
changes (-> (pcb/empty-changes) changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file)) (pcb/with-library-data (:data file))
(clt/generate-set-theme-status tokens-status tokens-lib theme-id false)) (clt/generate-set-theme-status tokens-status tokens-lib theme-id false))]
file' (thf/apply-changes file changes) (t/is (= [] (:redo-changes changes)))
tokens-status' (tht/get-tokens-status file')] (t/is (= [] (:undo-changes changes))))))
(t/is (not (ctos/theme-active? tokens-status' theme-id))))))
(t/deftest generate-toggle-theme-test (t/deftest generate-toggle-theme-test
(t/testing "toggling an active theme deactivates it" (t/testing "toggling an active theme deactivates it"
@ -775,7 +691,7 @@
;; Undo: theme is active again ;; Undo: theme is active again
(t/is (ctos/theme-active? tokens-status'' theme-id)))) (t/is (ctos/theme-active? tokens-status'' theme-id))))
(t/testing "toggling an inactive theme activates it" (t/testing "toggling an inexistent theme returns same changes"
(let [theme-id (uuid/next) (let [theme-id (uuid/next)
file (tht/sample-file-with-tokens file (tht/sample-file-with-tokens
:lib-fn #(-> % :lib-fn #(-> %
@ -786,15 +702,151 @@
tokens-lib (tht/get-tokens-lib file) tokens-lib (tht/get-tokens-lib file)
changes (-> (pcb/empty-changes) changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file)) (pcb/with-library-data (:data file))
(clt/generate-toggle-theme tokens-status tokens-lib theme-id)) (clt/generate-toggle-theme tokens-status tokens-lib (uuid/next)))]
file' (thf/apply-changes file changes) (t/is (= [] (:redo-changes changes)))
tokens-status' (tht/get-tokens-status file') (t/is (= [] (:undo-changes changes))))))
file'' (thf/apply-undo-changes file' changes)
tokens-status'' (tht/get-tokens-status file'')] (t/deftest generate-set-enabled-token-set-test
;; Redo: theme is active (t/testing "enabling an inactive set creates changes that activate it and clear themes"
(t/is (ctos/theme-active? tokens-status' theme-id)) (let [set-id (thi/new-id! :set-a)
;; Undo: theme is inactive theme-id (uuid/next)
(t/is (not (ctos/theme-active? tokens-status'' theme-id)))))) file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-set (ctob/make-token-set :id set-id :name "set-a"))
(ctob/add-theme (ctob/make-token-theme :id theme-id
:name "theme"
:sets #{"set-a"})))
:status-fn #(ctos/set-tokens-status % #{theme-id} #{}))
tokens-status (tht/get-tokens-status file)
tokens-lib (tht/get-tokens-lib file)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(clt/generate-set-enabled-token-set tokens-status tokens-lib set-id true))
redo (thf/apply-changes file changes)
redo-status (tht/get-tokens-status redo)
undo (thf/apply-undo-changes redo changes)
undo-status (tht/get-tokens-status undo)]
;; Redo: set active, themes cleared
(t/is (ctos/set-active? redo-status set-id))
(t/is (= #{} (ctos/get-active-theme-ids redo-status)))
;; Undo: set inactive, themes restored
(t/is (not (ctos/set-active? undo-status set-id)))
(t/is (= #{theme-id} (ctos/get-active-theme-ids undo-status)))))
(t/testing "enabling an already-active set returns no changes"
(let [set-id (thi/new-id! :set-a)
file (tht/sample-file-with-tokens
:lib-fn #(ctob/add-set % (ctob/make-token-set :id set-id :name "set-a"))
:status-fn #(ctos/set-tokens-status % #{} #{set-id}))
tokens-status (tht/get-tokens-status file)
tokens-lib (tht/get-tokens-lib file)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(clt/generate-set-enabled-token-set tokens-status tokens-lib set-id true))]
(t/is (= [] (:redo-changes changes)))
(t/is (= [] (:undo-changes changes))))))
(t/deftest generate-toggle-token-set-test
(t/testing "toggling an active set will deactivate it"
(let [theme-id (uuid/next)
set-id (thi/new-id! :foo-bar)
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-set (ctob/make-token-set :id set-id :name "foo/bar"))
(ctob/add-theme (ctob/make-token-theme :id theme-id
:name "theme"
:sets #{"foo/bar"})))
:status-fn #(ctos/set-tokens-status % #{theme-id} #{set-id}))
tokens-status (tht/get-tokens-status file)
tokens-lib (tht/get-tokens-lib file)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(clt/generate-toggle-token-set tokens-status tokens-lib set-id))
redo (thf/apply-changes file changes)
redo-status (tht/get-tokens-status redo)
undo (thf/apply-undo-changes redo changes)
undo-status (tht/get-tokens-status undo)]
;; Redo: set is deactivated, all themes deactivated
(t/is (not (ctos/set-active? redo-status set-id)))
(t/is (= #{} (ctos/get-active-theme-ids redo-status)))
;; Undo: set is active again, themes restored
(t/is (ctos/set-active? undo-status set-id))
(t/is (= #{theme-id} (ctos/get-active-theme-ids undo-status)))))
(t/testing "toggling an inexistent set will return no changes"
(let [theme-id (uuid/next)
set-id (thi/new-id! :foo-bar)
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-set (ctob/make-token-set :id set-id :name "foo/bar"))
(ctob/add-theme (ctob/make-token-theme :id theme-id
:name "theme"
:sets #{"foo/bar"})))
:status-fn #(ctos/set-tokens-status % #{theme-id} #{}))
tokens-status (tht/get-tokens-status file)
tokens-lib (tht/get-tokens-lib file)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(clt/generate-toggle-token-set tokens-status tokens-lib (uuid/next)))]
(t/is (= [] (:redo-changes changes)))
(t/is (= [] (:undo-changes changes))))))
(t/deftest generate-toggle-token-set-group-test
(t/testing "toggling set group with no active sets inside will activate all child sets"
(let [set-bar-id (thi/new-id! :foo-bar)
set-baz-id (thi/new-id! :foo-bar-baz)
set-child-id (thi/new-id! :baz-child)
theme-id (uuid/next)
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-set (ctob/make-token-set :id set-bar-id :name "foo/bar"))
(ctob/add-set (ctob/make-token-set :id set-baz-id :name "foo/bar/baz"))
(ctob/add-set (ctob/make-token-set :id set-child-id :name "foo/bar/baz/baz-child"))
(ctob/add-theme (ctob/make-token-theme :id theme-id :name "theme")))
:status-fn #(ctos/set-tokens-status % #{theme-id} #{}))
tokens-status (tht/get-tokens-status file)
tokens-lib (tht/get-tokens-lib file)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(clt/generate-toggle-token-set-group tokens-status tokens-lib ["foo" "bar"]))
redo (thf/apply-changes file changes)
redo-status (tht/get-tokens-status redo)
undo (thf/apply-undo-changes redo changes)
undo-status (tht/get-tokens-status undo)]
;; Redo: all child sets activated, all themes deactivated
(t/is (ctos/set-active? redo-status set-baz-id))
(t/is (ctos/set-active? redo-status set-child-id))
(t/is (= #{} (ctos/get-active-theme-ids redo-status)))
;; Undo: child sets deactivated, themes restored
(t/is (not (ctos/set-active? undo-status set-baz-id)))
(t/is (not (ctos/set-active? undo-status set-child-id)))
(t/is (= #{theme-id} (ctos/get-active-theme-ids undo-status)))))
(t/testing "toggling an inexistent set group will return no changes"
(let [set-bar-id (thi/new-id! :foo-bar)
set-baz-id (thi/new-id! :foo-bar-baz)
set-child-id (thi/new-id! :baz-child)
theme-id (uuid/next)
file (tht/sample-file-with-tokens
:lib-fn #(-> %
(ctob/add-set (ctob/make-token-set :id set-bar-id :name "foo/bar"))
(ctob/add-set (ctob/make-token-set :id set-baz-id :name "foo/bar/baz"))
(ctob/add-set (ctob/make-token-set :id set-child-id :name "foo/bar/baz/baz-child"))
(ctob/add-theme (ctob/make-token-theme :id theme-id
:name "theme"
:sets #{"foo/bar/baz"})))
:status-fn #(ctos/set-tokens-status % #{theme-id} #{set-baz-id}))
tokens-status (tht/get-tokens-status file)
tokens-lib (tht/get-tokens-lib file)
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(clt/generate-toggle-token-set-group tokens-status tokens-lib ["foo" "nonexistent"]))]
(t/is (= [] (:redo-changes changes)))
(t/is (= [] (:undo-changes changes))))))
(t/deftest generate-sync-tokens-status-with-lib-test (t/deftest generate-sync-tokens-status-with-lib-test
(t/testing "sync removes stale theme and set ids from status" (t/testing "sync removes stale theme and set ids from status"
@ -834,4 +886,5 @@
changes (-> (pcb/empty-changes) changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file)) (pcb/with-library-data (:data file))
(clt/generate-sync-tokens-status-with-lib tokens-status tokens-lib))] (clt/generate-sync-tokens-status-with-lib tokens-status tokens-lib))]
(t/is (= [] (:redo-changes changes)))))) (t/is (= [] (:redo-changes changes)))
(t/is (= [] (:undo-changes changes))))))

View File

@ -599,206 +599,6 @@
(t/is (= (get-in tokens ["token-2" :value]) 20)) (t/is (= (get-in tokens ["token-2" :value]) 20))
(t/is (= (get-in tokens ["token-3" :value]) 300)))) (t/is (= (get-in tokens ["token-3" :value]) 300))))
#_(t/deftest list-active-themes-tokens-one-theme
(let [tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :name "set-a"
:tokens {"token-1"
(ctob/make-token :name "token-1"
:type :border-radius
:value 10)
"token-2"
(ctob/make-token :name "token-2"
:type :border-radius
:value 20)}))
(ctob/add-set (ctob/make-token-set :name "set-b"
:tokens {"token-1"
(ctob/make-token :name "token-1"
:type :border-radius
:value 100)
"token-3"
(ctob/make-token :name "token-3"
:type :border-radius
:value 300)}))
(ctob/add-set (ctob/make-token-set :name "set-c"
:tokens {"token-1"
(ctob/make-token :name "token-1"
:type :border-radius
:value 1000)
"token-2"
(ctob/make-token :name "token-2"
:type :border-radius
:value 2000)
"token-3"
(ctob/make-token :name "token-3"
:type :border-radius
:value 3000)
"token-4"
(ctob/make-token :name "token-4"
:type :border-radius
:value 4000)}))
(ctob/add-theme (ctob/make-token-theme :name "single-theme"
:sets #{"set-b" "set-c" "set-a"})))
theme-id (ctob/get-id (ctob/get-theme-by-name tokens-lib "" "single-theme"))
tokens-status (cfo/set-active-themes (ctos/make-tokens-status) tokens-lib #{theme-id})
tokens (cfo/get-tokens-in-active-sets tokens-status tokens-lib)]
;; Note that sets order inside the theme is undefined. What matters is order in that the
;; sets have been added to the library.
(t/is (= (mapv key tokens) ["token-1" "token-2" "token-3" "token-4"]))
(t/is (= (get-in tokens ["token-1" :value]) 1000))
(t/is (= (get-in tokens ["token-2" :value]) 2000))
(t/is (= (get-in tokens ["token-3" :value]) 3000))
(t/is (= (get-in tokens ["token-4" :value]) 4000))))
#_(t/deftest list-active-themes-tokens-two-themes
(let [tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :name "set-a"
:tokens {"token-1"
(ctob/make-token :name "token-1"
:type :border-radius
:value 10)
"token-2"
(ctob/make-token :name "token-2"
:type :border-radius
:value 20)}))
(ctob/add-set (ctob/make-token-set :name "set-b"
:tokens {"token-1"
(ctob/make-token :name "token-1"
:type :border-radius
:value 100)
"token-3"
(ctob/make-token :name "token-3"
:type :border-radius
:value 300)}))
(ctob/add-set (ctob/make-token-set :name "set-c"
:tokens {"token-1"
(ctob/make-token :name "token-1"
:type :border-radius
:value 1000)
"token-2"
(ctob/make-token :name "token-2"
:type :border-radius
:value 2000)
"token-3"
(ctob/make-token :name "token-3"
:type :border-radius
:value 3000)
"token-4"
(ctob/make-token :name "token-4"
:type :border-radius
:value 4000)}))
(ctob/add-theme (ctob/make-token-theme :name "theme-1"
:sets #{"set-b"}))
(ctob/add-theme (ctob/make-token-theme :name "theme-2"
:sets #{"set-b" "set-a"})))
theme-1-id (ctob/get-id (ctob/get-theme-by-name tokens-lib "" "theme-1"))
theme-2-id (ctob/get-id (ctob/get-theme-by-name tokens-lib "" "theme-2"))
tokens-status (cfo/set-active-themes (ctos/make-tokens-status) tokens-lib #{theme-1-id theme-2-id})
tokens (cfo/get-tokens-in-active-sets tokens-status tokens-lib)]
;; Note that themes order is irrelevant. What matters is the union of the active sets
;; and the order of the sets in the library.
(t/is (= (mapv key tokens) ["token-1" "token-2" "token-3"]))
(t/is (= (get-in tokens ["token-1" :value]) 100))
(t/is (= (get-in tokens ["token-2" :value]) 20))
(t/is (= (get-in tokens ["token-3" :value]) 300))))
#_(t/deftest list-active-themes-tokens-bug-taiga-10617
(let [tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :name "Mode/Dark"
:tokens {"red"
(ctob/make-token :name "red"
:type :color
:value "#700000")}))
(ctob/add-set (ctob/make-token-set :name "Mode/Light"
:tokens {"red"
(ctob/make-token :name "red"
:type :color
:value "#ff0000")}))
(ctob/add-set (ctob/make-token-set :name "Device/Desktop"
:tokens {"border1"
(ctob/make-token :name "border1"
:type :border-radius
:value 30)}))
(ctob/add-set (ctob/make-token-set :name "Device/Mobile"
:tokens {"border1"
(ctob/make-token :name "border1"
:type :border-radius
:value 50)}))
(ctob/add-theme (ctob/make-token-theme :group "App"
:name "Mobile"
:sets #{"Mode/Dark" "Device/Mobile"}))
(ctob/add-theme (ctob/make-token-theme :group "App"
:name "Web"
:sets #{"Mode/Dark" "Mode/Light" "Device/Desktop"}))
(ctob/add-theme (ctob/make-token-theme :group "Brand"
:name "Brand A"
:sets #{"Mode/Dark" "Mode/Light" "Device/Desktop" "Device/Mobile"}))
(ctob/add-theme (ctob/make-token-theme :group "Brand"
:name "Brand B"
:sets #{})))
web-id (ctob/get-id (ctob/get-theme-by-name tokens-lib "App" "Web"))
brand-a-id (ctob/get-id (ctob/get-theme-by-name tokens-lib "Brand" "Brand A"))
tokens-status (cfo/set-active-themes (ctos/make-tokens-status) tokens-lib #{web-id brand-a-id})
tokens (cfo/get-tokens-in-active-sets tokens-status tokens-lib)]
(t/is (= (mapv key tokens) ["red" "border1"]))
(t/is (= (get-in tokens ["red" :value]) "#ff0000"))
(t/is (= (get-in tokens ["border1" :value]) 50))))
#_(t/deftest list-active-themes-tokens-no-tokens
(let [tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :name "set-a")))
tokens-status (ctos/make-tokens-status)
tokens (cfo/get-tokens-in-active-sets tokens-status tokens-lib)]
(t/is (empty? tokens))))
#_(t/deftest list-active-themes-tokens-no-sets
(let [tokens-lib (ctob/make-tokens-lib)
tokens-status (ctos/make-tokens-status)
tokens (cfo/get-tokens-in-active-sets tokens-status tokens-lib)]
(t/is (empty? tokens))))
#_(t/deftest sets-at-path-active-state
(let [tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :name "foo/bar/baz"))
(ctob/add-set (ctob/make-token-set :name "foo/bar/bam"))
(ctob/add-theme (ctob/make-token-theme :name "none"))
(ctob/add-theme (ctob/make-token-theme :name "partial"
:sets #{"foo/bar/baz"}))
(ctob/add-theme (ctob/make-token-theme :name "all"
:sets #{"foo/bar/baz"
"foo/bar/bam"}))
(ctob/add-theme (ctob/make-token-theme :name "invalid"
:sets #{"foo/missing"})))
none-id (ctob/get-id (ctob/get-theme-by-name tokens-lib "" "none"))
partial-id (ctob/get-id (ctob/get-theme-by-name tokens-lib "" "partial"))
all-id (ctob/get-id (ctob/get-theme-by-name tokens-lib "" "all"))
invalid-id (ctob/get-id (ctob/get-theme-by-name tokens-lib "" "invalid"))
expected-none (-> (ctos/make-tokens-status)
(cfo/set-active-themes tokens-lib #{none-id})
(cfo/sets-at-path-all-active? tokens-lib ["foo"]))
expected-all (-> (ctos/make-tokens-status)
(cfo/set-active-themes tokens-lib #{all-id})
(cfo/sets-at-path-all-active? tokens-lib ["foo"]))
expected-partial (-> (ctos/make-tokens-status)
(cfo/set-active-themes tokens-lib #{partial-id})
(cfo/sets-at-path-all-active? tokens-lib ["foo"]))
expected-invalid-none (-> (ctos/make-tokens-status)
(cfo/set-active-themes tokens-lib #{invalid-id})
(cfo/sets-at-path-all-active? tokens-lib ["foo"]))]
(t/is (= :none expected-none))
(t/is (= :all expected-all))
(t/is (= :partial expected-partial))
(t/is (= :none expected-invalid-none))))
(t/deftest add-token-theme (t/deftest add-token-theme
(let [theme-id (uuid/next) (let [theme-id (uuid/next)
tokens-lib (ctob/make-tokens-lib) tokens-lib (ctob/make-tokens-lib)
@ -1306,12 +1106,12 @@
(let [theme-1-id (uuid/next) (let [theme-1-id (uuid/next)
theme-2-id (uuid/next) theme-2-id (uuid/next)
theme-3-id (uuid/next) theme-3-id (uuid/next)
theme-4-id (uuid/next) ;; theme-4-id (uuid/next)
tokens-lib (-> (ctob/make-tokens-lib) tokens-lib (-> (ctob/make-tokens-lib)
(ctob/add-theme (ctob/make-token-theme :id theme-1-id :group "" :name "token-theme-1")) (ctob/add-theme (ctob/make-token-theme :id theme-1-id :group "" :name "token-theme-1"))
(ctob/add-theme (ctob/make-token-theme :id theme-2-id :group "group1" :name "token-theme-2")) (ctob/add-theme (ctob/make-token-theme :id theme-2-id :group "group1" :name "token-theme-2"))
(ctob/add-theme (ctob/make-token-theme :id theme-3-id :group "group1" :name "token-theme-3")) (ctob/add-theme (ctob/make-token-theme :id theme-3-id :group "group1" :name "token-theme-3"))
#_(ctob/add-theme (ctob/make-token-theme :in-theme-4-id :group "group2" :name "token-theme-4"))) #_(ctob/add-theme (ctob/make-token-theme :id theme-4-id :group "group2" :name "token-theme-4")))
tokens-lib' (-> tokens-lib tokens-lib' (-> tokens-lib
(ctob/update-theme theme-2-id (ctob/update-theme theme-2-id

View File

@ -83,7 +83,8 @@
(t/is (= (ctob/get-description theme2') (ctob/get-description theme2)))))) (t/is (= (ctob/get-description theme2') (ctob/get-description theme2))))))
(t/deftest make-tokens-status-from-tokens-lib (t/deftest make-tokens-status-from-tokens-lib
(let [tokens-lib (-> (ctob/make-tokens-lib) (t/testing "active themes and sets from a legacy tokens-lib should be added to the status"
(let [base-lib (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-a) (ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-a)
:name "set-a")) :name "set-a"))
(ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-b) (ctob/add-set (ctob/make-token-set :id (thi/new-id! :set-b)
@ -101,18 +102,33 @@
(ctob/add-theme (ctob/make-token-theme :id (thi/new-id! :theme-3) (ctob/add-theme (ctob/make-token-theme :id (thi/new-id! :theme-3)
:name "theme-3" :name "theme-3"
:sets #{"set-c" "set-d"}))) :sets #{"set-c" "set-d"})))
;; Build a legacy tokens lib to test migration ;; Build a legacy tokens lib to test migration
tokens-lib (ctob/map->tokens-lib {:sets (.-sets tokens-lib) tokens-lib (ctob/map->tokens-lib {:sets (.-sets base-lib)
:themes (.-themes tokens-lib) :themes (.-themes base-lib)
:active-themes #{"/theme-1" "/theme-2"}}) :active-themes #{"/theme-1" "/theme-2"}})
tokens-status (cfo/make-tokens-status-from-lib tokens-lib)] tokens-status (cfo/make-tokens-status-from-lib tokens-lib)]
(t/is (ctos/tokens-status? tokens-status)) (t/is (ctos/tokens-status? tokens-status))
(t/is (ctos/check-tokens-status tokens-status)) (t/is (ctos/check-tokens-status tokens-status))
(t/is (= (count (ctos/get-active-theme-ids tokens-status)) 2)) (t/is (= (count (ctos/get-active-theme-ids tokens-status)) 2))
(t/is (ctos/theme-active? tokens-status (thi/id :theme-1))) (t/is (ctos/theme-active? tokens-status (thi/id :theme-1)))
(t/is (ctos/theme-active? tokens-status (thi/id :theme-2))) (t/is (ctos/theme-active? tokens-status (thi/id :theme-2)))
(t/is (= 2 (count (ctos/get-active-set-ids tokens-status)))) (t/is (= 2 (count (ctos/get-active-set-ids tokens-status))))
(t/is (ctos/set-active? tokens-status (thi/id :set-a))) (t/is (ctos/set-active? tokens-status (thi/id :set-a)))
(t/is (ctos/set-active? tokens-status (thi/id :set-b))))) (t/is (ctos/set-active? tokens-status (thi/id :set-b)))))
(t/testing "hidden theme should be excluded from active theme ids"
(let [tokens-lib (ctob/make-tokens-lib)
status (cfo/make-tokens-status-from-lib tokens-lib)]
(t/is (not (contains? (ctos/get-active-set-ids status) ctob/hidden-theme-id)))))
(t/testing "returns empty sets when no active themes"
(let [base-lib (ctob/make-tokens-lib)
tokens-lib (ctob/map->tokens-lib
{:sets (:sets (.sets base-lib))
:themes (:themes (.themes base-lib))
:active-themes #{}})
status (cfo/make-tokens-status-from-lib tokens-lib)]
(t/is (= #{} (ctos/get-active-theme-ids status)))
(t/is (= #{} (ctos/get-active-set-ids status))))))

View File

@ -274,6 +274,7 @@
(defn toggle-token-theme-active (defn toggle-token-theme-active
[id] [id]
(assert (uuid? id) "expected a uuid for `id`")
(ptk/reify ::toggle-token-theme-active (ptk/reify ::toggle-token-theme-active
ptk/WatchEvent ptk/WatchEvent
(watch [it state _] (watch [it state _]
@ -289,6 +290,7 @@
(defn delete-token-theme (defn delete-token-theme
[id] [id]
(assert (uuid? id) "expected a uuid for `id`")
(ptk/reify ::delete-token-theme (ptk/reify ::delete-token-theme
ptk/WatchEvent ptk/WatchEvent
(watch [it state _] (watch [it state _]
@ -357,8 +359,8 @@
(dch/commit-changes changes))))))))) (dch/commit-changes changes)))))))))
(defn set-enabled-token-set (defn set-enabled-token-set
[name enabled?] [id enabled?]
(assert (string? name) "expected a string for `name`") (assert (uuid? id) "expected a uuid for `id`")
(assert (boolean? enabled?) "expected a boolean for `enabled?`") (assert (boolean? enabled?) "expected a boolean for `enabled?`")
(ptk/reify ::set-enabled-token-set (ptk/reify ::set-enabled-token-set
ptk/WatchEvent ptk/WatchEvent
@ -368,14 +370,14 @@
tokens-status (dsh/lookup-tokens-status state) tokens-status (dsh/lookup-tokens-status state)
changes (-> (pcb/empty-changes) changes (-> (pcb/empty-changes)
(pcb/with-library-data data) (pcb/with-library-data data)
(clt/generate-set-enabled-token-set tokens-status tokens-lib name enabled?))] (clt/generate-set-enabled-token-set tokens-status tokens-lib id enabled?))]
(rx/of (dch/commit-changes changes) (rx/of (dch/commit-changes changes)
(dwtp/propagate-workspace-tokens)))))) (dwtp/propagate-workspace-tokens))))))
(defn toggle-token-set (defn toggle-token-set
[name] [id]
(assert (string? name) "expected a string for `name`") (assert (uuid? id) "expected a uuid for `id`")
(ptk/reify ::toggle-token-set (ptk/reify ::toggle-token-set
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
@ -384,7 +386,7 @@
tokens-status (dsh/lookup-tokens-status state) tokens-status (dsh/lookup-tokens-status state)
changes (-> (pcb/empty-changes) changes (-> (pcb/empty-changes)
(pcb/with-library-data data) (pcb/with-library-data data)
(clt/generate-toggle-token-set tokens-status tokens-lib name))] (clt/generate-toggle-token-set tokens-status tokens-lib id))]
(rx/of (rx/of
(dch/commit-changes changes) (dch/commit-changes changes)

View File

@ -496,7 +496,6 @@
(def workspace-token-sets-tree (def workspace-token-sets-tree
(l/derived (d/nilf ctob/get-set-tree) tokens-lib)) (l/derived (d/nilf ctob/get-set-tree) tokens-lib))
;; TODOstatus cambiar para que sean ids en todas partes
(def workspace-active-theme-paths (def workspace-active-theme-paths
(l/derived (d/nilf ctos/get-active-theme-ids) tokens-status)) (l/derived (d/nilf ctos/get-active-theme-ids) tokens-status))

View File

@ -13,6 +13,7 @@
[app.common.types.component :as ctc] [app.common.types.component :as ctc]
[app.common.types.components-list :as ctkl] [app.common.types.components-list :as ctkl]
[app.common.types.shape.layout :as ctl] [app.common.types.shape.layout :as ctl]
[app.common.types.tokens-lib :as ctob]
[app.main.data.style-dictionary :as sd] [app.main.data.style-dictionary :as sd]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.ui.inspect.exports :as exports] [app.main.ui.inspect.exports :as exports]
@ -115,7 +116,7 @@
active-themes (mf/deref refs/workspace-active-theme-paths) active-themes (mf/deref refs/workspace-active-theme-paths)
active-sets (mf/with-memo [tokens-status tokens-lib] active-sets (mf/with-memo [tokens-status tokens-lib]
(when (and tokens-status tokens-lib) (when (and tokens-status tokens-lib)
(cfo/get-active-set-names tokens-status tokens-lib))) (cfo/get-active-sets tokens-status tokens-lib)))
active-tokens (mf/with-memo [tokens-status tokens-lib] active-tokens (mf/with-memo [tokens-status tokens-lib]
(when (and tokens-status tokens-lib) (when (and tokens-status tokens-lib)
(cfo/get-tokens-in-active-sets tokens-status tokens-lib))) (cfo/get-tokens-in-active-sets tokens-status tokens-lib)))
@ -155,7 +156,7 @@
(when (or (seq active-themes) (seq active-sets)) (when (or (seq active-themes) (seq active-sets))
[:li [:li
[:> style-box* {:panel :token} [:> style-box* {:panel :token}
[:> tokens-panel* {:theme-paths active-themes :set-names active-sets}]]]) [:> tokens-panel* {:theme-paths active-themes :set-names (map ctob/get-name active-sets)}]]])
(for [panel panels] (for [panel panels]
[:li {:key (d/name panel)} [:li {:key (d/name panel)}
(case panel (case panel

View File

@ -769,7 +769,9 @@
active-sets-names active-sets-names
(mf/with-memo [tokens-status tokens-lib] (mf/with-memo [tokens-status tokens-lib]
(when (and tokens-status tokens-lib) (when (and tokens-status tokens-lib)
(cfo/get-active-set-names tokens-status tokens-lib))) (into #{}
(map ctob/get-name)
(cfo/get-active-sets tokens-status tokens-lib))))
active-tokens (if (delay? active-tokens) active-tokens (if (delay? active-tokens)
@active-tokens @active-tokens
@ -785,7 +787,7 @@
(filter-active-sets active-sets-names) (filter-active-sets active-sets-names)
(filter-non-empty-sets) (filter-non-empty-sets)
(group-sets) (group-sets)
(combine-groups-with-resolved color-tokens)))] (combine-groups-with-resolved color-tokens)))]
(mf/with-effect [] (mf/with-effect []
(st/emit! (st/emit! (dsc/push-shortcuts ::colorpicker sc/shortcuts))) (st/emit! (st/emit! (dsc/push-shortcuts ::colorpicker sc/shortcuts)))

View File

@ -2,10 +2,10 @@
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.files.tokens :as cfo]
[app.common.path-names :as cpn] [app.common.path-names :as cpn]
[app.common.types.shape.layout :as ctsl] [app.common.types.shape.layout :as ctsl]
[app.common.types.tokens-lib :as ctob] [app.common.types.tokens-lib :as ctob]
[app.common.types.tokens-status :as ctos]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.config :as cf] [app.config :as cf]
[app.main.data.helpers :as dh] [app.main.data.helpers :as dh]
@ -56,16 +56,12 @@
(when selected-token-set-id (when selected-token-set-id
(some-> tokens-lib (ctob/get-set selected-token-set-id)))) (some-> tokens-lib (ctob/get-set selected-token-set-id))))
active-token-sets-names
(mf/with-memo [tokens-status tokens-lib]
(when (and tokens-status tokens-lib)
(cfo/get-active-set-names tokens-status tokens-lib)))
token-set-active? token-set-active?
(mf/use-fn (mf/use-fn
(mf/deps active-token-sets-names) (mf/deps tokens-status)
(fn [name] (fn [id]
(contains? active-token-sets-names name)))] (ctos/set-active? tokens-status id)))]
[:div {:class (stl/css :sets-header-container)} [:div {:class (stl/css :sets-header-container)}
[:> text* {:as "span" [:> text* {:as "span"
:typography "headline-small" :typography "headline-small"
@ -73,7 +69,7 @@
:data-testid "active-token-set-title"} :data-testid "active-token-set-title"}
(tr "workspace.tokens.tokens-section-title" (ctob/get-name selected-token-set))] (tr "workspace.tokens.tokens-section-title" (ctob/get-name selected-token-set))]
(when (and (some? selected-token-set-id) (when (and (some? selected-token-set-id)
(not (token-set-active? (ctob/get-name selected-token-set)))) (not (token-set-active? selected-token-set-id)))
[:div {:class (stl/css :sets-header-status) :title (tr "workspace.tokens.inactive-set-description")} [:div {:class (stl/css :sets-header-status) :title (tr "workspace.tokens.inactive-set-description")}
;; NOTE: when no set in tokens-lib, the selected-token-set-id ;; NOTE: when no set in tokens-lib, the selected-token-set-id
;; will be `nil`, so for properly hide the inactive message we ;; will be `nil`, so for properly hide the inactive message we
@ -86,7 +82,7 @@
(mf/defc tokens-section* (mf/defc tokens-section*
{::mf/private true} {::mf/private true}
[{:keys [tokens-lib active-tokens resolved-active-tokens]}] [{:keys [tokens-lib tokens-status active-tokens resolved-active-tokens]}]
(let [objects (mf/deref refs/workspace-page-objects) (let [objects (mf/deref refs/workspace-page-objects)
selected (mf/deref refs/selected-shapes) selected (mf/deref refs/selected-shapes)
@ -307,6 +303,7 @@
:on-delete-node delete-node}] :on-delete-node delete-node}]
[:> selected-set-info* {:tokens-lib tokens-lib [:> selected-set-info* {:tokens-lib tokens-lib
:tokens-status tokens-status
:selected-token-set-id selected-token-set-id}] :selected-token-set-id selected-token-set-id}]
(for [type filled-group] (for [type filled-group]

View File

@ -20,8 +20,8 @@
(st/emit! (dwtl/clear-tokens-paths) (st/emit! (dwtl/clear-tokens-paths)
(dwtl/set-selected-token-set-id id))) (dwtl/set-selected-token-set-id id)))
(defn- on-toggle-token-set-click [name] (defn- on-toggle-token-set-click [id]
(st/emit! (dwtl/toggle-token-set name))) (st/emit! (dwtl/toggle-token-set id)))
(defn- on-toggle-token-set-group-click [path] (defn- on-toggle-token-set-group-click [path]
(st/emit! (dwtl/toggle-token-set-group path))) (st/emit! (dwtl/toggle-token-set-group path)))

View File

@ -10,7 +10,6 @@
(:require (:require
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.types.tokens-lib :as ctob] [app.common.types.tokens-lib :as ctob]
[app.common.types.tokens-status :as ctos]
[app.main.data.workspace.tokens.library-edit :as dwtl] [app.main.data.workspace.tokens.library-edit :as dwtl]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.context :as ctx] [app.main.ui.context :as ctx]
@ -245,7 +244,7 @@
(fn [event] (fn [event]
(dom/stop-propagation event) (dom/stop-propagation event)
(when (fn? on-toggle) (when (fn? on-toggle)
(on-toggle (ctob/get-name set))))) (on-toggle (ctob/get-id set)))))
on-edit-submit' on-edit-submit'
(mf/use-fn (mf/use-fn
@ -327,9 +326,7 @@
new-path new-path
edition-id]}] edition-id]}]
(let [tokens-status (mf/use-ctx ctx/tokens-status) (let [collapsed-paths* (mf/use-state #{})
collapsed-paths* (mf/use-state #{})
collapsed-paths (deref collapsed-paths*) collapsed-paths (deref collapsed-paths*)
collapsed? collapsed?

View File

@ -348,20 +348,16 @@
:enumerable false :enumerable false
:get :get
(fn [_] (fn [_]
(let [tokens-lib (u/locate-tokens-lib file-id) (let [tokens-status (u/locate-tokens-status file-id)]
tokens-status (u/locate-tokens-status file-id) (ctos/set-active? tokens-status id)))
set (u/locate-token-set file-id id)]
(cfo/token-set-active? tokens-status tokens-lib (ctob/get-name set))))
:schema ::sm/boolean :schema ::sm/boolean
:set :set
(fn [_ value] (fn [_ value]
(let [set (u/locate-token-set file-id id)] (st/emit! (dwtl/set-enabled-token-set id value)))}
(st/emit! (dwtl/set-enabled-token-set (ctob/get-name set) value))))}
:toggleActive :toggleActive
(fn [_] (fn [_]
(let [set (u/locate-token-set file-id id)] (st/emit! (dwtl/toggle-token-set id)))
(st/emit! (dwtl/toggle-token-set (ctob/get-name set)))))
:tokens :tokens
{:this true {:this true

View File

@ -87,17 +87,16 @@
done done
(let [file (setup-file-with-empty-lib) (let [file (setup-file-with-empty-lib)
store (ths/setup-store file) store (ths/setup-store file)
set (ctob/make-token-set :name "primitives") set (ctob/make-token-set :id (cthi/new-id! :set1) :name "primitives")
events [(dwtl/create-token-set set)]] events [(dwtl/create-token-set set)]]
(tohs/run-store-async (tohs/run-store-async
store done events store done events
(fn [new-state] (fn [new-state]
(let [file' (ths/get-file-from-state new-state) (let [file' (ths/get-file-from-state new-state)
lib (get-in file' [:data :tokens-lib])] lib (ctht/get-tokens-lib file')
status (ctht/get-tokens-status file')]
(t/is (some? (ctob/get-set lib (ctob/get-id set)))) (t/is (some? (ctob/get-set lib (ctob/get-id set))))
(t/is (false? (cfo/token-set-active? (t/is (false? (ctos/set-active? status (cthi/id :set1)))))))))))
(ctht/get-tokens-status file')
lib "primitives"))))))))))
(t/deftest test-create-then-enable-token-set (t/deftest test-create-then-enable-token-set
(t/testing "create followed by set-enabled (as the plugin addSet does) yields an active set" (t/testing "create followed by set-enabled (as the plugin addSet does) yields an active set"
@ -105,18 +104,17 @@
done done
(let [file (setup-file-with-empty-lib) (let [file (setup-file-with-empty-lib)
store (ths/setup-store file) store (ths/setup-store file)
set (ctob/make-token-set :name "primitives") set (ctob/make-token-set :id (cthi/new-id! :set1) :name "primitives")
events [(dwtl/create-token-set set) events [(dwtl/create-token-set set)
(dwtl/set-enabled-token-set "primitives" true)]] (dwtl/set-enabled-token-set (cthi/id :set1) true)]]
(tohs/run-store-async (tohs/run-store-async
store done events store done events
(fn [new-state] (fn [new-state]
(let [file' (ths/get-file-from-state new-state) (let [file' (ths/get-file-from-state new-state)
lib (get-in file' [:data :tokens-lib])] lib (ctht/get-tokens-lib file')
status (ctht/get-tokens-status file')]
(t/is (some? (ctob/get-set lib (ctob/get-id set)))) (t/is (some? (ctob/get-set lib (ctob/get-id set))))
(t/is (true? (cfo/token-set-active? (t/is (true? (ctos/set-active? status (cthi/id :set1)))))))))))
(ctht/get-tokens-status file')
lib "primitives"))))))))))
(t/deftest test-apply-token (t/deftest test-apply-token
(t/testing "applies token to shape and updates shape attributes to resolved value" (t/testing "applies token to shape and updates shape attributes to resolved value"