Skip to content

Commit e2d160b

Browse files
authored
[ruby][bidi] Add filtering capability to LogInspector
1 parent 332988c commit e2d160b

File tree

4 files changed

+214
-45
lines changed

4 files changed

+214
-45
lines changed

rb/.rubocop.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Metrics/ClassLength:
3535
- 'lib/selenium/webdriver/common/driver.rb'
3636
- 'lib/selenium/webdriver/remote/bridge.rb'
3737
- 'lib/selenium/webdriver/remote/capabilities.rb'
38+
- 'spec/integration/selenium/webdriver/bidi/log_inspector_spec.rb'
3839
- 'spec/integration/selenium/webdriver/spec_support/test_environment.rb'
3940

4041
Metrics/CyclomaticComplexity:
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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 FilterBy
24+
attr_accessor :level
25+
26+
def initialize(level)
27+
@level = level
28+
end
29+
30+
def self.log_level(level = nil)
31+
unless %w[debug error info warning].include?(level)
32+
raise Error::WebDriverError,
33+
"Valid log levels are 'debug', 'error', 'info' and 'warning'. Received: #{level}"
34+
end
35+
FilterBy.new(level)
36+
end
37+
end # FilterBy
38+
end # BiDi
39+
end # WebDriver
40+
end # Selenium

rb/lib/selenium/webdriver/bidi/log_inspector.rb

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
require_relative 'log/generic_log_entry'
2424
require_relative 'log/console_log_entry'
2525
require_relative 'log/javascript_log_entry'
26+
require_relative 'log/filter_by'
2627

2728
module Selenium
2829
module WebDriver
@@ -49,43 +50,41 @@ def initialize(driver, browsing_context_ids = nil)
4950
@bidi.session.subscribe('log.entryAdded', browsing_context_ids)
5051
end
5152

52-
def on_console_entry(&block)
53-
enabled = log_listeners[:console].any?
54-
log_listeners[:console] << block
55-
return if enabled
53+
def on_console_entry(filter_by = nil, &block)
54+
check_valid_filter(filter_by)
5655

5756
on_log do |params|
5857
type = params['type']
59-
console_log_events(params) if type.eql?('console')
58+
console_log_events(params, filter_by, &block) if type.eql?('console')
6059
end
6160
end
6261

63-
def on_javascript_log(&block)
64-
enabled = log_listeners[:javascript].any?
65-
log_listeners[:javascript] << block
66-
return if enabled
62+
def on_javascript_log(filter_by = nil, &block)
63+
check_valid_filter(filter_by)
6764

6865
on_log do |params|
6966
type = params['type']
70-
javascript_log_events(params) if type.eql?('javascript')
67+
javascript_log_events(params, filter_by, &block) if type.eql?('javascript')
7168
end
7269
end
7370

7471
def on_javascript_exception(&block)
75-
enabled = log_listeners[:js_exception].any?
76-
log_listeners[:js_exception] << block
77-
log_listeners[:javascript] << block
78-
return if enabled
79-
8072
on_log do |params|
8173
type = params['type']
82-
level = params['level']
83-
84-
javascript_log_events(params) if type.eql?('javascript') && level.eql?(LOG_LEVEL[:ERROR])
74+
javascript_log_events(params, FilterBy.log_level('error'), &block) if type.eql?('javascript')
8575
end
8676
end
8777

88-
def on_log(&block)
78+
def on_log(filter_by = nil, &block)
79+
unless filter_by.nil?
80+
check_valid_filter(filter_by)
81+
82+
on(:entry_added) do |params|
83+
yield(params) if params['level'] == filter_by.level
84+
end
85+
return
86+
end
87+
8988
on(:entry_added, &block)
9089
end
9190

@@ -96,11 +95,13 @@ def on(event, &block)
9695
@bidi.callbacks["log.#{event}"] << block
9796
end
9897

99-
def log_listeners
100-
@log_listeners ||= Hash.new { |listeners, kind| listeners[kind] = [] }
98+
def check_valid_filter(filter_by)
99+
return if filter_by.nil? || filter_by.instance_of?(FilterBy)
100+
101+
raise "Pass valid FilterBy object. Received: #{filter_by.inspect}"
101102
end
102103

103-
def console_log_events(params)
104+
def console_log_events(params, filter_by)
104105
event = ConsoleLogEntry.new(
105106
level: params['level'],
106107
text: params['text'],
@@ -111,28 +112,30 @@ def console_log_events(params)
111112
args: params['args'],
112113
stack_trace: params['stackTrace']
113114
)
114-
log_listeners[:console].each do |listener|
115-
listener.call(event)
115+
116+
unless filter_by.nil?
117+
yield(event) if params['level'] == filter_by.level
118+
return
116119
end
120+
121+
yield(event)
117122
end
118123

