Skip to main content

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.

Info

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-scenario reads.
  • 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):

Terminal

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:

Warning

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.

Tip

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:

Terminal
Warning

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.