Skip to content

Commit

Permalink
Implement method to retrieve logs for Chrome (#44)
Browse files Browse the repository at this point in the history
* Implement method to retrieve logs for Chrome

* bump ameba

* fix ameba warnings

* add logging specs

* revert to set command_handler in initializer

* revert .ameba.yml
  • Loading branch information
mamantoha authored Aug 13, 2024
1 parent 94bc783 commit 0b8cca4
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 2 deletions.
31 changes: 31 additions & 0 deletions spec/features/logging_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require "../spec_helper"

module Selenium::Command
describe "logging", tags: ["feature", "chrome"] do
it "#available_log_types" do
TestServer.route "/home", ""

with_session do |session|
session.navigate_to("http://localhost:3002/home")

available_log_types = session.available_log_types
available_log_types.should eq(["browser", "driver"])
end
end

it "#log" do
TestServer.route "/home", <<-HTML
<script>
console.warn("Hello, Console!");
</script>
HTML

with_session do |session|
session.navigate_to("http://localhost:3002/home")

logs = session.log("browser")
logs.any? { |log| log.level == "WARNING" && log.message.ends_with?("\"Hello, Console!\"") }.should be_truthy
end
end
end
end
2 changes: 1 addition & 1 deletion spec/version_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ describe Selenium do
file.gets_to_end
end

version = /version\:(.*?)\n/.match(content).not_nil![1].strip
version = /version\:(.*?)\n/.match!(content)[1].strip
version.should eq Selenium::VERSION
end
end
13 changes: 13 additions & 0 deletions src/selenium/chrome/capabilities.cr
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ class Selenium::Chrome::Capabilities < Selenium::Capabilities
@[JSON::Field(key: "goog:chromeOptions")]
property chrome_options = ChromeOptions.new

# Enable logging
#
# ```
# capabilities = Selenium::Chrome::Capabilities.new
# capabilities.logging_prefs = {
# "browser" => "ALL",
# "driver" => "ALL",
# "performance" => "ALL",
# }
# ```
@[JSON::Field(key: "goog:loggingPrefs")]
property logging_prefs : Hash(String, String)?

class ChromeOptions
include JSON::Serializable

Expand Down
10 changes: 10 additions & 0 deletions src/selenium/chrome/command_handler.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class Selenium::Chrome::CommandHandler < Selenium::CommandHandler
CHROME_COMMANDS = {
get_available_log_types: {:get, "/session/:session_id/se/log/types"},
get_log: {:post, "/session/:session_id/se/log"},
}

def commands
DEFAULT_COMMANDS.merge(CHROME_COMMANDS)
end
end
4 changes: 4 additions & 0 deletions src/selenium/chrome/driver.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ class Selenium::Chrome::Driver < Selenium::Driver
super(capabilities)
end

private def command_handler
Chrome::CommandHandler.new(@http_client)
end

def create_session(args : Array(String)) : Session
capabilities = Chrome::Capabilities.new
capabilities.chrome_options.args = args
Expand Down
8 changes: 8 additions & 0 deletions src/selenium/chrome/log_entry.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class Selenium::Chrome::LogEntry
include JSON::Serializable

property level : String
property message : String
property source : String?
property timestamp : Int64
end
7 changes: 6 additions & 1 deletion src/selenium/command_handler.cr
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
class Selenium::CommandHandler
include DefaultCommands

getter http_client : HttpClient

def initialize(@http_client)
end

def commands
DEFAULT_COMMANDS
end

def execute(command, path_variables : Hash(String, String) = {} of String => String, parameters = {} of String => String) : JSON::Any
method, path = DEFAULT_COMMANDS[command]
method, path = commands[command]
full_path = path_variables.reduce(path) { |acc, entry| acc.sub(entry.first, entry.last) }

execute(method, full_path, parameters.to_json)
Expand Down
18 changes: 18 additions & 0 deletions src/selenium/session.cr
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,24 @@ class Selenium::Session
perform_actions([sequence])
end

# Get available log types
def available_log_types : Array(String)
data = command_handler.execute(:get_available_log_types, path_variables)

data["value"].as_a.map(&.as_s)
end

# Get the log for a given log type. Log buffer is reset after each request
#
# List of common log types: "client", "driver", "browser", "server"
def log(type : String) : Array(Selenium::Chrome::LogEntry)
data = command_handler.execute(:get_log, path_variables, {"type" => type})

data.as_h["value"].as_a.map do |log|
Selenium::Chrome::LogEntry.from_json(log.to_json)
end
end

private def path_variables
{":session_id" => id}
end
Expand Down

0 comments on commit 0b8cca4

Please sign in to comment.