0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-20 05:34:23 -05:00

🔧 Fix wrong code in merge

This commit is contained in:
Andrés Moya 2024-11-08 16:08:07 +01:00
parent 5fee74cea8
commit b4440aad04
14 changed files with 16 additions and 887 deletions

View file

@ -1,7 +1,6 @@
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------

View file

@ -401,7 +401,7 @@
(update :redo-changes conj add-change)
(cond->
(and (ctk/in-component-copy? parent) (not ignore-touched))
(update :undo-changes conj restore-touched-change))
(update :undo-changes conj restore-touched-change))
(update :undo-changes conj del-change)
(apply-changes-local)))))
@ -462,7 +462,7 @@
(update :redo-changes conj set-parent-change)
(cond->
(ctk/in-component-copy? parent)
(update :undo-changes conj restore-touched-change))
(update :undo-changes conj restore-touched-change))
(update :undo-changes #(reduce mk-undo-change % shapes))
(apply-changes-local)))))

View file

@ -128,9 +128,9 @@
(sm/register! ::dimensions
(merge-schemas ::sizing
::spacing
::stroke-width
::border-radius))
::spacing
::stroke-width
::border-radius))
(def dimensions-keys (schema-keys ::dimensions))
@ -145,8 +145,8 @@
(sm/register! ::applied-tokens
(merge-schemas ::tokens
::border-radius
::sizing
::spacing
::rotation
::dimensions))
::border-radius
::sizing
::spacing
::rotation
::dimensions))

View file

@ -1,7 +0,0 @@
(ns preload
(:require
[devtools.core :as devtools]))
;; Silence shadow-cljs devtools (ns reloading)
(devtools/set-pref! :dont-display-banner true)
(devtools/set-pref! :min-expandable-sequable-count-for-well-known-types 0)

View file

@ -63,11 +63,11 @@
:browser
:webworker))
(def default-flags ;;uncomment the below flags when Penpot Tokens Studio is ready to be merged into Penpot
[;;:enable-onboarding
;;:enable-onboarding-team
;;:enable-onboarding-questions
;;:enable-onboarding-newsletter
(def default-flags
[:enable-onboarding
:enable-onboarding-team
:enable-onboarding-questions
:enable-onboarding-newsletter
:enable-dashboard-templates-section
:enable-google-fonts-provider
:enable-component-thumbnails])

View file

@ -20,7 +20,6 @@
[app.main.ui.onboarding.team-choice :refer [onboarding-team-modal]]
[app.main.ui.releases :refer [release-notes-modal]]
[app.main.ui.static :as static]
[app.main.ui.workspace.tokens.modals.themes :as wtmt]
[app.util.dom :as dom]
[app.util.i18n :refer [tr]]
[rumext.v2 :as mf]))

View file

