Example data a host supplies for a chart: named scenario datamodels and example event payloads (ADR-0003).
A fixture bundle is two maps:
scenarios- a scenario name (for example"gold-tier-user") mapped to a complete example of the host-supplied datamodel for that situation.events- an event name (for example"payment.success") mapped to a sample_event.datapayload for that event.
Two delivery paths converge on this one struct: a host module implementing
StatifierUI.Fixtures.Source (from_source/1), and a JSON sidecar next to
a chart (a later phase's loader). Every consumer downstream of either path
is indifferent to which one produced the struct.
new/1 validates rather than raises: scenario datamodels must have string
keys at every level, so a fixture that would blow up deep inside the engine
is instead rejected at load time. Event payloads are preserved verbatim,
including the three-way :undefined / nil / map distinction predicator's
_event.data semantics require.
Scenario validation is deliberately stricter than the engine's, not a
mirror of it. Statifier.MachineState.new/2 rejects only atom keys that
are not booleans, so it accepts an integer or boolean key; this rejects
every key that is not a string. The reason is convergence: a JSON object
key is always a string, so a scenario a behaviour source could supply but
a sidecar could never express would break the one-struct guarantee
ADR-0003 rests on. Rejecting it in both paths keeps them interchangeable.
Summary
Types
An example datamodel: string keys at every level.
A diagnostic surfaced while loading a fixture bundle. path is the key
path inside the bundle; source is the file it came from, or nil for a
bundle that never was a file.
The name of a fixture event, matching an SCXML event name.
The name of a fixture scenario.
Functions
Fetches an event's sample payload by name. Returns :error when the event
has no fixture, distinct from an event whose fixture value is nil or
:undefined.
Event names, sorted (ADR-0005's canonical-order rule).
Builds a validated fixture bundle from a StatifierUI.Fixtures.Source
module.
Builds a validated fixture bundle from :scenarios and :events options.
Fetches a scenario's datamodel by name.
Scenario names, sorted (ADR-0005's canonical-order rule).
Types
An example datamodel: string keys at every level.
@type diagnostic() :: %{ kind: atom(), message: String.t(), path: [String.t()], source: Path.t() | nil }
A diagnostic surfaced while loading a fixture bundle. path is the key
path inside the bundle; source is the file it came from, or nil for a
bundle that never was a file.
@type event_name() :: String.t()
The name of a fixture event, matching an SCXML event name.
@type scenario_name() :: String.t()
The name of a fixture scenario.
@type t() :: %StatifierUI.Fixtures{ diagnostics: [diagnostic()], events: %{optional(event_name()) => term()}, scenarios: %{optional(scenario_name()) => datamodel()} }
Functions
@spec event(t(), event_name()) :: {:ok, term()} | :error
Fetches an event's sample payload by name. Returns :error when the event
has no fixture, distinct from an event whose fixture value is nil or
:undefined.
@spec event_names(t()) :: [event_name()]
Event names, sorted (ADR-0005's canonical-order rule).
Builds a validated fixture bundle from a StatifierUI.Fixtures.Source
module.
Calls module.scenarios() and module.example_events() and routes both
through new/1, so this path and the sidecar loader share exactly one
validation implementation. Returns {:error, {:not_a_source, module}} when
module does not implement the behaviour.
Builds a validated fixture bundle from :scenarios and :events options.
Both options default to %{}. Returns {:error, reason} rather than
raising when a scenario or event key is not a string, when a scenario
datamodel is not a map, or when a scenario datamodel contains a non-string
key at any depth. A non-string key found inside a datamodel is reported as
{:invalid_key, key, path}, where path starts with the scenario name -
or, when the offending map is a predicator duration, as
{:duration_in_scenario, path}, which says why rather than naming a unit
key the author never wrote.
Examples
iex> StatifierUI.Fixtures.new(scenarios: %{"gold-tier-user" => %{"tier" => "gold"}})
{:ok, %StatifierUI.Fixtures{scenarios: %{"gold-tier-user" => %{"tier" => "gold"}}}}
@spec scenario(t(), scenario_name()) :: {:ok, datamodel()} | :error
Fetches a scenario's datamodel by name.
@spec scenario_names(t()) :: [scenario_name()]
Scenario names, sorted (ADR-0005's canonical-order rule).