# `StatifierBlocks.Runtime.FixtureRuns`
[🔗](https://github.com/riddler/statifier_blocks/blob/v0.44.1/lib/statifier_blocks/runtime/fixture_runs.ex#L1)

Turns `(document, palette, fixtures)` into a list of per-row verdicts, by
compiling the document once and driving the compiled chart once per
fixture row.

## Namespace: `StatifierBlocks.Runtime.*`, not `StatifierBlocks.Fixtures.*`

This module runs a chart at session time - `Statifier.compile/2` plus one
`Statifier.initialize/2` per row - rather than authoring anything, and
`lib/statifier_blocks/runtime/subchart.ex`'s moduledoc already set the
precedent for what that half of the package is called:
`StatifierBlocks.Runtime.*` reads as "the half that runs", set against the
authoring half that is everything else in `lib/`.

## Unguarded, on purpose

Every LiveView module in this package sits behind an
`Code.ensure_loaded?(...)` presence check on the LiveView library itself
(ADR-0005 decision 1). This module carries no such guard and names no
LiveView module, because it is not a LiveView concern - it is a pure
function of a document, a palette and a fixtures source, and
`StatifierBlocks.Shell`'s own moduledoc states the rule this follows:
"what is worth testing goes in `lib/statifier_blocks/`, unguarded." The
headless suite (the one CI job proves compiles and passes with that
library entirely absent) exercises this module directly.

## Why this calls `Statifier.compile/2` and `Statifier.initialize/2` directly

`Statifier.Testing.Case` is the ExUnit case template that names the
four-function driving surface (`compile/2`, `initialize/2`, `send_event/2`,
`active_leaf_states/1` - ADR-0053, ADR-0006). It is `use`-able only from a
test, and its own moduledoc forbids any module under `lib/` outside
`Statifier.Testing.*` from referencing anything inside it. So this module
calls the four functions on `Statifier` itself - that direct call *is* the
ADR-0053 surface, not a way around it - and the test suite below is free
to `use Statifier.Testing.Case` where that helps.

## `:declare` is the host's raw list, never `host_roots`

`opts[:declare]` is forwarded verbatim to `StatifierBlocks.Compiler.compile/3`
as its own `:declare` option: the host's raw `{id, expr}` declaration
**list**. It is never the derived `host_roots` a LiveView editor keeps (a
`MapSet.t(String.t())` of root ids, built for undeclared-path advisories) -
`StatifierBlocks.Compiler.DeclaredRoots.declarations/1` answers a `MapSet`
with `{:error, [{:invalid_declaration, _}]}`, so passing one here would
fail every compile.

# `status`

```elixir
@type status() :: :no_fixtures | :compile_error | :ready
```

`:no_fixtures` - the fixtures source is `nil`, or holds no table for any
block. `:compile_error` - the document does not compile (normal mid-edit,
not exceptional); `findings` carries why. `:ready` - every row in `runs`
was driven.

# `t`

```elixir
@type t() :: %StatifierBlocks.Runtime.FixtureRuns{
  failure_count: non_neg_integer(),
  findings: [StatifierBlocks.Compiler.Finding.t()],
  row_count: non_neg_integer(),
  runs: [StatifierBlocks.Runtime.FixtureRuns.Run.t()],
  status: status()
}
```

# `run`

```elixir
@spec run(
  StatifierBlocks.Document.t(),
  StatifierBlocks.Palette.t(),
  StatifierBlocks.Shell.fixtures(),
  keyword()
) :: t()
```

Compiles `document` against `palette` once and drives every fixture row
in `fixtures` once, returning a `t()`.

`opts` is the compiler's own option list, plus one option of this
module's own. Every key but `:view_model` is forwarded verbatim to
`StatifierBlocks.Compiler.compile/3`: a row is driven through the chart
the document compiles to, and `terminate:`, `child_use:`,
`known_invoke_types:` and `datamodel:` each change what that chart is. A
caller that compiles with them and asks for fixture runs without them is
asking about a different chart. Nothing here validates the list - the
compiler is the authority on its own options.

  * `:declare` - the compiler's own `:declare` option. Defaults to `[]`.
    This is the host's raw `{id, expr}` declaration list, **never** the
    derived `host_roots` `MapSet` a LiveView editor keeps - see the
    moduledoc.
  * `:view_model` - an already-built `%StatifierBlocks.ViewModel{}`, and
    the one key this module keeps for itself. A caller that already has
    one (an editor always does) should pass it rather than have this
    function build a second one. When absent, this function builds its
    own with `ViewModel.build(document, palette, [])`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
