LiveLoad.Browser.Connection behaviour (LiveLoad v0.0.1-rc.51)

Copy Markdown View Source

LiveLoad.Browser.Connection defines a behaviour for how to connect to browsers with LiveLoad.

By default, an implementation for a Playwright instance (LiveLoad.Browser.Connection.Playwright) is included in LiveLoad and can be looked at as reference implementation for implementing other browsers.

Summary

Types

A serializable storage snapshot that contains the current browser context's cookies, local storage, and session storage.

t()

Any module implementing the LiveLoad.Browser.Connection behaviour.

Callbacks

A hook called after the supervision tree for the browser is initialized.

A hook called after the supervision tree for the browser is stopped.

A hook called before the supervision tree for the browser is initialized.

A hook called before the supervision tree for the browser is stopped.

Different browser implementations may have different CPU requirements, depending on how they are implemented. The LiveLoad.Cluster initialization procedure uses this callback in order to calculate the optimal amount of nodes to use for running a LiveLoad.Scenario based on the number of users for the test and the resources available on each cluster node.

Different browser implementations may have different memory requirements, depending on how they are implemented. The LiveLoad.Cluster initialization procedure uses this callback in order to calculate the optimal amount of nodes to use for running a LiveLoad.Scenario based on the number of users for the test and the resources available on each cluster node.

Different browser implementations may have different memory requirements, depending on how they are implemented. The LiveLoad.Cluster initialization procedure uses this callback in order to calculate the optimal amount of nodes to use for running a LiveLoad.Scenario based on the number of users for the test and the resources available on each cluster node.

Any connection can broadcast telemetry events that correspond to load test metrics which LiveLoad tracks during a scenario. Since connections are generally modeled around Ports, the telemetry sent by those ports may be asynchronous in nature, meaning that stopping a context does not necessarily mean that all metrics have completed sending and been consumed. To avoid race conditions and dropping metrics, this callback can be implemented by a connection's metrics collection mechanism to ensure that all metrics have been sent and drained.

Types

context_storage_snapshot()

@type context_storage_snapshot() :: term()

A serializable storage snapshot that contains the current browser context's cookies, local storage, and session storage.

This type is intentionally left as an ambiguous term, as it is meant to be usable as a storage and restoration mechanism, however it is not guaranteed to be uniform across different browser connections.

option()

opts()

@type opts() :: [option()]

t()

@type t() :: module()

Any module implementing the LiveLoad.Browser.Connection behaviour.

Callbacks

after_start(browser)

@callback after_start(browser :: LiveLoad.Browser.t()) ::
  {:ok, LiveLoad.Browser.t()} | {:error, term()}

A hook called after the supervision tree for the browser is initialized.

after_stop(browser)

@callback after_stop(browser :: LiveLoad.Browser.t()) :: :ok

A hook called after the supervision tree for the browser is stopped.

This hook is meant for side effects and as such cannot return any value other than :ok

before_start(browser)

@callback before_start(browser :: LiveLoad.Browser.t()) ::
  {:ok, LiveLoad.Browser.t()} | {:error, term()}

A hook called before the supervision tree for the browser is initialized.

before_stop(browser)

@callback before_stop(browser :: LiveLoad.Browser.t()) :: :ok

A hook called before the supervision tree for the browser is stopped.

This hook is meant for side effects and as such cannot return any value other than :ok

blur(context, selector)

@callback blur(context :: LiveLoad.Browser.Context.t(), selector :: String.t()) ::
  {:ok, LiveLoad.Browser.Context.t()} | {:error, term()}

browser_contexts_per_core()

@callback browser_contexts_per_core() :: pos_integer()

Different browser implementations may have different CPU requirements, depending on how they are implemented. The LiveLoad.Cluster initialization procedure uses this callback in order to calculate the optimal amount of nodes to use for running a LiveLoad.Scenario based on the number of users for the test and the resources available on each cluster node.

browser_memory_usage_bytes()

@callback browser_memory_usage_bytes() :: pos_integer()

Different browser implementations may have different memory requirements, depending on how they are implemented. The LiveLoad.Cluster initialization procedure uses this callback in order to calculate the optimal amount of nodes to use for running a LiveLoad.Scenario based on the number of users for the test and the resources available on each cluster node.

check(context, selector)

@callback check(context :: LiveLoad.Browser.Context.t(), selector :: String.t()) ::
  {:ok, LiveLoad.Browser.Context.t()} | {:error, term()}

checked?(context, selector)

@callback checked?(context :: LiveLoad.Browser.Context.t(), selector :: String.t()) ::
  {:ok, {LiveLoad.Browser.Context.t(), boolean()}} | {:error, term()}

child_spec(opts)

@callback child_spec(opts :: opts()) :: Supervisor.child_spec()

click(context, selector)

@callback click(context :: LiveLoad.Browser.Context.t(), selector :: String.t()) ::
  {:ok, LiveLoad.Browser.Context.t()} | {:error, term()}

context_memory_usage_bytes()

@callback context_memory_usage_bytes() :: pos_integer()

Different browser implementations may have different memory requirements, depending on how they are implemented. The LiveLoad.Cluster initialization procedure uses this callback in order to calculate the optimal amount of nodes to use for running a LiveLoad.Scenario based on the number of users for the test and the resources available on each cluster node.

context_storage_snapshot(context)

@callback context_storage_snapshot(context :: LiveLoad.Browser.Context.t()) ::
  {:ok, {LiveLoad.Browser.Context.t(), context_storage_snapshot()}}
  | {:error, term()}

