README.md

# SandboxCase

Batteries-included test isolation for Elixir and Phoenix.

One config, one setup call, zero boilerplate. Built-in adapters for Ecto, Cachex, FunWithFlags, Mimic, and Mox — each activated only if the dep is loaded.

All macros expand at compile time. Outside `MIX_ENV=test`, `sandbox_plugs` and `sandbox_on_mount` emit nothing, and `socket_with_sandbox` emits a plain `socket` call. No runtime checks, no dead branches, no production dependencies on test libraries.

## Installation

```elixir
{:sandbox_case, "~> 0.1"}
```

## Configuration

```elixir
# config/test.exs
config :sandbox_case,
  otp_app: :my_app,
  mox_mocks: [MyApp.MockWeather],
  sandbox: [
    ecto: true,
    cachex: [:my_cache],
    fun_with_flags: true,
    mimic: [MyApp.ExternalService, MyApp.Payments],
    mox: [{MyApp.MockWeather, MyApp.WeatherBehaviour}]
  ]
```

## Setup

```elixir
# test/test_helper.exs
SandboxCase.Sandbox.setup()
ExUnit.start()
```

## Endpoint and LiveView

```elixir
# lib/your_app_web/endpoint.ex
import SandboxCase
sandbox_plugs()

socket_with_sandbox "/live", Phoenix.LiveView.Socket,
  websocket: [connect_info: [session: @session_options]]
```

```elixir
# lib/your_app_web.ex
def live_view do
  quote do
    use Phoenix.LiveView
    import SandboxCase
    sandbox_on_mount()
  end
end
```

Outside test env, both macros emit nothing.

## Test modules

```elixir
use SandboxCase.Sandbox.Case
```

Checks out all sandboxes in `setup`, checks them back in via `on_exit`. Ecto metadata for browser sessions:

```elixir
SandboxCase.Sandbox.ecto_metadata(context.sandbox_tokens)
```

## Custom adapters

Implement `SandboxCase.Sandbox.Adapter`:

```elixir
config :sandbox_case,
  sandbox: [
    {MyApp.RedisSandbox, pool_size: 4}
  ]
```

## License

MIT