Custom Mutare mutators for the Phoenix controller
surface — the Phoenix.Controller calls a controller action performs on the conn — plus
the defensive macro routing that keeps Phoenix's compile-time macros from poisoning the
metamutant build.
This package builds on mutare_plug the way phoenix builds on plug: it depends on it,
so the Plug.Conn families (Mutare.Plug.all/0) are on your code path too, ready to
compose.
Usage
Add mutare_phoenix to your deps, then list the families in .mutare.exs and this module
under :extensions. Setting :mutators replaces Mutare's default set, so include the
:builtins family to keep the built-ins on:
# .mutare.exs
[
mutators: [:builtins] ++ Mutare.Plug.all() ++ Mutare.Phoenix.all(),
extensions: [Mutare.Phoenix]
]all/0 returns this package's three families:
Mutare.Phoenix.Redirect—:redirect_status, swaps the explicit atom:statusoption ofPhoenix.Controller.redirect/2for a redirect-status sibling.Mutare.Phoenix.Body—:controller_body, blanks the body ofPhoenix.Controller.json/2(to%{}),text/2, andhtml/2(to"").Mutare.Phoenix.Download—:download_disposition, flips the explicit:dispositionoption ofPhoenix.Controller.send_download/3between:attachmentand:inline.
It does not include the mutare_plug families; compose Mutare.Plug.all/0 explicitly
as shown above. Each family matches its call written directly
(Phoenix.Controller.redirect(conn, ...)), aliased, or bare-imported
(redirect(conn, ...), the form use MyAppWeb, :controller produces).
The :extensions entry
This module is also a Mutare.CallRouting extension. Listed under :extensions, it
routes Phoenix's compile-time-only macro calls :skip — the whole call is an inert leaf, so
Mutare neither descends into their arguments nor rewrites the calls themselves:
- the
Phoenix.RouterDSL (get/post/scope/…), because route definitions run once at compile time under Mutare's compile-once model — a mutation there could never activate; Phoenix.Component.sigil_H/2(~H), because HEEx sigil arguments must remain compile-time literals — left unregistered, Mutare's imported-call witness would splice an unreachablesigil_H(arg1, arg2)that Phoenix rejects at compile time, sinking the whole metamutant build before poison recovery can isolate a single mutant.
Mutations around a ~H expression (for example a render/1 :return_value mutant)
remain available; only the sigil's own arguments are opaque.
Summary
Functions
This package's mutator families, for splicing into :mutators (see the module docs for
the Mutare.Plug.all/0 and :builtins pairing).
Functions
@spec all() :: [module()]
This package's mutator families, for splicing into :mutators (see the module docs for
the Mutare.Plug.all/0 and :builtins pairing).
iex> Mutare.Phoenix.all()
[Mutare.Phoenix.Redirect, Mutare.Phoenix.Body, Mutare.Phoenix.Download]