# `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_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() :: :ok
```

Reset all handlers and logs for the current process.

# `set_fn_handler`

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

Register a function as the handler for a contract.

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

# `set_handler`

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

Register a module as the handler for a contract.

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

# `set_mode_to_global`

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

Set the ownership server to global mode.

In global mode, all handlers registered by the calling process are
visible to every process in the VM — no `allow/3` calls needed.
This is useful for integration-style tests that involve supervision
trees, named GenServers, Broadway pipelines, or Oban workers where
individual process pids are not easily accessible.

The calling process becomes the "shared owner". Any handlers set
by this process (before or after calling `set_mode_to_global/0`)
are accessible to all processes.

## Warning

Global mode is **incompatible with `async: true`**. When global
mode is active, all tests share the same handlers, so concurrent
tests will interfere with each other. Only use global mode in
tests with `async: false`.

Call `set_mode_to_private/0` to restore per-process isolation.

## Example

    setup do
      DoubleDown.Testing.set_mode_to_global()
      DoubleDown.Testing.set_handler(MyApp.Repo, MyApp.Repo.OpenInMemory)
      on_exit(fn -> DoubleDown.Testing.set_mode_to_private() end)
      :ok
    end

# `set_mode_to_private`

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

Restore the ownership server to private (per-process) mode.

After calling this, handlers are once again scoped to the process
that registered them. Use this to clean up after `set_mode_to_global/0`.

# `set_stateful_handler`

```elixir
@spec set_stateful_handler(module(), (... -&gt; {term(), term()}), 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.

# `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*
