# `PlaywrightEx.EventWaiter`
[🔗](https://github.com/ftes/playwright_ex/blob/v0.11.0/lib/playwright_ex/event_waiter.ex#L1)

Captures the first matching protocol event using a linked `Task`.

Call `arm/3`, trigger the action, then call `await/1`. Registration completes
before `arm/3` returns. The event timeout starts when arming begins; filtering
events or awaiting later does not restart it.

Only the process that armed the listener can await or cancel it. Await once,
and cancel in an `after` block if the action can raise. Owner exit cleans up
the task; unexpected task failures propagate to the owner.

An optional `:predicate` filters raw event maps. Returning `false` or `nil`
skips an event. Keep predicates quick and nonblocking.

Events are matched by channel GUID and message `method`. Unrelated events
are discarded without extending the timeout. Opt-in Page and BrowserContext
events are enabled before arming returns and released when the task exits.
Routing stays at the protocol level: console and network messages arrive on
the BrowserContext channel, with the page identified in their parameters.

An optional `:transform` runs in the task when the predicate accepts an event,
without waiting for `await/1`. It can capture metadata or handle a dialog while
the owner's action is blocked. Its return value becomes the successful result.
The event timeout covers capture, not the transform; give browser commands
inside it their own timeout. Unexpected callback failures propagate.

# `error`

```elixir
@type error() :: %{reason: atom(), message: String.t()}
```

# `opt`

```elixir
@type opt() ::
  {:connection, GenServer.name()}
  | {:timeout, timeout()}
  | {:predicate, (term() -&gt; term())}
  | {:transform, (term() -&gt; term())}
  | {:subscription, term()}
```

# `result`

```elixir
@type result() :: {:ok, term()} | {:error, error()}
```

# `t`

```elixir
@opaque t()
```

# `arm`

```elixir
@spec arm(PlaywrightEx.guid(), atom(), [opt() | PlaywrightEx.unknown_opt()]) ::
  {:ok, t()} | {:error, error()}
```

Arms a one-shot listener for `event` on `guid`.

Fails if the channel has already been disposed. The calling process owns the
task; its exit cleans up even if `await/1` was never called.

## Options
* `:connection` (`t:term/0`) - The Connection process name. Defaults to `PlaywrightEx.Supervisor.Connection`. The default value is `PlaywrightEx.Supervisor.Connection`.

* `:timeout` (`t:timeout/0`) - Required. Time to capture an event in milliseconds. `0` means no waiting; `:infinity` disables the timeout.

* `:predicate` (function of arity 1) - Filter applied to raw event maps. The first truthy result accepts the event.

* `:transform` (function of arity 1) - Maps the accepted raw event to the result, inside the waiting task.

* `:subscription` - Opt-in event to enable when it differs from the raw message method, e.g. `:dialog` for a Dialog `:__create__`.

# `await`

```elixir
@spec await(t()) :: result()
```

Consumes the captured event or waits for the original deadline.

Like `Task.await/2`, this must be called once, by the process that armed the
listener. Do not await a consumed or canceled handle.

# `cancel`

```elixir
@spec cancel(t()) :: :ok
```

Shuts down the task and discards its result from the owner's mailbox.

Must be called by the process that armed the listener. Safe to call after
awaiting or more than once. This cancels event capture, not a browser download
or the triggering action.

---

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