mirror of
https://github.com/penpot/penpot.git
synced 2026-05-24 09:23:40 +00:00
✨ Allow running a single frontend test via --focus
Previously `pnpm run test` always ran the full frontend-tests suite, which made tight iteration on a single namespace or var painful. The runner now accepts `--focus <ns>` or `--focus <ns>/<var>` and executes only the matching tests, preserving each namespace's `:once` and `:each` fixtures so behavior matches a full-suite run. pnpm run test -- --focus frontend-tests.logic.groups-test pnpm run test -- --focus frontend-tests.logic.groups-test/some-test Also updates the developer guide and the testing memory so the flag is discoverable from both docs and agent context.
This commit is contained in:
parent
63e7df5fda
commit
17041b53a7
@ -8,8 +8,10 @@ Frontend unit tests live under `frontend/test/frontend_tests/` and use `cljs.tes
|
||||
|
||||
From `frontend/`:
|
||||
- Full unit test run: `pnpm run test`.
|
||||
- Focused unit tests: edit `test/frontend_tests/runner.cljs` to narrow the suite, then run `pnpm run test`.
|
||||
- Focus a frontend CLJS test namespace: `pnpm run test -- --focus frontend-tests.logic.components-and-tokens`.
|
||||
- Focus one frontend CLJS test var: `pnpm run test -- --focus frontend-tests.logic.components-and-tokens/change-spacing-token-in-main-updates-copy-layout`.
|
||||
- Build test target only: `pnpm run build:test`.
|
||||
- After `pnpm run build:test`, direct compiled runner focus is faster: `node target/tests/test.js --focus frontend-tests.logic.components-and-tokens/change-spacing-token-in-main-updates-copy-layout`.
|
||||
- Watch tests: `pnpm run watch:test`.
|
||||
|
||||
## Playwright integration tests
|
||||
|
||||
@ -281,8 +281,17 @@ for how to define custom metadata and other ways of selecting tests.
|
||||
it, but for now we use shadow-cljs with <code class="language-text">package.json</code> scripts:
|
||||
|
||||
```bash
|
||||
# To run all frontend tests once
|
||||
pnpm run test
|
||||
pnpm run test:watch
|
||||
|
||||
# To run all frontend tests and keep watching for changes
|
||||
pnpm run watch:test
|
||||
|
||||
# To run a single frontend tests module
|
||||
pnpm run test -- --focus frontend-tests.logic.components-and-tokens
|
||||
|
||||
# To run a single frontend test
|
||||
pnpm run test -- --focus frontend-tests.logic.components-and-tokens/change-token-in-main
|
||||
```
|
||||
|
||||
#### Test output
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
(ns frontend-tests.runner
|
||||
(:require
|
||||
[cljs.test :as t]
|
||||
[clojure.string :as str]
|
||||
[clojure.tools.cli :refer [parse-opts]]
|
||||
[frontend-tests.basic-shapes-test]
|
||||
[frontend-tests.copy-as-svg-test]
|
||||
[frontend-tests.data.nitrate-test]
|
||||
@ -38,7 +40,8 @@
|
||||
[frontend-tests.util-range-tree-test]
|
||||
[frontend-tests.util-simple-math-test]
|
||||
[frontend-tests.util-webapi-test]
|
||||
[frontend-tests.worker-snap-test]))
|
||||
[frontend-tests.worker-snap-test]
|
||||
[goog.object :as gobj]))
|
||||
|
||||
(enable-console-print!)
|
||||
|
||||
@ -47,44 +50,176 @@
|
||||
(.exit js/process 0)
|
||||
(.exit js/process 1)))
|
||||
|
||||
(def test-namespaces
|
||||
'[frontend-tests.basic-shapes-test
|
||||
frontend-tests.copy-as-svg-test
|
||||
frontend-tests.data.nitrate-test
|
||||
frontend-tests.data.repo-test
|
||||
frontend-tests.errors-test
|
||||
frontend-tests.main-errors-test
|
||||
frontend-tests.data.uploads-test
|
||||
frontend-tests.data.viewer-test
|
||||
frontend-tests.data.workspace-colors-test
|
||||
frontend-tests.data.workspace-media-test
|
||||
frontend-tests.data.workspace-shortcuts-test
|
||||
frontend-tests.data.workspace-texts-test
|
||||
frontend-tests.data.workspace-thumbnails-test
|
||||
frontend-tests.helpers-shapes-test
|
||||
frontend-tests.logic.comp-remove-swap-slots-test
|
||||
frontend-tests.logic.components-and-tokens
|
||||
frontend-tests.logic.copying-and-duplicating-test
|
||||
frontend-tests.logic.frame-guides-test
|
||||
frontend-tests.logic.groups-test
|
||||
frontend-tests.logic.pasting-in-containers-test
|
||||
frontend-tests.plugins.context-shapes-test
|
||||
frontend-tests.plugins.parser-test
|
||||
frontend-tests.plugins.tokens-test
|
||||
frontend-tests.plugins.utils-test
|
||||
frontend-tests.svg-fills-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.workspace-tokens-remap-test
|
||||
frontend-tests.ui.ds-controls-numeric-input-test
|
||||
frontend-tests.util-object-test
|
||||
frontend-tests.util-range-tree-test
|
||||
frontend-tests.util-simple-math-test
|
||||
frontend-tests.util-webapi-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")
|
||||
|
||||
(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"]
|
||||
["-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"))
|
||||
|
||||
(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/run-block
|
||||
(concat [(fn [] (t/set-env! env))]
|
||||
(t/test-vars-block vars)
|
||||
[(fn []
|
||||
(vswap! summary
|
||||
(partial merge-with +)
|
||||
(:report-counters (t/get-and-clear-env!))))
|
||||
(fn []
|
||||
(t/set-env! env)
|
||||
(t/do-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 init
|
||||
[]
|
||||
(t/run-tests
|
||||
'frontend-tests.basic-shapes-test
|
||||
'frontend-tests.copy-as-svg-test
|
||||
'frontend-tests.data.nitrate-test
|
||||
'frontend-tests.data.repo-test
|
||||
'frontend-tests.errors-test
|
||||
'frontend-tests.main-errors-test
|
||||
'frontend-tests.data.uploads-test
|
||||
'frontend-tests.data.viewer-test
|
||||
'frontend-tests.data.workspace-colors-test
|
||||
'frontend-tests.data.workspace-media-test
|
||||
'frontend-tests.data.workspace-shortcuts-test
|
||||
'frontend-tests.data.workspace-texts-test
|
||||
'frontend-tests.data.workspace-thumbnails-test
|
||||
'frontend-tests.helpers-shapes-test
|
||||
'frontend-tests.logic.comp-remove-swap-slots-test
|
||||
'frontend-tests.logic.components-and-tokens
|
||||
'frontend-tests.logic.copying-and-duplicating-test
|
||||
'frontend-tests.logic.frame-guides-test
|
||||
'frontend-tests.logic.groups-test
|
||||
'frontend-tests.logic.pasting-in-containers-test
|
||||
'frontend-tests.plugins.context-shapes-test
|
||||
'frontend-tests.plugins.parser-test
|
||||
'frontend-tests.plugins.tokens-test
|
||||
'frontend-tests.plugins.utils-test
|
||||
'frontend-tests.svg-fills-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.workspace-tokens-remap-test
|
||||
'frontend-tests.ui.ds-controls-numeric-input-test
|
||||
'frontend-tests.util-object-test
|
||||
'frontend-tests.util-range-tree-test
|
||||
'frontend-tests.util-simple-math-test
|
||||
'frontend-tests.util-webapi-test
|
||||
'frontend-tests.worker-snap-test))
|
||||
(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))
|
||||
|
||||
(:focus options)
|
||||
(run-focused-test! (:focus options))
|
||||
|
||||
:else
|
||||
(run-test-vars! (map #(selected-tests {:ns %}) test-namespaces)))))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user