diff --git a/frontend/src/app/main/data/style_dictionary.cljs b/frontend/src/app/main/data/style_dictionary.cljs index 280b431046..4045589a4f 100644 --- a/frontend/src/app/main/data/style_dictionary.cljs +++ b/frontend/src/app/main/data/style_dictionary.cljs @@ -302,36 +302,38 @@ {:errors [(wte/error-with-value :error.style-dictionary/invalid-token-value-typography value)]} :else - (let [converted (js->clj value :keywordize-keys true) - add-keyed-errors (fn [typography-map k errors] - (update typography-map :errors concat (map #(assoc % :typography-key k) errors))) - ;; Separate line-height to process in an extra step - without-line-height (dissoc converted :line-height) - valid-typography (reduce - (fn [acc [k v]] - (let [{:keys [errors value]} (parse-atomic-typography-value k v)] - (if (seq errors) - (add-keyed-errors acc k errors) - (assoc-in acc [:value k] (or value v))))) - {:value {}} - without-line-height) + (let [converted (js->clj value :keywordize-keys true)] + (if-not (map? converted) + {:errors [(wte/error-with-value :error.style-dictionary/invalid-token-value-typography value)]} + (let [add-keyed-errors (fn [typography-map k errors] + (update typography-map :errors concat (map #(assoc % :typography-key k) errors))) + ;; Separate line-height to process in an extra step + without-line-height (dissoc converted :line-height) + valid-typography (reduce + (fn [acc [k v]] + (let [{:keys [errors value]} (parse-atomic-typography-value k v)] + (if (seq errors) + (add-keyed-errors acc k errors) + (assoc-in acc [:value k] (or value v))))) + {:value {}} + without-line-height) - ;; Calculate line-height based on the resolved font-size and add it back to the map - line-height (when-let [line-height (:line-height converted)] - (-> (parse-sd-token-typography-line-height - line-height - (get-in valid-typography [:value :font-size]) - (get-in valid-typography [:errors :font-size])))) - valid-typography (cond - (:errors line-height) - (add-keyed-errors valid-typography :line-height (:errors line-height)) + ;; Calculate line-height based on the resolved font-size and add it back to the map + line-height (when-let [line-height (:line-height converted)] + (-> (parse-sd-token-typography-line-height + line-height + (get-in valid-typography [:value :font-size]) + (get-in valid-typography [:errors :font-size])))) + valid-typography (cond + (:errors line-height) + (add-keyed-errors valid-typography :line-height (:errors line-height)) - line-height - (assoc-in valid-typography [:value :line-height] line-height) + line-height + (assoc-in valid-typography [:value :line-height] line-height) - :else - valid-typography)] - valid-typography)))) + :else + valid-typography)] + valid-typography)))))) (defn collect-typography-errors [token] (group-by :typography-key (:errors token))) diff --git a/frontend/test/frontend_tests/tokens/style_dictionary_test.cljs b/frontend/test/frontend_tests/tokens/style_dictionary_test.cljs index 1dbe9d12cf..220dd1f36b 100644 --- a/frontend/test/frontend_tests/tokens/style_dictionary_test.cljs +++ b/frontend/test/frontend_tests/tokens/style_dictionary_test.cljs @@ -97,6 +97,31 @@ (-> errors first :error/code))))) (done)))))))) +;; Regression: a composite typography token whose value is a plain +;; array (e.g. ["Roboto"]) instead of a map must not crash with +;; "No protocol method IMap.-dissoc defined for type object". +;; It should return an invalid-token-value-typography error instead. +(t/deftest resolve-tokens-typography-array-value-test + (t/async + done + (t/testing "typography token with array value produces error instead of crashing" + (let [tokens (-> (ctob/make-tokens-lib) + (ctob/add-set (ctob/make-token-set :id (cthi/new-id! :core-set) + :name "core")) + (ctob/add-token (cthi/id :core-set) + (ctob/make-token {:name "typography.bad" + :value ["Roboto"] + :type :typography})) + (ctob/get-all-tokens-map))] + (-> (sd/resolve-tokens tokens) + (rx/sub! + (fn [resolved-tokens] + (t/is (contains? resolved-tokens "typography.bad")) + (t/is (nil? (get-in resolved-tokens ["typography.bad" :resolved-value]))) + (t/is (= :error.style-dictionary/invalid-token-value-typography + (get-in resolved-tokens ["typography.bad" :errors 0 :error/code]))) + (done)))))))) + (t/deftest resolve-tokens-interactive-test (t/async done