Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ruby][BiDi] Browsing context commands #11446

Merged
merged 3 commits into from
Dec 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rb/lib/selenium/webdriver/bidi.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ module WebDriver
class BiDi
autoload :Session, 'selenium/webdriver/bidi/session'
autoload :LogInspector, 'selenium/webdriver/bidi/log_inspector'
autoload :BrowsingContext, 'selenium/webdriver/bidi/browsing_context'

def initialize(url:)
@ws = WebSocketConnection.new(url: url)
Expand Down
88 changes: 88 additions & 0 deletions rb/lib/selenium/webdriver/bidi/browsing_context.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# frozen_string_literal: true

# Licensed to the Software Freedom Conservancy (SFC) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The SFC licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

require_relative 'navigate_result'
require_relative 'browsing_context_info'

module Selenium
module WebDriver
class BiDi
class BrowsingContext
attr_accessor :id

READINESS_STATE = {
none: "none",
interactive: "interactive",
complete: "complete"
}.freeze

def initialize(driver:, browsing_context_id: nil, type: nil, reference_context: nil)
unless driver.capabilities.web_socket_url
raise Error::WebDriverError, "WebDriver instance must support BiDi protocol"
end

unless type.nil? || %i[window tab].include?(type)
raise ArgumentError,
"Valid types are :window & :tab. Received: #{type.inspect}"
end

@bidi = driver.bidi
@id = browsing_context_id.nil? ? create(type, reference_context)["context"] : browsing_context_id
end

def navigate(url:, readiness_state: nil)
unless readiness_state.nil? || READINESS_STATE.key?(readiness_state)
raise ArgumentError,
"Valid readiness states are :none, :interactive & :complete. Received: #{readiness_state.inspect}"
end

navigate_result = @bidi.send_cmd("browsingContext.navigate", context: @id, url: url,
wait: READINESS_STATE[readiness_state])

NavigateResult.new(
url: navigate_result["url"],
navigation_id: navigate_result["navigation"]
)
end

def get_tree(max_depth: nil)
result = @bidi.send_cmd("browsingContext.getTree", root: @id, maxDepth: max_depth).dig("contexts", 0)

BrowsingContextInfo.new(
id: result['context'],
url: result['url'],
children: result['children'],
parent_context: result['parent']
)
end

def close
@bidi.send_cmd("browsingContext.close", context: @id)
end

private

def create(type, reference_context)
@bidi.send_cmd("browsingContext.create", type: type.to_s, referenceContext: reference_context)
end

end # BrowsingContext
end # BiDi
end # WebDriver
end # Selenium
36 changes: 36 additions & 0 deletions rb/lib/selenium/webdriver/bidi/browsing_context_info.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

# Licensed to the Software Freedom Conservancy (SFC) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The SFC licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

module Selenium
module WebDriver
class BiDi
class BrowsingContextInfo
attr_accessor :id, :url, :children, :parent_browsing_context

def initialize(id:, url:, children:, parent_context:)
@id = id
@url = url
@children = children
@parent_browsing_context = parent_context
end

end # BrowsingContextInfo
end # BiDi
end # WebDriver
end # Selenium
34 changes: 34 additions & 0 deletions rb/lib/selenium/webdriver/bidi/navigate_result.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

# Licensed to the Software Freedom Conservancy (SFC) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The SFC licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

module Selenium
module WebDriver
class BiDi
class NavigateResult
attr_accessor :url, :navigation_id

def initialize(url:, navigation_id:)
@url = url
@navigation_id = navigation_id
end

end # NavigateResult
end # BiDi
end # WebDriver
end # Selenium
114 changes: 114 additions & 0 deletions rb/spec/integration/selenium/webdriver/bidi/browsing_context_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# frozen_string_literal: true

# Licensed to the Software Freedom Conservancy (SFC) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The SFC licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

require_relative '../spec_helper'

module Selenium
module WebDriver
class BiDi
describe BrowsingContext, exclusive: {browser: %i[chrome firefox]} do
before do
quit_driver
create_driver!(web_socket_url: true)
end

it 'can create a browsing context for given id' do
id = driver.window_handle
browsing_context = BrowsingContext.new(driver: driver, browsing_context_id: id)
expect(browsing_context.id).to eq(id)
end

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

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

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

it 'can create a tab with a reference context' do
browsing_context = BrowsingContext.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' do
browsing_context = BrowsingContext.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' do
browsing_context = BrowsingContext.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' do
browsing_context_id = driver.window_handle
parent_window = BrowsingContext.new(driver: driver, browsing_context_id: browsing_context_id)
parent_window.navigate(url: url_for('iframes.html'),
readiness_state: :complete)

context_info = parent_window.get_tree
expect(context_info.children.size).to eq(1)
expect(context_info.id).to eq(browsing_context_id)
expect(context_info.children[0]["url"]).to include('formPage.html')
end

it 'can get tree with depth' do
browsing_context_id = driver.window_handle
parent_window = BrowsingContext.new(driver: driver, browsing_context_id: browsing_context_id)
parent_window.navigate(url: url_for('iframes.html'),
readiness_state: :complete)

context_info = parent_window.get_tree(max_depth: 0)
expect(context_info.children).to be_nil
expect(context_info.id).to eq(browsing_context_id)
end

it 'can close a window' do
window1 = BrowsingContext.new(driver: driver, type: :window)
window2 = BrowsingContext.new(driver: driver, type: :window)

window2.close

expect { window1.get_tree }.not_to raise_error
expect { window2.get_tree }.to raise_error(Error::WebDriverError)
end
end # BrowsingContext
end # BiDi
end # WebDriver
end # Selenium