# `MishkaCmsCore.DataCase`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.3/lib/mishka_cms_core/test/data_case.ex#L5)

Test case for anything that touches the database but not the web layer — the resources, their
actions and policies, the version trail, the dashboard queries.

Stands in for the CMS's `MishkaCms.DataCase` so this suite, and an extension's, runs without the
CMS around it: it ships in `lib` for that, and sandboxes the repo `config :mishka_cms_core, repo: …`
names. Each test gets its own sandboxed connection and everything it writes is rolled back at the
end; `async: false` (the default here) shares that connection with any process the test spawns,
which the async data loaders behind the dashboard widgets rely on.

See `MishkaCmsCore.ConnCase` for tests that go through the JSON API instead.

# `errors_on`

Turns changeset errors into a map of field to messages.

    assert %{password: ["password is too short"]} = errors_on(changeset)

# `forget_settings`

```elixir
@spec forget_settings([String.t()], [String.t() | nil]) :: :ok
```

Drops settings keys from the RAM cache when the test ends.

    setup do
      forget_settings(~w(cms.offline), [nil, site.id])
      :ok
    end

The cache is process-global rather than sandboxed, so a value a test writes is still in it when
the next suite runs — and `cms.offline` is not an inert one: left on, it takes the front end down
and closes registration for everything that follows. A write reaches the cache through the
`"setting:updated"` broadcast, so this is needed whether the test went through
`MishkaCmsCore.Settings` or straight at the `Setting` resource.

The keys are dropped rather than re-read: `on_exit` runs in its own process, which does not hold
the sandbox's connection, so there is no database to re-read them from.

# `module_sandbox`

```elixir
@spec module_sandbox() :: %{module_sandbox: pid()}
```

One sandboxed connection for a whole module, opened in its `setup_all` and shared with every test
and every process they spawn; what the module wrote is rolled back after its last test.

For a module whose tests only READ what one slow setup writes — a UI kit installed into the
database, seconds each time — so it is written once instead of before every test:

    setup_all do
      context = module_sandbox()
      UiKitHandler.install_chelekom!(site_id: nil)
      context
    end

A test in such a module sees what the tests before it wrote, so keep them to reading. Only for a
module that is not async.

# `serve_the_site`

```elixir
@spec serve_the_site(map()) :: :ok
```

Makes this node one that serves the site (`MishkaCmsCore.Runtime.Handlers.BootHandler.serving?/0`)
until the test ends, by setting the host's endpoint to serve — what `mix phx.server` and a
release's `PHX_SERVER` do. The suite's endpoint does not serve, so a test without it runs as a node
that does not. Only for a test that is not async: the setting is the node's.

    setup :serve_the_site

# `setup_sandbox`

Checks out a sandboxed connection for the test, shared with its spawned processes unless async,
and — for a test that is not async — puts `MishkaCmsCore.Runtime.States.SiteState` back as it
found it when the test ends, and unloads the runtime modules the test built.

A site a test creates is saved to `SiteState`, which is the node's, not the test's: the rollback
takes the row back and leaves the entry, and a later test that saves a site of the same name or
host is refused — its pages and its email then read as a site the node does not know. ExUnit runs
the async modules first and the others one at a time after them, so a test that is not async is
the only one touching the tables while it runs.

A runtime module is the node's too — see `unload_built_on_exit/0`.

# `unload_built_on_exit`

```elixir
@spec unload_built_on_exit() :: :ok
```

Unloads, when the test (or the `setup_all`) that calls it ends, every runtime module —
`MishkaCmsCore.Runtime.<hash>.Component`, `.Page`, `.Layout`, … — that was built while it ran,
and forgets the compile failures recorded while it ran.

`setup_sandbox/1` calls it for every test that is not async, and `module_sandbox/0` for the
module. A module built from a row is node-wide and outlives the rollback that takes the row away,
and the runtime reaches a loaded module by its name without reading the row again; so a later
test that writes its own row of the same name, from another bundle or with other attributes,
would be drawn with the earlier test's build. What was loaded before the call is left as it was,
unless it was rebuilt while the test ran.

# `watch_queue_signals`

```elixir
@spec watch_queue_signals() :: :ok
```

Sends the test `{:signal, payload}` for every Oban queue signal — a pause, resume, scale, start or
stop — sent from then on until it ends, by any Oban instance on the node.

---

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