mirror of
https://github.com/penpot/penpot.git
synced 2026-11-13 21:40:33 +00:00
The language profile and Japanese layout selects labelled mixed values with "labels.mixed-values", a key that no longer exists, so they showed the raw key. Use "settings.multiple", as the other text options do. The "No language profile" choice had a blank id, which the select shows as "--". Give it the "plain" id and map it back to no language. AI-assisted-by: claude-opus-5-5
532 lines
27 KiB
Clojure
532 lines
27 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 INC Sucursal en España SL
|
|
|
|
(ns frontend-tests.ui.text-options-test
|
|
(:require
|
|
["react-dom/server" :as rds]
|
|
[app.common.types.text.cjk-layout :as cjk]
|
|
[app.main.data.workspace.texts :as dwt]
|
|
[app.main.ui.ds.controls.select :as select]
|
|
[app.main.ui.hooks :as hooks]
|
|
[app.main.ui.shapes.text.html-text :as html-text]
|
|
[app.main.ui.shapes.text.styles :as text-styles]
|
|
[app.main.ui.workspace.sidebar.options.common :refer [radio-selected]]
|
|
[app.main.ui.workspace.sidebar.options.menus.text :as text-menu]
|
|
[app.main.ui.workspace.sidebar.options.menus.text-japanese-layout :as tjl]
|
|
[app.main.ui.workspace.sidebar.options.menus.text-language-layout :as tll]
|
|
[app.util.text.layout :as tl]
|
|
[app.util.text.writing-mode :as wm]
|
|
[cljs.test :as t :include-macros true]
|
|
[cuerdas.core :as str]
|
|
[rumext.v2 :as mf]))
|
|
|
|
(def ^:private japanese-span-attrs
|
|
[:text-combine-upright
|
|
:text-emphasis
|
|
:ruby
|
|
:ruby-hidden
|
|
:ruby-size
|
|
:ruby-align
|
|
:ruby-overhang
|
|
:ruby-side
|
|
:warichu
|
|
:font-features
|
|
:annotation-clearance])
|
|
|
|
|
|
(t/deftest layout-controls-follow-file-or-profile-configuration
|
|
(with-redefs [wm/vertical-layout-active? (constantly true)]
|
|
(t/is (false? (tl/controls-enabled? {})))
|
|
(t/is (false? (tl/controls-enabled? {:feature-enabled true :file? false :all-files? false})))
|
|
(t/is (true? (tl/controls-enabled? {:feature-enabled true :file? true :all-files? false})))
|
|
(t/is (true? (tl/controls-enabled? {:feature-enabled true :file? false :all-files? true}))))
|
|
(with-redefs [wm/vertical-layout-active? (constantly false)]
|
|
(t/is (false? (tl/controls-enabled? {:feature-enabled true :file? true :all-files? true})))))
|
|
|
|
(t/deftest language-controls-and-menu-actions-respect-independent-preferences
|
|
(with-redefs [wm/vertical-layout-active? (constantly true)]
|
|
(doseq [file? [true false] all-files? [true false]]
|
|
(let [config {:feature-enabled true :file? file? :all-files? all-files?}]
|
|
(t/is (= (or file? all-files?) (tl/controls-enabled? config)))
|
|
(t/is (= (not all-files?) (tl/file-action-visible? config true false)))
|
|
(t/is (false? (tl/file-action-visible? config false false)))
|
|
(t/is (false? (tl/file-action-visible? config true true)))
|
|
(t/is (false? (tl/controls-enabled? (assoc config :feature-enabled false)))))))
|
|
(with-redefs [wm/vertical-layout-active? (constantly false)]
|
|
(t/is (false? (tl/controls-enabled? {:feature-enabled true :file? true})))
|
|
(t/is (false? (tl/file-action-visible? {:feature-enabled true :file? true} true false)))))
|
|
|
|
(t/deftest choosing-a-profile-only-changes-the-paragraph-language
|
|
(t/is (= {:text-language "ko"} (tll/profile-change "ko")))
|
|
(t/is (= {:text-language nil} (tll/profile-change tll/plain-profile)))
|
|
(t/is (tl/profile-matches? :japanese "ja-JP"))
|
|
(t/is (tl/profile-matches? :chinese "zh-Hant-TW"))
|
|
(t/is (tl/profile-matches? :korean "KO-kr"))
|
|
(t/is (not (tl/profile-matches? :chinese "ja")))
|
|
(t/is (not (tl/profile-matches? :korean :multiple)))
|
|
(t/is (not (tl/profile-matches? :japanese nil))))
|
|
|
|
(t/deftest profile-choices-keep-mixed-and-other-language-values-visible
|
|
(let [mixed (last (tll/profile-options :korean :multiple identity))
|
|
other (last (tll/profile-options :chinese "ja" identity))]
|
|
(t/is (= {:id "multiple" :label "settings.multiple" :disabled true :dimmed true} mixed))
|
|
(t/is (= {:id "ja" :label "ja" :disabled true :dimmed true} other))
|
|
(t/is (= ["plain" "zh-Hans" "zh-Hant" "zh-Hans-CN" "zh-Hant-CN" "zh-Hant-TW" "zh-Hant-HK"]
|
|
(mapv :id (tll/profile-options :chinese nil identity))))
|
|
;; The DS select shows "--" for a blank id, so the plain choice needs one.
|
|
(t/is (not-any? (comp str/blank? :id) (tll/profile-options :korean nil identity)))
|
|
(t/is (= "plain" (tll/selected-profile nil)))
|
|
(t/is (= "multiple" (tll/selected-profile :multiple)))
|
|
(t/is (= "ko" (tll/selected-profile "ko")))))
|
|
|
|
(t/deftest korean-word-wrapping-is-distinct-from-the-saved-experiment
|
|
(t/is (= ["syllable" "keep-words"]
|
|
(mapv :id (tll/korean-wrap-options nil identity))))
|
|
(t/is (= ["syllable" "keep-words" "spaces-only"]
|
|
(mapv :id (tll/korean-wrap-options "spaces-only" identity))))
|
|
(t/is (= "workspace.options.text-options.profile-chinese-taiwan"
|
|
(:label (select/get-option (tll/profile-options :chinese "zh-Hant-TW" identity) "zh-Hant-TW"))))
|
|
(t/is (= {:text-language "zh-Hant-CN"} (tll/profile-change "zh-Hant-CN"))))
|
|
|
|
(t/deftest language-specific-controls-require-an-explicit-matching-profile
|
|
(with-redefs [hooks/use-portal-container (fn ([] nil) ([_] nil))]
|
|
(doseq [[language attr label] [[:japanese "ja" "workspace.options.text-options.line-adjustment"]
|
|
[:korean "ko" "workspace.options.text-options.korean-wrap"]]
|
|
profile [nil :multiple "zh-Hans" attr]]
|
|
(let [changes (atom [])
|
|
markup (rds/renderToStaticMarkup
|
|
(mf/element tll/language-layout-options*
|
|
#js {:language language
|
|
:values {:text-language profile}
|
|
:on-change #(swap! changes conj %)}))]
|
|
(t/is (= (= profile attr) (str/includes? markup label)))
|
|
(t/is (str/includes? markup "horizontal-tb-writing-mode"))
|
|
(t/is (empty? @changes) "Showing controls must not assign a profile")))))
|
|
|
|
|
|
(t/deftest chinese-decoration-controls-require-a-matching-profile
|
|
(with-redefs [hooks/use-portal-container (fn ([] nil) ([_] nil))]
|
|
(doseq [profile [nil :multiple "ja" "ko" "zh-Hans-CN" "zh-Hant-TW"]]
|
|
(let [changes (atom [])
|
|
markup (rds/renderToStaticMarkup
|
|
(mf/element tll/language-layout-options*
|
|
(mf/props {:language :chinese
|
|
:values {:text-language profile}
|
|
:on-change #(swap! changes conj %)})))]
|
|
(doseq [label ["workspace.options.text-options.text-emphasis"
|
|
"workspace.options.text-options.emphasis-position"
|
|
"workspace.options.text-options.underline-position"]]
|
|
(t/is (= (tl/profile-matches? :chinese profile) (str/includes? markup label))))
|
|
(t/is (empty? @changes))))))
|
|
|
|
(t/deftest pinyin-reading-editor-requires-a-chinese-profile-and-text-selection
|
|
(with-redefs [hooks/use-portal-container (fn ([] nil) ([_] nil))]
|
|
(doseq [profile [nil :multiple "ja" "ko" "zh-Hans" "zh-Hant-TW"]
|
|
selected [false true]]
|
|
(let [changes (atom [])
|
|
markup (rds/renderToStaticMarkup
|
|
(mf/element tll/language-layout-options*
|
|
(mf/props {:language :chinese
|
|
:values {:text-language profile :ruby "nǐ hǎo"}
|
|
:ruby-values {:ruby-hidden true}
|
|
:text-selection-active selected
|
|
:reading-selection-active selected
|
|
:on-change #(swap! changes conj %)
|
|
:on-ruby-presentation-change #(swap! changes conj %)})))
|
|
chinese (tl/profile-matches? :chinese profile)]
|
|
(t/is (= (and chinese selected)
|
|
(str/includes? markup "workspace.options.text-options.pinyin-placeholder")))
|
|
(t/is (= chinese
|
|
(str/includes? markup "workspace.options.text-options.pinyin-advanced-options")))
|
|
(t/is (not (str/includes? markup "workspace.options.text-options.ruby-placeholder")))
|
|
(t/is (empty? @changes) "Showing Pinyin controls must not edit text")))))
|
|
|
|
(t/deftest pinyin-reading-editor-rejects-a-selection-across-text-styles
|
|
(with-redefs [hooks/use-portal-container (fn ([] nil) ([_] nil))]
|
|
(let [markup (rds/renderToStaticMarkup
|
|
(mf/element tll/language-layout-options*
|
|
(mf/props {:language :chinese
|
|
:values {:text-language "zh-Hans"}
|
|
:text-selection-active true
|
|
:reading-selection-active false
|
|
:on-change identity})))]
|
|
(t/is (str/includes? markup "workspace.options.text-options.pinyin-selection-hint"))
|
|
(t/is (not (str/includes? markup "workspace.options.text-options.pinyin-placeholder"))))))
|
|
|
|
(t/deftest pinyin-presentation-offers-guidance-without-a-text-selection
|
|
(with-redefs [hooks/use-portal-container (fn ([] nil) ([_] nil))]
|
|
(let [markup (rds/renderToStaticMarkup
|
|
(mf/element tll/language-layout-options*
|
|
(mf/props {:language :chinese
|
|
:values {:text-language "zh-Hant-HK"}
|
|
:ruby-values {}
|
|
:text-selection-active false
|
|
:on-change identity
|
|
:on-ruby-presentation-change identity})))]
|
|
(t/is (str/includes? markup "workspace.options.text-options.pinyin-selection-hint"))
|
|
(t/is (str/includes? markup "ruby-presentation-options-toggle"))
|
|
(t/is (not (str/includes? markup "ruby-advanced-options-toggle"))))))
|
|
|
|
(t/deftest shared-writing-mode-controls-have-independent-radio-groups
|
|
(with-redefs [hooks/use-portal-container (fn ([] nil) ([_] nil))]
|
|
(let [markup (rds/renderToStaticMarkup
|
|
(mf/html
|
|
[:div
|
|
[:> tll/language-layout-options* {:language :japanese :values {} :on-change identity}]
|
|
[:> tll/language-layout-options* {:language :chinese :values {} :on-change identity}]
|
|
[:> tll/language-layout-options* {:language :korean :values {} :on-change identity}]]))
|
|
inputs (re-seq #"<input[^>]+>" markup)
|
|
ids (map #(second (re-find #"id=\"([^\"]+)\"" %)) inputs)
|
|
names (map #(second (re-find #"name=\"([^\"]+)\"" %)) inputs)]
|
|
(t/is (= 6 (count (set ids))))
|
|
(t/is (= 3 (count (set names))))
|
|
(t/is (= 3 (count (filter #(str/includes? % "checked=\"\"") inputs)))))))
|
|
|
|
(t/deftest text-emphasis-select-reports-and-restores-canonical-values
|
|
(let [options (tjl/text-emphasis-options identity)
|
|
reported-id (:id (select/get-option options "filled-dot"))]
|
|
(t/is (= "filled-dot" reported-id))
|
|
(t/is (= "filled-dot"
|
|
(:id (select/get-option options reported-id))))))
|
|
|
|
(t/deftest annotation-clearance-select-reports-canonical-values
|
|
(let [options (tjl/annotation-clearance-options identity)]
|
|
(t/is (= ["none" "auto"] (mapv :id options)))
|
|
(t/is (= "auto" (:id (select/get-option options "auto"))))))
|
|
|
|
(t/deftest unrestricted-tcy-is-only-offered-for-a-text-selection
|
|
(t/is (= ["none" "digits"]
|
|
(mapv :value (tjl/text-combine-upright-options false identity))))
|
|
(t/is (= ["none" "all" "digits"]
|
|
(mapv :value (tjl/text-combine-upright-options true identity)))))
|
|
|
|
(t/deftest ruby-container-styles-preserve-customization
|
|
(let [style (text-styles/generate-ruby-container-styles
|
|
{:ruby-align "space-between"
|
|
:ruby-overhang "none"
|
|
:ruby-side "under"})]
|
|
(t/is (= "space-between" (.-rubyAlign style)))
|
|
(t/is (= "none" (.-rubyOverhang style)))
|
|
(t/is (= "under" (.-rubyPosition style)))))
|
|
|
|
(t/deftest advanced-furigana-options-are-collapsed-by-default
|
|
(let [markup (rds/renderToStaticMarkup
|
|
(mf/element tjl/ruby-presentation-options*
|
|
#js {:values {}
|
|
:on-change identity
|
|
:on-blur identity}))]
|
|
(t/is (str/includes? markup "data-testid=\"ruby-presentation-options-toggle\""))
|
|
(t/is (str/includes? markup "aria-expanded=\"false\""))
|
|
(t/is (str/includes? markup "workspace.options.text-options.ruby-advanced-options"))))
|
|
|
|
(t/deftest advanced-furigana-options-include-hide-toggle
|
|
(let [markup (rds/renderToStaticMarkup
|
|
(mf/element tjl/ruby-hidden-option*
|
|
#js {:values {:ruby-hidden true}
|
|
:on-change identity
|
|
:on-blur identity}))]
|
|
(t/is (str/includes? markup "workspace.options.text-options.ruby-hidden"))
|
|
(t/is (str/includes? markup "role=\"switch\""))
|
|
(t/is (str/includes? markup "aria-checked=\"true\""))))
|
|
|
|
(t/deftest hidden-furigana-renders-base-text-without-ruby-layout
|
|
(let [markup (rds/renderToStaticMarkup
|
|
(mf/element html-text/render-text*
|
|
#js {:node {:text "日"
|
|
:ruby "にち"
|
|
:ruby-hidden true}
|
|
:parent {}
|
|
:shape {}}))]
|
|
(t/is (str/includes? markup ">日</span>"))
|
|
(t/is (not (str/includes? markup "<ruby")))))
|
|
|
|
(t/deftest shape-level-furigana-presentation-only-updates-ruby-spans
|
|
(let [shape {:content
|
|
{:type "root"
|
|
:children
|
|
[{:type "paragraph-set"
|
|
:children
|
|
[{:type "paragraph"
|
|
:children
|
|
[{:text "日"
|
|
:ruby "にち"
|
|
:ruby-hidden false
|
|
:ruby-size "half"}
|
|
{:text "本"
|
|
:ruby ""
|
|
:ruby-hidden false
|
|
:ruby-size "quarter"}]}]}]}}
|
|
values (dwt/current-ruby-values {:shape shape
|
|
:attrs cjk/ruby-presentation-attrs})
|
|
updated (dwt/update-ruby-presentation-attrs
|
|
shape {:ruby-hidden true :ruby-size "third"})
|
|
spans (get-in updated [:content :children 0 :children 0 :children])]
|
|
(t/is (= "half" (:ruby-size values)))
|
|
(t/is (false? (:ruby-hidden values)))
|
|
(t/is (= "third" (:ruby-size (first spans))))
|
|
(t/is (true? (:ruby-hidden (first spans))))
|
|
(t/is (= "quarter" (:ruby-size (second spans))))
|
|
(t/is (false? (:ruby-hidden (second spans))))))
|
|
|
|
(t/deftest mixed-span-values-select-a-disabled-mixed-option
|
|
(let [options (tjl/with-mixed-span-option (tjl/text-emphasis-options identity) :multiple)]
|
|
(t/is (= "mixed" (tjl/span-select-value :multiple "none")))
|
|
(t/is (= "none" (tjl/span-select-value nil "none")))
|
|
(t/is (= "mixed" (:id (last options))))
|
|
(t/is (true? (:disabled (last options))))
|
|
(t/is (= options (tjl/with-mixed-span-option options "none"))
|
|
"an unmixed value adds no entry")))
|
|
|
|
(t/deftest mixed-radio-values-select-nothing
|
|
(t/is (= "" (radio-selected :multiple "none")))
|
|
(t/is (= "none" (radio-selected nil "none")))
|
|
(t/is (= "vertical-rl" (radio-selected :vertical-rl))))
|
|
|
|
(t/deftest whole-text-selection-reports-every-differing-span-value-as-mixed
|
|
(let [shape {:content
|
|
{:type "root"
|
|
:children
|
|
[{:type "paragraph-set"
|
|
:children
|
|
[{:type "paragraph"
|
|
:children
|
|
[{:text "日"
|
|
:text-combine-upright "digits2"
|
|
:text-emphasis "filled-dot"
|
|
:ruby "にち"
|
|
:ruby-hidden true
|
|
:ruby-size "third"
|
|
:ruby-align "center"
|
|
:ruby-overhang "none"
|
|
:ruby-side "under"
|
|
:warichu "warichu"
|
|
:font-features "palt"
|
|
:annotation-clearance "auto"}
|
|
{:text "本"
|
|
:text-combine-upright "none"
|
|
:text-emphasis "none"
|
|
:ruby ""
|
|
:ruby-hidden false
|
|
:ruby-size "half"
|
|
:ruby-align "space-around"
|
|
:ruby-overhang "auto"
|
|
:ruby-side "over"
|
|
:warichu "none"
|
|
:font-features "none"
|
|
:annotation-clearance "none"}]}]}]}}
|
|
values (dwt/current-text-values {:shape shape
|
|
:attrs japanese-span-attrs})]
|
|
(t/is (= (zipmap japanese-span-attrs (repeat :multiple)) values))))
|
|
|
|
(t/deftest wasm-editor-span-styles-preserve-persisted-vertical-paragraph-values
|
|
(let [shape {:content
|
|
{:type "root"
|
|
:children
|
|
[{:type "paragraph-set"
|
|
:children
|
|
[{:type "paragraph"
|
|
:writing-mode "vertical-rl"
|
|
:text-orientation "upright"
|
|
:children [{:text "12" :text-combine-upright "none"}]}]}]}}
|
|
editor-styles {:text-combine-upright "digits2"}
|
|
paragraph-values (dwt/current-paragraph-values
|
|
{:editor-styles editor-styles
|
|
:shape shape
|
|
:attrs [:writing-mode :text-orientation]})
|
|
text-values (dwt/current-text-values
|
|
{:editor-styles editor-styles
|
|
:shape shape
|
|
:attrs [:text-combine-upright]})]
|
|
(t/is (= "vertical-rl" (:writing-mode paragraph-values)))
|
|
(t/is (= "upright" (:text-orientation paragraph-values)))
|
|
(t/is (= "digits2" (:text-combine-upright text-values)))))
|
|
|
|
(t/deftest japanese-controls-distinguish-horizontal-and-vertical-modes
|
|
(t/is (false? (tjl/vertical-japanese-layout? {})))
|
|
(t/is (false? (tjl/vertical-japanese-layout?
|
|
{:writing-mode "horizontal-tb"})))
|
|
(t/is (true? (tjl/vertical-japanese-layout?
|
|
{:writing-mode "vertical-rl"})))
|
|
(t/is (= "palt"
|
|
(tjl/proportional-metrics-feature "horizontal-tb")))
|
|
(t/is (= "palt"
|
|
(tjl/proportional-metrics-feature nil)))
|
|
(t/is (= "vpal"
|
|
(tjl/proportional-metrics-feature "vertical-rl"))))
|
|
|
|
(t/deftest sidebar-options-offer-the-japanese-enum-values
|
|
(let [ids #(mapv :id %)
|
|
values #(mapv :value %)]
|
|
(t/is (= (:writing-mode cjk/enum-values) (values (tjl/writing-mode-options identity))))
|
|
(t/is (= (:text-orientation cjk/enum-values) (values (tjl/text-orientation-options identity))))
|
|
(t/is (= (:warichu cjk/enum-values) (values (tjl/warichu-options identity))))
|
|
(t/is (= (:text-emphasis cjk/enum-values) (ids (tjl/text-emphasis-options identity))))
|
|
(t/is (= (:annotation-clearance cjk/enum-values) (ids (tjl/annotation-clearance-options identity))))
|
|
(t/is (= (:ruby-size cjk/enum-values) (ids (tjl/ruby-size-options identity))))
|
|
(t/is (= (:ruby-align cjk/enum-values) (ids (tjl/ruby-align-options identity))))
|
|
(t/is (= (:ruby-overhang cjk/enum-values) (ids (tjl/ruby-overhang-options identity))))
|
|
(t/is (= (:ruby-side cjk/enum-values) (ids (tjl/ruby-side-options identity))))
|
|
(t/is (= (:line-adjustment cjk/enum-values) (ids (tjl/line-adjustment-options identity))))
|
|
(t/is (every? #(cjk/valid-enum-value? :text-combine-upright %)
|
|
(values (tjl/text-combine-upright-options true identity))))
|
|
(t/is (every? cjk/digit-combine? (ids (tjl/text-combine-upright-count-options identity))))))
|
|
|
|
(t/deftest html-text-drops-vertical-writing-under-a-horizontal-renderer
|
|
(let [shape {:id (random-uuid) :width 100 :height 100
|
|
:content {:type "root"
|
|
:children
|
|
[{:type "paragraph-set"
|
|
:children
|
|
[{:type "paragraph"
|
|
:writing-mode "vertical-rl"
|
|
:text-orientation "upright"
|
|
:children [{:text "縦"}]}]}]}}
|
|
markup #(rds/renderToStaticMarkup (mf/element html-text/text-shape* #js {:shape shape}))]
|
|
(with-redefs [wm/vertical-layout-active? (constantly false)]
|
|
(t/is (not (str/includes? (markup) "vertical-rl"))))
|
|
(with-redefs [wm/vertical-layout-active? (constantly true)]
|
|
(t/is (str/includes? (markup) "writing-mode:vertical-rl")))))
|
|
|
|
(defn- alignment-markup
|
|
([component writing-mode wasm-enabled]
|
|
(alignment-markup component writing-mode wasm-enabled {}))
|
|
([component writing-mode wasm-enabled values]
|
|
;; Server rendering has no DOM container for tooltip portals.
|
|
(with-redefs [wm/vertical-layout-active? (constantly wasm-enabled)
|
|
hooks/use-portal-container (fn ([] nil) ([_] nil))]
|
|
(rds/renderToStaticMarkup
|
|
(mf/element component #js {:values (assoc values :writing-mode writing-mode)
|
|
:on-change identity})))))
|
|
|
|
(defn- alignment-labels
|
|
[markup]
|
|
(mapv second (re-seq #"aria-label=\"([^\"]+)\"" markup)))
|
|
|
|
(defn- alignment-icons
|
|
[markup]
|
|
(mapv second (re-seq #"href=\"#icon-([^\"]+)\"" markup)))
|
|
|
|
(t/deftest vertical-paragraph-alignment-shows-top-middle-bottom-and-vertical-justify
|
|
(let [markup (alignment-markup text-menu/text-align-options* "vertical-rl" true)]
|
|
(t/is (= ["text-align-top" "text-align-middle" "text-align-bottom" "text-justify-vertical"]
|
|
(alignment-icons markup)))
|
|
(t/is (= ["workspace.options.text-options.align-top"
|
|
"workspace.options.text-options.align-middle"
|
|
"workspace.options.text-options.align-bottom"
|
|
"workspace.options.text-options.text-align-justify"]
|
|
(alignment-labels markup)))
|
|
(t/is (= ["left" "center" "right" "justify"]
|
|
(mapv second (re-seq #"value=\"([^\"]+)\"" markup))))))
|
|
|
|
(t/deftest distributed-alignment-is-a-switch-of-the-language-layout
|
|
(let [markup #(alignment-markup tll/distribute-option* "horizontal-tb" true {:text-align %})
|
|
checked #(second (re-find #"aria-checked=\"([^\"]+)\"" %))]
|
|
(t/is (= ["workspace.options.text-options.text-align-distribute"]
|
|
(alignment-labels (markup "left"))))
|
|
(t/is (= "true" (checked (markup "distribute"))))
|
|
(t/is (= "false" (checked (markup "left"))))
|
|
(t/is (= "false" (checked (markup :multiple))))))
|
|
|
|
(t/deftest vertical-column-block-alignment-shows-right-center-and-left
|
|
(let [markup (alignment-markup text-menu/vertical-align* "vertical-rl" true)]
|
|
(t/is (= ["text-right" "text-horizontal-center" "text-left"]
|
|
(alignment-icons markup)))
|
|
(t/is (= ["workspace.options.text-options.text-align-right"
|
|
"workspace.options.text-options.text-align-center"
|
|
"workspace.options.text-options.text-align-left"]
|
|
(alignment-labels markup)))
|
|
(t/is (= ["top" "center" "bottom"]
|
|
(mapv second (re-seq #"value=\"([^\"]+)\"" markup))))))
|
|
|
|
(t/deftest horizontal-and-mixed-writing-modes-use-horizontal-alignment-controls
|
|
(doseq [writing-mode [nil "horizontal-tb" :multiple]]
|
|
(let [paragraph (alignment-markup text-menu/text-align-options* writing-mode true)
|
|
block (alignment-markup text-menu/vertical-align* writing-mode true)]
|
|
(t/is (= ["text-align-left" "text-align-center" "text-align-right" "text-justify"]
|
|
(alignment-icons paragraph)))
|
|
(t/is (= ["text-top" "text-middle" "text-bottom"] (alignment-icons block))))))
|
|
|
|
(t/deftest svg-renderer-keeps-horizontal-alignment-for-stored-vertical-text
|
|
(let [paragraph (alignment-markup text-menu/text-align-options* "vertical-rl" false)
|
|
block (alignment-markup text-menu/vertical-align* "vertical-rl" false)]
|
|
(t/is (= ["text-align-left" "text-align-center" "text-align-right" "text-justify"]
|
|
(alignment-icons paragraph)))
|
|
(t/is (= ["text-top" "text-middle" "text-bottom"] (alignment-icons block)))
|
|
(t/is (= "workspace.options.text-options.text-align-left" (first (alignment-labels paragraph))))
|
|
(t/is (= "workspace.options.text-options.align-top" (first (alignment-labels block))))))
|
|
|
|
|
|
(t/deftest vertical-text-growth-controls-show-the-physical-growth-direction
|
|
(let [markup (alignment-markup text-menu/grow-options* "vertical-rl" true)]
|
|
(t/is (= ["text-fixed" "text-auto-width-vertical" "text-auto-height-vertical"]
|
|
(alignment-icons markup)))
|
|
(t/is (= ["workspace.options.text-options.grow-fixed"
|
|
"workspace.options.text-options.grow-auto-height"
|
|
"workspace.options.text-options.grow-auto-width"]
|
|
(alignment-labels markup)))
|
|
(t/is (= ["fixed" "auto-width" "auto-height"]
|
|
(mapv second (re-seq #"value=\"([^\"]+)\"" markup))))))
|
|
|
|
(t/deftest horizontal-and-svg-text-growth-controls-keep-horizontal-directions
|
|
(doseq [[writing-mode wasm-enabled] [[nil true]
|
|
["horizontal-tb" true]
|
|
[:multiple true]
|
|
["vertical-rl" false]]]
|
|
(let [markup (alignment-markup text-menu/grow-options* writing-mode wasm-enabled)]
|
|
(t/is (= ["text-fixed" "text-auto-width" "text-auto-height"]
|
|
(alignment-icons markup)))
|
|
(t/is (= ["workspace.options.text-options.grow-fixed"
|
|
"workspace.options.text-options.grow-auto-width"
|
|
"workspace.options.text-options.grow-auto-height"]
|
|
(alignment-labels markup))))))
|
|
|
|
|
|
(t/deftest japanese-layout-controls-include-line-adjustment
|
|
(let [markup (alignment-markup tjl/japanese-layout-options* "vertical-rl" true)]
|
|
(t/is (str/includes? markup "workspace.options.text-options.line-adjustment"))))
|
|
|
|
|
|
(t/deftest vertical-text-hides-ltr-and-rtl-controls
|
|
(t/is (empty? (alignment-markup text-menu/text-direction-options* "vertical-rl" true))))
|
|
|
|
(t/deftest horizontal-and-svg-text-show-ltr-and-rtl-controls
|
|
(doseq [[writing-mode wasm-enabled] [[nil true]
|
|
["horizontal-tb" true]
|
|
[:multiple true]
|
|
["vertical-rl" false]]]
|
|
(let [markup (alignment-markup text-menu/text-direction-options* writing-mode wasm-enabled)]
|
|
(t/is (= ["text-ltr" "text-rtl"] (alignment-icons markup))))))
|
|
|
|
(t/deftest hiding-direction-controls-preserves-the-stored-direction
|
|
(let [values {:text-direction "rtl"}
|
|
render #(alignment-markup text-menu/text-direction-options* % true values)]
|
|
(t/is (str/includes? (re-find #"<input[^>]*id=\"rtl-text-direction\"[^>]*>"
|
|
(render "horizontal-tb"))
|
|
"checked=\"\""))
|
|
(t/is (empty? (render "vertical-rl")))
|
|
(t/is (str/includes? (re-find #"<input[^>]*id=\"rtl-text-direction\"[^>]*>"
|
|
(render "horizontal-tb"))
|
|
"checked=\"\""))))
|
|
|
|
|
|
(t/deftest decoration-position-changes-refresh-the-text-options
|
|
(doseq [attr [:text-emphasis-position :text-underline-position]]
|
|
(let [before (mf/props {:values {attr "auto"}})
|
|
after (mf/props {:values {attr "under-left"}})]
|
|
(t/is (false? (@#'text-menu/check-props before after))))))
|
|
|
|
(t/deftest zhuyin-handoff-sets-symbols-upright-in-a-right-side-strip
|
|
(let [html (rds/renderToStaticMarkup
|
|
(mf/element html-text/render-text*
|
|
{:node {:text "中" :ruby "ㄋㄧˇ" :ruby-zhuyin true :font-size "40"}
|
|
:shape {} :parent {}}))]
|
|
(t/is (str/includes? html "width:1.6em"))
|
|
(t/is (str/includes? html "writing-mode:horizontal-tb"))
|
|
(t/is (str/includes? html "ㄋ"))
|
|
(t/is (str/includes? html "ㄧ"))
|
|
(t/is (str/includes? html "ˇ"))
|
|
(t/is (not (str/includes? html "<rt")))))
|