Current section
Files
Jump to
Current section
Files
lib/phoenix_test_only.ex
defmodule PhoenixTestOnly do
@moduledoc """
Compile-time conditional `plug` and `on_mount` for test-only modules.
Phoenix's `plug` and `on_mount` macros accumulate module attributes at the
top level. When wrapped in `if Application.compile_env(...)`, the call ends
up inside a `case` node in the AST and Phoenix silently ignores it.
These macros move the check to **macro expansion time**: the emitted code is
either a bare `plug`/`on_mount` call or nothing at all. They only emit in
test — if `Mix` isn't loaded (release) or `Mix.env()` isn't `:test`, nothing
is emitted.
## Usage
# endpoint.ex
import PhoenixTestOnly
plug_if_test Phoenix.Ecto.SQL.Sandbox
plug_if_test Wallabidi.Sandbox.Plug
# your_app_web.ex
def live_view do
quote do
use Phoenix.LiveView
import PhoenixTestOnly
on_mount_if_test Wallabidi.Sandbox.Hook
end
end
"""
@doc """
Emits `plug(module)` if compiling in test env and the module is loaded;
otherwise nothing.
Any extra options are forwarded as plug options.
## Examples
plug_if_test Phoenix.Ecto.SQL.Sandbox
plug_if_test Wallabidi.Sandbox.Plug
plug_if_test MyPlug, some_option: true
"""
defmacro plug_if_test(module, opts \\ []) do
module = Macro.expand(module, __CALLER__)
if test_env?() and Code.ensure_loaded?(module) do
if opts == [] do
quote do: plug(unquote(module))
else
quote do: plug(unquote(module), unquote(opts))
end
end
end
@doc """
Emits `on_mount(module)` if compiling in test env and the module is loaded;
otherwise nothing.
## Examples
on_mount_if_test Wallabidi.Sandbox.Hook
"""
defmacro on_mount_if_test(module, _opts \\ []) do
module = Macro.expand(module, __CALLER__)
if test_env?() and Code.ensure_loaded?(module) do
quote do: on_mount(unquote(module))
end
end
@doc false
def test_env? do
function_exported?(Mix, :env, 0) and Mix.env() == :test
end
end