# `Mutare.Phoenix.LiveView.SendUpdate`
[🔗](https://github.com/foxbenjaminfox/mutare_phoenix_live_view/blob/v0.2.1/lib/mutare/phoenix/live_view/send_update.ex#L1)

`:lv_send_update` — mutates a `Phoenix.LiveView` call that sends new assigns to a child
`Phoenix.LiveComponent` for re-rendering. Two kinds, each a variant label:

**`remove`** drops the update ("does the update matter?"):

    send_update(Cart, id: "cart", count: 3)            ->  :ok
    send_update(pid, Cart, id: "cart", count: 3)       ->  :ok
    send_update_after(Cart, [id: "cart"], 1_000)       ->  :erlang.make_ref()
    send_update_after(pid, Cart, [id: "cart"], 1_000)  ->  :erlang.make_ref()

**`immediate`** keeps the update but drops the *delay* ("does the timing matter?"):

    send_update_after(Cart, [id: "cart"], 1_000)       ->  send_update(Cart, id: "cart")
                                                           :erlang.make_ref()

A `remove` survivor means no test asserts the child component received the update — that it
re-renders with the new assigns (`Phoenix.LiveViewTest.render_component/2`, or asserting the
live render reflects the change). Like `:lv_event`, this mutation removes a side effect:
a server→component update in this case, rather than a server→client event.
An `immediate` survivor means no test depends on the update being *deferred* — the delay
could be deleted without a failure.
Suppress one kind with `# mutare:ignore[lv_send_update:remove]` / `[lv_send_update:immediate]`,
or the whole family with `# mutare:ignore[lv_send_update]`.

Unlike `push_event` (socket-in, socket-out), `send_update`/`send_update_after` are
fire-and-forget side effects that never return the socket — so both kinds collapse the whole
call to a happy-path return (not to an argument), and the two calls differ. `send_update`'s
return is undocumented (the return value of `send/2`), so the conventional `:ok`
stands in; the documented return type of `send_update_after` is `reference()` for the
scheduled timer, so its replacements end in a fresh `:erlang.make_ref()`. The `immediate`
mutant is a two-expression block for the same reason: `send_update/2,3` alone would change
the return type, while
`(send_update(...); :erlang.make_ref())` sends the update immediately and keeps the documented
ref type. Matching that type allows the result of either replacement to be passed to
`Process.cancel_timer/1` — cancelling an unknown ref returns `false`, whereas passing `:ok`
would raise, killing the mutant without testing the update behaviour.

The delay argument itself is marked with the shared `:timeout` label
(`c:Mutare.Mutator.argument_marks/1`), so core's `IntegerLiteral`/`AtomLiteral` leave the
duration literal alone. The `immediate` mutant tests whether the delay matters; an off-by-one
mutation such as `1_000 → 1_001` is unlikely to affect observable behaviour, which is why
those families skip timeout literals.

No socket flows through these calls, so a pipe into one feeds the module/pid slot
(`Cart |> send_update(id: 1)`); it is the same call, and gets the same mutants, reported
over the whole pipe. Only calls to `send_update/2,3` and `send_update_after/3,4` are
mutated, so a name-matched call of any other arity (reachable only by an explicit
qualifier) is left alone, keeping every metamutant compiling.

Matches direct (`Phoenix.LiveView.send_update(...)`), aliased, and bare-imported
(`use`-injected) calls. Like `:lv_event`, this family has a high equivalent-mutant rate in
suites that never assert a component re-rendered — drop it from your preset if that is noisy.

---

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