diff --git a/frontend/test/frontend_tests/runner.cljs b/frontend/test/frontend_tests/runner.cljs index 63fee9982b..70b1ef0a47 100644 --- a/frontend/test/frontend_tests/runner.cljs +++ b/frontend/test/frontend_tests/runner.cljs @@ -112,11 +112,15 @@ [frontend-tests.tokens.logic.tokens-source-test] [frontend-tests.tokens.logic.tokens-status-test] [frontend-tests.tokens.referenced-token-value-test] + [frontend-tests.tokens.shadow-form-test] [frontend-tests.tokens.style-dictionary-test] [frontend-tests.tokens.token-errors-test] + [frontend-tests.tokens.token-parsing-test] [frontend-tests.tokens.token-path-test] [frontend-tests.tokens.token-pill-test] + [frontend-tests.tokens.token-tree-test] [frontend-tests.tokens.tokenscript-test] + [frontend-tests.tokens.typography-form-test] [frontend-tests.tokens.workspace-tokens-remap-test] [frontend-tests.ui.check-updates-test] [frontend-tests.ui.color-token-position-test] @@ -285,11 +289,15 @@ 'frontend-tests.tokens.logic.token-data-test 'frontend-tests.tokens.logic.token-remapping-test 'frontend-tests.tokens.referenced-token-value-test + 'frontend-tests.tokens.shadow-form-test 'frontend-tests.tokens.style-dictionary-test 'frontend-tests.tokens.token-errors-test + 'frontend-tests.tokens.token-parsing-test 'frontend-tests.tokens.token-path-test 'frontend-tests.tokens.token-pill-test + 'frontend-tests.tokens.token-tree-test 'frontend-tests.tokens.tokenscript-test + 'frontend-tests.tokens.typography-form-test 'frontend-tests.tokens.logic.tokens-source-test 'frontend-tests.tokens.logic.tokens-status-test 'frontend-tests.tokens.workspace-tokens-remap-test diff --git a/frontend/test/frontend_tests/tokens/shadow_form_test.cljs b/frontend/test/frontend_tests/tokens/shadow_form_test.cljs new file mode 100644 index 0000000000..f940620095 --- /dev/null +++ b/frontend/test/frontend_tests/tokens/shadow_form_test.cljs @@ -0,0 +1,105 @@ +;; 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.shadow-form-test + (:require + [app.common.schema :as sm] + [app.common.schema.messages :as csm] + [app.common.types.tokens-lib :as ctob] + [app.main.data.workspace.tokens.errors :as wte] + [app.main.ui.workspace.tokens.management.forms.shadow :as wtsh] + [app.util.i18n :refer [tr]] + [cljs.test :as t :include-macros true])) + +(def ^:private make-schema @#'wtsh/make-schema) +(def ^:private form-value @#'wtsh/make-default-value) +(def ^:private check-self-reference @#'wtsh/check-shadow-token-self-reference) + +(def ^:private shadow + (assoc @#'wtsh/default-token-shadow :color "#000000")) + +(def ^:private token + (ctob/make-token :name "shadow.md" :type :shadow :value [shadow])) + +(defn- schema + [tab] + (make-schema (ctob/get-token-path token) + (ctob/tokens-tree {(:name token) token}) + tab)) + +(defn- form-data + [value] + {:name (:name token) :description "" :value value}) + +(defn- shadows + [& shadows] + (form-data {:reference nil :shadow (vec shadows)})) + +(defn- errors + [tab data] + (csm/collect-schema-errors (schema tab) [] {:data data})) + +(defn- valid? + [tab data] + (sm/validate (schema tab) data)) + +(t/deftest composite-tab + (t/testing "a complete shadow is valid" + (t/is (valid? :composite (shadows shadow)))) + + (t/testing "blur can't be negative" + (t/is (= (tr "workspace.tokens.shadow-token-blur-value-error") + (get-in (errors :composite (shadows (assoc shadow :blur "-2"))) + [:value :shadow 0 :blur :message])))) + + (t/testing "spread can be negative" + (t/is (valid? :composite (shadows (assoc shadow :spread "-2"))))) + + (t/testing "blur and spread can stay blank" + (t/is (valid? :composite (shadows (assoc shadow :blur "" :spread ""))))) + + (t/testing "every shadow needs its offsets and color" + (t/is (not (valid? :composite (shadows shadow (assoc shadow :color ""))))) + (t/is (not (valid? :composite (shadows (assoc shadow :offset-x ""))))) + (t/is (contains? (errors :composite (shadows (dissoc shadow :color))) :value)))) + +(t/deftest reference-tab + (t/testing "a reference is required" + (t/is (not (valid? :reference (form-data {:reference "" :shadow []})))) + (t/is (valid? :reference (form-data {:reference "{shadow.sm}" :shadow []})))) + + (t/testing "the token can't reference itself" + (t/is (= (tr "errors.tokens.self-reference") + (get-in (errors :reference (form-data {:reference "{shadow.md}" :shadow []})) + [:value :reference :message]))))) + +(t/deftest composite-self-reference + (t/testing "the error names the shadow and field that reference the token" + (t/is (= (assoc (wte/get-error-code :error.token/direct-self-reference) + :shadow-key :color + :shadow-index 1) + (check-self-reference + {:name "shadow.md" + :value [shadow (assoc shadow :color "{shadow.md}")]})))) + + (t/testing "references to other tokens pass" + (t/is (nil? (check-self-reference + {:name "shadow.md" + :value [(assoc shadow :color "{color.black}")]}))))) + +(t/deftest initial-form-value + (t/testing "a reference opens on the reference tab" + (t/is (= {:reference "{shadow.sm}" :shadow []} + (form-value "{shadow.sm}")))) + + (t/testing "blank or missing blur and spread show as 0" + (t/is (= {:reference nil :shadow [(assoc shadow :blur "0" :spread "0")]} + (form-value [(assoc shadow :blur "" :spread " ")]) + (form-value [(dissoc shadow :blur :spread)])))) + + (t/testing "a new token starts with one default shadow" + (t/is (= {:reference nil :shadow [@#'wtsh/default-token-shadow]} + (form-value nil))))) diff --git a/frontend/test/frontend_tests/tokens/token_parsing_test.cljs b/frontend/test/frontend_tests/tokens/token_parsing_test.cljs new file mode 100644 index 0000000000..b37e8fe663 --- /dev/null +++ b/frontend/test/frontend_tests/tokens/token_parsing_test.cljs @@ -0,0 +1,46 @@ +;; 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-parsing-test + (:require + [app.main.ui.workspace.tokens.management.forms.controls.token-parsing :as tp] + [cljs.test :as t :include-macros true])) + +(t/deftest extract-partial-token + (t/testing "an open reference at the cursor" + (t/is (= {:start 0 :end 4 :partial "col"} + (tp/extract-partial-token "{col" 4)))) + + (t/testing "the last open reference when an earlier one is closed" + (t/is (= {:start 14 :end 17 :partial "sp"} + (tp/extract-partial-token "{color.red} + {sp" 17)))) + + (t/testing "the reference ends at its closing brace after the cursor" + (t/is (= {:start 0 :end 5 :partial "co"} + (tp/extract-partial-token "{colo}" 3)))) + + (t/testing "nothing after a closed reference" + (t/is (nil? (tp/extract-partial-token "{color} " 8)))) + + (t/testing "nothing without a reference" + (t/is (nil? (tp/extract-partial-token "12" 2))) + (t/is (nil? (tp/extract-partial-token "" 0))))) + +(t/deftest token-at-cursor + (t/testing "the token name when the cursor is inside a reference" + (t/is (= "color.red" (tp/token-at-cursor "{color.red}" 3))) + (t/is (= "color.red" (tp/token-at-cursor "{color.red} + {spacing.md}" 1))) + (t/is (= "spacing.md" (tp/token-at-cursor "{color.red} + {spacing.md}" 18)))) + + (t/testing "nothing for a reference that isn't closed" + (t/is (nil? (tp/token-at-cursor "{color" 3)))) + + (t/testing "nothing for an empty reference or one with spaces" + (t/is (nil? (tp/token-at-cursor "{}" 1))) + (t/is (nil? (tp/token-at-cursor "{color red}" 3)))) + + (t/testing "nothing before the first reference" + (t/is (nil? (tp/token-at-cursor "1 + {color}" 1))))) diff --git a/frontend/test/frontend_tests/tokens/token_tree_test.cljs b/frontend/test/frontend_tests/tokens/token_tree_test.cljs new file mode 100644 index 0000000000..2fa83904a1 --- /dev/null +++ b/frontend/test/frontend_tests/tokens/token_tree_test.cljs @@ -0,0 +1,37 @@ +;; 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-tree-test + (:require + [app.common.path-names :as cpn] + [app.common.types.tokens-lib :as ctob] + [app.main.ui.workspace.tokens.management.token-tree :as wtt] + [cljs.test :as t :include-macros true])) + +(def ^:private sort-nodes @#'wtt/sort-nodes) + +(defn- tree + [& names] + (cpn/build-tree-root + (map #(ctob/make-token :name % :type :spacing :value "4") names) + ctob/token-separator)) + +(defn- sorted-names + [nodes] + (map :name (sort-nodes nodes))) + +(t/deftest sort-nodes-test + (t/testing "tokens come before groups" + (t/is (= ["zeta" "alpha" "beta"] + (sorted-names (tree "alpha.sm" "zeta" "beta.md"))))) + + (t/testing "numbers in names sort by value" + (t/is (= ["size2" "size10" "group2" "group10"] + (sorted-names (tree "size10" "group10.sm" "size2" "group2.sm"))))) + + (t/testing "a token that also has tokens below it sorts with the groups" + (t/is (= ["md" "space"] + (sorted-names (tree "space.sm" "md" "space")))))) diff --git a/frontend/test/frontend_tests/tokens/typography_form_test.cljs b/frontend/test/frontend_tests/tokens/typography_form_test.cljs new file mode 100644 index 0000000000..64cc06be21 --- /dev/null +++ b/frontend/test/frontend_tests/tokens/typography_form_test.cljs @@ -0,0 +1,99 @@ +;; 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.typography-form-test + (:require + [app.common.schema :as sm] + [app.common.schema.messages :as csm] + [app.common.types.tokens-lib :as ctob] + [app.main.data.workspace.tokens.errors :as wte] + [app.main.ui.workspace.tokens.management.forms.typography :as wtty] + [app.util.i18n :refer [tr]] + [beicon.v2.core :as rx] + [cljs.test :as t :include-macros true])) + +(def ^:private make-schema @#'wtty/make-schema) +(def ^:private form-value @#'wtty/composite-value->form-value) +(def ^:private check-self-reference @#'wtty/check-typography-token-self-reference) +(def ^:private validate-token @#'wtty/validate-typography-token) + +(def ^:private token + (ctob/make-token :name "type.body" :type :typography :value {:font-size "16"})) + +(defn- schema + [tab] + (make-schema (ctob/get-token-path token) + (ctob/tokens-tree {(:name token) token}) + tab)) + +(defn- form-data + [value] + {:name (:name token) :description "" :value value}) + +(defn- errors + [tab data] + (csm/collect-schema-errors (schema tab) [] {:data data})) + +(defn- valid? + [tab data] + (sm/validate (schema tab) data)) + +(t/deftest composite-tab + (t/testing "one field is enough" + (t/is (valid? :composite (form-data {:font-size "16"})))) + + (t/testing "at least one field must be set" + (t/is (not (valid? :composite (form-data {})))) + (t/is (not (valid? :composite (form-data {:font-size "" :font-weight ""}))))) + + (t/testing "a line height needs a font size" + (t/is (= (tr "errors.tokens.composite-line-height-needs-font-size") + (get-in (errors :composite (form-data {:line-height "1.5"})) + [:value :line-height :message]))) + (t/is (valid? :composite (form-data {:line-height "1.5" :font-size "16"}))))) + +(t/deftest reference-tab + (t/testing "a reference is required" + (t/is (not (valid? :reference (form-data {:reference ""})))) + (t/is (valid? :reference (form-data {:reference "{type.heading}"})))) + + (t/testing "the token can't reference itself" + (t/is (= (tr "errors.tokens.self-reference") + (get-in (errors :reference (form-data {:reference "{type.body}"})) + [:value :reference :message]))))) + +(t/deftest composite-self-reference + (let [self-reference (wte/get-error-code :error.token/direct-self-reference)] + (t/testing "the error names the field that references the token" + (t/is (= (assoc self-reference :typography-key :font-size) + (check-self-reference {:name "type.body" :value {:font-size "{type.body}"}})))) + + (t/testing "each font family is checked" + (t/is (= (assoc self-reference :typography-key :font-family) + (check-self-reference {:name "type.body" :value {:font-family ["Inter" "{type.body}"]}})))) + + (t/testing "references to other tokens pass" + (t/is (nil? (check-self-reference {:name "type.body" :value {:font-size "{font.size.md}"}})))))) + +(t/deftest submit-without-fields + (t/async + done + (->> (validate-token {:token-name "type.body" :token-value nil :tokens {}}) + (rx/subs! (fn [_] + (t/is false "a token without fields must be rejected, not saved") + (done)) + (fn [error] + (t/is (= {:errors [(wte/get-error-code :error.token/empty-input)]} error)) + (done)))))) + +(t/deftest initial-form-value + (t/testing "font families show as one comma separated field" + (t/is (= {:font-family "Inter, Arial" :font-size "16"} + (form-value {:font-family ["Inter" "Arial"] :font-size "16"})))) + + (t/testing "only the typography fields are kept" + (t/is (= {:line-height "1.5"} + (form-value {:line-height "1.5" :paragraph-spacing "4"})))))