mirror of
https://github.com/penpot/penpot.git
synced 2026-11-06 01:50:39 +00:00
* 🐛 Show the size badge on paths and straight lines The badge was hidden when the shape was smaller than the badge in either side. Flat paths have a zero width or height, so they never showed it, and straight two-point paths hid it on purpose. Paths now only compare their longest side with the badge width. A straight line compares its length, and the badge runs along the line, rotated with it and kept upright. Near the bottom of the viewport the badge moves to the other side of the line. The badge now reads the size from the shape :selrect, like the measures inputs, so a rotated path shows the same values in both places. The three badge branches share a single render block. AI-assisted-by: claude-opus-5-5 * ♻️ Extract the size badge layout and add tests for it Move the badge geometry out of selection-size-badge* into the pure size-badge-layout function, so it can be tested without rendering. The component now only picks the color and draws the result. Add unit tests for rects, flat paths and straight lines: when the badge hides, where it sits, how it rotates and how it moves when it reaches the bottom of the viewport. Keep the line rotation between -90 and 90 degrees instead of returning 360 for lines drawn leftward. The e2e test still expected straight lines to hide the badge. It now checks that the badge shows and follows the line angle. AI-assisted-by: claude-opus-5-5 * ✨ Show the length of straight lines in the size badge A straight two-point path is measured by its length, not by the box around it, so its size badge now shows the length with two decimals at most instead of width x height. Other shapes and paths keep width x height. The shorter text makes the badge narrower, so it also shows on shorter lines; the rule is the same, the badge needs the line to be at least as long as the badge. Relates to #12064 AI-assisted-by: claude-opus-5-5 * 🐛 Hide the path size badge when the path is lower than it Paths other than a straight line only hid the size badge when their longest side was narrower than it, so a wide but low path, or a narrow but tall one, still showed it. Flat paths no longer need that special case, since straight lines get their own length badge. Use the same rule as any other shape: hide the badge when either the width or the height of the path is smaller than the badge. AI-assisted-by: claude-opus-5-5
416 lines
16 KiB
Clojure
416 lines
16 KiB
Clojure
(ns frontend-tests.runner
|
|
(:require
|
|
[app.common.logging :as l]
|
|
[cljs.test :as t]
|
|
[clojure.string :as str]
|
|
[clojure.tools.cli :refer [parse-opts]]
|
|
[frontend-tests.basic-shapes-test]
|
|
[frontend-tests.code-gen-style-test]
|
|
[frontend-tests.composable-tests.comp.sync-test]
|
|
[frontend-tests.copy-as-svg-test]
|
|
[frontend-tests.data.comments-filters-test]
|
|
[frontend-tests.data.dashboard-test]
|
|
[frontend-tests.data.event-test]
|
|
[frontend-tests.data.exports-assets-test]
|
|
[frontend-tests.data.nitrate-test]
|
|
[frontend-tests.data.persistence-retry-test]
|
|
[frontend-tests.data.persistence-test]
|
|
[frontend-tests.data.profile-test]
|
|
[frontend-tests.data.repo-test]
|
|
[frontend-tests.data.store-test]
|
|
[frontend-tests.data.svg-upload-test]
|
|
[frontend-tests.data.uploads-test]
|
|
[frontend-tests.data.viewer-test]
|
|
[frontend-tests.data.workspace-colors-test]
|
|
[frontend-tests.data.workspace-comments-test]
|
|
[frontend-tests.data.workspace-context-menu-test]
|
|
[frontend-tests.data.workspace-interactions-test]
|
|
[frontend-tests.data.workspace-mcp-test]
|
|
[frontend-tests.data.workspace-media-test]
|
|
[frontend-tests.data.workspace-pages-test]
|
|
[frontend-tests.data.workspace-path-edition-test]
|
|
[frontend-tests.data.workspace-reflow-test]
|
|
[frontend-tests.data.workspace-shortcuts-test]
|
|
[frontend-tests.data.workspace-texts-test]
|
|
[frontend-tests.data.workspace-thumbnails-test]
|
|
[frontend-tests.data.workspace-versions-test]
|
|
[frontend-tests.debug-logging-test]
|
|
[frontend-tests.errors-governor-test]
|
|
[frontend-tests.errors-test]
|
|
[frontend-tests.fonts-test]
|
|
[frontend-tests.helpers-shapes-test]
|
|
[frontend-tests.logic.comp-remove-swap-slots-test]
|
|
[frontend-tests.logic.components-and-tokens]
|
|
[frontend-tests.logic.copy-paste-typography-test]
|
|
[frontend-tests.logic.copying-and-duplicating-test]
|
|
[frontend-tests.logic.frame-guides-test]
|
|
[frontend-tests.logic.groups-test]
|
|
[frontend-tests.logic.nudge-selected-shapes-test]
|
|
[frontend-tests.logic.pasting-in-containers-test]
|
|
[frontend-tests.logic.path-actions-test]
|
|
[frontend-tests.logic.path-clipboard-test]
|
|
[frontend-tests.logic.path-helpers-test]
|
|
[frontend-tests.logic.path-lifecycle-test]
|
|
[frontend-tests.logic.path-tools-test]
|
|
[frontend-tests.logic.sidebar-transform-coalescing-test]
|
|
[frontend-tests.logic.update-position-test]
|
|
[frontend-tests.logic.wasm-modifiers-nil-id-test]
|
|
[frontend-tests.logic.wasm-pixel-snap-test]
|
|
[frontend-tests.main-errors-test]
|
|
[frontend-tests.main.refs-test]
|
|
[frontend-tests.plugins.comments-test]
|
|
[frontend-tests.plugins.context-shapes-test]
|
|
[frontend-tests.plugins.events-test]
|
|
[frontend-tests.plugins.file-test]
|
|
[frontend-tests.plugins.flex-test]
|
|
[frontend-tests.plugins.format-test]
|
|
[frontend-tests.plugins.grid-test]
|
|
[frontend-tests.plugins.interactions-test]
|
|
[frontend-tests.plugins.library-test]
|
|
[frontend-tests.plugins.local-storage-test]
|
|
[frontend-tests.plugins.page-active-validation-test]
|
|
[frontend-tests.plugins.page-test]
|
|
[frontend-tests.plugins.parser-test]
|
|
[frontend-tests.plugins.register-test]
|
|
[frontend-tests.plugins.shape-bugfixes-test]
|
|
[frontend-tests.plugins.text-test]
|
|
[frontend-tests.plugins.tokens-test]
|
|
[frontend-tests.plugins.user-test]
|
|
[frontend-tests.plugins.utils-test]
|
|
[frontend-tests.plugins.value-objects-test]
|
|
[frontend-tests.render-dimensions-test]
|
|
[frontend-tests.render-wasm.process-objects-test]
|
|
[frontend-tests.render-wasm.serialization-test]
|
|
[frontend-tests.render-wasm.text-editor-apply-styles-test]
|
|
[frontend-tests.render-wasm.text-editor-caret-color-test]
|
|
[frontend-tests.router-test]
|
|
[frontend-tests.svg-fills-test]
|
|
[frontend-tests.svg-filters-test]
|
|
[frontend-tests.text-editor-paste-guard-test]
|
|
[frontend-tests.tokens.context-menu-test]
|
|
[frontend-tests.tokens.copy-paste-props-test]
|
|
[frontend-tests.tokens.import-export-test]
|
|
[frontend-tests.tokens.logic.token-actions-test]
|
|
[frontend-tests.tokens.logic.token-data-test]
|
|
[frontend-tests.tokens.logic.token-remapping-test]
|
|
[frontend-tests.tokens.logic.tokens-status-test]
|
|
[frontend-tests.tokens.style-dictionary-test]
|
|
[frontend-tests.tokens.token-errors-test]
|
|
[frontend-tests.tokens.workspace-tokens-remap-test]
|
|
[frontend-tests.ui.check-updates-test]
|
|
[frontend-tests.ui.color-token-position-test]
|
|
[frontend-tests.ui.colorpicker-token-set-order-test]
|
|
[frontend-tests.ui.comment-input-ime-test]
|
|
[frontend-tests.ui.comments-clustering-test]
|
|
[frontend-tests.ui.comments-position-modifier-test]
|
|
[frontend-tests.ui.ds-controls-numeric-input-test]
|
|
[frontend-tests.ui.gradient-handlers-test]
|
|
[frontend-tests.ui.history-test]
|
|
[frontend-tests.ui.inspect-stroke-tokens-test]
|
|
[frontend-tests.ui.layout-container-multiple-test]
|
|
[frontend-tests.ui.measurements-test]
|
|
[frontend-tests.ui.measures-menu-props-test]
|
|
[frontend-tests.ui.organization-team-switch-test]
|
|
[frontend-tests.ui.routes-test]
|
|
[frontend-tests.ui.settings-password-schema-test]
|
|
[frontend-tests.ui.settings-shortcuts-test]
|
|
[frontend-tests.ui.shortcuts-labels-test]
|
|
[frontend-tests.ui.sidebar-scroll-test]
|
|
[frontend-tests.ui.stroke-menu-test]
|
|
[frontend-tests.util-clipboard-test]
|
|
[frontend-tests.util-object-test]
|
|
[frontend-tests.util-queue-test]
|
|
[frontend-tests.util-range-tree-test]
|
|
[frontend-tests.util-simple-math-test]
|
|
[frontend-tests.util-text-editor-test]
|
|
[frontend-tests.util-webapi-test]
|
|
[frontend-tests.util-zip-test]
|
|
[frontend-tests.util.dom.dnd-test]
|
|
[frontend-tests.worker-snap-test]
|
|
[goog.object :as gobj]))
|
|
|
|
(enable-console-print!)
|
|
|
|
(defmethod t/report [:cljs.test/default :begin-test-var] [m]
|
|
(let [v (:var m)]
|
|
(println (str " ▸ " (:ns (meta v)) "/" (:name (meta v))))))
|
|
|
|
(defmethod t/report [:cljs.test/default :end-run-tests] [m]
|
|
(if (cljs.test/successful? m)
|
|
(.exit js/process 0)
|
|
(.exit js/process 1)))
|
|
|
|
(def test-namespaces
|
|
['frontend-tests.basic-shapes-test
|
|
'frontend-tests.code-gen-style-test
|
|
'frontend-tests.composable-tests.comp.sync-test
|
|
'frontend-tests.copy-as-svg-test
|
|
'frontend-tests.data.comments-filters-test
|
|
'frontend-tests.data.dashboard-test
|
|
'frontend-tests.data.event-test
|
|
'frontend-tests.data.nitrate-test
|
|
'frontend-tests.data.persistence-retry-test
|
|
'frontend-tests.data.persistence-test
|
|
'frontend-tests.data.profile-test
|
|
'frontend-tests.data.repo-test
|
|
'frontend-tests.data.store-test
|
|
'frontend-tests.data.exports-assets-test
|
|
'frontend-tests.data.svg-upload-test
|
|
'frontend-tests.data.uploads-test
|
|
'frontend-tests.data.viewer-test
|
|
'frontend-tests.data.workspace-colors-test
|
|
'frontend-tests.data.workspace-comments-test
|
|
'frontend-tests.data.workspace-context-menu-test
|
|
'frontend-tests.data.workspace-interactions-test
|
|
'frontend-tests.data.workspace-mcp-test
|
|
'frontend-tests.data.workspace-media-test
|
|
'frontend-tests.data.workspace-pages-test
|
|
'frontend-tests.data.workspace-path-edition-test
|
|
'frontend-tests.data.workspace-reflow-test
|
|
'frontend-tests.data.workspace-shortcuts-test
|
|
'frontend-tests.data.workspace-texts-test
|
|
'frontend-tests.data.workspace-thumbnails-test
|
|
'frontend-tests.data.workspace-versions-test
|
|
'frontend-tests.debug-logging-test
|
|
'frontend-tests.errors-governor-test
|
|
'frontend-tests.errors-test
|
|
'frontend-tests.fonts-test
|
|
'frontend-tests.helpers-shapes-test
|
|
'frontend-tests.logic.comp-remove-swap-slots-test
|
|
'frontend-tests.logic.components-and-tokens
|
|
'frontend-tests.logic.copy-paste-typography-test
|
|
'frontend-tests.logic.copying-and-duplicating-test
|
|
'frontend-tests.logic.frame-guides-test
|
|
'frontend-tests.logic.groups-test
|
|
'frontend-tests.logic.nudge-selected-shapes-test
|
|
'frontend-tests.logic.path-actions-test
|
|
'frontend-tests.logic.path-clipboard-test
|
|
'frontend-tests.logic.path-helpers-test
|
|
'frontend-tests.logic.path-lifecycle-test
|
|
'frontend-tests.logic.path-tools-test
|
|
'frontend-tests.logic.pasting-in-containers-test
|
|
'frontend-tests.main.refs-test
|
|
'frontend-tests.main-errors-test
|
|
'frontend-tests.logic.sidebar-transform-coalescing-test
|
|
'frontend-tests.logic.update-position-test
|
|
'frontend-tests.logic.wasm-modifiers-nil-id-test
|
|
'frontend-tests.logic.wasm-pixel-snap-test
|
|
'frontend-tests.plugins.comments-test
|
|
'frontend-tests.plugins.context-shapes-test
|
|
'frontend-tests.plugins.events-test
|
|
'frontend-tests.plugins.file-test
|
|
'frontend-tests.plugins.flex-test
|
|
'frontend-tests.plugins.format-test
|
|
'frontend-tests.plugins.grid-test
|
|
'frontend-tests.plugins.interactions-test
|
|
'frontend-tests.plugins.library-test
|
|
'frontend-tests.plugins.local-storage-test
|
|
'frontend-tests.plugins.page-active-validation-test
|
|
'frontend-tests.plugins.page-test
|
|
'frontend-tests.plugins.parser-test
|
|
'frontend-tests.plugins.register-test
|
|
'frontend-tests.plugins.shape-bugfixes-test
|
|
'frontend-tests.plugins.text-test
|
|
'frontend-tests.plugins.tokens-test
|
|
'frontend-tests.plugins.user-test
|
|
'frontend-tests.plugins.utils-test
|
|
'frontend-tests.plugins.value-objects-test
|
|
'frontend-tests.render-wasm.process-objects-test
|
|
'frontend-tests.render-wasm.serialization-test
|
|
'frontend-tests.render-wasm.text-editor-apply-styles-test
|
|
'frontend-tests.render-wasm.text-editor-caret-color-test
|
|
'frontend-tests.router-test
|
|
'frontend-tests.svg-fills-test
|
|
'frontend-tests.svg-filters-test
|
|
'frontend-tests.tokens.copy-paste-props-test
|
|
'frontend-tests.tokens.context-menu-test
|
|
'frontend-tests.tokens.import-export-test
|
|
'frontend-tests.tokens.logic.token-actions-test
|
|
'frontend-tests.tokens.logic.token-data-test
|
|
'frontend-tests.tokens.logic.token-remapping-test
|
|
'frontend-tests.tokens.style-dictionary-test
|
|
'frontend-tests.tokens.token-errors-test
|
|
'frontend-tests.tokens.logic.tokens-status-test
|
|
'frontend-tests.tokens.workspace-tokens-remap-test
|
|
'frontend-tests.ui.check-updates-test
|
|
'frontend-tests.ui.color-token-position-test
|
|
'frontend-tests.ui.colorpicker-token-set-order-test
|
|
'frontend-tests.ui.comment-input-ime-test
|
|
'frontend-tests.ui.comments-clustering-test
|
|
'frontend-tests.ui.comments-position-modifier-test
|
|
'frontend-tests.ui.ds-controls-numeric-input-test
|
|
'frontend-tests.ui.gradient-handlers-test
|
|
'frontend-tests.ui.history-test
|
|
'frontend-tests.ui.inspect-stroke-tokens-test
|
|
'frontend-tests.ui.layout-container-multiple-test
|
|
'frontend-tests.ui.measurements-test
|
|
'frontend-tests.ui.measures-menu-props-test
|
|
'frontend-tests.ui.organization-team-switch-test
|
|
'frontend-tests.ui.routes-test
|
|
'frontend-tests.render-dimensions-test
|
|
'frontend-tests.text-editor-paste-guard-test
|
|
'frontend-tests.ui.settings-password-schema-test
|
|
'frontend-tests.ui.settings-shortcuts-test
|
|
'frontend-tests.ui.shortcuts-labels-test
|
|
'frontend-tests.ui.sidebar-scroll-test
|
|
'frontend-tests.ui.stroke-menu-test
|
|
'frontend-tests.util-clipboard-test
|
|
'frontend-tests.util-object-test
|
|
'frontend-tests.util-queue-test
|
|
'frontend-tests.util-range-tree-test
|
|
'frontend-tests.util-simple-math-test
|
|
'frontend-tests.util-text-editor-test
|
|
'frontend-tests.util-webapi-test
|
|
'frontend-tests.util.dom.dnd-test
|
|
'frontend-tests.util-zip-test
|
|
'frontend-tests.worker-snap-test])
|
|
|
|
(assert (every? find-ns-obj test-namespaces)
|
|
"test-namespaces contains a namespace that isn't required in runner.cljs")
|
|
|
|
;; This runner intentionally mirrors common-tests.runner. Both runners need
|
|
;; forwarded CLI args, focused namespace/var execution, fixture preservation,
|
|
;; and app log-level setup. A shared helper could own those mechanics, but we
|
|
;; keep the logic local while there are only two test targets because sharing
|
|
;; it would add cross-module test classpath coupling.
|
|
(def ^:private log-levels
|
|
#{:trace :debug :info :warn :error})
|
|
|
|
(def cli-options
|
|
[["-f" "--focus FOCUS" "Run one test namespace or one test var, e.g. frontend-tests.logic.components-and-tokens/change-token-in-main"]
|
|
["-l" "--log-level LEVEL" "Set app logger level: trace|debug|info|warn|error"
|
|
:parse-fn keyword
|
|
:validate [log-levels "must be one of trace, debug, info, warn, error"]]
|
|
["-h" "--help"]])
|
|
|
|
(defn- argv
|
|
[]
|
|
(let [args (->> (.-argv js/process)
|
|
(array-seq)
|
|
(drop 2))]
|
|
;; `pnpm run test -- --focus ...` forwards the separator to the node
|
|
;; process, so drop one leading `--` before handing args to tools.cli.
|
|
(cond-> args
|
|
(= "--" (first args)) rest)))
|
|
|
|
(defn- usage
|
|
[summary]
|
|
(str "Usage: pnpm run test -- [options]\n\n"
|
|
"Options:\n"
|
|
summary "\n\n"
|
|
"Focus examples:\n"
|
|
" pnpm run test -- --focus frontend-tests.logic.components-and-tokens\n"
|
|
" pnpm run test -- --focus frontend-tests.logic.components-and-tokens/change-token-in-main\n\n"
|
|
"Log level example (quiets app logging during the run):\n"
|
|
" pnpm run test -- --focus frontend-tests.logic.groups-test --log-level warn"))
|
|
|
|
(defn- fail!
|
|
[message]
|
|
(js/console.error message)
|
|
(.exit js/process 1))
|
|
|
|
(defn- parse-focus
|
|
[focus]
|
|
(let [[ns-name test-name & extra] (str/split focus #"/")]
|
|
(cond
|
|
(or (str/blank? ns-name) (seq extra))
|
|
(fail! (str "Invalid --focus value: " focus))
|
|
|
|
(some? test-name)
|
|
{:ns (symbol ns-name) :test test-name}
|
|
|
|
:else
|
|
{:ns (symbol ns-name)})))
|
|
|
|
(defn- fixture-value
|
|
[ns-obj fixture-name]
|
|
(let [value (gobj/get ns-obj (munge fixture-name))]
|
|
(when-not (undefined? value)
|
|
value)))
|
|
|
|
(defn- ns-test-vars
|
|
[ns-sym]
|
|
(when-let [ns-obj (find-ns-obj ns-sym)]
|
|
(->> (js-keys ns-obj)
|
|
(keep (fn [key]
|
|
(some-> (gobj/get ns-obj key)
|
|
(.-cljs$lang$var))))
|
|
(filter (comp :test meta))
|
|
(sort-by (comp :line meta)))))
|
|
|
|
(defn- ns-fixtures
|
|
[ns-sym vars]
|
|
(when-let [ns-obj (find-ns-obj ns-sym)]
|
|
(let [ns-key (or (some-> vars first meta :ns) ns-sym)
|
|
once-fixtures (fixture-value ns-obj "cljs-test-once-fixtures")
|
|
each-fixtures (fixture-value ns-obj "cljs-test-each-fixtures")]
|
|
{:once (when once-fixtures {ns-key once-fixtures})
|
|
:each (when each-fixtures {ns-key each-fixtures})})))
|
|
|
|
(defn- selected-tests
|
|
[{:keys [ns test]}]
|
|
(when-not (some #{ns} test-namespaces)
|
|
(fail! (str "Unknown test namespace: " ns)))
|
|
(let [vars (vec (ns-test-vars ns))]
|
|
(when (empty? vars)
|
|
(fail! (str "No tests found in namespace: " ns)))
|
|
(if test
|
|
(let [test-sym (symbol test)
|
|
test-var (some #(when (= test-sym (:name (meta %))) %) vars)]
|
|
(if test-var
|
|
{:vars [test-var]
|
|
:fixtures (ns-fixtures ns [test-var])}
|
|
(fail! (str "Unknown test var: " ns "/" test))))
|
|
{:vars vars
|
|
:fixtures (ns-fixtures ns vars)})))
|
|
|
|
(defn- merge-fixtures
|
|
[fixtures]
|
|
{:once (apply merge (keep :once fixtures))
|
|
:each (apply merge (keep :each fixtures))})
|
|
|
|
(defn- run-test-vars!
|
|
[tests]
|
|
(let [vars (vec (mapcat :vars tests))
|
|
fixtures (merge-fixtures (map :fixtures tests))
|
|
env (assoc (t/empty-env)
|
|
:once-fixtures (:once fixtures)
|
|
:each-fixtures (:each fixtures))
|
|
summary (volatile! {:test 0 :pass 0 :fail 0 :error 0 :type :summary})]
|
|
|
|
(t/set-env! env)
|
|
|
|
(t/run-block
|
|
(concat (t/test-vars-block vars)
|
|
[(fn []
|
|
(vswap! summary
|
|
(partial merge-with +)
|
|
(:report-counters (t/get-current-env))))
|
|
(fn []
|
|
(t/report @summary)
|
|
(t/report (assoc @summary :type :end-run-tests)))]))))
|
|
|
|
(defn- run-focused-test!
|
|
[focus]
|
|
(run-test-vars! [(selected-tests (parse-focus focus))]))
|
|
|
|
(defn init
|
|
[]
|
|
(let [{:keys [options errors summary]} (parse-opts (argv) cli-options)]
|
|
(cond
|
|
(seq errors)
|
|
(fail! (str/join "\n" errors))
|
|
|
|
(:help options)
|
|
(do
|
|
(println (usage summary))
|
|
(.exit js/process 0))
|
|
|
|
:else
|
|
(do
|
|
(l/setup! {:app (or (:log-level options) :warn)})
|
|
|
|
(if (:focus options)
|
|
(run-focused-test! (:focus options))
|
|
(run-test-vars! (map #(selected-tests {:ns %}) test-namespaces)))))))
|