Skip to main content

There are three ways to produce something you can replay. sbrs record watches you use a real browser and saves what you did; sbrs replay plays that file back. The BaseCase recorder is code-driven: every action you perform through the API is stored in an internal ActionRecorder, which you can turn into Rust source or the same action file. And sbrs run-scenario runs a hand-written JSON scenario, which is a different, richer format.

Info

What you will learn

  • How to record manual browsing with sbrs record and replay it.
  • How BaseCase records actions automatically, and how to export them.
  • The two JSON formats: recorded actions, and scenarios for run-scenario.

The three routes at a glance:

Record, write by hand, or run a scenario

Record manual browsing#

record opens a browser on the URL, injects a small listener into the page, and saves what you do in that window. Run it headed (the default; do not pass --headless) and, as for every sbrs option, put any flags such as --browser before record. It captures:

  • clicks, as click with a CSS path to the element;
  • text typed into a field, as type (recorded when the field changes);
  • changes to a <select>, as select_option_by_value;
  • navigation, as goto whenever the page URL changes.

It checks the page every half second and stops when you press Ctrl-C, after --duration SECONDS if you gave one, or when you close the browser. It then writes the file given by -o/--output (default actions.json). A .yaml or .yml extension writes YAML; anything else writes JSON. Only JSON can be replayed.

Replay a recording#

replay starts a fresh browser, runs each step, and prints ok or FAIL for each one followed by a summary such as Replayed 3 step(s): 3 passed, 0 failed, 0 skipped. The command exits with status 1 if any step failed. Replay understands these action names (aliases in parentheses): goto (open, navigate), click, type (type_text, update_text), select_option_by_value, assert_text, assert_title and assert_url. Anything else is counted as skipped and does not fail the run.

The file is a JSON array of actions. Each has a name, an optional target and value, and a timestamp_ms:

actions.json

timestamp_ms may be left out when you write one by hand. A JSON object with an actions array is accepted as well.

Record from code#

There is no separate “record” toggle in the API. As soon as you call BaseCase methods such as open, click, or type_text, the action is appended to the recorder:

save_recorded_actions takes a plain file name, with no directory part, and writes it into the latest_logs folder of the working directory. save_recording_to_logs writes a timestamped recording JSON and .rs pair there. The JSON is the action array above, so sbrs replay latest_logs/recorded.json plays it back.

With --rec-sb-cdp (BrowserConfig::with_rec_sb_cdp(true), SB_REC_SB_CDP=true) the Rust program that export_recording_as_rust and save_recording_to_logs write calls the pure CDP engine (Page and Locator) instead of BaseCase; sbrs --rec-sb-cdp run-scenario --file scenario.json saves such a program. See Recorder Mode.

start_recording() and stop_recording() mark a window inside the action log: stop_recording returns only what was recorded since start_recording, and recorder_session() wraps that window as a RecorderSession you can serialize or replay with replay_actions.

sbrs mkrec --file my_recording.rs writes a small starter program to fill in.

Type a recording by hand#

sbrs recorder needs no browser. You type one action per line, as <action> <selector> [value], and it writes the Rust test:

sbrs recorder

<action> is the name of a BaseCase method the generator knows (type stands for type_text). A line the generator cannot turn into a call, because the action is unknown or an argument is missing or malformed, is refused with the reason and, for a typo, the closest known action, instead of being acknowledged and then missing from the file. save never overwrites an existing file: if it cannot write, the recording is kept and you can try another name. quit, or the end of the input, leaves without saving. In code, ActionRecorder::try_record does the same check.

Run a JSON scenario#

A scenario is a different file: a hand-written JSON object with a name and a list of steps, each step an action plus the fields that action needs. It is not the array that record writes. Run it, and optionally choose where the HTML dashboard goes:

scenario.json

The available actions and their fields are:

ActionFields
openurl
click, hover, clear, submit, double_click, context_click, js_click, scroll_to, switch_to_frame, assert_elementcss
type_text, js_typecss, text
assert_textcss, contains
wait_for_textcss, text, timeout (seconds)
sleepseconds
hover_and_clickhover_css, click_css
select_option_by_textcss, text
select_option_by_valuecss, value
drag_and_dropsource_css, target_css
click_link_texttext
type_alert_texttext
set_attributecss, attribute, value
remove_attributecss, attribute
choose_filecss, file_path
set_local_storage_itemkey, value
remove_local_storage_itemkey
switch_to_windowhandle
accept_alert, dismiss_alert, switch_to_default_content, go_back, go_forward, refresh, delete_all_cookies, clear_local_storage, switch_to_new_window, maximize_window, scroll_to_bottom, scroll_to_topnone

A file that names an unknown action, or leaves out a field, is rejected as a whole before any browser starts.

Warning

A failing step does not stop the run: the steps that failed are listed, and the process still exits with status 0. The command also writes the dashboard, prints the pass/fail counts, and saves a recording JSON and .rs pair of what it did into latest_logs. If you gate CI on the result, read the printed counts or the dashboard rather than the exit status.

Best practices#

  • Review generated code before committing it.
  • Replace brittle auto-generated selectors with stable data-testid attributes. record builds CSS paths such as div > button:nth-of-type(2) when an element has no id.
  • Add explicit assertions after the recording stops; record captures no assertions.
  • Keep scenario and action files under version control so CI replays the same steps.