From 5ac1bb8e132125e4ec8a4dadf8c3fe2c990bca78 Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Fri, 11 Oct 2024 23:39:43 +0200 Subject: [PATCH] Selenium: Refactor WaitFor* scripts to prevent crashes The previously used approach with `Timeout.timeout` works. However, it might interrupt the `page.evaluate_script`, which will cause an unhandled exception with the Selenium webdriver which in turn crashes. Once crashed, all further Selenium-based tests will fail, too. --- spec/support/wait_for_ajax.rb | 11 +++++++++-- spec/support/wait_for_websocket.rb | 11 +++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/spec/support/wait_for_ajax.rb b/spec/support/wait_for_ajax.rb index 1bbf05a42..e05098c57 100644 --- a/spec/support/wait_for_ajax.rb +++ b/spec/support/wait_for_ajax.rb @@ -2,12 +2,19 @@ module WaitForAjax def wait_for_ajax - Timeout.timeout(Capybara.default_max_wait_time) do - loop until ajax_requests_finished? + start_time = Time.current + timeout = Capybara.default_max_wait_time + + loop do + break if ajax_requests_finished? || (Time.current - start_time) > timeout + + sleep 0.1 # Short sleep time to prevent busy waiting end end def ajax_requests_finished? + # This method MUST NOT be interrupted. Hence, Timeout.timeout is not used here. + # Otherwise, Selenium and the browser driver might crash, preventing further tests from running. page.evaluate_script('jQuery.active').zero? end end diff --git a/spec/support/wait_for_websocket.rb b/spec/support/wait_for_websocket.rb index 12fdc2ec6..b14068f72 100644 --- a/spec/support/wait_for_websocket.rb +++ b/spec/support/wait_for_websocket.rb @@ -2,12 +2,19 @@ module WaitForWebsocket def wait_for_websocket - Timeout.timeout(Capybara.default_max_wait_time) do - loop until websocket_finished? + start_time = Time.current + timeout = Capybara.default_max_wait_time + + loop do + break if websocket_finished? || (Time.current - start_time) > timeout + + sleep 0.1 # Short sleep time to prevent busy waiting end end def websocket_finished? + # This method MUST NOT be interrupted. Hence, Timeout.timeout is not used here. + # Otherwise, Selenium and the browser driver might crash, preventing further tests from running. page.evaluate_script('CodeOceanEditorWebsocket?.websocket?.getReadyState() === WebSocket.CLOSED').present? end end