drag_and_drop(context, source, target)

@callback drag_and_drop(
  context :: LiveLoad.Browser.Context.t(),
  source :: String.t(),
  target :: String.t()
) ::
  {:ok, LiveLoad.Browser.Context.t()} | {:error, term()}

drain_metrics(browser)

@callback drain_metrics(browser :: LiveLoad.Browser.t()) :: :ok

Any connection can broadcast telemetry events that correspond to load test metrics which LiveLoad tracks during a scenario. Since connections are generally modeled around Ports, the telemetry sent by those ports may be asynchronous in nature, meaning that stopping a context does not necessarily mean that all metrics have completed sending and been consumed. To avoid race conditions and dropping metrics, this callback can be implemented by a connection's metrics collection mechanism to ensure that all metrics have been sent and drained.

A reference implementation can be found in the LiveLoad.Browser.Connection.Playwright implementation of the connection behaviour.

fill(context, selector, value)

@callback fill(
  context :: LiveLoad.Browser.Context.t(),
  selector :: String.t(),
  value :: String.t()
) ::
  {:ok, LiveLoad.Browser.Context.t()} | {:error, term()}

focus(context, selector)

@callback focus(context :: LiveLoad.Browser.Context.t(), selector :: String.t()) ::
  {:ok, LiveLoad.Browser.Context.t()} | {:error, term()}

get_attribute(context, selector, name)

@callback get_attribute(
  context :: LiveLoad.Browser.Context.t(),
  selector :: String.t(),
  name :: String.t()
) ::
  {:ok, {LiveLoad.Browser.Context.t(), String.t() | nil}} | {:error, term()}

hover(context, selector)

@callback hover(context :: LiveLoad.Browser.Context.t(), selector :: String.t()) ::
  {:ok, LiveLoad.Browser.Context.t()} | {:error, term()}

inner_html(context, selector)

@callback inner_html(context :: LiveLoad.Browser.Context.t(), selector :: String.t()) ::
  {:ok, {LiveLoad.Browser.Context.t(), String.t()}} | {:error, term()}

inner_text(context, selector)

@callback inner_text(context :: LiveLoad.Browser.Context.t(), selector :: String.t()) ::
  {:ok, {LiveLoad.Browser.Context.t(), String.t()}} | {:error, term()}

input_value(context, selector)

@callback input_value(context :: LiveLoad.Browser.Context.t(), selector :: String.t()) ::
  {:ok, {LiveLoad.Browser.Context.t(), String.t()}} | {:error, term()}

navigate(context, url)

@callback navigate(context :: LiveLoad.Browser.Context.t(), url :: String.t() | URI.t()) ::
  {:ok, LiveLoad.Browser.Context.t()} | {:error, term()}

new_context(browser)

@callback new_context(browser :: LiveLoad.Browser.t()) ::
  {:ok, LiveLoad.Browser.Context.t()} | {:error, term()}

page_content(context)

@callback page_content(context :: LiveLoad.Browser.Context.t()) ::
  {:ok, {LiveLoad.Browser.Context.t(), String.t()}} | {:error, term()}

press(context, selector, key)

@callback press(
  context :: LiveLoad.Browser.Context.t(),
  selector :: String.t(),
  key :: String.t()
) ::
  {:ok, LiveLoad.Browser.Context.t()} | {:error, term()}

reload(context)

@callback reload(context :: LiveLoad.Browser.Context.t()) ::
  {:ok, LiveLoad.Browser.Context.t()} | {:error, term()}

reset_context_storage(context)

@callback reset_context_storage(context :: LiveLoad.Browser.Context.t()) ::
  {:ok, LiveLoad.Browser.Context.t()} | {:error, term()}

restore_context_storage(context, snapshot)

@callback restore_context_storage(
  context :: LiveLoad.Browser.Context.t(),
  snapshot :: context_storage_snapshot()
) :: {:ok, LiveLoad.Browser.Context.t()} | {:error, term()}

select_multiple_options(context, selector, values)

@callback select_multiple_options(
  context :: LiveLoad.Browser.Context.t(),
  selector :: String.t(),
  values :: [String.t()]
) :: {:ok, LiveLoad.Browser.Context.t()} | {:error, term()}

select_option(context, selector, value)

@callback select_option(
  context :: LiveLoad.Browser.Context.t(),
  selector :: String.t(),
  value :: String.t()
) :: {:ok, LiveLoad.Browser.Context.t()} | {:error, term()}

stop_context(context)

@callback stop_context(context :: LiveLoad.Browser.Context.t()) :: :ok | {:error, term()}

text_content(context, selector)

@callback text_content(context :: LiveLoad.Browser.Context.t(), selector :: String.t()) ::
  {:ok, {LiveLoad.Browser.Context.t(), String.t() | nil}} | {:error, term()}

uncheck(context, selector)

@callback uncheck(context :: LiveLoad.Browser.Context.t(), selector :: String.t()) ::
  {:ok, LiveLoad.Browser.Context.t()} | {:error, term()}

visible?(context, selector)

@callback visible?(context :: LiveLoad.Browser.Context.t(), selector :: String.t()) ::
  {:ok, {LiveLoad.Browser.Context.t(), boolean()}} | {:error, term()}

wait_for_selector(context, selector)

@callback wait_for_selector(
  context :: LiveLoad.Browser.Context.t(),
  selector :: String.t()
) ::
  {:ok, LiveLoad.Browser.Context.t()} | {:error, term()}