# `Statifier.Testing.FeatureDetector`
[🔗](https://github.com/riddler/statifier-ex/blob/v2.1.1/lib/statifier/testing/feature_detector.ex#L1)

Detects SCXML features used in documents so the test harness can fail
precisely on unsupported features.

Test-side surface for chart authors, versioned with the engine: no module in
`lib/` outside `Statifier.Testing.*` may reference anything inside it, so the
engine never consults feature detection to decide behavior (ADR-0053,
amending ADR-0006).
A test whose document uses an unsupported feature flunks with that feature
named, so it can never masquerade as passing (see `docs/testing.md`, ADR-0006).

Detection is regex-based over raw XML. v2 has no parsed document struct yet;
when one lands, a `detect_features/1` clause for it is added alongside the
string clause.

The registry reflects what v2 actually supports today:
basic/compound/parallel/final/history states, the initial attribute and
`<initial>` element, event/eventless/targetless/internal/wildcard
transitions, `<onentry>`/`<onexit>`, `<raise>`, `<log>`, static
`<donedata>`, `<datamodel>`/`<data>`, `<assign>`, `cond`-guarded
transitions (including `<if>`/`<elseif>`/`<else>`), `<foreach>`, and
`<script>` (`:partial` - see the registry entry), `<send>`/`<invoke>`/
`<cancel>`/`<finalize>` and their attributes. `script_elements` is the only
entry that is not `:supported`; see `feature_registry/0` for the
authoritative, up-to-date list.

# `detect_features`

```elixir
@spec detect_features(xml :: String.t()) :: MapSet.t(atom())
```

Detects features used in an SCXML document.

Returns a `MapSet` of feature atoms.

## Examples

    iex> Statifier.Testing.FeatureDetector.detect_features("<scxml><state id='s1'/></scxml>")
    MapSet.new([:basic_states])

# `feature_registry`

```elixir
@spec feature_registry() :: %{
  required(atom()) =&gt; :supported | :unsupported | :partial
}
```

Returns every known SCXML feature with its support status in v2.

- `:supported` - fully implemented
- `:partial` - partially implemented, allowed to run since simple cases may work
- `:unsupported` - not yet implemented

# `validate_features`

```elixir
@spec validate_features(detected_features :: MapSet.t(atom())) ::
  {:ok, MapSet.t(atom())} | {:error, MapSet.t(atom())}
```

Checks that every detected feature is supported or partial.

Returns `{:ok, detected_features}` when all are, otherwise
`{:error, unsupported_features}`. Partial features are allowed through since
they may work in simple cases. A feature absent from the registry counts as
unsupported.

---

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