vibium internals · candy-mapping test case

The 8-step test case: CLI commands vs MCP tool calls

The canonical test case (references/test-case.md) run two ways. Every command below is copied verbatim from scripts/journey_cli.sh and the prompt scripts/journey_mcp.py sends the agent — not paraphrased, not simplified. Both arms run the identical sequence of actions against the identical page; only how each action gets issued differs.

Scripted CLI — journey_cli.sh Agent-driven MCP — journey_mcp.py's prompt
1Go to candymapper.com
CLI
vibium go "$URL"
MCP
mcp__vibium__browser_navigate
  {"url": "https://candymapper.com/"}
2Dismiss the Pop-Up Challenge modal
CLI
vibium wait "$DISMISS" --state visible --timeout 10000
vibium click "$DISMISS"
MCP
mcp__vibium__browser_wait
  {"selector": "[id$=-close-icon]", "state": "visible"}
mcp__vibium__browser_click
  {"selector": "[id$=-close-icon]"}
3Scroll down to Contact Us
CLI
vibium scroll into-view 'input[data-aid="First Name"]'
Section heading has no stable selector — scrolls the form's own First Name field into view instead (see references/selectors.md).
MCP
mcp__vibium__browser_scroll_into_view
  {"selector": "input[data-aid=\"First Name\"]"}
4Fill in first and last name
CLI
vibium fill 'input[data-aid="First Name"]' "Test"
vibium fill 'input[data-aid="Last Name"]' "Testerson"
MCP
mcp__vibium__browser_fill
  {"selector": "input[data-aid=\"First Name\"]", "text": "Test"}
mcp__vibium__browser_fill
  {"selector": "input[data-aid=\"Last Name\"]", "text": "Testerson"}
5Submit without the mandatory email
CLI
vibium click "$ACTION"
Not the timed click — this one is itself subject to the same startup race, and usually loses to it (see step 6).
MCP
mcp__vibium__browser_click
  {"selector": "button[data-aid=\"CONTACT_SUBMIT_BUTTON_REND\"]"}
6Verify error "Please enter a valid email address."
CLI
vibium wait text "$VALIDATION_TEXT" --timeout 800
Bounded, non-fatal — a long wait here would force the run past the same window step 8 needs to land inside. Confirmed 2026-08-04: reads false 0/70 times (the click was raced).
MCP
mcp__vibium__browser_evaluate
  {"expression": "document.body.innerText.includes(
     \"Please enter a valid email address\")"}
Unconditional, no timeout — the agent's own reasoning time already carries it past the window. Confirmed: reads true 70/70 times.
7Fill in email
CLI
vibium fill 'input[data-aid="CONTACT_FORM_EMAIL"]' \
  "test@example.invalid"
vibium value 'input[data-aid="CONTACT_FORM_EMAIL"]'
Read-back verified — a mismatch logs precondition_failed and skips the run rather than reporting a fake timing result.
MCP
mcp__vibium__browser_fill
  {"selector": "input[data-aid=\"CONTACT_FORM_EMAIL\"]",
   "text": "test@example.invalid"}
8Submit again — verify success message
CLI
CLI
vibium eval '(arm MutationObserver on success text)'
vibium eval "(()=>{const t=Math.round(performance.now());
  document.querySelector('$ACTION').click();return t})()"
vibium sleep 3000
vibium eval '(read window.__hit / success text -> "worked"|"SWALLOWED")'
Timestamp-read and click fire in the same eval call — no inter-process gap between "the time recorded" and "the click that fired" (see timing-methodology.md).
MCP
MCP
mcp__vibium__browser_evaluate  (arm MutationObserver)
mcp__vibium__browser_click
  {"selector": "button[data-aid=\"CONTACT_SUBMIT_BUTTON_REND\"]"}
mcp__vibium__browser_sleep  {"ms": 3000}
mcp__vibium__browser_evaluate  (read result -> "worked"|"SWALLOWED")
Arrival time derived from the transcript's own tool-call timestamps (navigate → this click), not agent self-report.