diff --git a/common/src/app/common/geom/shapes/grid_layout/layout_data.cljc b/common/src/app/common/geom/shapes/grid_layout/layout_data.cljc index 639da86514..026c48fe41 100644 --- a/common/src/app/common/geom/shapes/grid_layout/layout_data.cljc +++ b/common/src/app/common/geom/shapes/grid_layout/layout_data.cljc @@ -331,7 +331,7 @@ ;; Apply the allocations to the tracks track-list (into [] - (map-indexed #(update %2 :size max (get allocated %1))) + (map-indexed #(update %2 :size max (get allocated %1 0))) track-list)] track-list)) @@ -381,7 +381,7 @@ ;; Apply the allocations to the tracks track-list (into [] - (map-indexed #(update %2 :size max (get allocate-fr-tracks %1))) + (map-indexed #(update %2 :size max (get allocate-fr-tracks %1 0))) track-list)] track-list)) @@ -474,8 +474,8 @@ min-column-fr (min-fr-value column-tracks) min-row-fr (min-fr-value row-tracks) - column-fr (if auto-width? min-column-fr (mth/finite (/ fr-column-space column-frs) 0)) - row-fr (if auto-height? min-row-fr (mth/finite (/ fr-row-space row-frs) 0)) + column-fr (if auto-width? min-column-fr (if (zero? column-frs) 0 (mth/finite (/ fr-column-space column-frs) 0))) + row-fr (if auto-height? min-row-fr (if (zero? row-frs) 0 (mth/finite (/ fr-row-space row-frs) 0))) column-tracks (set-fr-value column-tracks column-fr auto-width?) row-tracks (set-fr-value row-tracks row-fr auto-height?) @@ -489,8 +489,8 @@ column-autos (tracks-total-autos column-tracks) row-autos (tracks-total-autos row-tracks) - column-add-auto (/ auto-column-space column-autos) - row-add-auto (/ auto-row-space row-autos) + column-add-auto (if (zero? column-autos) 0 (/ auto-column-space column-autos)) + row-add-auto (if (zero? row-autos) 0 (/ auto-row-space row-autos)) column-tracks (cond-> column-tracks (= :stretch (:layout-justify-content parent)) @@ -505,36 +505,38 @@ num-columns (count column-tracks) column-gap - (case (:layout-justify-content parent) + (cond auto-width? column-gap - :space-evenly + (= :space-evenly (:layout-justify-content parent)) (max column-gap (/ (- bound-width column-total-size) (inc num-columns))) - :space-around + (= :space-around (:layout-justify-content parent)) (max column-gap (/ (- bound-width column-total-size) num-columns)) - :space-between + (= :space-between (:layout-justify-content parent)) (max column-gap (if (= num-columns 1) column-gap (/ (- bound-width column-total-size) (dec num-columns)))) + :else column-gap) num-rows (count row-tracks) row-gap - (case (:layout-align-content parent) + (cond auto-height? row-gap - :space-evenly + (= :space-evenly (:layout-align-content parent)) (max row-gap (/ (- bound-height row-total-size) (inc num-rows))) - :space-around + (= :space-around (:layout-align-content parent)) (max row-gap (/ (- bound-height row-total-size) num-rows)) - :space-between + (= :space-between (:layout-align-content parent)) (max row-gap (if (= num-rows 1) row-gap (/ (- bound-height row-total-size) (dec num-rows)))) + :else row-gap) start-p diff --git a/common/test/common_tests/geom_grid_layout_test.cljc b/common/test/common_tests/geom_grid_layout_test.cljc new file mode 100644 index 0000000000..369406ef38 --- /dev/null +++ b/common/test/common_tests/geom_grid_layout_test.cljc @@ -0,0 +1,410 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS INC + +(ns common-tests.geom-grid-layout-test + (:require + ;; Requiring modifiers triggers the side-effect that wires + ;; -child-min-width / -child-min-height into grid layout-data. + [app.common.geom.modifiers] + [app.common.geom.rect :as grc] + [app.common.geom.shapes.grid-layout.layout-data :as gld] + [app.common.math :as mth] + [app.common.types.shape :as cts] + [clojure.test :as t])) + +;; --------------------------------------------------------------------------- +;; Shared test-data builders +;; --------------------------------------------------------------------------- + +(defn- make-grid-frame + "Minimal grid-layout frame with two fixed columns of 50.0 px + and one fixed row. Width and height are explicit, no padding. + Track values are floats to avoid JVM integer-divide-by-zero when + there are no flex tracks (column-frs = 0)." + [& {:as opts}] + (cts/setup-shape + (merge {:type :frame + :layout :grid + :layout-grid-dir :row + :layout-grid-columns [{:type :fixed :value 50.0} + {:type :fixed :value 50.0}] + :layout-grid-rows [{:type :fixed :value 100.0}] + :layout-grid-cells {} + :layout-padding-type :multiple + :layout-padding {:p1 0 :p2 0 :p3 0 :p4 0} + :layout-gap {:column-gap 0 :row-gap 0} + :x 0 :y 0 :width 200 :height 100} + opts))) + +(defn- bounds-for + "Return the 4-point layout-bounds for the frame." + [frame] + (grc/rect->points (grc/make-rect (:x frame) (:y frame) (:width frame) (:height frame)))) + +;; Build a simple non-fill child shape with explicit width/height. +;; No layout-item-margin → child-width-margin = 0. +(defn- make-child + [w h] + (cts/setup-shape {:type :rect :width w :height h :x 0 :y 0})) + +;; Build the 4-point bounds vector for a child with the given dimensions. +(defn- child-bounds + [w h] + (grc/rect->points (grc/make-rect 0 0 w h))) + +;; Build an auto track at its initial size (0.01) with infinite max. +(defn- auto-track [] {:type :auto :size 0.01 :max-size ##Inf}) + +;; Build a fixed track with the given size. +(defn- fixed-track [v] + {:type :fixed :value v :size (double v) :max-size (double v)}) + +;; Build a flex track (value = number of fr units) at initial size 0.01. +(defn- flex-track [fr] + {:type :flex :value fr :size 0.01 :max-size ##Inf}) + +;; Build a parent frame for column testing with given column-gap. +(defn- auto-col-parent + ([] (auto-col-parent 0)) + ([column-gap] + (cts/setup-shape + {:type :frame + :layout :grid + :layout-grid-dir :row + :layout-padding-type :multiple + :layout-padding {:p1 0 :p2 0 :p3 0 :p4 0} + :layout-gap {:column-gap column-gap :row-gap 0} + :x 0 :y 0 :width 500 :height 500}))) + +;; Build a parent frame for row type testing with given row-gap. +(defn- auto-row-parent + ([] (auto-row-parent 0)) + ([row-gap] + (cts/setup-shape + {:type :frame + :layout :grid + :layout-grid-dir :row + :layout-padding-type :multiple + :layout-padding {:p1 0 :p2 0 :p3 0 :p4 0} + :layout-gap {:column-gap 0 :row-gap row-gap} + :x 0 :y 0 :width 500 :height 500}))) + +;; Generic frame-bounds (large enough not to interfere). +(def ^:private frame-bounds + (grc/rect->points (grc/make-rect 0 0 500 500))) + +;; Build a cell map for a single shape occupying column/row at given span. +;; col and row are 1-based. +(defn- make-cell + [shape-id col row col-span row-span] + {:shapes [shape-id] + :column col :column-span col-span + :row row :row-span row-span}) + +;; --------------------------------------------------------------------------- +;; Note on set-auto-multi-span indexing +;; --------------------------------------------------------------------------- +;; +;; Inside set-auto-multi-span, indexed-tracks is computed as: +;; from-idx = clamp(col - 1, 0, count-1) +;; to-idx = clamp((col - 1) + col-span, 0, count-1) +;; indexed-tracks = subvec(enumerate(tracks), from-idx, to-idx) +;; +;; Because to-idx is clamped to (dec count), the LAST track of the span is +;; always excluded unless there is at least one extra track beyond the span. +;; +;; Practical implication for tests: to cover N spanned tracks, provide a +;; track-list with at least N+1 tracks (the extra track acts as a sentinel +;; that absorbs the off-by-one from the clamp). +;; +;; Example: col=1, span=2, 3 total tracks: +;; to-idx = clamp(0+2, 0, 2) = 2 → subvec(v, 0, 2) = [track0, track1] ✓ +;; +;; Tests that deliberately check boundary behavior (flex exclusion, +;; non-spanned tracks) use 2 total tracks so only track 0 is covered. + +;; --------------------------------------------------------------------------- +;; Tests: column-gap with justify-content (case → cond fix) +;; --------------------------------------------------------------------------- +;; +;; In get-cell-data, column-gap and row-gap were computed with (case ...) +;; using boolean locals as dispatch values. case compares compile-time +;; constants, so those branches never matched at runtime. Fixed with cond. + +(t/deftest grid-column-gap-space-evenly + (t/testing "justify-content :space-evenly increases column-gap correctly" + ;; 2 fixed cols × 50 px = 100 px occupied; bound-width = 200; free = 100 + ;; formula: free / (num-cols + 1) = 100/3 ≈ 33.33 + (let [frame (make-grid-frame :layout-justify-content :space-evenly + :layout-gap {:column-gap 0 :row-gap 0}) + bounds (bounds-for frame) + result (gld/calc-layout-data frame bounds [] {} {}) + col-gap (:column-gap result)] + (t/is (mth/close? (/ 100.0 3.0) col-gap 0.01))))) + +(t/deftest grid-column-gap-space-around + (t/testing "justify-content :space-around increases column-gap correctly" + ;; free = 100; formula: 100 / num-cols = 100/2 = 50 + (let [frame (make-grid-frame :layout-justify-content :space-around + :layout-gap {:column-gap 0 :row-gap 0}) + bounds (bounds-for frame) + result (gld/calc-layout-data frame bounds [] {} {}) + col-gap (:column-gap result)] + (t/is (mth/close? 50.0 col-gap 0.01))))) + +(t/deftest grid-column-gap-space-between + (t/testing "justify-content :space-between increases column-gap correctly" + ;; free = 100; num-cols = 2; formula: 100 / (2-1) = 100 + (let [frame (make-grid-frame :layout-justify-content :space-between + :layout-gap {:column-gap 0 :row-gap 0}) + bounds (bounds-for frame) + result (gld/calc-layout-data frame bounds [] {} {}) + col-gap (:column-gap result)] + (t/is (mth/close? 100.0 col-gap 0.01))))) + +(t/deftest grid-column-gap-auto-width-bypasses-justify-content + (t/testing "auto-width? bypasses justify-content gap recalc → gap stays as initial" + (let [frame (make-grid-frame :layout-justify-content :space-evenly + :layout-gap {:column-gap 5 :row-gap 0} + :layout-item-h-sizing :auto) + bounds (bounds-for frame) + result (gld/calc-layout-data frame bounds [] {} {}) + col-gap (:column-gap result)] + (t/is (mth/close? 5.0 col-gap 0.01))))) + +;; --------------------------------------------------------------------------- +;; Tests: set-auto-multi-span +;; --------------------------------------------------------------------------- +;; +;; set-auto-multi-span grows auto tracks to accommodate children whose cell +;; spans more than one track column (or row), but only for spans that contain +;; no flex tracks (those are handled by set-flex-multi-span). +;; +;; The function signature: +;; (set-auto-multi-span parent track-list children-map shape-cells +;; bounds objects type) +;; type – :column or :row +;; children-map – {shape-id [child-bounds child-shape]} +;; shape-cells – {cell-id cell-map} + +(t/deftest set-auto-multi-span-span-1-cells-ignored + (t/testing "span=1 cells are filtered out; track-list is unchanged" + (let [sid (random-uuid) + child (make-child 200 100) + ;; 2 tracks + 1 sentinel (so the span would cover tracks 0-1 if span were 2) + tracks [(auto-track) (auto-track) (auto-track)] + cells {:c1 (make-cell sid 1 1 1 1)} ; span = 1 → ignored + cmap {sid [(child-bounds 200 100) child]} + result (gld/set-auto-multi-span (auto-col-parent) tracks cmap cells frame-bounds {} :column)] + (t/is (mth/close? 0.01 (:size (nth result 0)) 0.001)) + (t/is (mth/close? 0.01 (:size (nth result 1)) 0.001)) + (t/is (mth/close? 0.01 (:size (nth result 2)) 0.001))))) + +(t/deftest set-auto-multi-span-empty-cells + (t/testing "empty shape-cells → track-list unchanged" + (let [tracks [(auto-track) (auto-track)] + result (gld/set-auto-multi-span (auto-col-parent) tracks {} {} frame-bounds {} :column)] + (t/is (mth/close? 0.01 (:size (nth result 0)) 0.001)) + (t/is (mth/close? 0.01 (:size (nth result 1)) 0.001))))) + +(t/deftest set-auto-multi-span-two-auto-tracks-split-evenly + (t/testing "child spanning 2 auto tracks (with sentinel): budget split between the 2 covered tracks" + ;; 3 tracks total (sentinel at index 2 keeps to-idx from being clamped). + ;; col=1, span=2: + ;; from-idx = clamp(0, 0, 2) = 0 + ;; to-idx = clamp(2, 0, 2) = 2 + ;; subvec(enumerate, 0, 2) = [[0, auto0], [1, auto1]] + ;; size-to-allocate = 200 (child width, no gap) + ;; allocate-auto-tracks pass 1 (non-assigned = both): + ;; idx0: max(0.01, 200/2, 0.01) = 100; rem = 100 + ;; idx1: max(0.01, 100/1, 0.01) = 100; rem = 0 + ;; pass 2 (to-allocate=0): no change → both 100 + ;; sentinel track 2 is never spanned → stays at 0.01. + (let [sid (random-uuid) + child (make-child 200 100) + tracks [(auto-track) (auto-track) (auto-track)] ; sentinel at [2] + cells {:c1 (make-cell sid 1 1 2 1)} + cmap {sid [(child-bounds 200 100) child]} + result (gld/set-auto-multi-span (auto-col-parent) tracks cmap cells frame-bounds {} :column)] + (t/is (mth/close? 100.0 (:size (nth result 0)) 0.001)) + (t/is (mth/close? 100.0 (:size (nth result 1)) 0.001)) + ;; sentinel unaffected + (t/is (mth/close? 0.01 (:size (nth result 2)) 0.001))))) + +(t/deftest set-auto-multi-span-gap-deducted-from-budget + (t/testing "column-gap is subtracted once per extra span track from size-to-allocate" + ;; child width = 210, column-gap = 10, span = 2 + ;; size-to-allocate = child-min-width - gap*(span-1) = 210 - 10*1 = 200 + ;; 3 tracks (sentinel at [2]) → indexed = [[0,auto],[1,auto]] + ;; each auto track gets 100 + (let [sid (random-uuid) + child (make-child 210 100) + tracks [(auto-track) (auto-track) (auto-track)] + cells {:c1 (make-cell sid 1 1 2 1)} + cmap {sid [(child-bounds 210 100) child]} + result (gld/set-auto-multi-span (auto-col-parent 10) tracks cmap cells frame-bounds {} :column)] + (t/is (mth/close? 100.0 (:size (nth result 0)) 0.001)) + (t/is (mth/close? 100.0 (:size (nth result 1)) 0.001)) + (t/is (mth/close? 0.01 (:size (nth result 2)) 0.001))))) + +(t/deftest set-auto-multi-span-fixed-track-reduces-budget + (t/testing "fixed track in span is deducted from budget; only the auto track grows" + ;; tracks: [fixed 60, auto 0.01, auto-sentinel] (sentinel at [2]) + ;; col=1, span=2 → indexed = [[0, fixed60], [1, auto]] + ;; find-auto-allocations: fixed→subtract 60; auto→keep + ;; to-allocate after fixed = 200 - 60 = 140; indexed-auto = [[1, auto]] + ;; pass 1: idx1: max(0.01, 140/1, 0.01) = 140 + ;; apply: track0 = max(60, 0) = 60; track1 = max(0.01, 140) = 140 + (let [sid (random-uuid) + child (make-child 200 100) + tracks [(fixed-track 60) (auto-track) (auto-track)] + cells {:c1 (make-cell sid 1 1 2 1)} + cmap {sid [(child-bounds 200 100) child]} + result (gld/set-auto-multi-span (auto-col-parent) tracks cmap cells frame-bounds {} :column)] + (t/is (mth/close? 60.0 (:size (nth result 0)) 0.001)) + (t/is (mth/close? 140.0 (:size (nth result 1)) 0.001)) + (t/is (mth/close? 0.01 (:size (nth result 2)) 0.001))))) + +(t/deftest set-auto-multi-span-child-smaller-than-existing-tracks + (t/testing "when child is smaller than the existing track sizes, tracks are not shrunk" + ;; tracks: [auto 80, auto 80, auto-sentinel] + ;; child width = 50; size-to-allocate = 50 + ;; indexed = [[0, auto80], [1, auto80]] + ;; pass 1 (non-assigned, to-alloc=50): + ;; idx0: max(0.01, 50/2, 80) = 80; rem = 50-80 = -30 + ;; idx1: max(0.01, max(-30,0)/1, 80) = 80 + ;; pass 2 (to-alloc=max(-30,0)=0): same max, no change + ;; both tracks stay at 80 + (let [sid (random-uuid) + child (make-child 50 100) + tracks [{:type :auto :size 80.0 :max-size ##Inf} + {:type :auto :size 80.0 :max-size ##Inf} + (auto-track)] + cells {:c1 (make-cell sid 1 1 2 1)} + cmap {sid [(child-bounds 50 100) child]} + result (gld/set-auto-multi-span (auto-col-parent) tracks cmap cells frame-bounds {} :column)] + (t/is (mth/close? 80.0 (:size (nth result 0)) 0.001)) + (t/is (mth/close? 80.0 (:size (nth result 1)) 0.001))))) + +(t/deftest set-auto-multi-span-flex-track-in-span-excluded + (t/testing "cells whose span contains a flex track are skipped (handled by set-flex-multi-span)" + ;; tracks: [flex 1fr, auto] col=1, span=2 → has-flex-track? = true → cell excluded + ;; 2 tracks total (no sentinel needed since the cell is excluded before indexing) + (let [sid (random-uuid) + child (make-child 300 100) + tracks [(flex-track 1) (auto-track)] + cells {:c1 (make-cell sid 1 1 2 1)} + cmap {sid [(child-bounds 300 100) child]} + result (gld/set-auto-multi-span (auto-col-parent) tracks cmap cells frame-bounds {} :column)] + (t/is (mth/close? 0.01 (:size (nth result 0)) 0.001)) + (t/is (mth/close? 0.01 (:size (nth result 1)) 0.001))))) + +(t/deftest set-auto-multi-span-non-spanned-track-unaffected + (t/testing "tracks outside the span keep their size – tests (get allocated %1 0) default" + ;; 4 tracks; child at col=2 span=2 → indexed covers tracks 1 and 2 (sentinel [3]). + ;; Track 0 (before the span) and track 3 (sentinel) are never allocated. + ;; from-idx = clamp(2-1, 0, 3) = 1 + ;; to-idx = clamp((2-1)+2, 0, 3) = 3 + ;; subvec(enumerate, 1, 3) = [[1,auto],[2,auto]] + ;; size-to-allocate = 200 → both indexed tracks get 100 + ;; apply: track0 = max(0.01, get({},0,0)) = max(0.01,0) = 0.01 ← uses default 0 + ;; track1 = max(0.01, 100) = 100 + ;; track2 = max(0.01, 100) = 100 + ;; track3 = max(0.01, get({},3,0)) = 0.01 (sentinel) + (let [sid (random-uuid) + child (make-child 200 100) + tracks [(auto-track) (auto-track) (auto-track) (auto-track)] + cells {:c1 (make-cell sid 2 1 2 1)} + cmap {sid [(child-bounds 200 100) child]} + result (gld/set-auto-multi-span (auto-col-parent) tracks cmap cells frame-bounds {} :column)] + ;; track before span: size stays at 0.01 (default 0 from missing allocation entry) + (t/is (mth/close? 0.01 (:size (nth result 0)) 0.001)) + ;; spanned tracks grow + (t/is (mth/close? 100.0 (:size (nth result 1)) 0.001)) + (t/is (mth/close? 100.0 (:size (nth result 2)) 0.001)) + ;; sentinel after span also unaffected + (t/is (mth/close? 0.01 (:size (nth result 3)) 0.001))))) + +(t/deftest set-auto-multi-span-row-type + (t/testing ":row type uses :row/:row-span and grows row tracks by child height" + ;; child height = 200, row-gap = 0, row=1 span=2, 3 row tracks (sentinel at [2]) + ;; from-idx=0, to-idx=clamp(2,0,2)=2 → [[0,auto],[1,auto]] + ;; size-to-allocate = 200 → each row track gets 100 + (let [sid (random-uuid) + child (make-child 100 200) + tracks [(auto-track) (auto-track) (auto-track)] + cells {:c1 (make-cell sid 1 1 1 2)} + cmap {sid [(child-bounds 100 200) child]} + result (gld/set-auto-multi-span (auto-row-parent) tracks cmap cells frame-bounds {} :row)] + (t/is (mth/close? 100.0 (:size (nth result 0)) 0.001)) + (t/is (mth/close? 100.0 (:size (nth result 1)) 0.001)) + (t/is (mth/close? 0.01 (:size (nth result 2)) 0.001))))) + +(t/deftest set-auto-multi-span-row-gap-deducted + (t/testing "row-gap is deducted from budget for :row type" + ;; child height = 210, row-gap = 10, row-span = 2 + ;; size-to-allocate = 210 - 10*1 = 200 → each track gets 100 + (let [sid (random-uuid) + child (make-child 100 210) + tracks [(auto-track) (auto-track) (auto-track)] + cells {:c1 (make-cell sid 1 1 1 2)} + cmap {sid [(child-bounds 100 210) child]} + result (gld/set-auto-multi-span (auto-row-parent 10) tracks cmap cells frame-bounds {} :row)] + (t/is (mth/close? 100.0 (:size (nth result 0)) 0.001)) + (t/is (mth/close? 100.0 (:size (nth result 1)) 0.001)) + (t/is (mth/close? 0.01 (:size (nth result 2)) 0.001))))) + +(t/deftest set-auto-multi-span-smaller-span-processed-first + (t/testing "cells are sorted by span ascending (sort-by span -): smaller span allocates first" + ;; NOTE: (sort-by prop-span -) uses `-` as a comparator; this yields ascending + ;; order (smaller span first), not descending as the code comment implies. + ;; + ;; 4 tracks (sentinel at [3]): + ;; cell-B: col=1 span=2 (covers indexed [0,1]) – processed first (span=2) + ;; cell-A: col=1 span=3 (covers indexed [0,1,2]) – processed second (span=3) + ;; + ;; cell-B: child=100px, to-allocate=100. + ;; non-assigned=[0,1]; pass1: idx0→max(0.01,50,0.01)=50; idx1→max(0.01,50,0.01)=50 + ;; allocated = {0:50, 1:50} + ;; + ;; cell-A: child=300px, to-allocate=300. + ;; indexed=[0,1,2]; non-assigned=[2] (tracks 0,1 already allocated) + ;; pass1 (non-assigned only): idx2→max(0.01,300/1,0.01)=300 ; rem=0 + ;; pass2 (to-alloc=0): max preserves existing values → no change + ;; allocated = {0:50, 1:50, 2:300} + ;; + ;; Final: track0=50, track1=50, track2=300, track3(sentinel)=0.01 + (let [sid-a (random-uuid) + sid-b (random-uuid) + child-a (make-child 300 100) + child-b (make-child 100 100) + tracks [(auto-track) (auto-track) (auto-track) (auto-track)] ; sentinel at [3] + cells {:ca (make-cell sid-a 1 1 3 1) + :cb (make-cell sid-b 1 1 2 1)} + cmap {sid-a [(child-bounds 300 100) child-a] + sid-b [(child-bounds 100 100) child-b]} + result (gld/set-auto-multi-span (auto-col-parent) tracks cmap cells frame-bounds {} :column)] + (t/is (mth/close? 50.0 (:size (nth result 0)) 0.001)) + (t/is (mth/close? 50.0 (:size (nth result 1)) 0.001)) + (t/is (mth/close? 300.0 (:size (nth result 2)) 0.001)) + (t/is (mth/close? 0.01 (:size (nth result 3)) 0.001))))) + +(t/deftest set-auto-multi-span-all-fixed-tracks-in-span + (t/testing "when all spanned tracks are fixed, no auto allocation occurs; fixed tracks unchanged" + ;; tracks: [fixed 100, fixed 100, auto-sentinel] + ;; col=1, span=2 → indexed = [[0,fixed100],[1,fixed100]] + ;; find-auto-allocations: both fixed → auto-indexed-tracks = [] + ;; allocate-auto-tracks on empty list → no entries in allocated map + ;; apply: track0 = max(100, get({},0,0)) = max(100,0) = 100 (unchanged) + ;; track1 = max(100, get({},1,0)) = max(100,0) = 100 (unchanged) + (let [sid (random-uuid) + child (make-child 50 100) + tracks [(fixed-track 100) (fixed-track 100) (auto-track)] + cells {:c1 (make-cell sid 1 1 2 1)} + cmap {sid [(child-bounds 50 100) child]} + result (gld/set-auto-multi-span (auto-col-parent) tracks cmap cells frame-bounds {} :column)] + (t/is (mth/close? 100.0 (:size (nth result 0)) 0.001)) + (t/is (mth/close? 100.0 (:size (nth result 1)) 0.001))))) diff --git a/common/test/common_tests/runner.cljc b/common/test/common_tests/runner.cljc index 31a2eab331..10ab8a48f6 100644 --- a/common/test/common_tests/runner.cljc +++ b/common/test/common_tests/runner.cljc @@ -15,6 +15,7 @@ [common-tests.files-migrations-test] [common-tests.geom-align-test] [common-tests.geom-bounds-map-test] + [common-tests.geom-grid-layout-test] [common-tests.geom-grid-test] [common-tests.geom-line-test] [common-tests.geom-modif-tree-test]