alonso.torres ae22eaa296 🔥 Remove dead code from the component helpers
- generate-relocate set :component-root on the moved shapes twice. The
  second pass looked at the same copy heads again and wrote the values
  the first had written, and update-shapes had already applied them,
  so it emitted nothing. It goes. Delete and relocate found the masked
  groups whose mask leaves them with the same reduce;
  groups-losing-mask finds them for both. The comment "Remove the hide
  in viewer flag" sat above code that sets it.
- generate-duplicate-shape-change took unames, update-unames! and ids
  only to pass them to its own recursive call, assigned each shape the
  name it already had, and had a 13-argument arity that nothing
  called. It takes the values that stay the same along the subtree in
  one map, and it is private.
- make-component-instance collected the names used in the page and
  the new ids in two volatiles: the names were never read, and the ids
  only fed a second remap of the grid cells, which clone-shape already
  does.
- ctk/in-component-copy-not-root? had no caller, and
  ctn/get-container-root and ctk/valid-touched-group? only their
  tests.
- ctf/swapped-subhead? tells whether a copy head refers to a main
  shape that is not a child of the main shape its parent refers to;
  its docstring still spoke of swap slots. It is
  ref-outside-near-main?.
- dump-shape-component-info built the name of a nested head's
  component in a branch whose condition ended in `true`, so it never
  ran.

No behavior change: the golden masters and the suites are unchanged.

Benchmark (lower quantile, ms; baseline / now / ratio):
  deepest-edit-through-three-levels    35.2 /  16.1 / 0.46
  edit-through-a-chain-of-dependents   68.9 /  30.1 / 0.44
  library-update-into-copies           83.1 /  39.4 / 0.47
  main-edit-among-many-shapes           4.8 /   2.2 / 0.45
  main-edit-into-10-copies              1.8 /   0.8 / 0.44
  main-edit-into-100-copies            15.4 /   7.7 / 0.50
  main-edit-into-1000-copies          153.1 /  78.1 / 0.51
  variant-switch-into-copies           32.1 /  18.5 / 0.58

AI-assisted-by: claude-opus-5-5

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 00:35:55 +02:00

