# `Filament.Test`

Rung 2 test API for Filament components.

Mount a component in isolation, drive it with simulated events, assert on rendered HTML.
No WebSocket required.

Example:

    import Filament.Test

    {:ok, stub} = Filament.Test.Stub.start(fn _ -> %{count: 0} end)

    {:ok, view} = mount(Counter, %{server: stub})
    assert render_text(view) =~ "Count: 0"

    {:ok, view} = click(view, "button")
    assert render_text(view) =~ "Count: 1"

# `t`

```elixir
@type t() :: %Filament.Test{
  component: module(),
  fiber_tree: map(),
  owner_pid: pid(),
  props: map(),
  rendered: Phoenix.LiveView.Rendered.t(),
  rendered_html: String.t(),
  stubs: %{required(term()) =&gt; pid()}
}
```

# `click`

```elixir
@spec click(t(), selector :: String.t()) :: {:ok, t()} | {:error, term()}
```

Simulate a click on the element matching `selector`.
Finds the `phx-click` attribute, dispatches the event handler, flushes resulting
state updates, and re-renders. Returns `{:ok, updated_view}` or `{:error, reason}`.

# `eventually`

```elixir
@spec eventually(assertion_fn :: (-&gt; term()), opts :: keyword()) :: :ok
```

Assert that `assertion_fn.()` returns a truthy value within `timeout` milliseconds.
Retries every `interval` ms. Raises `ExUnit.AssertionError` on timeout.

The assertion function must be a zero-arity function. For assertions that need
to first call `update/1`, include that call inside the fn and use the returned
view for the assertion:

    Filament.Test.eventually(fn ->
      view = Filament.Test.update(view)
      render_text(view) =~ "Count: 5"
    end, timeout: 500)

# `has_class?`

```elixir
@spec has_class?(t(), selector :: String.t(), class_name :: String.t()) :: boolean()
```

Return true if the element matching `selector` has CSS class `class_name`.
Raises if selector matches no elements.

# `mount`

```elixir
@spec mount(component :: module(), props :: map(), opts :: keyword()) ::
  {:ok, t()} | {:error, term()}
```

Mount `component` with `props`. Returns `{:ok, view}` or `{:error, reason}`.

Options:
  * `:stub` — list of `{server_identity, stub_fn}` pairs (see `Filament.Test.Stub`).
    Example: `stub: [{CartServer, fn _req -> %{items: []} end}]`

# `render_text`

```elixir
@spec render_text(t()) :: String.t()
```

Return the rendered HTML as a plain string (with HTML tags stripped).

# `submit`

```elixir
@spec submit(t(), selector :: String.t(), params :: map()) ::
  {:ok, t()} | {:error, term()}
```

Simulate a form submission on the element matching `selector` with `params`.
Finds the `phx-submit` attribute on the form, dispatches the handler with params,
flushes state updates, re-renders. Returns `{:ok, updated_view}` or `{:error, reason}`.

# `update`

```elixir
@spec update(t()) :: t()
```

Drain pending filament messages and re-render the view.
Useful after pushing to an observable stub from outside the component.

---

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