Repository navigation
fix(driver): don't launch a browser to reset or quit when none has started - #356
andrewfader wants to merge 1 commit into
Conversation
by-ae
left a comment
There was a problem hiding this comment.
I reproduced this with a real launch failure, not the stub: browser_path points to a script that just sleeps, with process_timeout: 2, and I counted Browser.new calls through a prepended module.
On main (85ae97d), after the failed visit, reset! launches again and raises ProcessTimeoutError after another 2.1s, and so does quit (5 launches across visit, reset!, quit, quit on a fresh driver, and a second visit). On 3403d63 reset! and quit return immediately with no launch, quit on a driver that never started does nothing, and the next visit still launches and times out again, so the retry behaviour you describe holds. With a working headless Chrome, visit then reset! still ends on about:blank on both branches.
Since return unless @browser sits inside the method body, the ensure still clears @started on the early return. spec/lib/driver_spec.rb passes (8 examples). In the full suite (1859 examples) the only failure is the DNS error-message example at spec/features/driver_spec.rb:740, which depends on how the network resolves a bad host and doesn't touch reset or quit.
Driver#reset!andDriver#quitboth go throughbrowser, which launches Chrome if no browser exists yet. When the launch for a test fails, for example withFerrum::ProcessTimeoutErroron an overloaded CI box, Capybara'sreset!after the test launches Chrome again and waits another fullprocess_timeout, only so it can reset a browser that never ran a page.quitdoes the same: on a driver that never started a browser, it starts one just to close it.We hit this in CI: one slow launch turned into several timeouts in a row during teardown, which pushed the example past our job's deadline.
The fix is that
reset!returns early when no browser has started, andquitcloses the browser only if one exists. The nextvisitstill launches a browser as before, so a launch that fails once is still retried on the next test.Tests: two examples in
spec/lib/driver_spec.rbthat stubBrowser.newto raiseProcessTimeoutError. Without the change both fail (expected no Exception, got #<Ferrum::ProcessTimeoutError ...>); with it both pass. RuboCop is clean.