119-
def javascript_log_events(params)
124+
def javascript_log_events(params, filter_by)
120125
event = JavascriptLogEntry.new(
121126
level: params['level'],
122127
text: params['text'],
123128
timestamp: params['timestamp'],
124129
type: params['type'],
125130
stack_trace: params['stackTrace']
126131
)
127-
log_listeners[:javascript].each do |listener|
128-
listener.call(event)
129-
end
130132

131-
return unless params['level'].eql?(LOG_LEVEL[:ERROR])
132-
133-
log_listeners[:js_exception].each do |listener|
134-
listener.call(event)
133+
unless filter_by.nil?
134+
yield(event) if params['level'] == filter_by.level
135+
return
135136
end
137+
138+
yield(event)
136139
end
137140
end # LogInspector
138141
end # Bidi

rb/spec/integration/selenium/webdriver/bidi/log_inspector_spec.rb

Lines changed: 138 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,40 @@
2222
module Selenium
2323
module WebDriver
2424
class BiDi
25-
describe LogInspector, exclusive: {browser: %i[chrome firefox]} do
26-
before do
27-
@page = '/bidi/logEntryAdded.html'
25+
describe LogInspector, only: {browser: %i[chrome edge firefox]} do
26+
let(:page) { '/bidi/logEntryAdded.html' }
27+
28+
it 'can listen to console log' do
29+
reset_driver!(web_socket_url: true) do |driver|
30+
log_entry = nil
31+
log_inspector = described_class.new(driver)
32+
log_inspector.on_console_entry { |log| log_entry = log }
33+
34+
driver.navigate.to url_for(page)
35+
driver.find_element(id: 'consoleLog').click
36+
wait.until { !log_entry.nil? }
37+
38+
expect(log_entry).to have_attributes(
39+
text: 'Hello, world!',
40+
realm: nil,
41+
type: 'console',
42+
level: LogInspector::LOG_LEVEL[:INFO],
43+
method: 'log'
44+
)
45+
expect(log_entry.args.size).to eq(1)
46+
end
2847
end
2948

30-
it 'can listen to console log', except: {browser: :chrome} do
49+
it 'can listen to console log with different consumers' do
3150
reset_driver!(web_socket_url: true) do |driver|
3251
log_entry = nil
3352
log_inspector = described_class.new(driver)
3453
log_inspector.on_console_entry { |log| log_entry = log }
3554

36-
driver.navigate.to url_for(@page)
55+
log_entry_text = nil
56+
log_inspector.on_console_entry { |log| log_entry_text = log.text }
57+
58+
driver.navigate.to url_for(page)
3759
driver.find_element(id: 'consoleLog').click
3860
wait.until { !log_entry.nil? }
3961

@@ -42,10 +64,46 @@ class BiDi
4264
realm: nil,
4365
type: 'console',
4466
level: LogInspector::LOG_LEVEL[:INFO],
45-
method: 'log',
46-
stack_trace: nil
67+
method: 'log'
4768
)
4869
expect(log_entry.args.size).to eq(1)
70+
expect(log_entry_text).to eq('Hello, world!')
71+
end
72+
end
73+
74+
it 'can filter console info level log' do
75+
reset_driver!(web_socket_url: true) do |driver|
76+
log_entry = nil
77+
log_inspector = described_class.new(driver)
78+
log_inspector.on_console_entry(FilterBy.log_level('info')) { |log| log_entry = log }
79+
80+
driver.navigate.to url_for(page)
81+
driver.find_element(id: 'consoleLog').click
82+
wait.until { !log_entry.nil? }
83+
84+
expect(log_entry).to have_attributes(
85+
text: 'Hello, world!',
86+
realm: nil,
87+
type: 'console',
88+
level: LogInspector::LOG_LEVEL[:INFO],
89+
method: 'log'
90+
)
91+
expect(log_entry.args.size).to eq(1)
92+
end
93+
end
94+
95+
it 'can filter console log' do
96+
reset_driver!(web_socket_url: true) do |driver|
97+
log_entry = nil
98+
log_inspector = described_class.new(driver)
99+
log_inspector.on_console_entry(FilterBy.log_level('error')) { |log| log_entry = log }
100+
101+
driver.navigate.to url_for(page)
102+
# Generating info level log but we are filtering by error level
103+
wait.until { driver.find_element(id: 'consoleLog').displayed? }
104+
driver.find_element(id: 'consoleLog').click
105+
106+
expect(log_entry).to be_nil
49107
end
50108
end
51109

@@ -55,7 +113,7 @@ class BiDi
55113
log_inspector = described_class.new(driver)
56114
log_inspector.on_javascript_log { |log| log_entry = log }
57115

