Renders one StatifierUI.Fixtures.Bundle as the per-fragment "test this
step" panel: what the fragment's expressions evaluate to under each of its
datasets, and whether each expectation it states still holds.
A pure function over the bundle, in the shape of
StatifierUI.TruthTable.Markdown and StatifierUI.EventLog.Markdown: it
names Kino only in this moduledoc and calls nothing under Kino.*, so
the same string serves a Livebook cell, a generated docs page, or a test
assertion. StatifierUI.Kino.test_panel/2 is the widget wrapper.
Two questions, both shown
The panel is deliberately both halves of the fixture contract at once:
- the truth table (
StatifierUI.TruthTable) - what every expression actually evaluates to under every dataset, whether or not an expectation was stated. This is the reading surface. - the expectations (
StatifierUI.Fixtures.Expectations) - whether every statedexpectvalue held. This is the checking surface.
A fragment's panel is useless with only one: the table without the expectations says what happens but not what was meant, and the expectations without the table say a stated belief held while staying silent about every expression that stated none.
The summary counts rather than passes
The expectations summary reports four counts - matched, mismatched,
errored, and stated against a dataset the bundle does not carry - and never
collapses them into a pass or a fail. That is not indecision: this
package's two consumers of the same fact already disagree about it.
StatifierUI.Fixtures.Expectations.check/2 counts a :missing_dataset as
a failure, because an expectation naming no dataset was never actually
checked; StatifierUI.Fixtures.Lint reports the same dangling key as a
warning, per ADR-0006's severity reasoning. Both are right about their own
question, the reconciliation is not this renderer's to make, and a panel
that printed one verdict would silently pick a side. Four counts let the
reader see exactly which of the two situations they are in.
Orientation is passed through, not chosen here
:orientation is forwarded verbatim to
StatifierUI.TruthTable.Markdown.render/2, whose own default stands. This
renderer states no preference between the two axes.
Summary
Types
Options. :heading is this panel's own # heading; the truth table below
it is always rendered untitled, since the panel is already named. Every
other option is forwarded to the layer that owns it.
Functions
Renders bundle as a Markdown string.
Renders every bundle in a StatifierUI.Fixtures.Bundle.discovery/0, one
panel after another, followed by a section naming the entries that failed
to load.
Types
@type opt() :: {:heading, String.t() | nil} | {:origin, boolean()} | {:expectations, boolean()} | {:diagnostics, boolean()} | {:orientation, StatifierUI.TruthTable.Markdown.orientation()} | {:legend, boolean()} | {:sources, boolean()} | {:functions, map()} | {:providers, keyword()}
Options. :heading is this panel's own # heading; the truth table below
it is always rendered untitled, since the panel is already named. Every
other option is forwarded to the layer that owns it.
Functions
@spec render(StatifierUI.Fixtures.Bundle.t(), [opt()]) :: String.t()
Renders bundle as a Markdown string.
Options:
:heading- the#heading. Defaults to the bundle's name;nilfor none.:origin- include a line naming the module or file the bundle came from. Defaults totrue, because a panel that shows wrong examples is most often showing the wrong bundle.:expectations- include the expectations section. Defaults totrue.:diagnostics- include the bundle's load diagnostics (an unknown sidecar key, a future version). Defaults totrue.:orientation,:legend,:sources- forwarded toStatifierUI.TruthTable.Markdown.render/2.:functions,:providers- forwarded toPredicator.evaluate/3through both the table and the expectation run, so the panel's two halves evaluate under identical conditions.
Never raises: an expression that fails to evaluate is a cell and a row, not an exception.
@spec render_discovery(StatifierUI.Fixtures.Bundle.discovery(), [opt()]) :: String.t()
Renders every bundle in a StatifierUI.Fixtures.Bundle.discovery/0, one
panel after another, followed by a section naming the entries that failed
to load.
Entries that ship no bundle are not listed. A palette where most fragments carry no examples is the normal case, and a page reciting them says nothing a reader can act on; a bundle that was meant to load and did not is the opposite, and is always named.
:legend defaults to false here rather than true: the three-values
legend is worth one appearance on a page, not one per fragment.