cuprite
cuprite copied to clipboard
Feature request: Be able to see just console.log/console.error etc without all debug output
As discussed here: https://github.com/machinio/cuprite/issues/110#issuecomment-584557319
Indeed I just noticed this as I tried cuprite
(coming from selenium + chrome headless). I would really like the ability to display (or get as string) the console output of the browser. Is there a way to get it using some method in an after(:each)
maybe? I tried the logger
option but it is slightly too verbose ^^.
Little suggestion: maybe when passing a ruby Logger
object here you could send your debug with the "debug" level and the browser messages with their respective level so the user can then chose to set the logger level to "info" for example to not get those?
Otherwise a way to get them from a method would be perfect, as we could also filter them, mute them when we want, etc.. (like page.driver.browser.manage.logs.get("browser")
from selenium-webdriver + chrome)
I think we need to split them, that would solve all the issues. If I remember correct we pass IO like STDOUT not Ruby logger, maybe it's time to revisit this part, I borrowed it from Poltergeist.
Hi, is there a workaround for this under than using grep to exclude debug lines? Thanks!
Hi, is there a workaround for this under than using grep to exclude debug lines? Thanks!
You can define a custom logger (which still needs to omit the debug log lines, but is a different approach to grepping stdout as outlined here).
There's an example at https://github.com/rubycdp/ferrum/issues/55#issuecomment-595225879, I used this approach as a starting point. Happy to share more details about what I've done if that'd be helpful.
Hi @nfm , yeah that's what I have been doing with grep. Not sure of how to use the custom logger though. Can you help or should I ask in that thread? Thanks! :)
Happy to share my WIP. I expect you'll want to modify this a bit (we're trialing migrating from Selenium and I want to keep things backwards compatible-ish but haven't quite nailed that down yet):
# Create your own logger class
class FerrumLogger
attr_reader :logs
def initialize
@logs = []
end
# Filter out the noise - I believe Runtime.exceptionThrown and Log.entryAdded are the interesting log methods but there might be others you need
def puts(log_str)
_log_symbol, _log_time, log_body_str = log_str.strip.split(' ', 3)
log_body = JSON.parse(log_body_str)
if %w[Runtime.exceptionThrown Log.entryAdded].include?(log_body['method'])
selenium_compatible_log_message = "#{log_body["params"]["entry"]["url"]} - #{log_body["params"]["entry"]["text"]}"
@logs << { message: selenium_compatible_log_message, level: log_body["params"]["entry"]["level"] }
end
end
def truncate
@logs = []
end
end
# Here's how I'm setting up the cuprite driver with custom logger, you might have a different approach though
Capybara.register_driver(:cuprite) do |app|
Capybara::Cuprite::Driver.new(
app,
**{
logger: FerrumLogger.new,
# bunch of other options here that aren't relevant to custom logger
}
)
end
# And then reading the logs from whatever context you're interested in them (eg. `after(:each)`)
errors = page.driver.browser.logger.logs
...
Hi @nfm , thanks a lot! I made a couple of changes since I prefer to print the relevant log entries as they happen, plus I added Runtime.consoleAPICalled
since that's what seems to be used when I use console.log
from my code for debugging.
class FerrumLogger
def puts(log_str)
_log_symbol, _log_time, log_body_str = log_str.strip.split(' ', 3)
return if log_body_str.nil?
log_body = JSON.parse(log_body_str)
case log_body['method']
when "Runtime.consoleAPICalled"
log_body["params"]["args"].each do |arg|
Kernel.puts arg["value"]
end
when "Runtime.exceptionThrown", "Log.entryAdded"
Kernel.puts "#{log_body["params"]["entry"]["url"]} - #{log_body["params"]["entry"]["text"]}"
end
end
end
Thanks again!
An update version to log also object, not just strings. Also removed log of Runtime.exceptionThrown
since that's already caught by js_errors: true
.
class FerrumLogger
def puts(log_str)
_log_symbol, _log_time, log_body_str = log_str.strip.split(' ', 3)
return if log_body_str.nil?
log_body = JSON.parse(log_body_str)
case log_body['method']
when 'Runtime.consoleAPICalled'
log_body['params']['args'].each do |arg|
case arg['type']
when 'string'
Kernel.puts arg['value']
when 'object'
Kernel.puts arg['preview']['properties'].map { |x| [x["name"], x["value"]] }.to_h
end
end
when 'Runtime.exceptionThrown'
# noop, this is already logged because we have "js_errors: true" in cuprite.
when 'Log.entryAdded'
Kernel.puts "#{log_body['params']['entry']['url']} - #{log_body['params']['entry']['text']}"
end
end
end