Skip to content

Commit

Permalink
Allow to listen for console API messages
Browse files Browse the repository at this point in the history
  • Loading branch information
p0deje committed Sep 25, 2020
1 parent 44f1083 commit a640141
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 1 deletion.
1 change: 1 addition & 0 deletions rb/lib/selenium/webdriver/chrome/driver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class Driver < WebDriver::Driver
include DriverExtensions::DownloadsFiles
include DriverExtensions::HasDevTools
include DriverExtensions::HasAuthentication
include DriverExtensions::HasLogEvents

def browser
:chrome
Expand Down
1 change: 1 addition & 0 deletions rb/lib/selenium/webdriver/common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
require 'selenium/webdriver/common/driver_extensions/has_addons'
require 'selenium/webdriver/common/driver_extensions/has_devtools'
require 'selenium/webdriver/common/driver_extensions/has_authentication'
require 'selenium/webdriver/common/driver_extensions/has_log_events'
require 'selenium/webdriver/common/keys'
require 'selenium/webdriver/common/profile_helper'
require 'selenium/webdriver/common/options'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# 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
module DriverExtensions
module HasLogEvents

#
#
# Registers listener to be called whenever browser receives
# a new Console API message such as console.log().
# This currently relies on DevTools so is only supported in
# Chromium browsers.
#
# @example
# logs = []
# driver.on_log_event do |event|
# logs.push(event)
# end
#
# @param [#call] block which yields DevTools::ConsoleEvent
#

def on_log_event(&block)
console_listeners_enabled = console_listeners.any?
console_listeners << block
return if console_listeners_enabled

devtools.runtime.enable
devtools.runtime.on(:console_api_called) do |params|
event = DevTools::ConsoleEvent.new(
type: params['type'],
timestamp: params['timestamp'],
args: params['args']
)

console_listeners.each do |listener|
listener.call(event)
end
end
end

private

def console_listeners
@console_listeners ||= []
end

end # HasLogEvents
end # DriverExtensions
end # WebDriver
end # Selenium
2 changes: 2 additions & 0 deletions rb/lib/selenium/webdriver/devtools.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
module Selenium
module WebDriver
class DevTools
autoload :ConsoleEvent, 'selenium/webdriver/devtools/console_event'

SUPPORTED_VERSIONS = [84, 85, 86].freeze

def initialize(url:, version:)
Expand Down
38 changes: 38 additions & 0 deletions rb/lib/selenium/webdriver/devtools/console_event.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# 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 DevTools
class ConsoleEvent

attr_accessor :type, :timestamp, :args

def initialize(type:, timestamp:, args:)
@type = type.to_sym
@timestamp = Time.at(timestamp / 1000)
@args = args.map do |arg|
arg.key?('value') ? arg['value'] : arg
end
end

end # ConsoleEvent
end # DevTools
end # WebDriver
end # Selenium
5 changes: 4 additions & 1 deletion rb/lib/selenium/webdriver/support/cdp_client_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ module Selenium
module WebDriver
module Support
class CDPClientGenerator
# Input JSON files are generated from PDL tasks.
BROWSER_PROTOCOL_PATH = File.expand_path('cdp/browser_protocol.json', __dir__)
JS_PROTOCOL_PATH = File.expand_path('cdp/js_protocol.json', __dir__)
TEMPLATE_PATH = File.expand_path('cdp/domain.rb.erb', __dir__)
Expand All @@ -50,7 +51,9 @@ def process_domain(domain)
end

def snake_case(string)
name = string.gsub(/([a-z])([A-Z])/, '\1_\2').downcase
name = string.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
.downcase
# Certain CDP parameters conflict with Ruby keywords
# so we prefix the name with underscore.
name = "_#{name}" if RESERVED_KEYWORDS.include?(name)
Expand Down
21 changes: 21 additions & 0 deletions rb/spec/integration/selenium/webdriver/devtools_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,27 @@ module WebDriver
driver.navigate.to auth_url
expect(driver.find_element(tag_name: 'h1').text).to eq('authorized')
end

it 'notifies about log messages' do
logs = []
driver.on_log_event { |log| logs.push(log) }
driver.navigate.to url_for('javascriptPage.html')

driver.execute_script("console.log('I like cheese');")
driver.execute_script("console.log(true);")
driver.execute_script("console.log(null);")
driver.execute_script("console.log(undefined);")
driver.execute_script("console.log(document);")
wait.until { logs.size == 5 }

expect(logs).to include(
an_object_having_attributes(type: :log, args: ['I like cheese']),
an_object_having_attributes(type: :log, args: [true]),
an_object_having_attributes(type: :log, args: [nil]),
an_object_having_attributes(type: :log, args: [{'type' => 'undefined'}]),
an_object_having_attributes(type: :log, args: [hash_including('type' => 'object')])
)
end
end
end
end

0 comments on commit a640141

Please sign in to comment.