58-
driver.navigate.to url_for(@page)
116+
driver.navigate.to url_for(page)
59117
driver.find_element(id: 'jsException').click
60118
wait.until { !log_entry.nil? }
61119

@@ -67,13 +125,46 @@ class BiDi
67125
end
68126
end
69127

128+
it 'can filter javascript log at error level' do
129+
reset_driver!(web_socket_url: true) do |driver|
130+
log_entry = nil
131+
log_inspector = described_class.new(driver)
132+
log_inspector.on_javascript_log(FilterBy.log_level('error')) { |log| log_entry = log }
133+
134+
driver.navigate.to url_for(page)
135+
driver.find_element(id: 'jsException').click
136+
wait.until { !log_entry.nil? }
137+
138+
expect(log_entry).to have_attributes(
139+
text: 'Error: Not working',
140+
type: 'javascript',
141+
level: LogInspector::LOG_LEVEL[:ERROR]
142+
)
143+
end
144+
end
145+
146+
it 'can filter javascript log' do
147+
reset_driver!(web_socket_url: true) do |driver|
148+
log_entry = nil
149+
log_inspector = described_class.new(driver)
150+
log_inspector.on_javascript_log(FilterBy.log_level('info')) { |log| log_entry = log }
151+
152+
driver.navigate.to url_for(page)
153+
# Generating js error level log but we are filtering by info level
154+
wait.until { driver.find_element(id: 'jsException').displayed? }
155+
driver.find_element(id: 'jsException').click
156+
157+
expect(log_entry).to be_nil
158+
end
159+
end
160+
70161
it 'can listen to javascript error log' do
71162
reset_driver!(web_socket_url: true) do |driver|
72163
log_entry = nil
73164
log_inspector = described_class.new(driver)
74165
log_inspector.on_javascript_exception { |log| log_entry = log }
75166

76-
driver.navigate.to url_for(@page)
167+
driver.navigate.to url_for(page)
77168
driver.find_element(id: 'jsException').click
78169
wait.until { !log_entry.nil? }
79170

@@ -91,7 +182,7 @@ class BiDi
91182
log_inspector = described_class.new(driver)
92183
log_inspector.on_log { |log| log_entry = log }
93184

94-
driver.navigate.to url_for(@page)
185+
driver.navigate.to url_for(page)
95186
driver.find_element(id: 'consoleError').click
96187
wait.until { !log_entry.nil? }
97188

@@ -101,20 +192,54 @@ class BiDi
101192
end
102193
end
103194

104-
it 'can retrieve stack trace for a log', except: {browser: :chrome} do
195+
it 'can filter any log' do
196+
reset_driver!(web_socket_url: true) do |driver|
197+
log_entry = nil
198+
log_inspector = described_class.new(driver)
199+
log_inspector.on_log(FilterBy.log_level('info')) { |log| log_entry = log }
200+
201+
driver.navigate.to url_for(page)
202+
driver.find_element(id: 'consoleLog').click
203+
wait.until { !log_entry.nil? }
204+
205+
expect(log_entry['text']).to eq('Hello, world!')
206+
expect(log_entry['realm']).to be_nil
207+
expect(log_entry['type']).to eq('console')
208+
expect(log_entry['level']).to eq('info')
209+
expect(log_entry['method']).to eq('log')
210+
expect(log_entry['args'].size).to eq(1)
211+
end
212+
end
213+
214+
it 'can filter any log at error level' do
215+
reset_driver!(web_socket_url: true) do |driver|
216+
log_entry = nil
217+
log_inspector = described_class.new(driver)
218+
log_inspector.on_log(FilterBy.log_level('error')) { |log| log_entry = log }
219+
220+
driver.navigate.to url_for(page)
221+
driver.find_element(id: 'jsException').click
222+
wait.until { !log_entry.nil? }
223+
224+
expect(log_entry['text']).to eq('Error: Not working')
225+
expect(log_entry['type']).to eq('javascript')
226+
expect(log_entry['level']).to eq('error')
227+
end
228+
end
229+
230+
it 'can retrieve stack trace for a log' do
105231
reset_driver!(web_socket_url: true) do |driver|
106232
log_entry = nil
107233
log_inspector = described_class.new(driver)
108234
log_inspector.on_javascript_log { |log| log_entry = log }
109235

110-
driver.navigate.to url_for(@page)
236+
driver.navigate.to url_for(page)
111237
driver.find_element(id: 'jsException').click
112238
wait.until { !log_entry.nil? }
113239

114240
stack_trace = log_entry.stack_trace
115241

116242
expect(stack_trace).not_to be_nil
117-
expect(stack_trace['callFrames'].size).to eq(3)
118243
end
119244
end
120245
end

0 commit comments

Comments
 (0)