Render, inspect, and assert helpers for the PhoenixLiveGantt view. Replaces
ad-hoc probe scripts with a one-line call. Used from tests, IEx, and
the mix phoenix_live_gantt.dump task.
events = [%PhoenixLiveGantt.Task{id: "a", start: ~D[2026-04-01], end: ~D[2026-04-05]}]
html = render_waterfall(events)
geom = inspect_waterfall(events)
dump_waterfall(events) # pretty-prints to stdoutPass any waterfall attr as an option:
render_waterfall(events,
connectors: [%{from: "a", to: "b"}],
zoom: :day,
bus_stagger_outgoing_px: 4
):date_range defaults to a tight range derived from the events.
Also provides geometry assertions for tests:
assert_lanes_evenly_spaced/3— catches lane-stagger rounding bugsassert_source_attaches_inside_bar/2— catches corner-bleed bugsassert_arrow_tips_clear_target_bars/2— catches refX/gap bugs
Lives in lib/ (not test/support/) because the mix task uses it
at dev runtime.
Summary
Functions
Assert that no connector's arrow tip pierces meaningfully INTO the target bar.
Assert that every arrowhead sits on its connector's shaft END — the head is
drawn in a separate, non-stretched overlay layer (so it stays a crisp px
triangle while the shaft SVG stretches with the responsive fill), and it must
track the shaft's TRUE terminal point even after path rewrites
(consolidate_piercing_trunks can re-route a forward path so it ends at a
different y). :tol_px (default 2) absorbs the percent↔pixel round-trip.
Assert that every detour path satisfies the geometric invariants PhoenixLiveGantt's stem-shifting logic relies on
Assert that all SOURCE attach y values for connectors emerging from
source_id are evenly spaced. Catches lane-stagger rounding bugs.
Assert that no connector's trunk visually pierces an unrelated bar. Walks each path's vertical trunk segment and checks that no other task's bar rectangle (excluding the connector's own endpoints) sits in the trunk's x-column AND overlaps the trunk's y-span.
Assert every connector's path consists only of axis-aligned segments
(pure horizontal H or vertical V moves from the initial M point).
Catches malformed paths or unexpected shape families.
Assert all numeric path coordinates are non-negative. Negative coords mean a path went off the chart's left/top edge — usually a bug.
Assert that every connector's SOURCE attach y falls inside the source bar's actual vertical extent (with optional inset for rounded corners).
Compare two geometry maps and return a structured diff describing what changed. Useful for "I changed X — what else moved?" workflows.
Render, inspect, and pretty-print to stdout. Returns the geometry map for further inspection.
Run every geometry assertion against the given html and return a list
of issues found. Each issue is {name, exception_message}. Useful as
a one-stop "is this render sane?" check.
Render then immediately inspect into a structured geometry map.
Render the PhoenixLiveGantt component with the given events and options. All component attrs default to their declared defaults; opts override. Returns the rendered HTML string.
Functions
Assert that no connector's arrow tip pierces meaningfully INTO the target bar.
Arrow tips intentionally land ON the target bar's edge (gap 0) so they read as
connected at any responsive fill factor — visual separation is the fixed-px
arrowhead overlay's job, not a natural-px gap that would stretch. So this
guards against tips landing INSIDE the bar (a refX/offset bug): a tip is a
violation when it sits more than :tol_px (default 2, absorbing the
percent↔pixel round-trip) to the bar-interior side of the near edge. Only FS
arrows (target_entry=:west) are checked, since their geometry is the most
predictable.
Assert that every arrowhead sits on its connector's shaft END — the head is
drawn in a separate, non-stretched overlay layer (so it stays a crisp px
triangle while the shaft SVG stretches with the responsive fill), and it must
track the shaft's TRUE terminal point even after path rewrites
(consolidate_piercing_trunks can re-route a forward path so it ends at a
different y). :tol_px (default 2) absorbs the percent↔pixel round-trip.
Assert that every detour path satisfies the geometric invariants PhoenixLiveGantt's stem-shifting logic relies on:
stem_out > x1— source-side stem must be strictly east of the source bar's reference x (FS shape requirement).stem_in < arrow_stop— target-side stem must be strictly west of the arrow tip (FS approach requirement).
Catches regressions in maybe_shift_stem_out / maybe_shift_stem_in
where a stem could be shifted to an x that breaks the shape's
geometric validity.
Assert that all SOURCE attach y values for connectors emerging from
source_id are evenly spaced. Catches lane-stagger rounding bugs.
Pass :tolerance_px (default 0) to allow off-by-N differences in
spacings (useful for sub-pixel rendering).
Assert every connector's path consists only of axis-aligned segments
(pure horizontal H or vertical V moves from the initial M point).
Catches malformed paths or unexpected shape families.
Assert all numeric path coordinates are non-negative. Negative coords mean a path went off the chart's left/top edge — usually a bug.
Pass :allow_negative to skip (some edge cases legitimately do go
negative, e.g., :ss arrows near x=0).
Assert that every connector's SOURCE attach y falls inside the source bar's actual vertical extent (with optional inset for rounded corners).
Uses Inspector's per-bar top/bottom (derived from real row
positions, including group headers) — accurate even when group
headers shift the row stride.
:corner_inset_px (default 4) — px to inset from bar's top/bottom
for the rounded-corner area. Defaults match PhoenixLiveGantt's
bus_stagger_corner_clearance_px.
Compare two geometry maps and return a structured diff describing what changed. Useful for "I changed X — what else moved?" workflows.
before = inspect_waterfall(events)
# ... change something ...
after = inspect_waterfall(events)
diff_waterfalls(before, after)
# %{
# row_order: %{changed: false} | %{from: [...], to: [...]},
# connectors: %{added: [...], removed: [...], changed: [...]},
# edges: %{earlier_delta: int, later_delta: int}
# }
@spec dump_waterfall( [PhoenixLiveGantt.Task.t()], keyword() ) :: map()
Render, inspect, and pretty-print to stdout. Returns the geometry map for further inspection.
Run every geometry assertion against the given html and return a list
of issues found. Each issue is {name, exception_message}. Useful as
a one-stop "is this render sane?" check.
Pass :opts_for to override per-assertion options:
find_geometry_issues(html,
opts_for: %{
assert_arrow_tips_clear_target_bars: [min_gap_px: 2]
}
)
@spec inspect_waterfall( [PhoenixLiveGantt.Task.t()], keyword() ) :: map()
Render then immediately inspect into a structured geometry map.
@spec render_waterfall( [PhoenixLiveGantt.Task.t()], keyword() ) :: String.t()
Render the PhoenixLiveGantt component with the given events and options. All component attrs default to their declared defaults; opts override. Returns the rendered HTML string.