Raxol.MCP.Test (Raxol MCP v2.6.0)

Copy Markdown View Source

Test harness for Raxol MCP applications.

Provides session management, semantic interaction helpers, and a pipe-friendly API for testing apps via their MCP tool interface.

Usage

import Raxol.MCP.Test
import Raxol.MCP.Test.Assertions

test "user can search" do
  session = start_session(MyApp)

  session
  |> type_into("search_input", "elixir")
  |> click("search_btn")
  |> assert_component("results_table", fn c -> c[:content] != nil end)
  |> stop_session()
end

How It Works

start_session/2 spins up a headless TEA module (via Raxol.Headless), a per-session Raxol.MCP.Registry, and a ToolSynchronizer that auto-derives MCP tools from the view tree. Interaction helpers like click/2 and type_into/3 call tools through the registry, exercising the full MCP pipeline.

For unit tests that don't need a running app, use the lower-level modules directly: TreeWalker.derive_tools/2, Registry.call_tool/3.

Summary

Functions

Call an arbitrary MCP tool by its full name.

Clear an input Component by ID.

Click a Button Component by ID.

Find a Component by ID in the current view tree.

Get the current TEA model from the session.

Get the structured Component tree (all Components as summaries).

List all MCP tools currently registered for this session.

Get the plain text screenshot of the current session.

Select a row in a table or item in a list by ID.

Send a key event to the session via Headless.

Send a sequence of key events.

Start a headless MCP test session for the given TEA module.

Stop a test session, cleaning up all resources.

Toggle a checkbox by ID.

Type text into an input Component by ID.

Functions

call_tool(session, tool_name, args \\ %{})

Call an arbitrary MCP tool by its full name.

Returns the session for piping. Raises on failure.

session |> call_tool("component_id.action", %{"key" => "value"})

clear(session, component_id)

Clear an input Component by ID.

Calls the component_id.clear tool through the MCP registry.

session |> clear("search_input")

click(session, component_id)

Click a Button Component by ID.

Calls the component_id.click tool through the MCP registry.

session |> click("submit_btn")

get_component(session, component_id)

@spec get_component(Raxol.MCP.Test.Session.t(), String.t()) :: map() | nil

Find a Component by ID in the current view tree.

Returns the structured Component summary or nil if not found.

get_model(session)

@spec get_model(Raxol.MCP.Test.Session.t()) :: term()

Get the current TEA model from the session.

get_structured_components(session)

@spec get_structured_components(Raxol.MCP.Test.Session.t()) :: [
  Raxol.MCP.StructuredScreenshot.widget_summary()
]

Get the structured Component tree (all Components as summaries).

get_tools(session)

@spec get_tools(Raxol.MCP.Test.Session.t()) :: [map()]

List all MCP tools currently registered for this session.

Returns tool definitions (name, description, inputSchema).

screenshot(session)

@spec screenshot(Raxol.MCP.Test.Session.t()) :: String.t()

Get the plain text screenshot of the current session.

select(session, component_id, args \\ %{})

Select a row in a table or item in a list by ID.

session |> select("results_table", %{"index" => 0})

send_key(session, key, opts \\ [])

Send a key event to the session via Headless.

This bypasses MCP tools -- use for navigation (Tab, Escape, arrow keys) that don't map to Component tools.

session |> send_key(:tab) |> send_key("q", ctrl: true)

send_keys(session, keys)

@spec send_keys(Raxol.MCP.Test.Session.t(), [
  atom() | String.t() | {atom() | String.t(), keyword()}
]) ::
  Raxol.MCP.Test.Session.t()

Send a sequence of key events.

session |> send_keys([:tab, :tab, :enter])
session |> send_keys([{"a", ctrl: true}, :escape])

start_session(module_or_path, opts \\ [])

@spec start_session(
  module() | String.t(),
  keyword()
) :: Raxol.MCP.Test.Session.t()

Start a headless MCP test session for the given TEA module.

Returns a %Session{} struct that flows through all pipe-friendly helpers.

Options

  • :id - session ID (default: auto-generated unique atom)
  • :width - terminal width (default: 120)
  • :height - terminal height (default: 40)
  • :settle_ms - ms to wait after start for initial render (default: 100)

stop_session(session)

@spec stop_session(Raxol.MCP.Test.Session.t()) :: :ok

Stop a test session, cleaning up all resources.

Returns :ok. Can be used at the end of a pipe (the session is consumed).

toggle(session, component_id)

Toggle a checkbox by ID.

session |> toggle("remember_me")

type_into(session, component_id, text)

Type text into an input Component by ID.

Calls the component_id.type_into tool through the MCP registry.

session |> type_into("search_input", "elixir")