@ -1,114 +0,0 @@
# Changelog
Add changes that are meaningful to the user here after each PR so they can be updated in feature base.
<details>
<summary>Template</summary>
## Template
### <DATE> - <CHANGE_DESCRIPTION>
[Link to PR]()
If possible add video here from PR as well
- Outline of changes
</details>
## Changes
### 2024-08-05 - Fix opacity updating
[Link to PR](https://github.com/orgs/tokens-studio/projects/69/views/11?pane=issue&itemId=69801248)
Fixes opacity not being applied correctly to shapes.
### 2024-08-05 - Fix stroke witdth applying breaking app
[Link to PR](https://github.com/orgs/tokens-studio/projects/69/views/11?pane=issue&itemId=73072870)
`:stroke-width` token applying wont update for shapes without a stroke.
### 2024-07-25 - UX Improvements for the context menu
[Link to PR](https://github.com/tokens-studio/tokens-studio-for-penpot/pull/224)
Changes context menu behavior according to [Specs](https://github.com/tokens-studio/obsidian-docs/blob/31f0d7f98ff5ac922970f3009fe877cc02d6d0cd/Products/TS%20for%20Penpot/Specs/Token%20State%20Specs.md)
- Removing a token wont update the shape
- Mixed selection (shapes with applied, shapes without applied) will always unapply token
- Multi selection of shapes without token will apply the token to all
- Every shape change and token applying should be one undo step now
- Prevent token applying when nothign is selected
- `All` is a toggle instead of a checkbox if all tokens have been applied
- For instance with border radius the context menu can `:r1 :r2 :r3 :r4` which will highlight `All`
- If one attribute is missing it will check the single attributes
- Clicking a single attribute after clicking `All` will remove the other attributes
- Fixed some issues for switching between split and uniform border radius
- Clicking a token wont apply all attributes anymore. We apply only a select collection of attributes, which makes most sense. For instance on `sizing` we only apply `width` and `height` instead of all (`max-width`, `max-height`, `min-heigt`, `min-width`)
### 2024-07-05 - UX Improvements when applying tokens
[Link to PR](https://github.com/tokens-studio/tokens-studio-for-penpot/compare/token-studio-develop...ux-improvements?body=&expand=1)
- When unapplying tokens, the shape doesn't change anymore
- Multi Select behavior according to [Specs](https://github.com/tokens-studio/obsidian-docs/blob/31f0d7f98ff5ac922970f3009fe877cc02d6d0cd/Products/TS%20for%20Penpot/Specs/Token%20State%20Specs.md)
- Undo for applying tokens and change the shape is now one undo step
(before applying a token created multiple undo steps)
[Video](https://github.com/tokens-studio/tokens-studio-for-penpot/assets/1898374/01d9d429-cab1-41cd-a3ff-495003edd3e8
)
### 2024-07-01 - Disallow creating tokens at existing paths
Disallow creating tokens at an existing path.
[Video](https://github.com/tokens-studio/tokens-studio-for-penpot/assets/1898374/557990fe-efe7-445b-8a1d-824396049db7
)
Example:
We've got a token with `borderRadius.sm`, so we can't allow to create a token at `borderRadius` or `borderRadius.sm`.
But we can allow creating a token at `borderRadius.md`.
### 2024-06-26 - Disallow special characters in token name
- Only allows digits, letters and `-` as a part of a token name
[Video](https://github.com/tokens-studio/tokens-studio-for-penpot/assets/1898374/7c59c0cc-d6e1-4b0d-9646-9a27eafcccc4
)
https://github.com/tokens-studio/tokens-studio-for-penpot/pull/200
### 2024-06-26 - Make Tokens JSON Export DTCG compatible
![Screenshot of sample JSON Export in DTCG format](https://private-user-images.githubusercontent.com/9948167/343043570-b4bb39f7-ec53-409a-a053-b284d60848d9.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTk0MDMyMzcsIm5iZiI6MTcxOTQwMjkzNywicGF0aCI6Ii85OTQ4MTY3LzM0MzA0MzU3MC1iNGJiMzlmNy1lYzUzLTQwOWEtYTA1My1iMjg0ZDYwODQ4ZDkucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDYyNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA2MjZUMTE1NTM3WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MWEzZTU5OWQ0M2JkZWE5MTA5MDc4MTY1OTkyZWE5MmE5YzBlYmQ2NTcwMmEwZTdmMjViNGU5YTFjNWIxYjU5ZCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.qWJxRa_Y7LZ6EDJg5yPdOUIQkURFmZwMNec_BbdH9Co)
https://github.com/tokens-studio/tokens-studio-for-penpot/issues/197
### 2024-06-25 - Token Insert/Edit Validation + Value Preview
[Video](https://private-user-images.githubusercontent.com/1898374/342781533-06054a7e-3efb-4f48-a063-8b03f4b8fe5c.mp4?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTkzMjgwNzYsIm5iZiI6MTcxOTMyNzc3NiwicGF0aCI6Ii8xODk4Mzc0LzM0Mjc4MTUzMy0wNjA1NGE3ZS0zZWZiLTRmNDgtYTA2My04YjAzZjRiOGZlNWMubXA0P1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDYyNSUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA2MjVUMTUwMjU2WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZDliZmUwMzU1MWY3NWQ2NWZkYzA0ODYxYzYzMTYzMjMyOGZjZGMzZDNhMWJmZGI4ZmM3NmU2NzNjYjY2MTdmMCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.44rKA1h3Cvw-vDWevnx7xVUeuZ1ezV4pqEtekVXgVds)
https://github.com/tokens-studio/tokens-studio-for-penpot/pull/194
Adds validation to the token create/edit field
- Name duplication is not allowed and takes a min/max length
- Value has to be a resolvable value
- Description has max value
### 2024-06-24 - Added Ability to Export Tokens in JSON Format
Sample JSON Output - https://github.com/user-attachments/files/15957831/tokens.json
![JSON Export button Screenshot on the left Tokens Panel](https://private-user-images.githubusercontent.com/9948167/342395881-87ceaef0-79e5-4c6f-a25f-5130e47ed205.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTk0MDQ2NzQsIm5iZiI6MTcxOTQwNDM3NCwicGF0aCI6Ii85OTQ4MTY3LzM0MjM5NTg4MS04N2NlYWVmMC03OWU1LTRjNmYtYTI1Zi01MTMwZTQ3ZWQyMDUucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDYyNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA2MjZUMTIxOTM0WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZTg4NzAwZWFmNmM5ZDYzNDRmZjdlNWQzOTk3YjI4NTk4ODZiN2RiYTI1ODc0MDhmMzE3M2RkYTQwOGI2ZGU4NCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.LIjsIUutX72A_TtosO_I7f1z9v0nBo5brLl_BMOp-7Y)
https://github.com/tokens-studio/tokens-studio-for-penpot/pull/191
### 2024-06-19 - Added CHANGELOG.md
Added template for changelog

View file

@ -388,7 +388,7 @@ Token names should only contain letters and digits separated by . characters.")}
:on-change on-update-value
:ref value-input-ref}
:render-right (when color?
(mf/fnc []
(mf/fnc drop-down-button []
[:div {:class (stl/css :color-bullet)
:on-click #(swap! color-ramp-open? not)}
(if-let [hex (some-> @color tinycolor/valid-color tinycolor/->hex)]

View file

@ -1,74 +0,0 @@
(ns token-tests.helpers.state
(:require
[app.common.types.tokens-lib :as ctob]
[app.main.ui.workspace.tokens.style-dictionary :as sd]
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(defn end
"Apply `attributes` that match `token` for `shape-ids`.
Optionally remove attributes from `attributes-to-remove`,
this is useful for applying a single attribute from an attributes set
while removing other applied tokens from this set."
[]
(ptk/reify ::end
ptk/WatchEvent
(watch [_ _ _]
(rx/empty))))
(defn end+
[]
(ptk/reify ::end+
ptk/WatchEvent
(watch [_ state _]
(->> (rx/from (-> (get-in state [:workspace-data :tokens-lib])
(ctob/get-active-themes-set-tokens)
(sd/resolve-tokens+)))
(rx/mapcat #(rx/of (end)))))))
(defn stop-on
"Helper function to be used with async version of run-store.
Will stop the execution after event with `event-type` has completed."
[event-type]
(fn [stream]
(->> stream
#_(rx/tap #(prn (ptk/type %)))
(rx/filter #(ptk/type? event-type %)))))
(def stop-on-send-update-indices
"Stops on `send-update-indices` function being called, which should be the last function of an event chain."
(stop-on ::end))
;; Support for async events in tests
;; https://chat.kaleidos.net/penpot-partners/pl/tz1yoes3w3fr9qanxqpuhoz3ch
(defn run-store
"Async version of `frontend-tests.helpers.state/run-store`."
([store done events completed-cb]
(run-store store done events completed-cb nil))
([store done events completed-cb stopper]
(let [stream (ptk/input-stream store)
stopper-s (if (fn? stopper)
(stopper stream)
(rx/filter #(= :the/end %) stream))]
(->> stream
(rx/take-until stopper-s)
(rx/last)
(rx/tap (fn [_]
(completed-cb @store)))
(rx/subs! (fn [_] (done))
(fn [cause]
(js/console.log "[error]:" cause))
(fn [_]
#_(js/console.log "[complete]"))))
(doseq [event (concat events [(end+)])]
(ptk/emit! store event))
(ptk/emit! store :the/end))))
(defn run-store-async
"Helper version of `run-store` that automatically stops on the `send-update-indices` event"
([store done events completed-cb]
(run-store store done events completed-cb stop-on-send-update-indices))
([store done events completed-cb stop-on]
(run-store store done events completed-cb stop-on)))

View file

@ -1,26 +0,0 @@
(ns token-tests.helpers.tokens
(:require
[app.common.test-helpers.ids-map :as thi]
[app.common.types.tokens-lib :as ctob]
[app.main.ui.workspace.tokens.token :as wtt]))
(defn add-token [state label params]
(let [id (thi/new-id! label)
token (assoc params :id id)]
(update-in state [:data :tokens] assoc id token)))
(defn get-token [file name]
(some-> (get-in file [:data :tokens-lib])
(ctob/get-active-themes-set-tokens)
(get name)))
(defn apply-token-to-shape [file shape-label token-label attributes]
(let [first-page-id (get-in file [:data :pages 0])
shape-id (thi/id shape-label)
token (get-token file token-label)
applied-attributes (wtt/attributes-map attributes token)]
(update-in file [:data
:pages-index first-page-id
:objects shape-id
:applied-tokens]
merge applied-attributes)))

View file

@ -1,407 +0,0 @@
(ns token-tests.logic.token-actions-test
(:require
[app.common.logging :as log]
[app.common.test-helpers.compositions :as ctho]
[app.common.test-helpers.files :as cthf]
[app.common.test-helpers.shapes :as cths]
[app.common.types.tokens-lib :as ctob]
[app.main.ui.workspace.tokens.changes :as wtch]
[app.main.ui.workspace.tokens.token :as wtt]
[cljs.test :as t :include-macros true]
[frontend-tests.helpers.pages :as thp]
[frontend-tests.helpers.state :as ths]
[token-tests.helpers.state :as tohs]
[token-tests.helpers.tokens :as toht]))
(t/use-fixtures :each
{:before (fn []
;; Ignore rxjs async errors
(log/set-level! "app.main.data.changes" :error)
(thp/reset-idmap!))})
(defn setup-file []
(cthf/sample-file :file-1 :page-label :page-1))
(def border-radius-token
{:name "borderRadius.sm"
:value "12"
:type :border-radius})
(def reference-border-radius-token
{:name "borderRadius.md"
:value "{borderRadius.sm} * 2"
:type :border-radius})
(defn setup-file-with-tokens
[& {:keys [rect-1 rect-2 rect-3]}]
(-> (setup-file)
(ctho/add-rect :rect-1 rect-1)
(ctho/add-rect :rect-2 rect-2)
(ctho/add-rect :rect-3 rect-3)
(assoc-in [:data :tokens-lib]
(-> (ctob/make-tokens-lib)
(ctob/add-theme (ctob/make-token-theme :name "Theme A" :sets #{"Set A"}))
(ctob/set-active-themes #{"/Theme A"})
(ctob/add-set (ctob/make-token-set :name "Set A"))
(ctob/add-token-in-set "Set A" (ctob/make-token border-radius-token))
(ctob/add-token-in-set "Set A" (ctob/make-token reference-border-radius-token))))))
(t/deftest test-apply-token
(t/testing "applies token to shape and updates shape attributes to resolved value"
(t/async
done
(let [file (setup-file-with-tokens)
store (ths/setup-store file)
rect-1 (cths/get-shape file :rect-1)
events [(wtch/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:rx :ry}
:token (toht/get-token file "borderRadius.md")
:on-update-shape wtch/update-shape-radius-all})]]
(tohs/run-store-async
store done events
(fn [new-state]
(let [file' (ths/get-file-from-store new-state)
token (toht/get-token file' "borderRadius.md")
rect-1' (cths/get-shape file' :rect-1)]
(t/testing "shape `:applied-tokens` got updated"
(t/is (some? (:applied-tokens rect-1')))
(t/is (= (:rx (:applied-tokens rect-1')) (:name token)))
(t/is (= (:ry (:applied-tokens rect-1')) (:name token))))
(t/testing "shape radius got update to the resolved token value."
(t/is (= (:rx rect-1') 24))
(t/is (= (:ry rect-1') 24))))))))))
(t/deftest test-apply-multiple-tokens
(t/testing "applying a token twice with the same attributes will override the previously applied tokens values"
(t/async
done
(let [file (setup-file-with-tokens)
store (ths/setup-store file)
rect-1 (cths/get-shape file :rect-1)
events [(wtch/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:rx :ry}
:token (toht/get-token file "borderRadius.sm")
:on-update-shape wtch/update-shape-radius-all})
(wtch/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:rx :ry}
:token (toht/get-token file "borderRadius.md")
:on-update-shape wtch/update-shape-radius-all})]]
(tohs/run-store-async
store done events
(fn [new-state]
(let [file' (ths/get-file-from-store new-state)
token (toht/get-token file' "borderRadius.md")
rect-1' (cths/get-shape file' :rect-1)]
(t/testing "shape `:applied-tokens` got updated"
(t/is (some? (:applied-tokens rect-1')))
(t/is (= (:rx (:applied-tokens rect-1')) (:name token)))
(t/is (= (:ry (:applied-tokens rect-1')) (:name token))))
(t/testing "shape radius got update to the resolved token value."
(t/is (= (:rx rect-1') 24))
(t/is (= (:ry rect-1') 24))))))))))
(t/deftest test-apply-token-overwrite
(t/testing "removes old token attributes and applies only single attribute"
(t/async
done
(let [file (setup-file-with-tokens)
store (ths/setup-store file)
rect-1 (cths/get-shape file :rect-1)
events [;; Apply "borderRadius.sm" to all border radius attributes
(wtch/apply-token {:attributes #{:rx :ry :r1 :r2 :r3 :r4}
:token (toht/get-token file "borderRadius.sm")
:shape-ids [(:id rect-1)]
:on-update-shape wtch/update-shape-radius-all})
;; Apply single `:r1` attribute to same shape
;; while removing other attributes from the border-radius set
;; but keep `:r4` for testing purposes
(wtch/apply-token {:attributes #{:r1}
:attributes-to-remove #{:rx :ry :r1 :r2 :r3}
:token (toht/get-token file "borderRadius.md")
:shape-ids [(:id rect-1)]
:on-update-shape wtch/update-shape-radius-all})]]
(tohs/run-store-async
store done events
(fn [new-state]
(let [file' (ths/get-file-from-store new-state)
token-sm (toht/get-token file' "borderRadius.sm")
token-md (toht/get-token file' "borderRadius.md")
rect-1' (cths/get-shape file' :rect-1)]
(t/testing "other border-radius attributes got removed"
(t/is (nil? (:rx (:applied-tokens rect-1')))))
(t/testing "r1 got applied with borderRadius.md"
(t/is (= (:r1 (:applied-tokens rect-1')) (:name token-md))))
(t/testing "while :r4 was kept with borderRadius.sm"
(t/is (= (:r4 (:applied-tokens rect-1')) (:name token-sm)))))))))))
(t/deftest test-apply-dimensions
(t/testing "applies dimensions token and updates the shapes width and height"
(t/async
done
(let [dimensions-token {:name "dimensions.sm"
:value "100"
:type :dimensions}
file (-> (setup-file-with-tokens)
(update-in [:data :tokens-lib]
#(ctob/add-token-in-set % "Set A" (ctob/make-token dimensions-token))))
store (ths/setup-store file)
rect-1 (cths/get-shape file :rect-1)
events [(wtch/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:width :height}
:token (toht/get-token file "dimensions.sm")
:on-update-shape wtch/update-shape-dimensions})]]
(tohs/run-store-async
store done events
(fn [new-state]
(let [file' (ths/get-file-from-store new-state)
token-target' (toht/get-token file' "dimensions.sm")
rect-1' (cths/get-shape file' :rect-1)]
(t/testing "shape `:applied-tokens` got updated"
(t/is (some? (:applied-tokens rect-1')))
(t/is (= (:width (:applied-tokens rect-1')) (:name token-target')))
(t/is (= (:height (:applied-tokens rect-1')) (:name token-target'))))
(t/testing "shapes width and height got updated"
(t/is (= (:width rect-1') 100))
(t/is (= (:height rect-1') 100))))))))))
(t/deftest test-apply-sizing
(t/testing "applies sizing token and updates the shapes width and height"
(t/async
done
(let [sizing-token {:name "sizing.sm"
:value "100"
:type :sizing}
file (-> (setup-file-with-tokens)
(update-in [:data :tokens-lib]
#(ctob/add-token-in-set % "Set A" (ctob/make-token sizing-token))))
store (ths/setup-store file)
rect-1 (cths/get-shape file :rect-1)
events [(wtch/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:width :height}
:token (toht/get-token file "sizing.sm")
:on-update-shape wtch/update-shape-dimensions})]]
(tohs/run-store-async
store done events
(fn [new-state]
(let [file' (ths/get-file-from-store new-state)
token-target' (toht/get-token file' "sizing.sm")
rect-1' (cths/get-shape file' :rect-1)]
(t/testing "shape `:applied-tokens` got updated"
(t/is (some? (:applied-tokens rect-1')))
(t/is (= (:width (:applied-tokens rect-1')) (:name token-target')))
(t/is (= (:height (:applied-tokens rect-1')) (:name token-target'))))
(t/testing "shapes width and height got updated"
(t/is (= (:width rect-1') 100))
(t/is (= (:height rect-1') 100))))))))))
(t/deftest test-apply-opacity
(t/testing "applies opacity token and updates the shapes opacity"
(t/async
done
(let [opacity-float {:name "opacity.float"
:value "0.3"
:type :opacity}
opacity-percent {:name "opacity.percent"
:value "40%"
:type :opacity}
opacity-invalid {:name "opacity.invalid"
:value "100"
:type :opacity}
file (-> (setup-file-with-tokens)
(update-in [:data :tokens-lib]
#(-> %
(ctob/add-token-in-set "Set A" (ctob/make-token opacity-float))
(ctob/add-token-in-set "Set A" (ctob/make-token opacity-percent))
(ctob/add-token-in-set "Set A" (ctob/make-token opacity-invalid)))))
store (ths/setup-store file)
rect-1 (cths/get-shape file :rect-1)
rect-2 (cths/get-shape file :rect-2)
rect-3 (cths/get-shape file :rect-3)
events [(wtch/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:opacity}
:token (toht/get-token file "opacity.float")
:on-update-shape wtch/update-opacity})
(wtch/apply-token {:shape-ids [(:id rect-2)]
:attributes #{:opacity}
:token (toht/get-token file "opacity.percent")
:on-update-shape wtch/update-opacity})
(wtch/apply-token {:shape-ids [(:id rect-3)]
:attributes #{:opacity}
:token (toht/get-token file "opacity.invalid")
:on-update-shape wtch/update-opacity})]]
(tohs/run-store-async
store done events
(fn [new-state]
(let [file' (ths/get-file-from-store new-state)
rect-1' (cths/get-shape file' :rect-1)
rect-2' (cths/get-shape file' :rect-2)
rect-3' (cths/get-shape file' :rect-3)
token-opacity-float (toht/get-token file' "opacity.float")
token-opacity-percent (toht/get-token file' "opacity.percent")
token-opacity-invalid (toht/get-token file' "opacity.invalid")]
(t/testing "float value got translated to float and applied to opacity"
(t/is (= (:opacity (:applied-tokens rect-1')) (:name token-opacity-float)))
(t/is (= (:opacity rect-1') 0.3)))
(t/testing "percentage value got translated to float and applied to opacity"
(t/is (= (:opacity (:applied-tokens rect-2')) (:name token-opacity-percent)))
(t/is (= (:opacity rect-2') 0.4)))
(t/testing "invalid opacity value got applied but did not change shape"
(t/is (= (:opacity (:applied-tokens rect-3')) (:name token-opacity-invalid)))
(t/is (nil? (:opacity rect-3')))))))))))
(t/deftest test-apply-rotation
(t/testing "applies rotation token and updates the shapes rotation"
(t/async
done
(let [rotation-token {:name "rotation.medium"
:value "120"
:type :rotation}
file (-> (setup-file-with-tokens)
(update-in [:data :tokens-lib]
#(ctob/add-token-in-set % "Set A" (ctob/make-token rotation-token))))
store (ths/setup-store file)
rect-1 (cths/get-shape file :rect-1)
events [(wtch/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:rotation}
:token (toht/get-token file "rotation.medium")
:on-update-shape wtch/update-rotation})]]
(tohs/run-store-async
store done events
(fn [new-state]
(let [file' (ths/get-file-from-store new-state)
token-target' (toht/get-token file' "rotation.medium")
rect-1' (cths/get-shape file' :rect-1)]
(t/is (some? (:applied-tokens rect-1')))
(t/is (= (:rotation (:applied-tokens rect-1')) (:name token-target')))
(t/is (= (:rotation rect-1') 120)))))))))
(t/deftest test-apply-stroke-width
(t/testing "applies stroke-width token and updates the shapes with stroke"
(t/async
done
(let [stroke-width-token {:name "stroke-width.sm"
:value "10"
:type :stroke-width}
file (-> (setup-file-with-tokens {:rect-1 {:strokes [{:stroke-alignment :inner,
:stroke-style :solid,
:stroke-color "#000000",
:stroke-opacity 1,
:stroke-width 5}]}})
(update-in [:data :tokens-lib]
#(ctob/add-token-in-set % "Set A" (ctob/make-token stroke-width-token))))
store (ths/setup-store file)
rect-with-stroke (cths/get-shape file :rect-1)
rect-without-stroke (cths/get-shape file :rect-2)
events [(wtch/apply-token {:shape-ids [(:id rect-with-stroke) (:id rect-without-stroke)]
:attributes #{:stroke-width}
:token (toht/get-token file "stroke-width.sm")
:on-update-shape wtch/update-stroke-width})]]
(tohs/run-store-async
store done events
(fn [new-state]
(let [file' (ths/get-file-from-store new-state)
token-target' (toht/get-token file' "stroke-width.sm")
rect-with-stroke' (cths/get-shape file' :rect-1)
rect-without-stroke' (cths/get-shape file' :rect-2)]
(t/testing "token got applied to rect with stroke and shape stroke got updated"
(t/is (= (:stroke-width (:applied-tokens rect-with-stroke')) (:name token-target')))
(t/is (= (get-in rect-with-stroke' [:strokes 0 :stroke-width]) 10)))
(t/testing "token got applied to rect without stroke but shape didnt get updated"
(t/is (= (:stroke-width (:applied-tokens rect-without-stroke')) (:name token-target')))
(t/is (empty? (:strokes rect-without-stroke')))))))))))
(t/deftest test-toggle-token-none
(t/testing "should apply token to all selected items, where no item has the token applied"
(t/async
done
(let [file (setup-file-with-tokens)
store (ths/setup-store file)
rect-1 (cths/get-shape file :rect-1)
rect-2 (cths/get-shape file :rect-2)
events [(wtch/toggle-token {:shapes [rect-1 rect-2]
:token-type-props {:attributes #{:rx :ry}
:on-update-shape wtch/update-shape-radius-all}
:token (toht/get-token file "borderRadius.md")})]]
(tohs/run-store-async
store done events
(fn [new-state]
(let [file' (ths/get-file-from-store new-state)
token-2' (toht/get-token file' "borderRadius.md")
rect-1' (cths/get-shape file' :rect-1)
rect-2' (cths/get-shape file' :rect-2)]
(t/is (some? (:applied-tokens rect-1')))
(t/is (some? (:applied-tokens rect-2')))
(t/is (= (:rx (:applied-tokens rect-1')) (:name token-2')))
(t/is (= (:rx (:applied-tokens rect-2')) (:name token-2')))
(t/is (= (:ry (:applied-tokens rect-1')) (:name token-2')))
(t/is (= (:ry (:applied-tokens rect-2')) (:name token-2')))
(t/is (= (:rx rect-1') 24))
(t/is (= (:rx rect-2') 24)))))))))
(t/deftest test-toggle-token-mixed
(t/testing "should unapply given token if one of the selected items has the token applied while keeping other tokens with some attributes"
(t/async
done
(let [file (-> (setup-file-with-tokens)
(toht/apply-token-to-shape :rect-1 "borderRadius.sm" #{:rx :ry})
(toht/apply-token-to-shape :rect-3 "borderRadius.md" #{:rx :ry}))
store (ths/setup-store file)
rect-with-token (cths/get-shape file :rect-1)
rect-without-token (cths/get-shape file :rect-2)
rect-with-other-token (cths/get-shape file :rect-3)
events [(wtch/toggle-token {:shapes [rect-with-token rect-without-token rect-with-other-token]
:token (toht/get-token file "borderRadius.sm")
:token-type-props {:attributes #{:rx :ry}}})]]
(tohs/run-store-async
store done events
(fn [new-state]
(let [file' (ths/get-file-from-store new-state)
rect-with-token' (cths/get-shape file' :rect-1)
rect-without-token' (cths/get-shape file' :rect-2)
rect-with-other-token' (cths/get-shape file' :rect-3)]
(t/testing "rect-with-token got the token removed"
(t/is (nil? (:rx (:applied-tokens rect-with-token'))))
(t/is (nil? (:ry (:applied-tokens rect-with-token')))))
(t/testing "rect-without-token didn't get updated"
(t/is (= (:applied-tokens rect-without-token') (:applied-tokens rect-without-token))))
(t/testing "rect-with-other-token didn't get updated"
(t/is (= (:applied-tokens rect-with-other-token') (:applied-tokens rect-with-other-token)))))))))))
(t/deftest test-toggle-token-apply-to-all
(t/testing "should apply token to all if none of the shapes has it applied"
(t/async
done
(let [file (-> (setup-file-with-tokens)
(toht/apply-token-to-shape :rect-1 "borderRadius.md" #{:rx :ry})
(toht/apply-token-to-shape :rect-3 "borderRadius.md" #{:rx :ry}))
store (ths/setup-store file)
rect-with-other-token-1 (cths/get-shape file :rect-1)
rect-without-token (cths/get-shape file :rect-2)
rect-with-other-token-2 (cths/get-shape file :rect-3)
events [(wtch/toggle-token {:shapes [rect-with-other-token-1 rect-without-token rect-with-other-token-2]
:token (toht/get-token file "borderRadius.sm")
:token-type-props {:attributes #{:rx :ry}}})]]
(tohs/run-store-async
store done events
(fn [new-state]
(let [file' (ths/get-file-from-store new-state)
target-token (toht/get-token file' "borderRadius.sm")
rect-with-other-token-1' (cths/get-shape file' :rect-1)
rect-without-token' (cths/get-shape file' :rect-2)
rect-with-other-token-2' (cths/get-shape file' :rect-3)]
(t/testing "token got applied to all shapes"
(t/is (= (:rx (:applied-tokens rect-with-other-token-1')) (:name target-token)))
(t/is (= (:rx (:applied-tokens rect-without-token')) (:name target-token)))
(t/is (= (:rx (:applied-tokens rect-with-other-token-2')) (:name target-token)))
(t/is (= (:ry (:applied-tokens rect-with-other-token-1')) (:name target-token)))
(t/is (= (:ry (:applied-tokens rect-without-token')) (:name target-token)))
(t/is (= (:ry (:applied-tokens rect-with-other-token-2')) (:name target-token)))))))))))

View file

@ -1,115 +0,0 @@
(ns token-tests.style-dictionary-test
(:require
[app.common.transit :as tr]
[app.common.types.tokens-lib :as ctob]
[app.main.ui.workspace.tokens.style-dictionary :as sd]
[beicon.v2.core :as rx]
[cljs.test :as t :include-macros true]
[promesa.core :as p]))
(t/deftest resolve-tokens-test
(t/async
done
(t/testing "resolves tokens using style-dictionary from a ids map"
(let [tokens (-> (ctob/make-tokens-lib)
(ctob/add-set (ctob/make-token-set :name "core"))
(ctob/add-token-in-set "core" (ctob/make-token {:name "borderRadius.sm"
:value "12px"
:type :border-radius}))
(ctob/add-token-in-set "core" (ctob/make-token {:value "{borderRadius.sm} * 2"
:name "borderRadius.md-with-dashes"
:type :border-radius}))
(ctob/get-all-tokens))]
(-> (sd/resolve-tokens+ tokens)
(p/finally
(fn [resolved-tokens]
(t/is (= 12 (get-in resolved-tokens ["borderRadius.sm" :resolved-value])))
(t/is (= "px" (get-in resolved-tokens ["borderRadius.sm" :unit])))
(t/is (= 24 (get-in resolved-tokens ["borderRadius.md-with-dashes" :resolved-value])))
(t/is (= "px" (get-in resolved-tokens ["borderRadius.md-with-dashes" :unit])))
(done))))))))
(t/deftest process-json-stream-test
(t/async
done
(t/testing "processes empty json string"
(let [json (-> {"core" {"color" {"$value" "red"
"$type" "color"}}}
(tr/encode-str {:type :json-verbose}))]
(->> (rx/of json)
(sd/process-json-stream)
(rx/subs! (fn [tokens-lib]
(t/is (instance? ctob/TokensLib tokens-lib))
(t/is (= "red" (-> (ctob/get-set tokens-lib "core")
(ctob/get-token "color")
(:value))))
(done))))))))
(t/deftest reference-errros-test
(t/testing "Extracts reference errors from StyleDictionary errors"
;; Using unicode for the white-space after "Error: " as some editors might remove it and its more visible
(t/is (=
["Some token references (2) could not be found."
""
"foo.value tries to reference missing, which is not defined."
"color.value tries to reference missing, which is not defined."]
(sd/reference-errors "Error:\u0020
Reference Errors:
Some token references (2) could not be found.
foo.value tries to reference missing, which is not defined.
color.value tries to reference missing, which is not defined.")))
(t/is (nil? (sd/reference-errors nil)))
(t/is (nil? (sd/reference-errors "none")))))
(t/deftest process-empty-json-stream-test
(t/async
done
(t/testing "processes empty json string"
(->> (rx/of "{}")
(sd/process-json-stream)
(rx/subs! (fn [tokens-lib]
(t/is (instance? ctob/TokensLib tokens-lib))
(done)))))))
(t/deftest process-invalid-json-stream-test
(t/async
done
(t/testing "fails on invalid json"
(->> (rx/of "{,}")
(sd/process-json-stream)
(rx/subs!
(fn []
(throw (js/Error. "Should be an error")))
(fn [err]
(t/is (= :error.import/json-parse-error (:error/code (ex-data err))))
(done)))))))
(t/deftest process-non-token-json-stream-test
(t/async
done
(t/testing "fails on non-token json"
(->> (rx/of "{\"foo\": \"bar\"}")
(sd/process-json-stream)
(rx/subs!
(fn []
(throw (js/Error. "Should be an error")))
(fn [err]
(t/is (= :error.import/invalid-json-data (:error/code (ex-data err))))
(done)))))))
(t/deftest process-missing-references-json-test
(t/async
done
(t/testing "fails on missing references in tokens"
(let [json (-> {"core" {"color" {"$value" "{missing}"
"$type" "color"}}}
(tr/encode-str {:type :json-verbose}))]
(->> (rx/of json)
(sd/process-json-stream)
(rx/subs!
(fn []
(throw (js/Error. "Should be an error")))
(fn [err]
(t/is (= :error.import/style-dictionary-reference-errors (:error/code (ex-data err))))
(done))))))))

View file

@ -1,26 +0,0 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS INC
(ns token-tests.token-form-test
(:require
[app.main.ui.workspace.tokens.form :as wtf]
[cljs.test :as t :include-macros true]
[malli.core :as m]))
(t/deftest test-valid-token-name-schema
;; Allow regular namespace token names
(t/is (some? (m/validate wtf/valid-token-name-schema "Foo")))
(t/is (some? (m/validate wtf/valid-token-name-schema "foo")))
(t/is (some? (m/validate wtf/valid-token-name-schema "FOO")))
(t/is (some? (m/validate wtf/valid-token-name-schema "Foo.Bar.Baz")))
;; Allow trailing tokens
(t/is (nil? (m/validate wtf/valid-token-name-schema "Foo.Bar.Baz....")))
;; Disallow multiple separator dots
(t/is (nil? (m/validate wtf/valid-token-name-schema "Foo..Bar.Baz")))
;; Disallow any special characters
(t/is (nil? (m/validate wtf/valid-token-name-schema "Hey Foo.Bar")))
(t/is (nil? (m/validate wtf/valid-token-name-schema "Hey😈Foo.Bar")))
(t/is (nil? (m/validate wtf/valid-token-name-schema "Hey%Foo.Bar"))))

View file

@ -1,100 +0,0 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS INC
(ns token-tests.token-test
(:require
[app.main.ui.workspace.tokens.token :as wtt]
[cljs.test :as t :include-macros true]))
(t/deftest test-parse-token-value
(t/testing "parses double from a token value"
(t/is (= {:value 100.1 :unit nil} (wtt/parse-token-value "100.1")))
(t/is (= {:value -9 :unit nil} (wtt/parse-token-value "-9"))))
(t/testing "trims white-space"
(t/is (= {:value -1.3 :unit nil} (wtt/parse-token-value " -1.3 "))))
(t/testing "parses unit: px"
(t/is (= {:value 70.3 :unit "px"} (wtt/parse-token-value " 70.3px "))))
(t/testing "parses unit: %"
(t/is (= {:value -10 :unit "%"} (wtt/parse-token-value "-10%"))))
(t/testing "parses unit: px")
(t/testing "returns nil for any invalid characters"
(t/is (nil? (wtt/parse-token-value " -1.3a "))))
(t/testing "doesnt accept invalid double"
(t/is (nil? (wtt/parse-token-value ".3")))))
(t/deftest remove-attributes-for-token-id
(t/testing "removes attributes matching the `token`, keeps other attributes"
(t/is (= {:ry "b"}
(wtt/remove-attributes-for-token #{:rx :ry} {:name "a"} {:rx "a" :ry "b"})))))
(t/deftest token-applied-test
(t/testing "matches passed token with `:token-attributes`"
(t/is (true? (wtt/token-applied? {:name "a"} {:applied-tokens {:x "a"}} #{:x}))))
(t/testing "doesn't match empty token"
(t/is (nil? (wtt/token-applied? {} {:applied-tokens {:x "a"}} #{:x}))))
(t/testing "does't match passed token `:id`"
(t/is (nil? (wtt/token-applied? {:name "b"} {:applied-tokens {:x "a"}} #{:x}))))
(t/testing "doesn't match passed `:token-attributes`"
(t/is (nil? (wtt/token-applied? {:name "a"} {:applied-tokens {:x "a"}} #{:y})))))
(t/deftest shapes-ids-by-applied-attributes
(t/testing "Returns set of matched attributes that fit the applied token"
(let [attributes #{:x :y :z}
shape-applied-x {:id "shape-applied-x"
:applied-tokens {:x "1"}}
shape-applied-y {:id "shape-applied-y"
:applied-tokens {:y "1"}}
shape-applied-x-y {:id "shape-applied-x-y"
:applied-tokens {:x "1" :y "1"}}
shape-applied-none {:id "shape-applied-none"
:applied-tokens {}}
shape-applied-all {:id "shape-applied-all"
:applied-tokens {:x "1" :y "1" :z "1"}}
shape-ids (fn [& xs] (into #{} (map :id xs)))
shapes [shape-applied-x
shape-applied-y
shape-applied-x-y
shape-applied-all
shape-applied-none]
expected (wtt/shapes-ids-by-applied-attributes {:name "1"} shapes attributes)]
(t/is (= (:x expected) (shape-ids shape-applied-x
shape-applied-x-y
shape-applied-all)))
(t/is (= (:y expected) (shape-ids shape-applied-y
shape-applied-x-y
shape-applied-all)))
(t/is (= (:z expected) (shape-ids shape-applied-all)))
(t/is (true? (wtt/shapes-applied-all? expected (shape-ids shape-applied-all) attributes)))
(t/is (false? (wtt/shapes-applied-all? expected (apply shape-ids shapes) attributes)))
(shape-ids shape-applied-x
shape-applied-x-y
shape-applied-all))))
(t/deftest tokens-applied-test
(t/testing "is true when single shape matches the token and attributes"
(t/is (true? (wtt/shapes-token-applied? {:name "a"} [{:applied-tokens {:x "a"}}
{:applied-tokens {:x "b"}}]
#{:x}))))
(t/testing "is false when no shape matches the token or attributes"
(t/is (nil? (wtt/shapes-token-applied? {:name "a"} [{:applied-tokens {:x "b"}}
{:applied-tokens {:x "b"}}]
#{:x})))
(t/is (nil? (wtt/shapes-token-applied? {:name "a"} [{:applied-tokens {:x "a"}}
{:applied-tokens {:x "a"}}]
#{:y})))))
(t/deftest name->path-test
(t/is (= ["foo" "bar" "baz"] (wtt/token-name->path "foo.bar.baz")))
(t/is (= ["foo" "bar" "baz"] (wtt/token-name->path "foo..bar.baz")))
(t/is (= ["foo" "bar" "baz"] (wtt/token-name->path "foo..bar.baz...."))))
(t/deftest token-name-path-exists?-test
(t/is (true? (wtt/token-name-path-exists? "border-radius" {"border-radius" {"sm" {:name "sm"}}})))
(t/is (true? (wtt/token-name-path-exists? "border-radius" {"border-radius" {:name "sm"}})))
(t/is (true? (wtt/token-name-path-exists? "border-radius.sm" {"border-radius" {:name "sm"}})))
(t/is (true? (wtt/token-name-path-exists? "border-radius.sm.x" {"border-radius" {:name "sm"}})))
(t/is (false? (wtt/token-name-path-exists? "other" {"border-radius" {:name "sm"}})))
(t/is (false? (wtt/token-name-path-exists? "dark.border-radius.md" {"dark" {"border-radius" {"sm" {:name "sm"}}}}))))