423 lines
16 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 common-tests.runner
(:require
#?(:clj [common-tests.fressian-test])
#?(:cljs [app.common.logging :as l])
#?(:cljs [clojure.string :as str])
#?(:cljs [clojure.tools.cli :refer [parse-opts]])
#?(:cljs [goog.object :as gobj])
[clojure.test :as t]
[common-tests.attrs-test]
[common-tests.buffer-test]
[common-tests.colors-test]
[common-tests.data-test]
[common-tests.features-test]
[common-tests.files-builder-test]
[common-tests.files-changes-test]
[common-tests.files-migrations-0025-test]
[common-tests.files-migrations-0026-test]
[common-tests.files-migrations-test]
[common-tests.files.comp-processors-test]
[common-tests.files.convert-swap-slots-test]
[common-tests.files.convert-text-overrides-test]
[common-tests.files.helpers-test]
[common-tests.files.repair-components-test]
[common-tests.files.repair-test]
[common-tests.files.shapes-builder-test]
[common-tests.files.tokens-test]
[common-tests.files.validate-test]
[common-tests.geom-align-test]
[common-tests.geom-bounds-layout-nil-test]
[common-tests.geom-bounds-map-test]
[common-tests.geom-flex-layout-test]
[common-tests.geom-grid-layout-test]
[common-tests.geom-grid-test]
[common-tests.geom-image-bounds-resize-test]
[common-tests.geom-line-test]
[common-tests.geom-modif-tree-test]
[common-tests.geom-modifiers-test]
[common-tests.geom-point-test]
[common-tests.geom-proportions-test]
[common-tests.geom-rect-test]
[common-tests.geom-shapes-common-test]
[common-tests.geom-shapes-constraints-test]
[common-tests.geom-shapes-corners-test]
[common-tests.geom-shapes-effects-test]
[common-tests.geom-shapes-intersect-test]
[common-tests.geom-shapes-strokes-test]
[common-tests.geom-shapes-test]
[common-tests.geom-shapes-text-test]
[common-tests.geom-shapes-tree-seq-test]
[common-tests.geom-snap-test]
[common-tests.geom-test]
[common-tests.helpers-test]
[common-tests.logging-test]
[common-tests.logic.chained-propagation-test]
[common-tests.logic.comp-creation-test]
[common-tests.logic.comp-detach-with-nested-test]
[common-tests.logic.comp-flex-interactions-test]
[common-tests.logic.comp-main-edit-breaks-copy-slots-test]
[common-tests.logic.comp-move-swapped-copies-test]
[common-tests.logic.comp-reset-test]
[common-tests.logic.comp-sync-test]
[common-tests.logic.comp-touched-test]
[common-tests.logic.composable-runner-test]
[common-tests.logic.composable-sync-test]
[common-tests.logic.copying-and-duplicating-test]
[common-tests.logic.duplicated-pages-test]
[common-tests.logic.large-sync-undo-test]
[common-tests.logic.library-asset-sync-test]
[common-tests.logic.move-shapes-test]
[common-tests.logic.multiple-nesting-levels-test]
[common-tests.logic.placement-test]
[common-tests.logic.swap-and-reset-test]
[common-tests.logic.swap-as-override-test]
[common-tests.logic.swap-group-test]
[common-tests.logic.swap-keeps-id-test]
[common-tests.logic.text-editor-output-test]
[common-tests.logic.text-notation-test]
[common-tests.logic.text-override-operations-test]
[common-tests.logic.text-override-rule-test]
[common-tests.logic.text-override-switch-test]
[common-tests.logic.text-override-sync-test]
[common-tests.logic.text-sync-test]
[common-tests.logic.text-touched-test]
[common-tests.logic.token-apply-test]
[common-tests.logic.token-test]
[common-tests.logic.variants-switch-target-test]
[common-tests.logic.variants-switch-test]
[common-tests.logic.variants-test]
[common-tests.math-test]
[common-tests.media-test]
[common-tests.path-names-test]
[common-tests.record-test]
[common-tests.schema-test]
[common-tests.spec-test]
[common-tests.svg-path-test]
[common-tests.svg-test]
[common-tests.text-test]
[common-tests.time-test]
[common-tests.token-test]
[common-tests.types-shape-tree-test]
[common-tests.types.absorb-assets-test]
[common-tests.types.color-test]
[common-tests.types.container-test]
[common-tests.types.file-test]
[common-tests.types.fill-test]
[common-tests.types.font-test]
[common-tests.types.modifiers-test]
[common-tests.types.objects-map-test]
[common-tests.types.organization-test]
[common-tests.types.path-data-test]
[common-tests.types.plugins-test]
[common-tests.types.shape-decode-encode-test]
[common-tests.types.shape-interactions-test]
[common-tests.types.shape-layout-test]
[common-tests.types.stroke-test]
[common-tests.types.text-letters-test]
[common-tests.types.text-test]
[common-tests.types.token-test]
[common-tests.types.tokens-lib-test]
[common-tests.types.tokens-migrations-test]
[common-tests.types.tokens-status-test]
[common-tests.types.variant-test]
[common-tests.undo-stack-test]
[common-tests.uuid-test]
[common-tests.variant-test]))
(def test-namespaces
[#?(:clj 'common-tests.fressian-test)
'common-tests.attrs-test
'common-tests.buffer-test
'common-tests.colors-test
'common-tests.data-test
'common-tests.features-test
'common-tests.files-builder-test
'common-tests.files-changes-test
'common-tests.files-migrations-0025-test
'common-tests.files-migrations-0026-test
'common-tests.files-migrations-test
'common-tests.files.comp-processors-test
'common-tests.files.convert-swap-slots-test
'common-tests.files.convert-text-overrides-test
'common-tests.files.helpers-test
'common-tests.files.repair-components-test
'common-tests.files.repair-test
'common-tests.files.shapes-builder-test
'common-tests.files.tokens-test
'common-tests.files.validate-test
'common-tests.geom-align-test
'common-tests.geom-bounds-layout-nil-test
'common-tests.geom-bounds-map-test
'common-tests.geom-flex-layout-test
'common-tests.geom-grid-layout-test
'common-tests.geom-grid-test
'common-tests.geom-image-bounds-resize-test
'common-tests.geom-line-test
'common-tests.geom-modif-tree-test
'common-tests.geom-modifiers-test
'common-tests.geom-point-test
'common-tests.geom-proportions-test
'common-tests.geom-rect-test
'common-tests.geom-shapes-common-test
'common-tests.geom-shapes-constraints-test
'common-tests.geom-shapes-corners-test
'common-tests.geom-shapes-effects-test
'common-tests.geom-shapes-intersect-test
'common-tests.geom-shapes-strokes-test
'common-tests.geom-shapes-test
'common-tests.geom-shapes-text-test
'common-tests.geom-shapes-tree-seq-test
'common-tests.geom-snap-test
'common-tests.geom-test
'common-tests.helpers-test
'common-tests.logging-test
'common-tests.logic.chained-propagation-test
'common-tests.logic.comp-creation-test
'common-tests.logic.comp-detach-with-nested-test
'common-tests.logic.comp-flex-interactions-test
'common-tests.logic.comp-main-edit-breaks-copy-slots-test
'common-tests.logic.comp-move-swapped-copies-test
'common-tests.logic.comp-reset-test
'common-tests.logic.comp-sync-test
'common-tests.logic.comp-touched-test
'common-tests.logic.composable-runner-test
'common-tests.logic.composable-sync-test
'common-tests.logic.copying-and-duplicating-test
'common-tests.logic.duplicated-pages-test
'common-tests.logic.large-sync-undo-test
'common-tests.logic.library-asset-sync-test
'common-tests.logic.move-shapes-test
'common-tests.logic.multiple-nesting-levels-test
'common-tests.logic.placement-test
'common-tests.logic.swap-and-reset-test
'common-tests.logic.swap-as-override-test
'common-tests.logic.swap-group-test
'common-tests.logic.swap-keeps-id-test
'common-tests.logic.text-editor-output-test
'common-tests.logic.text-notation-test
'common-tests.logic.text-override-operations-test
'common-tests.logic.text-override-rule-test
'common-tests.logic.text-override-switch-test
'common-tests.logic.text-override-sync-test
'common-tests.logic.text-sync-test
'common-tests.logic.text-touched-test
'common-tests.logic.token-apply-test
'common-tests.logic.token-test
'common-tests.logic.variants-switch-target-test
'common-tests.logic.variants-switch-test
'common-tests.logic.variants-test
'common-tests.math-test
'common-tests.media-test
'common-tests.path-names-test
'common-tests.record-test
'common-tests.schema-test
'common-tests.spec-test
'common-tests.svg-path-test
'common-tests.svg-test
'common-tests.text-test
'common-tests.time-test
'common-tests.token-test
'common-tests.types-shape-tree-test
'common-tests.types.absorb-assets-test
'common-tests.types.color-test
'common-tests.types.container-test
'common-tests.types.file-test
'common-tests.types.fill-test
'common-tests.types.font-test
'common-tests.types.modifiers-test
'common-tests.types.objects-map-test
'common-tests.types.organization-test
'common-tests.types.path-data-test
'common-tests.types.plugins-test
'common-tests.types.shape-decode-encode-test
'common-tests.types.shape-interactions-test
'common-tests.types.shape-layout-test
'common-tests.types.stroke-test
'common-tests.types.text-letters-test
'common-tests.types.text-test
'common-tests.types.token-test
'common-tests.types.tokens-lib-test
'common-tests.types.tokens-migrations-test
'common-tests.types.tokens-status-test
'common-tests.types.variant-test
'common-tests.undo-stack-test
'common-tests.uuid-test
'common-tests.variant-test])
#?(:cljs
(assert (every? find-ns-obj test-namespaces)
"test-namespaces contains a namespace that isn't required in runner.cljc"))
#?(:cljs (enable-console-print!))
#?(:cljs
(defmethod cljs.test/report [:cljs.test/default :end-run-tests] [m]
(if (cljs.test/successful? m)
(.exit js/process 0)
(.exit js/process 1))))
#?(:cljs
(defmethod t/report [:cljs.test/default :begin-test-var] [m]
(let [v (:var m)]
(println (str " ▸ " (:ns (meta v)) "/" (:name (meta v)))))))
#?(:cljs
(do
;; This runner intentionally mirrors frontend-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. common-tests.logic.comp-sync-test/test-sync-when-changing-attribute"]
["-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))]
(cond-> args
(= "--" (first args)) rest)))
(defn- usage
[summary]
(str "Usage: pnpm run test:js -- [options]\n\n"
"Options:\n"
summary "\n\n"
"Focus examples:\n"
" pnpm run test:js -- --focus common-tests.logic.comp-sync-test\n"
" pnpm run test:js -- --focus common-tests.logic.comp-sync-test/test-sync-when-changing-attribute\n\n"
"Log level example (quiets app logging during the run):\n"
" pnpm run test:js -- --focus common-tests.logic.comp-sync-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-and-clear-env!))))
(fn []
(t/set-env! env)
(t/report @summary)
(t/report (assoc @summary :type :end-run-tests))
(t/clear-env!))]))))
(defn- run-focused-test!
[focus]
(run-test-vars! [(selected-tests (parse-focus focus))]))
(defn- run-all-tests!
[]
(run-test-vars! (map #(selected-tests {:ns %}) test-namespaces)))))
(defn -main
[& _args]
#?(:cljs
(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
(when-let [level (:log-level options)]
(l/setup! {:app level}))
(if (:focus options)
(run-focused-test! (:focus options))
(run-all-tests!)))))
:clj
(apply t/run-tests test-namespaces)))