mirror of
https://github.com/penpot/penpot.git
synced 2026-11-10 03:50:33 +00:00
229 lines
11 KiB
Clojure
229 lines
11 KiB
Clojure
;; This Source Code Form is subject to the terms of the Mozilla Public
|
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
;;
|
|
;; Copyright (c) KALEIDOS SUBSIDIARY SL
|
|
|
|
(ns frontend-tests.tokens.token-pill-test
|
|
(:require
|
|
[app.common.test-helpers.ids-map :as thi]
|
|
[app.common.test-helpers.shapes :as ths]
|
|
[app.common.types.token :as cto]
|
|
[app.common.types.tokens-lib :as ctob]
|
|
[app.config :as cf]
|
|
[app.main.ui.workspace.tokens.management.token-pill :as wtp]
|
|
[app.util.i18n :refer [tr]]
|
|
[cljs.test :as t :include-macros true]))
|
|
|
|
(t/use-fixtures :each thi/test-fixture)
|
|
|
|
(def ^:private pill-state @#'wtp/pill-state)
|
|
(def ^:private tooltip-info @#'wtp/tooltip-info)
|
|
|
|
(def ^:private radius
|
|
(ctob/make-token :name "radius.md" :type :border-radius :value "8"))
|
|
|
|
(def ^:private spacing
|
|
(ctob/make-token :name "spacing.md" :type :spacing :value "16"))
|
|
|
|
(def ^:private width
|
|
(ctob/make-token :name "width.md" :type :dimensions :value "100"))
|
|
|
|
(def ^:private active-theme-tokens
|
|
{"radius.md" (assoc radius :resolved-value 8)
|
|
"spacing.md" (assoc spacing :resolved-value 16)
|
|
"width.md" (assoc width :resolved-value 100)})
|
|
|
|
(defn- with-token
|
|
[shape token attributes]
|
|
(cto/apply-token-to-shape {:shape shape :token token :attributes attributes}))
|
|
|
|
(defn- state
|
|
[token selected-shapes & {:keys [tokens is-selected-inside-layout]
|
|
:or {tokens active-theme-tokens}}]
|
|
(pill-state token tokens selected-shapes is-selected-inside-layout))
|
|
|
|
(defn- with-flags
|
|
[flags f]
|
|
(with-redefs [cf/flags flags]
|
|
(f)))
|
|
|
|
(def ^:private no-tokenscript-flags (disj cf/flags :tokenscript))
|
|
(def ^:private tokenscript-flags (conj cf/flags :tokenscript))
|
|
|
|
(t/deftest applied-status
|
|
(t/testing "without a selection the token counts as fully applied"
|
|
(t/is (= {:is-applied false
|
|
:is-half-applied false
|
|
:is-disabled false
|
|
:status-icon-id "token-status-full"}
|
|
(select-keys (state radius [])
|
|
[:is-applied :is-half-applied :is-disabled :status-icon-id]))))
|
|
|
|
(t/testing "applied to every attribute of every selected shape"
|
|
(let [result (state radius [(with-token (ths/sample-shape :rect1) radius cto/border-radius-keys)
|
|
(with-token (ths/sample-shape :rect2) radius cto/border-radius-keys)])]
|
|
(t/is (true? (:is-applied result)))
|
|
(t/is (false? (:is-half-applied result)))
|
|
(t/is (= "token-status-full" (:status-icon-id result)))))
|
|
|
|
(t/testing "applied to only some of the attributes"
|
|
(let [result (state radius [(with-token (ths/sample-shape :rect1) radius #{:r1})])]
|
|
(t/is (true? (:is-applied result)))
|
|
(t/is (true? (:is-half-applied result)))
|
|
(t/is (= "token-status-partial" (:status-icon-id result)))))
|
|
|
|
(t/testing "applied to only some of the selected shapes"
|
|
(let [result (state radius [(with-token (ths/sample-shape :rect1) radius cto/border-radius-keys)
|
|
(ths/sample-shape :rect2)])]
|
|
(t/is (true? (:is-half-applied result)))
|
|
(t/is (= "token-status-partial" (:status-icon-id result)))))
|
|
|
|
(t/testing "another token on the same attributes does not count"
|
|
(let [other (ctob/make-token :name "radius.lg" :type :border-radius :value "16")
|
|
result (state radius [(with-token (ths/sample-shape :rect1) other #{:r1})])]
|
|
(t/is (false? (:is-applied result)))
|
|
(t/is (= "token-status-non-applied" (:status-icon-id result)))))
|
|
|
|
(t/testing "color tokens count all their attributes, not only the fill"
|
|
(let [color (ctob/make-token :name "brand" :type :color :value "#ff0000")]
|
|
(t/is (true? (:is-half-applied
|
|
(state color [(with-token (ths/sample-shape :rect1) color #{:fill})]
|
|
:tokens {"brand" color}))))
|
|
(t/is (false? (:is-half-applied
|
|
(state color [(with-token (ths/sample-shape :rect1) color #{:fill :stroke-color})]
|
|
:tokens {"brand" color})))))))
|
|
|
|
(t/deftest disabled-status
|
|
(t/testing "a token that applies to none of the selected shapes is disabled"
|
|
(t/is (true? (:is-disabled (state radius [(ths/sample-shape :circle1 :type :circle)]))))
|
|
(t/is (true? (:is-disabled (state spacing [(ths/sample-shape :rect1)])))))
|
|
|
|
(t/testing "one shape the token applies to is enough"
|
|
(t/is (false? (:is-disabled (state radius [(ths/sample-shape :circle1 :type :circle)
|
|
(ths/sample-shape :rect1)])))))
|
|
|
|
(t/testing "spacing applies to boards with a layout"
|
|
(t/is (false? (:is-disabled (state spacing [(ths/sample-shape :board1 :type :frame :layout :flex)])))))
|
|
|
|
(t/testing "spacing applies as margin to shapes inside a layout"
|
|
(t/is (false? (:is-disabled (state spacing [(ths/sample-shape :rect1)]
|
|
:is-selected-inside-layout true)))))
|
|
|
|
(t/testing "an applied token is never disabled"
|
|
(t/is (false? (:is-disabled (state radius [(with-token (ths/sample-shape :circle1 :type :circle)
|
|
radius cto/border-radius-keys)]))))))
|
|
|
|
(t/deftest error-status
|
|
(t/testing "a valid token has no errors"
|
|
(let [result (state radius [])]
|
|
(t/is (false? (:has-errors result)))
|
|
(t/is (nil? (:error-message result)))))
|
|
|
|
(t/testing "a reference to a token outside the active sets"
|
|
(with-flags no-tokenscript-flags
|
|
#(let [token (ctob/make-token :name "radius.ref" :type :border-radius :value "{radius.missing}")
|
|
result (state token [])]
|
|
(t/is (true? (:has-missing-reference result)))
|
|
(t/is (false? (:has-invalid-value result)))
|
|
(t/is (true? (:has-errors result)))
|
|
(t/is (nil? (:error-message result)))))
|
|
|
|
(with-flags no-tokenscript-flags
|
|
#(let [token (ctob/make-token :name "radius.ref" :type :border-radius :value "{radius.md}")]
|
|
(t/is (false? (:has-errors (state token []))))))
|
|
|
|
(with-flags tokenscript-flags
|
|
#(let [error {:error/code :error.style-dictionary/missing-reference
|
|
:message "Missing reference"}
|
|
token (ctob/make-token :name "radius.ref" :type :border-radius :value "{radius.missing}")
|
|
result (state token [] :tokens {"radius.ref" (assoc token :errors [error])})]
|
|
(t/is (true? (:has-missing-reference result)))
|
|
(t/is (true? (:has-invalid-value result)))
|
|
(t/is (= "Missing reference" (:error-message result))))))
|
|
|
|
(t/testing "an invalid value only shows its own message with tokenscript"
|
|
(let [error {:error/code :error.style-dictionary/invalid-token-value
|
|
:message "Invalid value"}
|
|
tokens {"radius.md" (assoc radius :errors [error])}]
|
|
(with-flags no-tokenscript-flags
|
|
#(let [result (state radius [] :tokens tokens)]
|
|
(t/is (true? (:has-invalid-value result)))
|
|
(t/is (true? (:has-errors result)))
|
|
(t/is (nil? (:error-message result)))))
|
|
(with-flags tokenscript-flags
|
|
#(t/is (= "Invalid value" (:error-message (state radius [] :tokens tokens)))))))
|
|
|
|
(t/testing "a name collision shows its message"
|
|
(with-flags no-tokenscript-flags
|
|
#(let [error {:error/code :error.token/name-collision
|
|
:error/value "radius.md"
|
|
:error/fn (fn [value] (str "Collides: " value))}
|
|
result (state radius [] :tokens {"radius.md" (assoc radius :errors [error])})]
|
|
(t/is (true? (:has-errors result)))
|
|
(t/is (= "Collides: radius.md" (:error-message result)))))))
|
|
|
|
(defn- tooltip
|
|
[token shapes & {:keys [tokens is-viewer] :or {tokens active-theme-tokens}}]
|
|
(tooltip-info token (get tokens (:name token)) (first shapes)
|
|
(pill-state token tokens shapes false)
|
|
is-viewer))
|
|
|
|
(t/deftest tooltip-messages
|
|
(t/testing "errors replace the token details"
|
|
(with-flags no-tokenscript-flags
|
|
#(let [token (ctob/make-token :name "radius.ref" :type :border-radius :value "{radius.missing}")]
|
|
(t/is (= {:message (tr "workspace.tokens.ref-not-valid" "radius.ref")}
|
|
(tooltip token [])))))
|
|
|
|
(with-flags no-tokenscript-flags
|
|
#(let [error {:error/code :error.style-dictionary/invalid-token-value}]
|
|
(t/is (= {:message (tr "workspace.tokens.value-not-valid")}
|
|
(tooltip radius [] :tokens {"radius.md" (assoc radius :errors [error])}))))))
|
|
|
|
(t/testing "a resolved error message replaces the generic one"
|
|
(let [error {:error/code :error.token/name-collision
|
|
:error/value "radius.md"
|
|
:error/fn (fn [value] (str "Collides: " value))}
|
|
tokens {"radius.md" (assoc radius :errors [error])}]
|
|
(t/is (= {:message "Collides: radius.md"}
|
|
(tooltip radius [] :tokens tokens)))))
|
|
|
|
(t/testing "a valid token shows its value and resolved value"
|
|
(t/is (= {:name "radius.md"
|
|
:value "8"
|
|
:resolved-value "8"
|
|
:has-more-options false
|
|
:applied-to nil}
|
|
(tooltip radius []))))
|
|
|
|
(t/testing "the resolved value comes from the active themes"
|
|
(let [token (ctob/make-token :name "radius.ref" :type :border-radius :value "{radius.md}")]
|
|
(t/is (= "8" (:resolved-value
|
|
(tooltip token [] :tokens (assoc active-theme-tokens
|
|
"radius.ref" (assoc token :resolved-value 8)))))))))
|
|
|
|
(t/deftest tooltip-applied-to
|
|
(t/testing "editors don't see where the token is applied"
|
|
(t/is (nil? (:applied-to (tooltip radius [(with-token (ths/sample-shape :rect1) radius cto/border-radius-keys)])))))
|
|
|
|
(t/testing "viewers see the attributes of the first selected shape"
|
|
(t/is (= (str "- Border Radius: " (tr "labels.all"))
|
|
(:applied-to (tooltip radius [(with-token (ths/sample-shape :rect1) radius cto/border-radius-keys)]
|
|
:is-viewer true))))
|
|
|
|
(t/is (= "- Border Radius: Top Left"
|
|
(:applied-to (tooltip radius [(with-token (ths/sample-shape :rect1) radius #{:r1})]
|
|
:is-viewer true)))))
|
|
|
|
(t/testing "dimension tokens list their attributes by category"
|
|
(t/is (= "- Sizing: Width."
|
|
(:applied-to (tooltip width [(with-token (ths/sample-shape :rect1) width #{:width})]
|
|
:is-viewer true)))))
|
|
|
|
(t/testing "nothing is listed when the token isn't applied to the first shape"
|
|
(t/is (nil? (:applied-to (tooltip radius [(ths/sample-shape :rect1)
|
|
(with-token (ths/sample-shape :rect2)
|
|
radius cto/border-radius-keys)]
|
|
:is-viewer true))))))
|