diff --git a/rb/lib/selenium/webdriver/common/selenium_manager.rb b/rb/lib/selenium/webdriver/common/selenium_manager.rb index f14f12c15b1c9..4a8603b6584b0 100644 --- a/rb/lib/selenium/webdriver/common/selenium_manager.rb +++ b/rb/lib/selenium/webdriver/common/selenium_manager.rb @@ -61,25 +61,12 @@ def binary end def run(*command) - WebDriver.logger.debug("Executing Process #{command}", id: :selenium_manager) - - begin - stdout, stderr, status = Open3.capture3(*command) - rescue StandardError => e - raise Error::WebDriverError, "Unsuccessful command executed: #{command}; #{e.message}" - end + stdout, stderr, status = execute_command(*command) + result = parse_result_and_log(stdout) - json_output = stdout.empty? ? {'logs' => [], 'result' => {}} : JSON.parse(stdout) - json_output['logs'].each do |log| - level = log['level'].casecmp('info').zero? ? 'debug' : log['level'].downcase - WebDriver.logger.send(level, log['message'], id: :selenium_manager) - end + validate_command_result(command, status, result, stderr) - result = json_output['result'] - return result unless status.exitstatus.positive? || result.nil? - - raise Error::WebDriverError, - "Unsuccessful command executed: #{command} - Code #{status.exitstatus}\n#{result}\n#{stderr}" + result end def platform_location @@ -98,6 +85,38 @@ def platform_location raise Error::WebDriverError, "unsupported platform: #{Platform.os}" end end + + def execute_command(*command) + WebDriver.logger.debug("Executing Process #{command}", id: :selenium_manager) + + Open3.capture3(*command) + rescue StandardError => e + raise Error::WebDriverError, "Unsuccessful command executed: #{command}; #{e.message}" + end + + def parse_result_and_log(stdout) + json_output = stdout.empty? ? {'logs' => [], 'result' => {}} : JSON.parse(stdout) + + json_output['logs'].each do |log| + level = log['level'].casecmp('info').zero? ? 'debug' : log['level'].downcase + WebDriver.logger.send(level, log['message'], id: :selenium_manager) + end + + json_output['result'] + end + + def validate_command_result(command, status, result, stderr) + if status.nil? || status.exitstatus.nil? + WebDriver.logger.info("No exit status for: #{command}. Assuming success if result is present.", + id: :selenium_manager) + end + + return unless status&.exitstatus&.positive? || result.nil? + + code = status&.exitstatus || 'exit status not available' + raise Error::WebDriverError, + "Unsuccessful command executed: #{command} - Code #{code}\n#{result}\n#{stderr}" + end end end # SeleniumManager end # WebDriver diff --git a/rb/spec/unit/selenium/webdriver/common/selenium_manager_spec.rb b/rb/spec/unit/selenium/webdriver/common/selenium_manager_spec.rb index d6816c14ac93b..9ccf65d1974f5 100644 --- a/rb/spec/unit/selenium/webdriver/common/selenium_manager_spec.rb +++ b/rb/spec/unit/selenium/webdriver/common/selenium_manager_spec.rb @@ -92,6 +92,26 @@ module WebDriver described_class.send(:run, 'anything') }.to raise_error(Error::WebDriverError, msg) end + + it 'succeeds when exitstatus is nil and result is present' do + status = instance_double(Process::Status, exitstatus: nil) + stdout = '{"result": "value", "logs": []}' + allow(Open3).to receive(:capture3).and_return([stdout, 'stderr', status]) + + expect { + expect(described_class.send(:run, 'anything')).to eq 'value' + }.to have_info(:selenium_manager) + end + + it 'raises if result is nil even with successful exitstatus' do + status = instance_double(Process::Status, exitstatus: 0) + stdout = '{"logs": []}' + allow(Open3).to receive(:capture3).and_return([stdout, 'stderr', status]) + + expect { + described_class.send(:run, 'anything') + }.to raise_error(Error::WebDriverError, /Unsuccessful command executed/) + end end describe '.binary_paths' do