SandboxCase.Sandbox (sandbox_case v0.3.12)

Copy Markdown View Source

Orchestrates test sandbox setup and per-test checkout/checkin.

Setup

Call once in test/test_helper.exs:

SandboxCase.Sandbox.setup()

This reads config and runs each adapter's setup/1.

Configuration

# config/test.exs
config :sandbox_case,
  otp_app: :my_app,
  sandbox: [
    ecto: true,                              # auto-discovers repos from otp_app
    cachex: [:my_cache],                     # cache names to sandbox
    fun_with_flags: true,                    # enable FWF sandbox pool
    mimic: [MyApp.External, MyApp.Payments], # modules to Mimic.copy
    mox: [{MyApp.MockWeather, MyApp.WeatherBehaviour}],
    redis: [url: "redis://localhost:6379"]
  ]

Each key maps to a built-in adapter. You can also pass custom adapters:

config :sandbox_case,
  sandbox: [
    {MyApp.CustomSandbox, [some: :config]}
  ]

Per-test checkout

Use the case template:

use SandboxCase.Sandbox.Case

Or call manually:

tokens = SandboxCase.Sandbox.checkout()
on_exit(fn -> SandboxCase.Sandbox.checkin(tokens) end)

Summary

Functions

Wait for orphaned processes to finish naturally (up to timeout). Does NOT kill survivors — call kill_orphans/1 separately.

Build a Plug.Conn with sandbox metadata encoded in the user-agent.

Per-test checkin. Order matters

Per-test checkout. Returns a map with :owner (the test pid) and :tokens (a list of {adapter, token} tuples). Pass the whole map to checkin/1 in on_exit.

Collects all on_mount modules declared by available adapters. Used by the sandbox_on_mount/0 macro at compile time.

Collects all plug modules declared by available adapters. Used by the sandbox_plugs/0 macro at compile time.

Returns the Ecto metadata from the most recent checkout, if any. Useful for passing to browser session start.

Find and kill orphaned processes immediately (no waiting).

Mark that cleanup has started. Call before closing browser sessions or other teardown that may trigger OwnershipErrors. Errors logged after this point are swallowed at checkin.

Register a cleanup callback to run during checkin, before sandbox rollback. Use for teardown that triggers processes needing DB access (e.g. closing browser sessions that kill LiveViews mid-transaction).

One-time setup. Call from test_helper.exs.

Returns true if setup/1 has been called.

Functions

await_orphans(owner, timeout \\ 5000)

Wait for orphaned processes to finish naturally (up to timeout). Does NOT kill survivors — call kill_orphans/1 separately.

Returns a list of pids that did NOT exit within the timeout.

The timeout can be configured per-test via:

Process.put(:sandbox_case_orphan_timeout, 15_000)

Or set in your test module setup:

setup do
  Process.put(:sandbox_case_orphan_timeout, 15_000)
  :ok
end

build_conn(sandbox)

Build a Plug.Conn with sandbox metadata encoded in the user-agent.

Use this instead of Phoenix.ConnTest.build_conn() when your endpoint has server: true — the metadata allows the Plug to propagate sandbox state (Ecto, Mimic, Mox, Cachex, FunWithFlags, Logger) to the Bandit handler process.

With server: false, Phoenix.ConnTest.build_conn() works fine since requests are dispatched inline in the test process.

checkin(map)

Per-test checkin. Order matters:

  1. Run cleanup callbacks (e.g. close browser sessions)
  2. Wait for orphans to finish naturally
  3. Rollback Ecto sandbox
  4. Kill any remaining orphans
  5. Check unconsumed logs + checkin remaining adapters

checkout(opts \\ [])

Per-test checkout. Returns a map with :owner (the test pid) and :tokens (a list of {adapter, token} tuples). Pass the whole map to checkin/1 in on_exit.

collect_hooks()

Collects all on_mount modules declared by available adapters. Used by the sandbox_on_mount/0 macro at compile time.

collect_plugs()

Collects all plug modules declared by available adapters. Used by the sandbox_plugs/0 macro at compile time.

ecto_metadata(tokens)

Returns the Ecto metadata from the most recent checkout, if any. Useful for passing to browser session start.

kill_orphans(owner)

Find and kill orphaned processes immediately (no waiting).

mark_cleanup_started()

Mark that cleanup has started. Call before closing browser sessions or other teardown that may trigger OwnershipErrors. Errors logged after this point are swallowed at checkin.

on_cleanup(sandbox, fun)

Register a cleanup callback to run during checkin, before sandbox rollback. Use for teardown that triggers processes needing DB access (e.g. closing browser sessions that kill LiveViews mid-transaction).

SandboxCase.Sandbox.on_cleanup(sandbox, fn ->
  Wallabidi.end_session(session)
end)

Callbacks run in registration order, before await_orphans. OwnershipErrors logged during callbacks are swallowed.

setup(opts \\ [])

One-time setup. Call from test_helper.exs.

setup?()

Returns true if setup/1 has been called.