Stampede.LiveView (stampede v0.2.0)

Copy Markdown View Source

A LiveView client for load tests.

{:ok, view} = Stampede.LiveView.connect("http://localhost:4000/counter")
{:ok, _reply} = Stampede.LiveView.click(view, "inc")
{:ok, _reply} = Stampede.LiveView.submit(view, "save", %{"user" => %{"name" => "jo"}})
{:ok, view} = Stampede.LiveView.navigate(view, "/posts")

connect/2 does what a browser does. It fetches the page over HTTP, reads the CSRF token and the LiveView's signed session from it, opens the LiveView socket with the cookies the page set, and joins the LiveView.

The connection is a Stampede.Channels socket, available as view.socket, so it sends heartbeats and is closed at the end of an iteration like any other. view.url is the URL of the LiveView the view is on.

Navigation

patch/3 and navigate/3 move between pages like <.link patch> and <.link navigate> do, without loading the page again when LiveView would not. When an event makes the LiveView navigate on its own, it returns {:error, {:live_redirect, %{"to" => to}}}, or {:error, {:redirect, %{"to" => to}}} for a full redirect, as Phoenix.LiveViewTest does. Follow either one with navigate/3.

Metrics

Inside a run, a view records:

  • "live.page" and "live.page.errors" - fetching the page
  • "live.join" and "live.join.errors" - joining the LiveView
  • "live.event" and "live.event.errors" - events and their replies
  • "live.patch" and "live.patch.errors" - patches
  • "live.navigate" and "live.navigate.errors" - navigations over the same socket. A navigation that needs a new page load records that load instead.

along with the connection metrics listed in Stampede.Channels.

Summary

Functions

Waits for the LiveView to send an update of its own, such as one caused by handle_info/2, and returns its diff.

Sends a form change, like a form with phx-change={event} would.

Sends a click, like an element with phx-click={event} would.

Closes the connection.

Fetches the page at url and connects to the LiveView it renders.

Navigates to the LiveView at to, like <.link navigate={to}> would.

Patches the LiveView to to, like <.link patch={to}> would.

Submits a form, like a form with phx-submit={event} would.

Types

t()

@type t() :: %Stampede.LiveView{
  opts: term(),
  params: term(),
  root: term(),
  socket: Stampede.Channels.socket(),
  topic: String.t(),
  url: String.t()
}

Functions

await(view, timeout_or_opts \\ [])

@spec await(t(), timeout() | keyword()) :: {:ok, map()} | {:error, term()}

Waits for the LiveView to send an update of its own, such as one caused by handle_info/2, and returns its diff.

Takes a timeout in milliseconds, or the same options as Stampede.Channels.await/4, with :match getting each diff.

change(view, event, params, opts \\ [])

@spec change(t(), String.t(), map(), keyword()) ::
  {:ok, map() | nil} | {:error, term()}

Sends a form change, like a form with phx-change={event} would.

params are the form's fields, nested the way handle_event/3 should get them, such as %{"user" => %{"name" => "jo"}}. Takes the same options and returns the same as click/4.

click(view, event, value \\ %{}, opts \\ [])

@spec click(t(), String.t(), map(), keyword()) ::
  {:ok, map() | nil} | {:error, term()}

Sends a click, like an element with phx-click={event} would.

value is what handle_event/3 gets as its params. Returns {:ok, reply} once the LiveView has handled it, where reply is the map given to {:reply, map, socket}, or nil when handle_event/3 returned {:noreply, socket}. Returns {:error, :channel_crashed} if the LiveView crashes while handling it.

Options

  • :target - the component to send the event to, like phx-target does. It is the number LiveView renders for phx-target={@myself}; components are numbered from 1, in the order they first render.
  • :timeout - how long to wait for the reply, in milliseconds. Defaults to 5_000.

close(view)

@spec close(t()) :: :ok

Closes the connection.

connect(url, opts \\ [])

@spec connect(String.t(), keyword()) :: {:ok, t()} | {:error, term()}

Fetches the page at url and connects to the LiveView it renders.

Options

  • :headers - extra headers for both the page and the socket, such as a cookie for pages behind a login
  • :max_redirects - how many redirects to follow while loading the page, keeping the cookies they set. Defaults to 5.
  • :socket_path - where the LiveView socket is mounted. Defaults to "/live".
  • :timeout - how long to wait for each page request and for the join, in milliseconds. Defaults to 5_000.
  • :transport_opts - options for :gen_tcp or :ssl

Returns {:error, {:http_status, status}} when the page does not load or redirects too many times, {:error, :no_live_view} when it has no LiveView, and {:error, reply} when the LiveView refuses the join, for example to redirect.

patch(view, to, opts \\ [])

@spec patch(t(), String.t(), keyword()) :: {:ok, t()} | {:error, term()}

Patches the LiveView to to, like <.link patch={to}> would.

to is a path, such as "/posts?page=2", or a full URL. The LiveView's handle_params/3 runs, and {:ok, view} returns the view at its new URL. When to belongs to another LiveView, it navigates there with navigate/3 instead, as a browser does.

Takes a :timeout option, in milliseconds, that defaults to 5_000.

submit(view, event, params, opts \\ [])

@spec submit(t(), String.t(), map(), keyword()) ::
  {:ok, map() | nil} | {:error, term()}

Submits a form, like a form with phx-submit={event} would.

Takes the same arguments and returns the same as change/4.