Recorder Mode captures your browser interactions and generates either a Rust source file or a JSON action file that can be replayed later. It is a fast way to bootstrap a UI test: point, click, type, assert, and then refine the generated output.
What you will learn
- How to record from the CLI and from code.
- What the generated Rust test looks like.
- How to export and replay JSON action files, and how they differ from the
scenario files
run-scenarioreads. - Tips for keeping generated tests maintainable.
Record from the CLI#
sbrs record opens a browser on a URL, captures your clicks, typing, <select>
changes and page navigations while you use it, and saves them as an action file
when you press Ctrl-C (or after --duration SECONDS, or when you close the
browser):
Run it headed (the default), and put any global options such as --browser
before record. replay runs the file in a fresh browser and exits with status
1 if a step fails. See Recorder CLI for the file
format and the actions replay understands.
Record from code#
BaseCase records every action you perform through its API automatically. There
is no separate start/stop toggle for the default recorder; simply run the
interactions you want to capture and then export the recording. If you want only
part of a run, start_recording() marks a starting point and stop_recording()
returns the actions recorded since then.
Generated output#
The recorder produces method calls such as:
Only some BaseCase methods record themselves: navigation and interaction ones
such as open, click, type_text, clear, hover, the select_option_*
methods and a few waits, and among assertions only assert_text. Calls to
other methods leave no trace in the recording.
export_recording_as_rust (and the .rs file save_recording_to_logs writes)
is a complete #[tokio::main] program: it imports BaseCase and
BrowserConfig, creates a BaseCase from BrowserConfig::default(), runs the
calls, and quits. To get a #[tokio::test] function instead, call
ActionRecorder::to_rust_test(name), or save_recording_as_test(dir, name) to
write it to dir/name.rs. The generated code has no custom timeout and does not
use the sb_test! macro.
Always review the output before committing it to your suite.
Pure CDP code (--rec-sb-cdp)#
The same recording can be written for the pure CDP engine (sb_cdp, no
chromedriver) instead of BaseCase, as Python’s --rec-sb-cdp does with
sb_cdp calls. ActionRecorder::to_cdp_script() returns a standalone
#[tokio::main] program, to_cdp_test(name) a #[tokio::test] function, and
save_recording_as_cdp_test(dir, name) writes that to dir/name.rs. For the
recording above the program is:
BaseCase::export_recording_as_cdp_rust() returns it from a live test. To make
export_recording_as_rust and save_recording_to_logs write it, as the Python
flag does, turn the setting on with BrowserConfig::with_rec_sb_cdp(true), the
sbrs --rec-sb-cdp flag or SB_REC_SB_CDP=true; the test itself still runs on
WebDriver, and only the generated code changes.
Every selector and value is written as a Rust string literal. 51 recorded
actions have a pure CDP call: open, the clicks, typing (type_text, which
empties the field first as BaseCase::type_text does, and send_keys for
add_text, which adds to what the field holds), the select_option_* methods, link
clicks (link= and p_link= selectors), drag and drop, the element waits, the
text, attribute and title assertions, history and reload, scrolling, cookies,
localStorage, maximize_window, click_with_offset (from the top-left corner,
or the centre when the recording says x, y, center) and sleep. The rest
(frame, window and alert switching, JavaScript clicks, set_window_size, and
so on) become a // skipped: comment that quotes the BaseCase call, so a gap
is never silent. Differences from the WebDriver program: a wait uses the pure
CDP engine’s own timeout, not ten seconds, and the program is not written when
the test ends; you ask for it.
JSON action files#
Recorded actions can also be saved as JSON. From code:
The file goes in the latest_logs folder (the name must be a plain file name),
and holds an array of { "name", "target", "value", "timestamp_ms" } objects.
Replay it with the CLI:
This is not the file sbrs run-scenario reads. That command takes a
hand-written scenario, an object with a name and a list of steps such as
{ "action": "click", "css": "#myButton" }; passing it an action file fails to
parse. See Recorder CLI for both formats.
Action files are portable and can be replayed by CI jobs without recompiling a
test binary. replay understands goto/open, click, type/type_text,
select_option_by_value, assert_text, assert_title and assert_url, and
skips any other action.
Best practices#
- Wait for elements to settle before acting; the recorder captures explicit waits automatically.
- Review the generated code and add assertions where needed.
- Use meaningful selectors in the application under test so generated locators remain stable.
- Run the generated test immediately to confirm it passes before editing it.
Troubleshooting#
Recording is empty
Likely cause: Actions were performed without a BaseCase method (e.g. raw JS).
Fix: Use BaseCase interaction methods so the internal recorder captures them.
Generated selector is brittle
Likely cause: Page uses auto-generated IDs.
Fix: Replace recorded selectors with stable data-testid or class selectors.
Replay fails
Likely cause: Target application changed.
Fix: Regenerate or hand-edit the action file.
run-scenario rejects the saved file
Likely cause: It is an action file, not a scenario.
Fix: Replay it with sbrs replay.
replay reports skipped steps
Likely cause: The action is not one replay understands.
Fix: Use the generated Rust test instead, or hand-edit the file.