# `DoubleDown.Testing`
[🔗](https://github.com/mccraigmccraig/double_down/blob/main/lib/double_down/testing.ex#L1)

Test helpers for DoubleDown contracts.

Start the ownership server in `test/test_helper.exs`:

    DoubleDown.Testing.start()

Then in your tests, register handlers per-contract:

    setup do
      DoubleDown.Testing.set_module_handler(MyApp.Todos, MyApp.Todos.InMemory)
      :ok
    end

Handlers are process-scoped via `NimbleOwnership`, so `async: true`
tests are isolated. Use `allow/3` to share handlers with child processes.

# `allow`

```elixir
@spec allow(module(), pid(), pid() | (-&gt; pid() | [pid()])) :: :ok | {:error, term()}
```

Allow a child process to use the current process's handlers.

Use this when spawning Tasks or other processes that need to
dispatch through the same test handlers.

# `enable_log`

```elixir
@spec enable_log(module()) :: :ok
```

Enable dispatch logging for a contract.

After enabling, all dispatches through the contract's facade will be
recorded. Retrieve with `get_log/1`.

# `get_log`

```elixir
@spec get_log(module()) :: [{module(), atom(), [term()], term()}]
```

Retrieve the dispatch log for a contract.

Returns a list of `{contract, operation, args, result}` tuples
in the order they were dispatched.

# `reset`

```elixir
@spec reset(pid()) :: :ok
```

Reset all handlers and logs for a process.

Clears all NimbleOwnership entries owned by `pid`. Defaults to
`self()`.

**`on_exit` caveat:** `reset()` (without arguments) uses `self()`,
which inside an `on_exit` callback is the callback process — not
the test process. To reset the test process's handlers from
`on_exit`, capture the pid first:

    setup do
      pid = self()
      on_exit(fn -> DoubleDown.Testing.reset(pid) end)
      :ok
    end

In most cases you don't need explicit cleanup — NimbleOwnership
automatically cleans up when the owning process exits.

# `set_module_handler`

```elixir
@spec set_module_handler(module(), module()) :: :ok
```

Register a module as the handler for a contract.

The module must implement the contract's `@behaviour`.

# `set_stateful_handler`

```elixir
@spec set_stateful_handler(module(), DoubleDown.Dispatch.Types.stateful_fun(), term()) ::
  :ok
```

Register a stateful handler for a contract.

The function may be 4-arity or 5-arity:

  * **4-arity:** `fn contract, operation, args, state -> {result, new_state} end`
  * **5-arity:** `fn contract, operation, args, state, all_states -> {result, new_state} end`

5-arity handlers receive a read-only snapshot of all contract states as
the 5th argument. This enables cross-contract state access (e.g. a Queries
handler reading the Repo InMemory store). The `all_states` map is keyed by
contract module and includes a `DoubleDown.Contract.GlobalState` sentinel key.
The handler must return only its own contract's new state — not the global map.

State is stored in NimbleOwnership and updated atomically on each dispatch.

# `set_stateless_handler`

```elixir
@spec set_stateless_handler(module(), (module(), atom(), [term()] -&gt; term())) :: :ok
```

Register a function as the handler for a contract.

The function receives `(contract, operation, args)` and returns the result.

# `start`

```elixir
@spec start() :: {:ok, pid()} | {:error, term()}
```

Start the DoubleDown ownership server.

Call this once in `test/test_helper.exs`.

---

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