Skip to content

Commit 10a9e52

Browse files
authored
[ruby][BiDi] Browsing context commands (#11446)
1 parent 8951418 commit 10a9e52

File tree

5 files changed

+273
-0
lines changed

5 files changed

+273
-0
lines changed

rb/lib/selenium/webdriver/bidi.rb

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ module WebDriver
2222
class BiDi
2323
autoload :Session, 'selenium/webdriver/bidi/session'
2424
autoload :LogInspector, 'selenium/webdriver/bidi/log_inspector'
25+
autoload :BrowsingContext, 'selenium/webdriver/bidi/browsing_context'
2526

2627
def initialize(url:)
2728
@ws = WebSocketConnection.new(url: url)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# frozen_string_literal: true
2+
3+
# Licensed to the Software Freedom Conservancy (SFC) under one
4+
# or more contributor license agreements. See the NOTICE file
5+
# distributed with this work for additional information
6+
# regarding copyright ownership. The SFC licenses this file
7+
# to you under the Apache License, Version 2.0 (the
8+
# "License"); you may not use this file except in compliance
9+
# with the License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing,
14+
# software distributed under the License is distributed on an
15+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
# KIND, either express or implied. See the License for the
17+
# specific language governing permissions and limitations
18+
# under the License.
19+
20+
require_relative 'navigate_result'
21+
require_relative 'browsing_context_info'
22+
23+
module Selenium
24+
module WebDriver
25+
class BiDi
26+
class BrowsingContext
27+
attr_accessor :id
28+
29+
READINESS_STATE = {
30+
none: "none",
31+
interactive: "interactive",
32+
complete: "complete"
33+
}.freeze
34+
35+
def initialize(driver:, browsing_context_id: nil, type: nil, reference_context: nil)
36+
unless driver.capabilities.web_socket_url
37+
raise Error::WebDriverError, "WebDriver instance must support BiDi protocol"
38+
end
39+
40+
unless type.nil? || %i[window tab].include?(type)
41+
raise ArgumentError,
42+
"Valid types are :window & :tab. Received: #{type.inspect}"
43+
end
44+
45+
@bidi = driver.bidi
46+
@id = browsing_context_id.nil? ? create(type, reference_context)["context"] : browsing_context_id
47+
end
48+
49+
def navigate(url:, readiness_state: nil)
50+
unless readiness_state.nil? || READINESS_STATE.key?(readiness_state)
51+
raise ArgumentError,
52+
"Valid readiness states are :none, :interactive & :complete. Received: #{readiness_state.inspect}"
53+
end
54+
55+
navigate_result = @bidi.send_cmd("browsingContext.navigate", context: @id, url: url,
56+
wait: READINESS_STATE[readiness_state])
57+
58+
NavigateResult.new(
59+
url: navigate_result["url"],
60+
navigation_id: navigate_result["navigation"]
61+
)
62+
end
63+
64+
def get_tree(max_depth: nil)
65+
result = @bidi.send_cmd("browsingContext.getTree", root: @id, maxDepth: max_depth).dig("contexts", 0)
66+
67+
BrowsingContextInfo.new(
68+
id: result['context'],
69+
url: result['url'],
70+
children: result['children'],
71+
parent_context: result['parent']
72+
)
73+
end
74+
75+
def close
76+
@bidi.send_cmd("browsingContext.close", context: @id)
77+
end
78+
79+
private
80+
81+
def create(type, reference_context)
82+
@bidi.send_cmd("browsingContext.create", type: type.to_s, referenceContext: reference_context)
83+
end
84+
85+
end # BrowsingContext
86+
end # BiDi
87+
end # WebDriver
88+
end # Selenium
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# frozen_string_literal: true
2+
3+
# Licensed to the Software Freedom Conservancy (SFC) under one
4+
# or more contributor license agreements. See the NOTICE file
5+
# distributed with this work for additional information
6+
# regarding copyright ownership. The SFC licenses this file
7+
# to you under the Apache License, Version 2.0 (the
8+
# "License"); you may not use this file except in compliance
9+
# with the License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing,
14+
# software distributed under the License is distributed on an
15+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
# KIND, either express or implied. See the License for the
17+
# specific language governing permissions and limitations
18+
# under the License.
19+
20+
module Selenium
21+
module WebDriver
22+
class BiDi
23+
class BrowsingContextInfo
24+
attr_accessor :id, :url, :children, :parent_browsing_context
25+
26+
def initialize(id:, url:, children:, parent_context:)
27+
@id = id
28+
@url = url
29+
@children = children
30+
@parent_browsing_context = parent_context
31+
end
32+
33+
end # BrowsingContextInfo
34+
end # BiDi
35+
end # WebDriver
36+
end # Selenium
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# frozen_string_literal: true
2+
3+
# Licensed to the Software Freedom Conservancy (SFC) under one
4+
# or more contributor license agreements. See the NOTICE file
5+
# distributed with this work for additional information
6+
# regarding copyright ownership. The SFC licenses this file
7+
# to you under the Apache License, Version 2.0 (the
8+
# "License"); you may not use this file except in compliance
9+
# with the License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing,
14+
# software distributed under the License is distributed on an
15+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
# KIND, either express or implied. See the License for the
17+
# specific language governing permissions and limitations
18+
# under the License.
19+
20+
module Selenium
21+
module WebDriver
22+
class BiDi
23+
class NavigateResult
24+
attr_accessor :url, :navigation_id
25+
26+
def initialize(url:, navigation_id:)
27+
@url = url
28+
@navigation_id = navigation_id
29+
end
30+
31+
end # NavigateResult
32+
end # BiDi
33+
end # WebDriver
34+
end # Selenium
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# frozen_string_literal: true
2+
3+
# Licensed to the Software Freedom Conservancy (SFC) under one
4+
# or more contributor license agreements. See the NOTICE file
5+
# distributed with this work for additional information
6+
# regarding copyright ownership. The SFC licenses this file
7+
# to you under the Apache License, Version 2.0 (the
8+
# "License"); you may not use this file except in compliance
9+
# with the License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing,
14+
# software distributed under the License is distributed on an
15+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
# KIND, either express or implied. See the License for the
17+
# specific language governing permissions and limitations
18+
# under the License.
19+
20+
require_relative '../spec_helper'
21+
22+
module Selenium
23+
module WebDriver
24+
class BiDi
25+
describe BrowsingContext, exclusive: {browser: %i[chrome firefox]} do
26+
before do
27+
quit_driver
28+
create_driver!(web_socket_url: true)
29+
end
30+
31+
it 'can create a browsing context for given id' do
32+
id = driver.window_handle
33+
browsing_context = BrowsingContext.new(driver: driver, browsing_context_id: id)
34+
expect(browsing_context.id).to eq(id)
35+
end
36+
37+
it 'can create a window' do
38+
browsing_context = BrowsingContext.new(driver: driver, type: :window)
39+
expect(browsing_context.id).not_to be_nil
40+
end
41+
42+
it 'can create a window with a reference context' do
43+
browsing_context = BrowsingContext.new(driver: driver, type: :window,
44+
reference_context: driver.window_handle)
45+
expect(browsing_context.id).not_to be_nil
46+
end
47+
48+
it 'can create a tab' do
49+
browsing_context = BrowsingContext.new(driver: driver, type: :tab)
50+
expect(browsing_context.id).not_to be_nil
51+
end
52+
53+
it 'can create a tab with a reference context' do
54+
browsing_context = BrowsingContext.new(driver: driver, type: :tab, reference_context: driver.window_handle)
55+
expect(browsing_context.id).not_to be_nil
56+
end
57+
58+
it 'can navigate to a url' do
59+
browsing_context = BrowsingContext.new(driver: driver, type: :tab)
60+
61+
info = browsing_context.navigate url: url_for('/bidi/logEntryAdded.html')
62+
63+
expect(browsing_context.id).not_to be_nil
64+
expect(info.navigation_id).to be_nil
65+
expect(info.url).to include('/bidi/logEntryAdded.html')
66+
end
67+
68+
it 'can navigate to a url with readiness state' do
69+
browsing_context = BrowsingContext.new(driver: driver, type: :tab)
70+
71+
info = browsing_context.navigate url: url_for('/bidi/logEntryAdded.html'),
72+
readiness_state: :complete
73+
74+
expect(browsing_context.id).not_to be_nil
75+
expect(info.navigation_id).to be_nil
76+
expect(info.url).to include('/bidi/logEntryAdded.html')
77+
end
78+
79+
it 'can get tree with a child' do
80+
browsing_context_id = driver.window_handle
81+
parent_window = BrowsingContext.new(driver: driver, browsing_context_id: browsing_context_id)
82+
parent_window.navigate(url: url_for('iframes.html'),
83+
readiness_state: :complete)
84+
85+
context_info = parent_window.get_tree
86+
expect(context_info.children.size).to eq(1)
87+
expect(context_info.id).to eq(browsing_context_id)
88+
expect(context_info.children[0]["url"]).to include('formPage.html')
89+
end
90+
91+
it 'can get tree with depth' do
92+
browsing_context_id = driver.window_handle
93+
parent_window = BrowsingContext.new(driver: driver, browsing_context_id: browsing_context_id)
94+
parent_window.navigate(url: url_for('iframes.html'),
95+
readiness_state: :complete)
96+
97+
context_info = parent_window.get_tree(max_depth: 0)
98+
expect(context_info.children).to be_nil
99+
expect(context_info.id).to eq(browsing_context_id)
100+
end
101+
102+
it 'can close a window' do
103+
window1 = BrowsingContext.new(driver: driver, type: :window)
104+
window2 = BrowsingContext.new(driver: driver, type: :window)
105+
106+
window2.close
107+
108+
expect { window1.get_tree }.not_to raise_error
109+
expect { window2.get_tree }.to raise_error(Error::WebDriverError)
110+
end
111+
end # BrowsingContext
112+
end # BiDi
113+
end # WebDriver
114+
end # Selenium

0 commit comments

Comments
 (0)