Class: SeleniumScreencast::Recorder
- Inherits:
-
Object
- Object
- SeleniumScreencast::Recorder
- Defined in:
- lib/selenium_screencast/recorder.rb
Overview
The recording lifecycle built on CDP (Chrome DevTools Protocol)'s Page.startScreencast. Receives a browser that responds to #devtools via injection, and knows nothing about Capybara or RSpec.
Instance Method Summary collapse
-
#initialize(browser, output_path:, config: SeleniumScreencast.config) ⇒ Recorder
constructor
A new instance of Recorder.
- #recording? ⇒ Boolean
- #start ⇒ Object
-
#stop(encode: true) ⇒ Object
Stops the recording.
Constructor Details
#initialize(browser, output_path:, config: SeleniumScreencast.config) ⇒ Recorder
Returns a new instance of Recorder.
10 11 12 13 14 15 |
# File 'lib/selenium_screencast/recorder.rb', line 10 def initialize(browser, output_path:, config: SeleniumScreencast.config) @browser = browser @output_path = Pathname(output_path.to_s) @config = config @state = nil end |
Instance Method Details
#recording? ⇒ Boolean
73 74 75 |
# File 'lib/selenium_screencast/recorder.rb', line 73 def recording? !@state.nil? end |
#start ⇒ Object
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/selenium_screencast/recorder.rb', line 17 def start raise "SeleniumScreencast::Recorder is already recording" if recording? devtools = @browser.devtools(target_type: "page") frame_store = FrameStore.for_output(@output_path) callback = build_frame_callback(devtools, frame_store) # on returns the array of registered callbacks. Removing our own # callback from this array on stop keeps it from lingering into the # next recording. callbacks = devtools.page.on(:screencast_frame, &callback) begin devtools.page.start_screencast( format: "jpeg", quality: @config.quality, every_nth_frame: @config.every_nth_frame ) rescue StandardError # If starting fails, remove ourselves from the shared callback array # immediately before re-raising, so we don't linger in it. callbacks.delete(callback) raise end @state = { devtools:, callback:, callbacks:, frame_store: } end |
#stop(encode: true) ⇒ Object
Stops the recording. With encode: false, the captured frames are discarded without invoking ffmpeg, so nothing is written to output_path. This lets a caller that only wants video under some condition (e.g. the RSpec adapter's "failed only" mode) skip the encode cost entirely rather than encoding and deleting afterwards. Recorder is told whether to encode, never why: it stays unaware of test outcomes.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/selenium_screencast/recorder.rb', line 50 def stop(encode: true) state = @state return if state.nil? stop_screencast(state, wait_for_inflight: encode) encode_frames(state) if encode ensure # Even if encode raises SeleniumScreencast::Error (invalid format value, # ffmpeg missing), always clean up in ensure so the intermediate JPEG # frames don't linger uncleaned. # debug? only applies when we actually encoded: keeping frames is for # inspecting what a produced video was built from, so with encode: false # they are always removed. Otherwise a full suite in "failed only" mode # would leave a *_frames dir behind for every passing example. state&.fetch(:frame_store)&.cleanup(keep: @config.debug? && encode) @state = nil # NOTE: never close devtools. It's a shared instance memoized per target # on the browser side; closing it would break other recordings and # selenium's own devtools usage too. Removing ourselves from the # callback array is sufficient cleanup. end |