# `Mutare.Phoenix.Swoosh`
[🔗](https://github.com/foxbenjaminfox/mutare_phoenix_swoosh/blob/v0.2.1/lib/mutare/phoenix/swoosh.ex#L1)

[Mutare](https://hex.pm/packages/mutare) mutators for the
[phoenix_swoosh](https://hexdocs.pm/phoenix_swoosh) template-rendering surface — the layer
`Phoenix.Swoosh` adds on top of a Swoosh mailer.

This package depends on `mutare_swoosh`, so the base email-construction/delivery families are
on your code path too; compose the two presets for a full mailer surface (see "Usage").

## Families

  * `Mutare.Phoenix.Swoosh.RenderBody` — `:render_body`: remove a `render_body/2,3` call
    (the email is sent with no rendered body), narrow an atom template to one of its two string
    forms (only the `.html` / only the `.text` body renders), or drop one entry from a
    literal `put_new_formats/2` map (that extension stops rendering).
  * `Mutare.Phoenix.Swoosh.Layout` — `:mail_layout`: remove a `put_layout/2` /
    `put_new_layout/2` call (the body renders in the previous/no layout), or suppress the
    layout at the render site by setting the `layout:` assign to `false` (the body renders
    bare wherever the layout was configured).

Both families also pin phoenix_swoosh's structural argument positions — the template name,
the layout tuple, the `put_new_formats/2` map — so core's value families do not generate the
missing-template crash mutants those positions would otherwise get.

## Usage

Splice `all/0` into `:mutators` alongside the `:builtins` group token and the `mutare_swoosh`
preset, and list this module under `:extensions` (see below for why):

    # .mutare.exs — a phoenix_swoosh mailer app
    [
      mutators:
        [:builtins] ++
          Mutare.Swoosh.all(mailer: MyApp.Mailer) ++
          Mutare.Phoenix.Swoosh.all(),
      extensions: [Mutare.Phoenix.Swoosh]
    ]

`all/0` returns only this package's two families — it does not include the base
`mutare_swoosh` families, so compose `Mutare.Swoosh.all/1` explicitly as shown above.

## Why the `:extensions` entry

`use Phoenix.Swoosh` defines a local `render_body` wrapper rather than importing it.
Its `__using__` injects `import Phoenix.Swoosh, except: [render_body: 3]` plus a **local**
`def render_body(email, template, assigns \\ %{})` that wraps the module function — so the
bare `render_body` calls in a mailer module resolve to a local definition, not to an import.
Mutare's in-process `use` expansion collects the injected imports, which exclude
`render_body`: the bare calls stay unresolved, and the `:render_body` family only matches
qualified/aliased call forms.

This module is therefore also a `Mutare.UseExpansion` extension. It handles expansion of
`use Phoenix.Swoosh` and returns `import Swoosh.Email` plus a **whole**
`import Phoenix.Swoosh` — deliberately without the `except:` — standing in for the injected
local wrapper, which forwards to `Phoenix.Swoosh.render_body/3` anyway. With it listed under
`:extensions`, bare `render_body` calls (both arities, the wrapper's default-argument form
included) resolve, mutate, and get their template position pinned. For the standalone
template style (`use Phoenix.Swoosh, template_root: ...` — which also does
`use Phoenix.View` in the caller) it additionally returns the `import Phoenix.View` that
nested `use` would inject.

It also records whether the mailer's `use` line configured a layout
(`layout: {MyApp.LayoutView, :email}`). That option is compile-time configuration no mutant
can be delivered into, but whether a layout is in effect determines whether suppressing one at
the render site is a real mutant or an equivalent one — so the expansion reports it to
`Mutare.Phoenix.Swoosh.Layout` as the `Mutare.Phoenix.Swoosh.LayoutConfigured` marker, the
one channel a `use` expansion has into a mutator's context.

Without the `:extensions` entry the families still work on qualified and aliased calls, and
`:mail_layout` works on bare setter calls too (`put_layout`/`put_new_layout` really are
imported) — but bare `render_body` sites are neither mutated nor pinned, and `:mail_layout`'s
`off` mutant is generated only where the author wrote the `layout:` assign themselves.

# `all`

```elixir
@spec all() :: [module(), ...]
```

This package's two phoenix_swoosh mutator families — `RenderBody`, `Layout`.

It does **not** include the base `mutare_swoosh` families; compose those explicitly with
`Mutare.Swoosh.all/1` when you want the full Swoosh + template surface (see the moduledoc's
"Usage").

    iex> Mutare.Phoenix.Swoosh.all()
    [Mutare.Phoenix.Swoosh.RenderBody, Mutare.Phoenix.Swoosh.Layout]

---

*Consult [api-reference.md](api-reference.md) for complete listing*
