mirror of
https://github.com/penpot/penpot.git
synced 2026-10-29 14:00:37 +00:00
🚧 WIP Step 8, simplify and clean up tests
This commit is contained in:
parent
44dfb47c98
commit
c16233f841
@ -7,48 +7,21 @@
|
||||
(ns frontend-tests.benches.boolean-fixture-test
|
||||
(:require
|
||||
[app.common.types.path :as path]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.common.uuid :as uuid]
|
||||
[benches.render-wasm.scenes.builder :as b :include-macros true]
|
||||
[benches.render-wasm.scenes.common :as common]
|
||||
[cljs.test :as t :include-macros true]))
|
||||
[cljs.test :as t :include-macros true]
|
||||
[frontend-tests.benches.test-helpers :as helpers]))
|
||||
|
||||
(defn- failure-data
|
||||
[f]
|
||||
(try
|
||||
(f)
|
||||
nil
|
||||
(catch :default cause
|
||||
(ex-data cause))))
|
||||
|
||||
(defn- selrect
|
||||
[shape]
|
||||
[(:x (:selrect shape)) (:y (:selrect shape))
|
||||
(:width (:selrect shape)) (:height (:selrect shape))])
|
||||
|
||||
(defn- children-of
|
||||
[instance id]
|
||||
(mapv (:objects instance) (get-in instance [:objects id :shapes])))
|
||||
|
||||
(defn- run-scope
|
||||
"Runs `f` inside a raw scope and returns the scope state, so tests can
|
||||
inspect partial builds without calling finish!."
|
||||
[params f]
|
||||
(let [state (b/start params)]
|
||||
(binding [b/*state* state
|
||||
b/*defaults* {}]
|
||||
(f))
|
||||
state))
|
||||
|
||||
(t/deftest difference-of-overlapping-rects-derives-the-l-shape
|
||||
(t/deftest difference-of-overlapping-rects-keeps-hierarchy-and-bounds
|
||||
(let [red {:fill-color "#ff0000" :fill-opacity 1}
|
||||
blue {:fill-color "#0000ff" :fill-opacity 1}
|
||||
instance (b/fixture {:seed 1}
|
||||
(b/bool :l-shape {:bool-type :difference :name "L"}
|
||||
(b/rect {:x 0 :y 0 :width 100 :height 100 :fills [red]})
|
||||
(b/rect {:x 50 :y 50 :width 100 :height 100 :fills [blue]})))
|
||||
bool (first (children-of instance uuid/zero))
|
||||
children (children-of instance (:id bool))]
|
||||
bool (first (helpers/children-of instance uuid/zero))
|
||||
children (helpers/children-of instance (:id bool))]
|
||||
(t/is (= :bool (:type bool)))
|
||||
(t/is (= :difference (:bool-type bool)))
|
||||
(t/is (= (:id bool) (common/ref-id instance :l-shape)))
|
||||
@ -58,25 +31,18 @@
|
||||
[(:parent-id (first children)) (:parent-id (second children))]))
|
||||
(t/is (= [uuid/zero uuid/zero]
|
||||
[(:frame-id (first children)) (:frame-id (second children))]))
|
||||
(t/is (= [0 0 100 100] (selrect bool)))
|
||||
(t/is (= (:selrect bool) (path/calc-selrect (:content bool))))
|
||||
(t/is (= 4 (count (:points bool))))
|
||||
(t/is (= #{[0 0] [100 0] [100 50] [50 50] [50 100] [0 100]}
|
||||
(set (map (juxt :x :y) (path/get-points (:content bool))))))))
|
||||
(t/is (= [0 0 100 100] (helpers/selrect bool)))))
|
||||
|
||||
(t/deftest union-intersection-and-exclude-derive-canonical-bounds
|
||||
(doseq [[bool-type expected] [[:union [0 0 150 150]]
|
||||
[:intersection [50 50 50 50]]
|
||||
[:exclude [0 0 150 150]]]]
|
||||
(let [instance (b/fixture {:seed 1}
|
||||
(b/bool {:bool-type bool-type}
|
||||
(b/rect {:x 0 :y 0 :width 100 :height 100})
|
||||
(b/rect {:x 50 :y 50 :width 100 :height 100})))
|
||||
bool (first (children-of instance uuid/zero))]
|
||||
(t/is (= bool-type (:bool-type bool)))
|
||||
(t/is (= expected (selrect bool)) (str bool-type)))))
|
||||
(t/deftest union-derives-canonical-bounds
|
||||
(let [instance (b/fixture {:seed 1}
|
||||
(b/bool {:bool-type :union}
|
||||
(b/rect {:x 0 :y 0 :width 100 :height 100})
|
||||
(b/rect {:x 50 :y 50 :width 100 :height 100})))
|
||||
bool (first (helpers/children-of instance uuid/zero))]
|
||||
(t/is (= :union (:bool-type bool)))
|
||||
(t/is (= [0 0 150 150] (helpers/selrect bool)))))
|
||||
|
||||
(t/deftest operation-picks-the-canonical-style-head
|
||||
(t/deftest difference-picks-the-first-child-as-style-head
|
||||
(let [red {:fill-color "#ff0000" :fill-opacity 1}
|
||||
blue {:fill-color "#0000ff" :fill-opacity 1}
|
||||
blur {:id (uuid/custom 3 3) :type :layer-blur :value 4 :hidden false}
|
||||
@ -86,18 +52,9 @@
|
||||
:fills [red] :blur blur})
|
||||
(b/rect {:x 5 :y 0 :width 10 :height 10
|
||||
:fills [blue]})))
|
||||
union (b/fixture {:seed 1}
|
||||
(b/bool {:bool-type :union}
|
||||
(b/rect {:x 0 :y 0 :width 10 :height 10
|
||||
:fills [red] :blur blur})
|
||||
(b/rect {:x 5 :y 0 :width 10 :height 10
|
||||
:fills [blue]})))
|
||||
diff-bool (first (children-of difference uuid/zero))
|
||||
union-bool (first (children-of union uuid/zero))]
|
||||
diff-bool (first (helpers/children-of difference uuid/zero))]
|
||||
(t/is (= [red] (:fills diff-bool)))
|
||||
(t/is (= blur (:blur diff-bool)))
|
||||
(t/is (= [blue] (:fills union-bool)))
|
||||
(t/is (nil? (:blur union-bool)))))
|
||||
(t/is (= blur (:blur diff-bool)))))
|
||||
|
||||
(t/deftest supplied-styles-override-inherited
|
||||
(let [instance (b/fixture {:seed 1}
|
||||
@ -106,7 +63,7 @@
|
||||
:fills [{:fill-color "#ff0000" :fill-opacity 1}]})
|
||||
(b/rect {:x 5 :y 0 :width 10 :height 10
|
||||
:fills [{:fill-color "#0000ff" :fill-opacity 1}]})))
|
||||
bool (first (children-of instance uuid/zero))]
|
||||
bool (first (helpers/children-of instance uuid/zero))]
|
||||
(t/is (= [] (:fills bool)))))
|
||||
|
||||
(t/deftest nil-styles-do-not-count-as-supplied
|
||||
@ -116,16 +73,16 @@
|
||||
(b/bool {:bool-type :union :fills nil}
|
||||
(b/rect {:x 0 :y 0 :width 10 :height 10 :fills [red]})
|
||||
(b/rect {:x 5 :y 0 :width 10 :height 10 :fills [blue]})))
|
||||
bool (first (children-of instance uuid/zero))]
|
||||
bool (first (helpers/children-of instance uuid/zero))]
|
||||
(t/is (= [blue] (:fills bool)))))
|
||||
|
||||
(t/deftest single-child-bool-uses-the-child-path
|
||||
(let [instance (b/fixture {:seed 1}
|
||||
(b/bool {:bool-type :difference}
|
||||
(b/rect {:x 10 :y 20 :width 30 :height 40})))
|
||||
bool (first (children-of instance uuid/zero))]
|
||||
bool (first (helpers/children-of instance uuid/zero))]
|
||||
(t/is (= 1 (count (:shapes bool))))
|
||||
(t/is (= [10 20 30 40] (selrect bool)))
|
||||
(t/is (= [10 20 30 40] (helpers/selrect bool)))
|
||||
(t/is (= (:selrect bool) (path/calc-selrect (:content bool))))))
|
||||
|
||||
(t/deftest nested-bools-finalize-inside-out
|
||||
@ -135,11 +92,11 @@
|
||||
(b/rect {:x 0 :y 0 :width 100 :height 100})
|
||||
(b/rect {:x 50 :y 50 :width 100 :height 100}))
|
||||
(b/rect {:x 200 :y 0 :width 50 :height 50})))
|
||||
outer (first (children-of instance uuid/zero))
|
||||
inner (first (children-of instance (:id outer)))]
|
||||
outer (first (helpers/children-of instance uuid/zero))
|
||||
inner (first (helpers/children-of instance (:id outer)))]
|
||||
(t/is (= :bool (:type inner)))
|
||||
(t/is (= [0 0 100 100] (selrect inner)))
|
||||
(t/is (= [0 0 250 100] (selrect outer)))
|
||||
(t/is (= [0 0 100 100] (helpers/selrect inner)))
|
||||
(t/is (= [0 0 250 100] (helpers/selrect outer)))
|
||||
(t/is (= (:selrect outer) (path/calc-selrect (:content outer))))))
|
||||
|
||||
(t/deftest bool-inside-frame-keeps-frame-ids
|
||||
@ -148,9 +105,9 @@
|
||||
(b/bool {:bool-type :union}
|
||||
(b/rect {:x 10 :y 10 :width 10 :height 10})
|
||||
(b/rect {:x 30 :y 10 :width 10 :height 10}))))
|
||||
frame (first (children-of instance uuid/zero))
|
||||
bool (first (children-of instance (:id frame)))
|
||||
rects (children-of instance (:id bool))]
|
||||
frame (first (helpers/children-of instance uuid/zero))
|
||||
bool (first (helpers/children-of instance (:id frame)))
|
||||
rects (helpers/children-of instance (:id bool))]
|
||||
(t/is (= (:id frame) (:parent-id bool)))
|
||||
(t/is (= (:id frame) (:frame-id bool)))
|
||||
(t/is (= [(:id frame) (:id frame)] (mapv :frame-id rects)))
|
||||
@ -162,30 +119,30 @@
|
||||
(b/bool {:bool-type :union}
|
||||
(b/rect {:x 10 :y 20 :width 30 :height 40})
|
||||
(b/rect {:x 50 :y 80 :width 10 :height 10}))))
|
||||
group (first (children-of instance uuid/zero))
|
||||
bool (first (children-of instance (:id group)))]
|
||||
group (first (helpers/children-of instance uuid/zero))
|
||||
bool (first (helpers/children-of instance (:id group)))]
|
||||
(t/is (= :bool (:type bool)))
|
||||
(t/is (= [10 20 50 70] (selrect group)))
|
||||
(t/is (= [10 20 50 70] (helpers/selrect group)))
|
||||
(t/is (= uuid/zero (:frame-id bool)))))
|
||||
|
||||
(t/deftest empty-bool-is-rejected
|
||||
(let [data (failure-data #(b/fixture {:seed 1} (b/bool {:bool-type :union})))]
|
||||
(let [data (helpers/failure-data #(b/fixture {:seed 1} (b/bool {:bool-type :union})))]
|
||||
(t/is (= ::b/empty-bool (:type data)))))
|
||||
|
||||
(t/deftest caught-empty-bool-still-fails-finish
|
||||
(let [state (run-scope {:seed 1}
|
||||
(fn []
|
||||
(try
|
||||
(b/bool {:bool-type :union})
|
||||
(catch :default _ nil))))]
|
||||
(let [state (helpers/run-scope {:seed 1}
|
||||
(fn []
|
||||
(try
|
||||
(b/bool {:bool-type :union})
|
||||
(catch :default _ nil))))]
|
||||
(t/is (= ::b/unfinished-container
|
||||
(:type (failure-data #(b/finish! state)))))))
|
||||
(:type (helpers/failure-data #(b/finish! state)))))))
|
||||
|
||||
(t/deftest bool-geometry-attrs-are-rejected
|
||||
(doseq [attrs [{:bool-type :union :x 1}
|
||||
{:bool-type :union :selrect {:x 0 :y 0 :width 1 :height 1}}
|
||||
{:bool-type :union :content []}]]
|
||||
(let [data (failure-data #(b/fixture {:seed 1} (b/bool attrs (b/rect))))]
|
||||
(let [data (helpers/failure-data #(b/fixture {:seed 1} (b/bool attrs (b/rect))))]
|
||||
(t/is (= ::b/bool-geometry (:type data)) (str attrs))
|
||||
(t/is (contains? #{:x :selrect :content} (:key data)) (str attrs)))))
|
||||
|
||||
@ -195,19 +152,19 @@
|
||||
{:bool-type :union :transform-inverse "m"}
|
||||
{:bool-type :union :flip-x true}
|
||||
{:bool-type :union :flip-y true}]]
|
||||
(let [data (failure-data #(b/fixture {:seed 1} (b/bool attrs (b/rect))))]
|
||||
(let [data (helpers/failure-data #(b/fixture {:seed 1} (b/bool attrs (b/rect))))]
|
||||
(t/is (= ::b/bool-transform (:type data)) (str attrs)))))
|
||||
|
||||
(t/deftest bool-type-is-required-and-validated
|
||||
(t/is (= ::b/bool-type
|
||||
(:type (failure-data #(b/fixture {:seed 1} (b/bool {:name "B"} (b/rect)))))))
|
||||
(let [data (failure-data #(b/fixture {:seed 1} (b/bool {:bool-type :merge} (b/rect))))]
|
||||
(:type (helpers/failure-data #(b/fixture {:seed 1} (b/bool {:name "B"} (b/rect)))))))
|
||||
(let [data (helpers/failure-data #(b/fixture {:seed 1} (b/bool {:bool-type :merge} (b/rect))))]
|
||||
(t/is (= ::b/bool-type (:type data)))
|
||||
(t/is (= :merge (:bool-type data)))
|
||||
(t/is (= cts/bool-types (:supported data)))))
|
||||
(t/is (= #{:union :difference :intersection :exclude} (set (:supported data))))))
|
||||
|
||||
(t/deftest frame-child-is-rejected
|
||||
(let [data (failure-data
|
||||
(let [data (helpers/failure-data
|
||||
#(b/fixture {:seed 1}
|
||||
(b/bool {:bool-type :union}
|
||||
(b/frame {:x 0 :y 0 :width 10 :height 10}
|
||||
@ -226,17 +183,17 @@
|
||||
(b/bool {:bool-type :difference}
|
||||
(b/rect {:x 0 :y 0 :width 100 :height 100})
|
||||
(b/rect {:x 50 :y 50 :width 100 :height 100})))
|
||||
bool (first (children-of instance uuid/zero))]
|
||||
(t/is (= [0 0 100 100] (selrect bool))))
|
||||
bool (first (helpers/children-of instance uuid/zero))]
|
||||
(t/is (= [0 0 100 100] (helpers/selrect bool))))
|
||||
(finally
|
||||
(set! path/wasm:calc-bool-content original)))))
|
||||
|
||||
(t/deftest non-map-bool-attrs-are-rejected
|
||||
(t/is (= ::b/invalid-attrs
|
||||
(:type (failure-data #(b/fixture {:seed 1} (b/bool :hero (b/rect)))))))
|
||||
(let [state (run-scope {:seed 1}
|
||||
(fn []
|
||||
(try
|
||||
(b/bool :hero (b/rect))
|
||||
(catch :default _ nil))))]
|
||||
(:type (helpers/failure-data #(b/fixture {:seed 1} (b/bool :hero (b/rect)))))))
|
||||
(let [state (helpers/run-scope {:seed 1}
|
||||
(fn []
|
||||
(try
|
||||
(b/bool :hero (b/rect))
|
||||
(catch :default _ nil))))]
|
||||
(t/is (= 1 (count (get-in @state [:objects uuid/zero :shapes]))))))
|
||||
|
||||
@ -10,26 +10,13 @@
|
||||
[benches.render-wasm.scenes.builder :as b :include-macros true]
|
||||
[benches.render-wasm.scenes.common :as common]
|
||||
[benches.render-wasm.scenes.rects :as rects]
|
||||
[cljs.test :as t :include-macros true]))
|
||||
[cljs.test :as t :include-macros true]
|
||||
[frontend-tests.benches.test-helpers :as helpers]))
|
||||
|
||||
(defn- build
|
||||
([] (build {}))
|
||||
([params] (rects/build (merge {:seed 42 :count 5} params))))
|
||||
|
||||
(defn- rect-shapes
|
||||
"Rectangles of a fixture instance in creation order."
|
||||
[instance]
|
||||
(mapv (:objects instance)
|
||||
(get-in instance [:objects uuid/zero :shapes])))
|
||||
|
||||
(defn- failure-data
|
||||
[f]
|
||||
(try
|
||||
(f)
|
||||
nil
|
||||
(catch :default cause
|
||||
(ex-data cause))))
|
||||
|
||||
(defn- add-tile
|
||||
"Helper defined outside a fixture scope, called from inside one."
|
||||
[index]
|
||||
@ -41,13 +28,13 @@
|
||||
|
||||
(t/deftest rectangle-workload-keeps-default-count
|
||||
(let [instance (rects/build {:seed 42})
|
||||
rects (rect-shapes instance)]
|
||||
rects (helpers/root-shapes instance)]
|
||||
(t/is (= 1000 (count rects)))
|
||||
(t/is (< 1 (count (distinct (map :x rects)))))))
|
||||
|
||||
(t/deftest default-workload-is-canonical
|
||||
(let [instance (build {:count 25})
|
||||
rects (rect-shapes instance)]
|
||||
rects (helpers/root-shapes instance)]
|
||||
(t/is (= 25 (count rects)))
|
||||
(t/is (every? #(= :rect (:type %)) rects))
|
||||
(t/is (every? (fn [rect]
|
||||
@ -65,7 +52,7 @@
|
||||
(t/deftest geometry-is-page-relative-and-in-range
|
||||
(let [params {:seed 7 :count 40 :width 800 :height 600 :min-size 5 :max-size 15}
|
||||
instance (build params)
|
||||
rects (rect-shapes instance)]
|
||||
rects (helpers/root-shapes instance)]
|
||||
(t/is (every? #(<= 0 (:x %) 800) rects))
|
||||
(t/is (every? #(<= 0 (:y %) 600) rects))
|
||||
(t/is (every? #(<= 5 (:width %) 15) rects))
|
||||
@ -79,7 +66,7 @@
|
||||
(b/rect :hero {})
|
||||
(b/rect [:tile 1] {}))
|
||||
refs (:refs instance)
|
||||
children (get-in instance [:objects uuid/zero :shapes])]
|
||||
children (helpers/child-ids instance uuid/zero)]
|
||||
(t/is (= #{:hero [:tile 1]} (set (keys refs))))
|
||||
(t/is (= (get refs :hero) (second children)))
|
||||
(t/is (= (get refs [:tile 1]) (nth children 2)))))
|
||||
@ -88,7 +75,7 @@
|
||||
(let [instance (b/fixture {:seed 1
|
||||
:defaults {:rect {:x (b/gen-int 0 100)}}}
|
||||
(b/rect {:x 7 :fills []}))
|
||||
rect (first (rect-shapes instance))]
|
||||
rect (first (helpers/root-shapes instance))]
|
||||
(t/is (= 7 (:x rect)))
|
||||
(t/is (= [] (:fills rect)))))
|
||||
|
||||
@ -100,7 +87,7 @@
|
||||
(add-tile index))
|
||||
(b/rect :last {:x 99}))
|
||||
refs (:refs instance)
|
||||
rects (rect-shapes instance)]
|
||||
rects (helpers/root-shapes instance)]
|
||||
(t/is (= 5 (count rects)))
|
||||
(t/is (= [0 10 20]
|
||||
(mapv #(:x (get-in instance [:objects (get refs [:tile %])]))
|
||||
@ -108,7 +95,7 @@
|
||||
(t/is (= 99 (:x (get-in instance [:objects (get refs :last)]))))))
|
||||
|
||||
(t/deftest duplicate-labels-are-rejected
|
||||
(let [data (failure-data
|
||||
(let [data (helpers/failure-data
|
||||
#(b/fixture {:seed 1}
|
||||
(b/rect :dup {})
|
||||
(b/rect :dup {})))]
|
||||
@ -117,17 +104,17 @@
|
||||
|
||||
(t/deftest failed-builds-leak-no-state
|
||||
(let [clean (build)]
|
||||
(failure-data #(b/fixture {:seed 99}
|
||||
(b/rect :dup {})
|
||||
(b/rect :dup {})))
|
||||
(helpers/failure-data #(b/fixture {:seed 99}
|
||||
(b/rect :dup {})
|
||||
(b/rect :dup {})))
|
||||
(t/is (= clean (build)))))
|
||||
|
||||
(t/deftest rect-outside-scope-is-rejected
|
||||
(let [data (failure-data #(b/rect))]
|
||||
(let [data (helpers/failure-data #(b/rect))]
|
||||
(t/is (= ::b/outside-scope (:type data)))))
|
||||
|
||||
(t/deftest nested-scopes-are-rejected
|
||||
(let [data (failure-data
|
||||
(let [data (helpers/failure-data
|
||||
#(b/fixture {:seed 1}
|
||||
(b/fixture {:seed 2}
|
||||
(b/rect))))]
|
||||
@ -135,17 +122,17 @@
|
||||
|
||||
(t/deftest invalid-seeds-are-rejected
|
||||
(t/is (= ::b/invalid-seed
|
||||
(:type (failure-data #(b/fixture {} (b/rect))))))
|
||||
(:type (helpers/failure-data #(b/fixture {} (b/rect))))))
|
||||
(t/is (= ::b/invalid-seed
|
||||
(:type (failure-data #(b/fixture {:seed -1} (b/rect))))))
|
||||
(:type (helpers/failure-data #(b/fixture {:seed -1} (b/rect))))))
|
||||
(t/is (= ::b/invalid-seed
|
||||
(:type (failure-data #(b/fixture {:seed 4294967296} (b/rect)))))))
|
||||
(:type (helpers/failure-data #(b/fixture {:seed 4294967296} (b/rect)))))))
|
||||
|
||||
(t/deftest runtime-attrs-maps-are-resolved
|
||||
(let [attrs {:x 11}
|
||||
instance (b/fixture {:seed 1}
|
||||
(b/rect attrs))
|
||||
rect (first (rect-shapes instance))]
|
||||
rect (first (helpers/root-shapes instance))]
|
||||
(t/is (= 11 (:x rect)))))
|
||||
|
||||
(t/deftest single-label-form-is-supported
|
||||
@ -153,7 +140,7 @@
|
||||
(b/rect :solo))
|
||||
id (get (:refs instance) :solo)]
|
||||
(t/is (uuid? id))
|
||||
(t/is (= [id] (get-in instance [:objects uuid/zero :shapes])))))
|
||||
(t/is (= [id] (helpers/child-ids instance uuid/zero)))))
|
||||
|
||||
(t/deftest built-instance-feeds-the-snapshot-api
|
||||
(let [instance (b/fixture {:seed 1}
|
||||
@ -163,14 +150,14 @@
|
||||
(t/is (= [uuid/zero hero-id] (mapv :id order)))))
|
||||
|
||||
(t/deftest invalid-labels-are-rejected
|
||||
(let [data (failure-data #(b/fixture {:seed 1} (b/rect "hero" {})))]
|
||||
(let [data (helpers/failure-data #(b/fixture {:seed 1} (b/rect "hero" {})))]
|
||||
(t/is (= ::b/invalid-label (:type data)))))
|
||||
|
||||
(t/deftest protected-keys-cannot-be-overridden
|
||||
(let [other (uuid/custom 9 9)
|
||||
instance (b/fixture {:seed 1}
|
||||
(b/rect {:type :circle :id other :parent-id other}))
|
||||
rect (first (rect-shapes instance))]
|
||||
rect (first (helpers/root-shapes instance))]
|
||||
(t/is (= :rect (:type rect)))
|
||||
(t/is (not= other (:id rect)))
|
||||
(t/is (= uuid/zero (:parent-id rect)))))
|
||||
@ -189,61 +176,47 @@
|
||||
(let [fill {:fill-color "#ffffff" :fill-opacity 1}
|
||||
instance (b/fixture {:seed 1}
|
||||
(b/rect {:fills [fill]}))
|
||||
rect (first (rect-shapes instance))]
|
||||
rect (first (helpers/root-shapes instance))]
|
||||
(t/is (= [fill] (:fills rect)))))
|
||||
|
||||
(t/deftest generator-helpers-produce-expected-values
|
||||
(let [instance (b/fixture {:seed 3
|
||||
:defaults {:rect {:opacity (b/gen-float 0.5 0.6)
|
||||
:x (b/gen-one-of [4 5])
|
||||
:r1 (b/gen-int 3 4)
|
||||
:r1 (b/gen-int 3 5)
|
||||
:fills (b/gen-vector (b/gen-fill))}}}
|
||||
(b/rect))
|
||||
rect (first (rect-shapes instance))]
|
||||
rect (first (helpers/root-shapes instance))]
|
||||
(t/is (<= 0.5 (:opacity rect) 0.6))
|
||||
(t/is (contains? #{4 5} (:x rect)))
|
||||
(t/is (= 3 (:r1 rect)))
|
||||
(t/is (<= 3 (:r1 rect) 4))
|
||||
(t/is (re-matches #"^#[0-9a-f]{6}$" (:fill-color (first (:fills rect)))))))
|
||||
|
||||
(t/deftest empty-one-of-is-rejected
|
||||
(let [data (failure-data #(b/gen-one-of []))]
|
||||
(let [data (helpers/failure-data #(b/gen-one-of []))]
|
||||
(t/is (= ::b/no-values (:type data)))))
|
||||
|
||||
(defn- circle-shapes
|
||||
"Circles of a fixture instance in creation order."
|
||||
[instance]
|
||||
(mapv (:objects instance)
|
||||
(get-in instance [:objects uuid/zero :shapes])))
|
||||
|
||||
(t/deftest circle-creates-ellipse-type
|
||||
(let [instance (b/fixture {:seed 1}
|
||||
(b/circle {:x 10 :y 20 :width 30 :height 40}))
|
||||
circle (first (circle-shapes instance))]
|
||||
circle (first (helpers/root-shapes instance))]
|
||||
(t/is (= :circle (:type circle)))
|
||||
(t/is (= [10 20 30 40] [(:x circle) (:y circle) (:width circle) (:height circle)]))
|
||||
(t/is (= 1 (count (get-in instance [:objects uuid/zero :shapes]))))))
|
||||
(t/is (= 1 (count (helpers/child-ids instance uuid/zero))))))
|
||||
|
||||
(t/deftest circle-uses-circle-defaults
|
||||
(let [instance (b/fixture {:seed 3
|
||||
:defaults {:circle {:x (b/gen-int 10 11)}}}
|
||||
:defaults {:circle {:x (b/gen-int 10 12)}}}
|
||||
(b/circle))
|
||||
circle (first (circle-shapes instance))]
|
||||
circle (first (helpers/root-shapes instance))]
|
||||
(t/is (contains? #{10 11} (:x circle)))))
|
||||
|
||||
(t/deftest circle-ignores-rect-defaults
|
||||
(let [instance (b/fixture {:seed 1
|
||||
:defaults {:rect {:x 999}}}
|
||||
(b/circle))
|
||||
circle (first (circle-shapes instance))]
|
||||
(t/is (= 0 (:x circle)))))
|
||||
|
||||
(t/deftest circle-attrs-override-generated-values
|
||||
(let [instance (b/fixture {:seed 1
|
||||
:defaults {:circle {:x (b/gen-int 0 100)}}}
|
||||
(b/circle {:x 7 :fills []}))
|
||||
circle (first (circle-shapes instance))]
|
||||
(t/is (= 7 (:x circle)))
|
||||
(t/is (= [] (:fills circle)))))
|
||||
circle (first (helpers/root-shapes instance))]
|
||||
(t/is (not= 999 (:x circle)))))
|
||||
|
||||
(t/deftest circle-geometry-is-page-relative-and-in-range
|
||||
(let [instance (b/fixture {:seed 7
|
||||
@ -253,101 +226,16 @@
|
||||
:height (b/gen-int 5 15)}}}
|
||||
(doseq [_ (range 40)]
|
||||
(b/circle)))
|
||||
circles (circle-shapes instance)]
|
||||
circles (helpers/root-shapes instance)]
|
||||
(t/is (= 40 (count circles)))
|
||||
(t/is (every? #(<= 0 (:x %) 800) circles))
|
||||
(t/is (every? #(<= 0 (:y %) 600) circles))
|
||||
(t/is (every? #(<= 5 (:width %) 15) circles))
|
||||
(t/is (every? #(<= 5 (:height %) 15) circles))))
|
||||
|
||||
(t/deftest circle-labels-are-instance-local
|
||||
(let [instance (b/fixture {:seed 1}
|
||||
(b/circle)
|
||||
(b/circle :hero {})
|
||||
(b/circle [:tile 1] {}))
|
||||
refs (:refs instance)
|
||||
children (get-in instance [:objects uuid/zero :shapes])]
|
||||
(t/is (= #{:hero [:tile 1]} (set (keys refs))))
|
||||
(t/is (= (get refs :hero) (second children)))
|
||||
(t/is (= (get refs [:tile 1]) (nth children 2)))))
|
||||
|
||||
(t/deftest circle-single-label-form-is-supported
|
||||
(let [instance (b/fixture {:seed 1}
|
||||
(b/circle :solo))
|
||||
id (get (:refs instance) :solo)]
|
||||
(t/is (uuid? id))
|
||||
(t/is (= [id] (get-in instance [:objects uuid/zero :shapes])))))
|
||||
|
||||
(t/deftest circle-runtime-attrs-maps-are-resolved
|
||||
(let [attrs {:x 11}
|
||||
instance (b/fixture {:seed 1}
|
||||
(b/circle attrs))
|
||||
circle (first (circle-shapes instance))]
|
||||
(t/is (= 11 (:x circle)))))
|
||||
|
||||
(t/deftest circle-duplicate-labels-are-rejected
|
||||
(let [data (failure-data
|
||||
#(b/fixture {:seed 1}
|
||||
(b/circle :dup {})
|
||||
(b/circle :dup {})))]
|
||||
(t/is (= ::b/duplicate-label (:type data)))
|
||||
(t/is (= :dup (:label data)))))
|
||||
|
||||
(t/deftest circle-invalid-labels-are-rejected
|
||||
(let [data (failure-data #(b/fixture {:seed 1} (b/circle "hero" {})))]
|
||||
(t/is (= ::b/invalid-label (:type data)))))
|
||||
|
||||
(t/deftest circle-outside-scope-is-rejected
|
||||
(let [data (failure-data #(b/circle))]
|
||||
(t/is (= ::b/outside-scope (:type data)))))
|
||||
|
||||
(t/deftest circle-protected-keys-cannot-be-overridden
|
||||
(let [other (uuid/custom 9 9)
|
||||
instance (b/fixture {:seed 1}
|
||||
(b/circle {:type :rect :id other :parent-id other}))
|
||||
circle (first (circle-shapes instance))]
|
||||
(t/is (= :circle (:type circle)))
|
||||
(t/is (not= other (:id circle)))
|
||||
(t/is (= uuid/zero (:parent-id circle)))))
|
||||
|
||||
(t/deftest circle-built-instance-feeds-the-snapshot-api
|
||||
(let [instance (b/fixture {:seed 1}
|
||||
(b/circle :hero {}))
|
||||
order (common/upload-order instance)
|
||||
hero-id (common/ref-id instance :hero)]
|
||||
(t/is (= [uuid/zero hero-id] (mapv :id order)))))
|
||||
|
||||
(t/deftest circle-repeatable-builds-are-identical
|
||||
(let [build (fn [seed]
|
||||
(b/fixture {:seed seed
|
||||
:defaults {:circle {:x (b/gen-int 0 100)}}}
|
||||
(b/circle)
|
||||
(b/circle)))]
|
||||
(t/is (= (build 42) (build 42)))
|
||||
(t/is (not= (build 42) (build 43)))))
|
||||
|
||||
(t/deftest circle-ordinary-forms-work-inside-the-scope
|
||||
(let [instance (b/fixture {:seed 1}
|
||||
(let [first-id (b/circle {:x 1})]
|
||||
(t/is (uuid? first-id)))
|
||||
(doseq [index (range 3)]
|
||||
(b/circle [:ring index] {:x (* 10 index)}))
|
||||
(b/circle :last {:x 99}))
|
||||
refs (:refs instance)
|
||||
circles (circle-shapes instance)]
|
||||
(t/is (= 5 (count circles)))
|
||||
(t/is (= [0 10 20]
|
||||
(mapv #(:x (get-in instance [:objects (get refs [:ring %])]))
|
||||
(range 3))))
|
||||
(t/is (= 99 (:x (get-in instance [:objects (get refs :last)]))))))
|
||||
|
||||
(t/deftest circle-preserves-radius-attrs
|
||||
(let [instance (b/fixture {:seed 1}
|
||||
(b/circle {:x 0 :y 0 :width 20 :height 20 :rx 5 :ry 7}))
|
||||
circle (first (circle-shapes instance))]
|
||||
circle (first (helpers/root-shapes instance))]
|
||||
(t/is (= [5 7] [(:rx circle) (:ry circle)]))))
|
||||
|
||||
(t/deftest circle-failed-builds-leak-no-state
|
||||
(let [clean (b/fixture {:seed 42 :defaults {:circle {:x (b/gen-int 0 100)}}} (b/circle) (b/circle))]
|
||||
(failure-data #(b/fixture {:seed 99} (b/circle :dup {}) (b/circle :dup {})))
|
||||
(t/is (= clean (b/fixture {:seed 42 :defaults {:circle {:x (b/gen-int 0 100)}}} (b/circle) (b/circle))))))
|
||||
|
||||
@ -8,46 +8,18 @@
|
||||
(:require
|
||||
[app.common.uuid :as uuid]
|
||||
[benches.render-wasm.scenes.builder :as builder :include-macros true]
|
||||
[benches.render-wasm.scenes.common :as common]
|
||||
[cljs.test :as t :include-macros true]))
|
||||
|
||||
(defn- failure-data
|
||||
[f]
|
||||
(try
|
||||
(f)
|
||||
nil
|
||||
(catch :default cause
|
||||
(ex-data cause))))
|
||||
|
||||
(defn- child-ids
|
||||
"Ids listed in the :shapes vector of `id`."
|
||||
[instance id]
|
||||
(get-in instance [:objects id :shapes]))
|
||||
|
||||
(defn- children-of
|
||||
"Child shapes of `id` in order."
|
||||
[instance id]
|
||||
(mapv (:objects instance) (child-ids instance id)))
|
||||
|
||||
(defn- run-scope
|
||||
"Runs `f` inside a raw scope and returns the scope state, so tests can
|
||||
inspect partial builds without calling finish!."
|
||||
[params f]
|
||||
(let [state (builder/start params)]
|
||||
(binding [builder/*state* state
|
||||
builder/*defaults* {}]
|
||||
(f))
|
||||
state))
|
||||
[cljs.test :as t :include-macros true]
|
||||
[frontend-tests.benches.test-helpers :as helpers]))
|
||||
|
||||
(t/deftest frame-attaches-children-in-order
|
||||
(let [instance (builder/fixture {:seed 1}
|
||||
(builder/frame {:x 0 :y 0 :width 100 :height 100 :name "F"}
|
||||
(builder/rect {:x 10 :y 10 :width 5 :height 5})
|
||||
(builder/rect {:x 20 :y 20 :width 5 :height 5})))
|
||||
frame (first (children-of instance uuid/zero))
|
||||
rects (children-of instance (:id frame))]
|
||||
frame (first (helpers/children-of instance uuid/zero))
|
||||
rects (helpers/children-of instance (:id frame))]
|
||||
(t/is (= :frame (:type frame)))
|
||||
(t/is (= [(:id frame)] (child-ids instance uuid/zero)))
|
||||
(t/is (= [(:id frame)] (helpers/child-ids instance uuid/zero)))
|
||||
(t/is (= 2 (count rects)))
|
||||
(t/is (every? #(= (:id frame) (:parent-id %)) rects))
|
||||
(t/is (every? #(= (:id frame) (:frame-id %)) rects))
|
||||
@ -60,9 +32,9 @@
|
||||
(builder/frame {:x 0 :y 0 :width 100 :height 100 :name "Outer"}
|
||||
(builder/frame {:x 10 :y 10 :width 50 :height 50 :name "Inner"}
|
||||
(builder/rect {:x 20 :y 20 :width 5 :height 5}))))
|
||||
outer (first (children-of instance uuid/zero))
|
||||
inner (first (children-of instance (:id outer)))
|
||||
rect (first (children-of instance (:id inner)))]
|
||||
outer (first (helpers/children-of instance uuid/zero))
|
||||
inner (first (helpers/children-of instance (:id outer)))
|
||||
rect (first (helpers/children-of instance (:id inner)))]
|
||||
(t/is (= uuid/zero (:frame-id outer)))
|
||||
(t/is (= (:id outer) (:parent-id inner)))
|
||||
(t/is (= (:id outer) (:frame-id inner)))
|
||||
@ -75,14 +47,11 @@
|
||||
(builder/group {}
|
||||
(builder/rect {:x 10 :y 20 :width 30 :height 40})
|
||||
(builder/rect {:x 50 :y 80 :width 10 :height 10})))
|
||||
group (first (children-of instance uuid/zero))
|
||||
rects (children-of instance (:id group))]
|
||||
group (first (helpers/children-of instance uuid/zero))
|
||||
rects (helpers/children-of instance (:id group))]
|
||||
(t/is (= :group (:type group)))
|
||||
(t/is (= [10 20 50 70]
|
||||
[(:x group) (:y group) (:width group) (:height group)]))
|
||||
(t/is (= [10 20 50 70]
|
||||
[(:x (:selrect group)) (:y (:selrect group))
|
||||
(:width (:selrect group)) (:height (:selrect group))]))
|
||||
(t/is (every? #(= uuid/zero (:frame-id %)) rects))
|
||||
(t/is (every? #(= (:id group) (:parent-id %)) rects))))
|
||||
|
||||
@ -92,8 +61,8 @@
|
||||
(builder/rect {:x 0 :y 0 :width 10 :height 10})
|
||||
(builder/group {:name "Inner"}
|
||||
(builder/rect {:x 100 :y 100 :width 10 :height 10}))))
|
||||
outer (first (children-of instance uuid/zero))
|
||||
inner (second (children-of instance (:id outer)))]
|
||||
outer (first (helpers/children-of instance uuid/zero))
|
||||
inner (second (helpers/children-of instance (:id outer)))]
|
||||
(t/is (= :group (:type inner)))
|
||||
(t/is (= [100 100 10 10]
|
||||
[(:x inner) (:y inner) (:width inner) (:height inner)]))
|
||||
@ -105,9 +74,9 @@
|
||||
(builder/frame {:x 0 :y 0 :width 200 :height 200}
|
||||
(builder/group {}
|
||||
(builder/rect {:x 10 :y 10 :width 10 :height 10}))))
|
||||
frame (first (children-of instance uuid/zero))
|
||||
group (first (children-of instance (:id frame)))
|
||||
rect (first (children-of instance (:id group)))]
|
||||
frame (first (helpers/children-of instance uuid/zero))
|
||||
group (first (helpers/children-of instance (:id frame)))
|
||||
rect (first (helpers/children-of instance (:id group)))]
|
||||
(t/is (= (:id frame) (:frame-id group)))
|
||||
(t/is (= (:id frame) (:frame-id rect)))
|
||||
(t/is (= (:id group) (:parent-id rect)))))
|
||||
@ -117,7 +86,7 @@
|
||||
(builder/group {:masked-group true}
|
||||
(builder/rect {:x 10 :y 20 :width 30 :height 40})
|
||||
(builder/rect {:x 0 :y 0 :width 500 :height 500})))
|
||||
group (first (children-of instance uuid/zero))]
|
||||
group (first (helpers/children-of instance uuid/zero))]
|
||||
(t/is (true? (:masked-group group)))
|
||||
(t/is (= [10 20 30 40]
|
||||
[(:x group) (:y group) (:width group) (:height group)]))))
|
||||
@ -129,25 +98,16 @@
|
||||
(builder/rect))))
|
||||
refs (:refs instance)]
|
||||
(t/is (= #{:hero [:g 1]} (set (keys refs))))
|
||||
(t/is (= (get refs :hero) (first (child-ids instance uuid/zero))))
|
||||
(t/is (= (get refs [:g 1]) (first (child-ids instance (get refs :hero)))))
|
||||
(t/is (= 1 (count (child-ids instance uuid/zero))))))
|
||||
|
||||
(t/deftest nested-order-follows-construction
|
||||
(let [instance (builder/fixture {:seed 1}
|
||||
(builder/frame {:x 0 :y 0 :width 100 :height 100}
|
||||
(builder/rect)
|
||||
(builder/group {}
|
||||
(builder/rect))))
|
||||
order (mapv :type (common/upload-order instance))]
|
||||
(t/is (= [:frame :frame :rect :group :rect] order))))
|
||||
(t/is (= (get refs :hero) (first (helpers/child-ids instance uuid/zero))))
|
||||
(t/is (= (get refs [:g 1]) (first (helpers/child-ids instance (get refs :hero)))))
|
||||
(t/is (= 1 (count (helpers/child-ids instance uuid/zero))))))
|
||||
|
||||
(t/deftest empty-group-is-rejected
|
||||
(let [data (failure-data #(builder/fixture {:seed 1} (builder/group {})))]
|
||||
(let [data (helpers/failure-data #(builder/fixture {:seed 1} (builder/group {})))]
|
||||
(t/is (= ::builder/empty-group (:type data)))))
|
||||
|
||||
(t/deftest group-geometry-attrs-are-rejected
|
||||
(let [data (failure-data
|
||||
(let [data (helpers/failure-data
|
||||
#(builder/fixture {:seed 1}
|
||||
(builder/group {:x 1}
|
||||
(builder/rect))))]
|
||||
@ -155,7 +115,7 @@
|
||||
(t/is (= :x (:key data)))))
|
||||
|
||||
(t/deftest frame-requires-bounds
|
||||
(let [data (failure-data
|
||||
(let [data (helpers/failure-data
|
||||
#(builder/fixture {:seed 1}
|
||||
(builder/frame {:name "F"}
|
||||
(builder/rect))))]
|
||||
@ -166,24 +126,24 @@
|
||||
instance (builder/fixture {:seed 1}
|
||||
(builder/frame frame-attrs
|
||||
(builder/rect)))
|
||||
frame (first (children-of instance uuid/zero))]
|
||||
frame (first (helpers/children-of instance uuid/zero))]
|
||||
(t/is (= :frame (:type frame)))
|
||||
(t/is (= 10 (:width frame)))))
|
||||
|
||||
(t/deftest non-map-attrs-are-rejected
|
||||
(t/is (= ::builder/invalid-attrs
|
||||
(:type (failure-data
|
||||
(:type (helpers/failure-data
|
||||
#(builder/fixture {:seed 1}
|
||||
(builder/frame :hero (builder/rect)))))))
|
||||
(let [state (run-scope {:seed 1}
|
||||
(fn []
|
||||
(try
|
||||
(builder/frame :hero (builder/rect))
|
||||
(catch :default _ nil))))]
|
||||
(t/is (= 1 (count (child-ids @state uuid/zero))))))
|
||||
(let [state (helpers/run-scope {:seed 1}
|
||||
(fn []
|
||||
(try
|
||||
(builder/frame :hero (builder/rect))
|
||||
(catch :default _ nil))))]
|
||||
(t/is (= 1 (count (helpers/child-ids @state uuid/zero))))))
|
||||
|
||||
(t/deftest non-numeric-frame-bounds-are-rejected
|
||||
(let [data (failure-data
|
||||
(let [data (helpers/failure-data
|
||||
#(builder/fixture {:seed 1}
|
||||
(builder/frame {:x 0 :y 0 :width "100" :height 10}
|
||||
(builder/rect))))]
|
||||
@ -191,7 +151,7 @@
|
||||
(t/is (= :width (:invalid data)))))
|
||||
|
||||
(t/deftest duplicate-container-labels-are-rejected
|
||||
(let [data (failure-data
|
||||
(let [data (helpers/failure-data
|
||||
#(builder/fixture {:seed 1}
|
||||
(builder/frame :dup {:x 0 :y 0 :width 10 :height 10}
|
||||
(builder/rect))
|
||||
@ -205,9 +165,9 @@
|
||||
(builder/group {}
|
||||
(builder/frame {:x 0 :y 0 :width 50 :height 50}
|
||||
(builder/rect))))
|
||||
group (first (children-of instance uuid/zero))
|
||||
frame (first (children-of instance (:id group)))
|
||||
rect (first (children-of instance (:id frame)))]
|
||||
group (first (helpers/children-of instance uuid/zero))
|
||||
frame (first (helpers/children-of instance (:id group)))
|
||||
rect (first (helpers/children-of instance (:id frame)))]
|
||||
(t/is (= (:id group) (:parent-id frame)))
|
||||
(t/is (= uuid/zero (:frame-id frame)))
|
||||
(t/is (= (:id frame) (:parent-id rect)))
|
||||
@ -218,44 +178,44 @@
|
||||
(builder/group {}
|
||||
(builder/group {}
|
||||
(builder/rect {:x 5 :y 5 :width 10 :height 10}))))
|
||||
outer (first (children-of instance uuid/zero))
|
||||
inner (first (children-of instance (:id outer)))]
|
||||
outer (first (helpers/children-of instance uuid/zero))
|
||||
inner (first (helpers/children-of instance (:id outer)))]
|
||||
(t/is (= [5 5 10 10]
|
||||
[(:x outer) (:y outer) (:width outer) (:height outer)]))
|
||||
(t/is (= [5 5 10 10]
|
||||
[(:x inner) (:y inner) (:width inner) (:height inner)]))
|
||||
(t/is (= 1 (count (child-ids instance (:id outer)))))))
|
||||
(t/is (= 1 (count (helpers/child-ids instance (:id outer)))))))
|
||||
|
||||
(t/deftest empty-frame-is-allowed
|
||||
(let [instance (builder/fixture {:seed 1}
|
||||
(builder/frame {:x 0 :y 0 :width 10 :height 10}))
|
||||
frame (first (children-of instance uuid/zero))]
|
||||
(t/is (= [] (child-ids instance (:id frame))))))
|
||||
frame (first (helpers/children-of instance uuid/zero))]
|
||||
(t/is (= [] (helpers/child-ids instance (:id frame))))))
|
||||
|
||||
(t/deftest caught-empty-group-still-fails-finish
|
||||
(let [state (run-scope {:seed 1}
|
||||
(fn []
|
||||
(try
|
||||
(builder/group {})
|
||||
(catch :default _ nil))))]
|
||||
(let [state (helpers/run-scope {:seed 1}
|
||||
(fn []
|
||||
(try
|
||||
(builder/group {})
|
||||
(catch :default _ nil))))]
|
||||
(t/is (= ::builder/unfinished-container
|
||||
(:type (failure-data #(builder/finish! state)))))))
|
||||
(:type (helpers/failure-data #(builder/finish! state)))))))
|
||||
|
||||
(t/deftest container-failure-restores-parent-and-marks-unfinished
|
||||
(let [state (run-scope {:seed 1}
|
||||
(fn []
|
||||
(builder/rect {:x 0})
|
||||
(try
|
||||
(builder/frame {:x 0 :y 0 :width 10 :height 10}
|
||||
(builder/rect :dup {:x 1})
|
||||
(builder/rect :dup {:x 2}))
|
||||
(catch :default _ nil))
|
||||
(builder/rect {:x 3})))
|
||||
root-children (child-ids @state uuid/zero)
|
||||
(let [state (helpers/run-scope {:seed 1}
|
||||
(fn []
|
||||
(builder/rect {:x 0})
|
||||
(try
|
||||
(builder/frame {:x 0 :y 0 :width 10 :height 10}
|
||||
(builder/rect :dup {:x 1})
|
||||
(builder/rect :dup {:x 2}))
|
||||
(catch :default _ nil))
|
||||
(builder/rect {:x 3})))
|
||||
root-children (helpers/child-ids @state uuid/zero)
|
||||
last-child (get-in @state [:objects (last root-children)])]
|
||||
(t/is (= 3 (count root-children)))
|
||||
(t/is (= :rect (:type last-child)))
|
||||
(t/is (= 3 (:x last-child)))
|
||||
(t/is (= 1 (count (:unfinished @state))))
|
||||
(t/is (= ::builder/unfinished-container
|
||||
(:type (failure-data #(builder/finish! state)))))))
|
||||
(:type (helpers/failure-data #(builder/finish! state)))))))
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
[app.common.schema :as sm]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.common.uuid :as uuid]
|
||||
[benches.render-wasm.scenes.common :as fixture]
|
||||
[benches.render-wasm.scenes.common :as common]
|
||||
[cljs.test :as t :include-macros true]))
|
||||
|
||||
(defn- sample-instance
|
||||
@ -67,7 +67,7 @@
|
||||
"Returns the ex-data of the validation failure, or nil when it passes."
|
||||
[instance]
|
||||
(try
|
||||
(fixture/validate! instance)
|
||||
(common/validate! instance)
|
||||
nil
|
||||
(catch :default cause
|
||||
(ex-data cause))))
|
||||
@ -75,14 +75,14 @@
|
||||
(t/deftest canonical-example-is-valid
|
||||
(t/testing "validate! returns the same instance"
|
||||
(let [instance (sample-instance)]
|
||||
(t/is (identical? instance (fixture/validate! instance)))))
|
||||
(t/is (identical? instance (common/validate! instance)))))
|
||||
|
||||
(t/testing "the envelope schema accepts the example"
|
||||
(t/is (true? (sm/validate fixture/schema:instance (sample-instance))))))
|
||||
(t/is (true? (sm/validate common/schema:instance (sample-instance))))))
|
||||
|
||||
(t/deftest nested-hierarchy-is-valid
|
||||
(let [instance (nested-instance)]
|
||||
(t/is (identical? instance (fixture/validate! instance)))))
|
||||
(t/is (identical? instance (common/validate! instance)))))
|
||||
|
||||
(t/deftest root-only-instance-is-valid
|
||||
(let [root (cts/setup-shape {:id uuid/zero :type :frame :name "Root Frame"
|
||||
@ -90,18 +90,17 @@
|
||||
:parent-id uuid/zero :frame-id uuid/zero
|
||||
:shapes []})
|
||||
instance {:objects {uuid/zero root} :refs {}}]
|
||||
(t/is (identical? instance (fixture/validate! instance)))
|
||||
(t/is (= [uuid/zero] (mapv :id (fixture/upload-order instance))))))
|
||||
(t/is (identical? instance (common/validate! instance)))
|
||||
(t/is (= [uuid/zero] (mapv :id (common/upload-order instance))))))
|
||||
|
||||
(t/deftest upload-order-starts-at-root
|
||||
(let [instance (sample-instance)
|
||||
ids (mapv :id (fixture/upload-order instance))]
|
||||
(t/is (= uuid/zero (first ids)))
|
||||
(t/is (= [uuid/zero (fixture/ref-id instance :rect)] ids))))
|
||||
ids (mapv :id (common/upload-order instance))]
|
||||
(t/is (= [uuid/zero (common/ref-id instance :rect)] ids))))
|
||||
|
||||
(t/deftest upload-order-is-parent-before-child
|
||||
(let [instance (nested-instance)
|
||||
order (fixture/upload-order instance)
|
||||
order (common/upload-order instance)
|
||||
names (mapv :name order)
|
||||
position (into {} (map-indexed (fn [index shape] [(:id shape) index]) order))]
|
||||
(t/is (= ["Root Frame" "A" "A1" "A2" "B" "B1"] names))
|
||||
@ -135,39 +134,39 @@
|
||||
a-id shape-a
|
||||
b-id shape-b}
|
||||
:refs {}}]
|
||||
(t/is (identical? instance (fixture/validate! instance)))
|
||||
(t/is (identical? instance (common/validate! instance)))
|
||||
(t/is (= ["Root Frame" "Flex" "B" "A"]
|
||||
(mapv :name (fixture/upload-order instance))))))
|
||||
(mapv :name (common/upload-order instance))))))
|
||||
|
||||
(t/deftest ref-id-resolves-labels
|
||||
(let [instance (sample-instance)]
|
||||
(t/is (= (uuid/custom 1 1) (fixture/ref-id instance :rect)))
|
||||
(t/is (nil? (fixture/ref-id instance :missing)))))
|
||||
(t/is (= (uuid/custom 1 1) (common/ref-id instance :rect)))
|
||||
(t/is (nil? (common/ref-id instance :missing)))))
|
||||
|
||||
(t/deftest missing-root-is-rejected
|
||||
(let [instance (sample-instance)
|
||||
data (validation-error (update instance :objects dissoc uuid/zero))]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (= uuid/zero (:id data)))))
|
||||
|
||||
(t/deftest non-frame-root-is-rejected
|
||||
(let [instance (sample-instance)
|
||||
data (validation-error (assoc-in instance [:objects uuid/zero :type] :rect))]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (= uuid/zero (:id data)))))
|
||||
|
||||
(t/deftest root-with-non-zero-parent-id-is-rejected
|
||||
(let [instance (sample-instance)
|
||||
data (validation-error
|
||||
(assoc-in instance [:objects uuid/zero :parent-id] (uuid/custom 9 9)))]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (= uuid/zero (:id data)))))
|
||||
|
||||
(t/deftest object-key-must-match-shape-id
|
||||
(let [instance (sample-instance)
|
||||
rect (get-in instance [:objects (fixture/ref-id instance :rect)])
|
||||
rect (get-in instance [:objects (common/ref-id instance :rect)])
|
||||
data (validation-error (assoc-in instance [:objects (uuid/custom 7 7)] rect))]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (= (:id rect) (:shape-id data)))))
|
||||
|
||||
(t/deftest missing-child-is-rejected
|
||||
@ -175,32 +174,32 @@
|
||||
bogus (uuid/custom 3 3)
|
||||
data (validation-error
|
||||
(assoc-in instance [:objects uuid/zero :shapes] [bogus]))]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (= bogus (:child data)))))
|
||||
|
||||
(t/deftest child-not-listed-by-parent-is-rejected
|
||||
(let [instance (sample-instance)
|
||||
rect-id (fixture/ref-id instance :rect)
|
||||
rect-id (common/ref-id instance :rect)
|
||||
data (validation-error (assoc-in instance [:objects uuid/zero :shapes] []))]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (= "object is not reachable from the root" (:hint data)))
|
||||
(t/is (= rect-id (:id data)))))
|
||||
|
||||
(t/deftest mismatched-parent-id-is-rejected
|
||||
(let [instance (sample-instance)
|
||||
rect-id (fixture/ref-id instance :rect)
|
||||
rect-id (common/ref-id instance :rect)
|
||||
data (validation-error
|
||||
(assoc-in instance [:objects rect-id :parent-id] (uuid/custom 9 7)))]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (= "shape :shapes lists a child with a different :parent-id" (:hint data)))
|
||||
(t/is (= rect-id (:child data)))))
|
||||
|
||||
(t/deftest duplicate-child-ids-are-rejected
|
||||
(let [instance (sample-instance)
|
||||
rect-id (fixture/ref-id instance :rect)
|
||||
rect-id (common/ref-id instance :rect)
|
||||
data (validation-error
|
||||
(assoc-in instance [:objects uuid/zero :shapes] [rect-id rect-id]))]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (= "an object is reachable more than once" (:hint data)))
|
||||
(t/is (= rect-id (:id data)))))
|
||||
|
||||
@ -208,7 +207,7 @@
|
||||
(let [instance (sample-instance)
|
||||
data (validation-error
|
||||
(assoc-in instance [:objects uuid/zero :shapes] [uuid/zero]))]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (= "root must not be a descendant of itself" (:hint data)))
|
||||
(t/is (= uuid/zero (:id data)))))
|
||||
|
||||
@ -228,7 +227,7 @@
|
||||
(assoc (get (sample-instance) :objects)
|
||||
c1-id shape1
|
||||
c2-id shape2)))]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (= "object is not reachable from the root" (:hint data)))
|
||||
(t/is (contains? #{c1-id c2-id} (:id data)))))
|
||||
|
||||
@ -248,24 +247,24 @@
|
||||
(assoc-in [:objects a-id] shape-a)
|
||||
(assoc-in [:objects b-id] shape-b))
|
||||
data (validation-error instance)]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (= "shape :shapes lists a child with a different :parent-id" (:hint data)))
|
||||
(t/is (= a-id (:child data)))))
|
||||
|
||||
(t/deftest non-vector-children-are-rejected
|
||||
(let [instance (sample-instance)
|
||||
rect-id (fixture/ref-id instance :rect)
|
||||
rect-id (common/ref-id instance :rect)
|
||||
data (validation-error (assoc-in instance [:objects rect-id :shapes] 5))]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (= "shape :shapes must be a vector" (:hint data)))
|
||||
(t/is (= rect-id (:id data)))))
|
||||
|
||||
(t/deftest frame-id-mismatch-is-rejected
|
||||
(let [instance (nested-instance)
|
||||
a1-id (fixture/ref-id instance :a1)
|
||||
a1-id (common/ref-id instance :a1)
|
||||
data (validation-error
|
||||
(assoc-in instance [:objects a1-id :frame-id] uuid/zero))]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (= :invalid-frame (:code data)))
|
||||
(t/is (= a1-id (:shape-id data)))))
|
||||
|
||||
@ -273,45 +272,45 @@
|
||||
(let [instance (sample-instance)
|
||||
data (validation-error
|
||||
(assoc-in instance [:refs :rect] (uuid/custom 6 6)))]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (= :rect (:label data)))))
|
||||
|
||||
(t/deftest non-uuid-ref-value-is-rejected
|
||||
(let [data (validation-error (assoc-in (sample-instance) [:refs :rect] "not-a-uuid"))]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (some? (::sm/explain data)))))
|
||||
|
||||
(t/deftest missing-refs-key-is-rejected
|
||||
(let [data (validation-error (dissoc (sample-instance) :refs))]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (some? (::sm/explain data)))))
|
||||
|
||||
(t/deftest non-canonical-shape-is-rejected
|
||||
(let [instance (sample-instance)
|
||||
rect-id (fixture/ref-id instance :rect)
|
||||
rect-id (common/ref-id instance :rect)
|
||||
data (validation-error (assoc-in instance [:objects rect-id] {:id rect-id}))]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (some? (::sm/explain data)))))
|
||||
|
||||
(t/deftest malformed-envelopes-are-rejected
|
||||
(t/testing "empty objects map"
|
||||
(let [data (validation-error {:objects {} :refs {}})]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (= uuid/zero (:id data)))))
|
||||
|
||||
(t/testing "nil instance"
|
||||
(let [data (validation-error nil)]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (some? (::sm/explain data)))))
|
||||
|
||||
(t/testing "nil shape value"
|
||||
(let [instance (sample-instance)
|
||||
rect-id (fixture/ref-id instance :rect)
|
||||
rect-id (common/ref-id instance :rect)
|
||||
data (validation-error (assoc-in instance [:objects rect-id] nil))]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (some? (::sm/explain data)))))
|
||||
|
||||
(t/testing "nil ref value"
|
||||
(let [data (validation-error (assoc-in (sample-instance) [:refs :rect] nil))]
|
||||
(t/is (= ::fixture/invalid-fixture (:type data)))
|
||||
(t/is (= ::common/invalid-fixture (:type data)))
|
||||
(t/is (some? (::sm/explain data))))))
|
||||
|
||||
49
frontend/test/frontend_tests/benches/test_helpers.cljs
Normal file
49
frontend/test/frontend_tests/benches/test_helpers.cljs
Normal file
@ -0,0 +1,49 @@
|
||||
(ns frontend-tests.benches.test-helpers
|
||||
"Shared helpers for renderer benchmark fixture tests.
|
||||
|
||||
These helpers assert nothing about shapes or the renderer. They only
|
||||
capture errors, read root children in order, and run raw scopes so each
|
||||
test namespace tells a complete story without copying bodies."
|
||||
(:require
|
||||
[app.common.uuid :as uuid]
|
||||
[benches.render-wasm.scenes.builder :as builder]))
|
||||
|
||||
(defn failure-data
|
||||
"Returns the ex-data of the thrown failure, or nil when `f` passes."
|
||||
[f]
|
||||
(try
|
||||
(f)
|
||||
nil
|
||||
(catch :default cause
|
||||
(ex-data cause))))
|
||||
|
||||
(defn child-ids
|
||||
"Ids listed in the :shapes vector of `id`."
|
||||
[instance id]
|
||||
(get-in instance [:objects id :shapes]))
|
||||
|
||||
(defn children-of
|
||||
"Child shapes of `id` in order."
|
||||
[instance id]
|
||||
(mapv (:objects instance) (child-ids instance id)))
|
||||
|
||||
(defn root-shapes
|
||||
"Root children of a fixture instance in creation order."
|
||||
[instance]
|
||||
(children-of instance uuid/zero))
|
||||
|
||||
(defn run-scope
|
||||
"Runs `f` inside a raw scope and returns the scope state, so tests can
|
||||
inspect partial builds without calling finish!."
|
||||
[params f]
|
||||
(let [state (builder/start params)]
|
||||
(binding [builder/*state* state
|
||||
builder/*defaults* {}]
|
||||
(f))
|
||||
state))
|
||||
|
||||
(defn selrect
|
||||
"Selrect of `shape` as an [x y width height] tuple."
|
||||
[shape]
|
||||
[(:x (:selrect shape)) (:y (:selrect shape))
|
||||
(:width (:selrect shape)) (:height (:selrect shape))])
|
||||
Loading…
x
Reference in New Issue
Block a user