Skip to content

Commit

Permalink
[rb] Close BiDi session on closing the last top-level browsing context
Browse files Browse the repository at this point in the history
  • Loading branch information
TamsilAmani authored Feb 13, 2023
1 parent 1e2a4c4 commit 332988c
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 15 deletions.
2 changes: 1 addition & 1 deletion rb/lib/selenium/webdriver/bidi.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def callbacks
end

def session
Session.new(self)
@session ||= Session.new(self)
end

def send_cmd(method, **params)
Expand Down
7 changes: 6 additions & 1 deletion rb/lib/selenium/webdriver/common/driver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ def for(browser, opts = {})
def initialize(bridge: nil, listener: nil, **opts)
@service_manager = nil
@devtools = nil
@bidi = nil
bridge ||= create_bridge(**opts)
add_extensions(bridge.browser)
@bridge = listener ? Support::EventFiringBridge.new(bridge, listener) : bridge
Expand Down Expand Up @@ -174,14 +175,18 @@ def quit
ensure
@service_manager&.stop
@devtools&.close
@bidi&.close
end

#
# Close the current window, or the browser if no windows are left.
#

def close
bridge.close
# If no top-level browsing contexts are open after calling close,
# it indicates that the WebDriver session is closed.
# If the WebDriver session is closed, the BiDi session also needs to be closed.
bridge.close.tap { |handles| @bidi&.close if handles&.empty? }
end

#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
module Selenium
module WebDriver
class BiDi
describe BrowsingContext, exclusive: {browser: %i[chrome firefox]} do
describe BrowsingContext, only: {browser: %i[chrome edge firefox]} do
before { reset_driver!(web_socket_url: true) }
after { quit_driver }

Expand All @@ -32,50 +32,47 @@ class BiDi
expect(browsing_context.id).to eq(id)
end

it 'can create a window without a reference context' do
it 'can create a window' do
browsing_context = described_class.new(driver: driver, type: :window)
expect(browsing_context.id).not_to be_nil
end

it 'can create a window with a reference context', except: {browser: :chrome} do
it 'can create a window with a reference context', except: {browser: %i[chrome edge]} do
browsing_context = described_class.new(driver: driver, type: :window,
reference_context: driver.window_handle)
expect(browsing_context.id).not_to be_nil
end

it 'can create a tab without a reference context' do
it 'can create a tab' do
browsing_context = described_class.new(driver: driver, type: :tab)
expect(browsing_context.id).not_to be_nil
end

it 'can create a tab with a reference context', except: {browser: :chrome} do
it 'can create a tab with a reference context', except: {browser: %i[chrome edge]} do
browsing_context = described_class.new(driver: driver, type: :tab, reference_context: driver.window_handle)
expect(browsing_context.id).not_to be_nil
end

it 'can navigate to a url without a readiness state',
except: {browser: :chrome, reason: 'navigation_id is not nil'} do
it 'can navigate to a url' do
browsing_context = described_class.new(driver: driver, type: :tab)

info = browsing_context.navigate url: url_for('/bidi/logEntryAdded.html')

expect(browsing_context.id).not_to be_nil
expect(info.navigation_id).to be_nil
expect(info.url).to include('/bidi/logEntryAdded.html')
end

it 'can navigate to a url with readiness state', except: {browser: :chrome} do
it 'can navigate to a url with readiness state' do
browsing_context = described_class.new(driver: driver, type: :tab)

info = browsing_context.navigate url: url_for('/bidi/logEntryAdded.html'),
readiness_state: :complete

expect(browsing_context.id).not_to be_nil
expect(info.navigation_id).to be_nil
expect(info.url).to include('/bidi/logEntryAdded.html')
end

it 'can get tree with a child', except: {browser: :chrome} do
it 'can get tree with a child', except: {browser: %i[chrome edge]} do
browsing_context_id = driver.window_handle
parent_window = described_class.new(driver: driver, browsing_context_id: browsing_context_id)
parent_window.navigate(url: url_for('iframes.html'),
Expand All @@ -87,7 +84,7 @@ class BiDi
expect(context_info.children[0]['url']).to include('formPage.html')
end

it 'can get tree with depth', except: {browser: :chrome, reason: 'not yet implemented'} do
it 'can get tree with depth', except: {browser: %i[chrome edge], reason: 'not yet implemented'} do
browsing_context_id = driver.window_handle
parent_window = described_class.new(driver: driver, browsing_context_id: browsing_context_id)
parent_window.navigate(url: url_for('iframes.html'),
Expand Down
33 changes: 32 additions & 1 deletion rb/spec/integration/selenium/webdriver/bidi_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@ module Selenium
module WebDriver
describe BiDi, only: {browser: %i[chrome edge firefox]} do
before { reset_driver!(web_socket_url: true) }
after { quit_driver }

after do
quit_driver
rescue Selenium::WebDriver::Error::InvalidSessionIdError
# do nothing
end

it 'gets session status' do
status = driver.bidi.session.status
Expand Down Expand Up @@ -52,6 +57,32 @@ module WebDriver
level: BiDi::LogInspector::LOG_LEVEL[:ERROR]
)
end

it 'does not close BiDi session if at least one window is opened' do
status = driver.bidi.session.status
expect(status.ready).to be false
expect(status.message).to be_a String

driver.switch_to.new_window(:window)
driver.switch_to.new_window(:tab)
driver.switch_to.new_window(:tab)

driver.close

status_after_closing = driver.bidi.session.status
expect(status_after_closing.ready).to be false
expect(status_after_closing.message).to be_a String
end

it 'closes BiDi session if last window is closed' do
status = driver.bidi.session.status
expect(status.ready).to be false
expect(status.message).to be_a String

driver.close

expect { driver.bidi.session.status }.to raise_error(IOError)
end
end
end
end

0 comments on commit 332988c

Please sign in to comment.