Is there a way to print javascript console.errors to the terminal with Rspec/Capybara/Selenium?

14,917

Solution 1

I don't know if this will be of any help, but you could try switching over to thoughtbot's capybara-webkit driver. It's an alternative to Selenium that's headless, meaning it doesn't open a browser to run the tests. When I run my tests using this driver (in an RSpec+Capybara setup), all Javascript errors get printed inline with my RSpec output.

I've never tried switching from Selenium to capybara-webkit, so I don't know how feasible this is on an existing project. If you're not doing anything really fancy with Selenium, the transition might be pretty smooth. However, if you depend on being able to watch the tests running in the browser, or have some other specific need for Selenium, then my answer unfortunately won't be of much use.

You can find capybara-webkit here: https://github.com/thoughtbot/capybara-webkit

Getting it installed might be a pain, since you'll need the Qt4 library. If you don't already have Qt4 on your system, the build process can take a long time. For me, it was well worth the trouble. I much prefer capybara-webkit to any other solution I've tried.

Solution 2

There's a code sample at the end of this gist https://gist.github.com/gkop/1371962 (the one from alexspeller) which worked very nicely for me.

I ended up doing this in the context of the JS tests I was trying to debug

after(:each) do
  errors = page.driver.browser.manage.logs.get(:browser)
  if errors.present?
    message = errors.map(&:message).join("\n")
    puts message
  end
end

Solution 3

Here is another way, currently working with Selenium and headless Chrome (should also work with Firefox).

Add the following to spec/rails_helper.rb, within the RSpec.configure do |config| block and all feature specs with js: true metadata will display JS errors.

class JavaScriptError< StandardError; end
RSpec.configure do |config|
  config.after(:each, type: :feature, js: true) do |spec|
    errors = page.driver.browser.manage.logs.get(:browser)
               .select {|e| e.level == "SEVERE" && e.message.present? }
               .map(&:message)
               .to_a
    if errors.present?
      raise JavaScriptError, errors.join("\n\n")
    end
  end
end

The code is an adaptation of this.

Solution 4

This isn't pretty, but you could inject a script to direct errors into the DOM and watch for those changes via Selenium.

More specifically, inject a script into each page which overrides window.onerror or console such that errors append the information to some hidden node you've injected into the DOM. Then, via Selenium, periodically check for and empty the contents of that element, printing the emptied data to the Java console.

Solution 5

I'm doing something similar to Leo, but including the browser logs as part of the test failure message:

def check_browser_logs_after_each_test(rspec_config)
  rspec_config.before(:each) {
    @prev_browser_logs = @browser.driver.manage.logs.get(:browser)
  }

  rspec_config.after(:each) {
    logs = @browser.driver.manage.logs.get(:browser)
    new_logs = logs - @prev_browser_logs
    if example.exception then
      s = new_logs.map { |l| l.to_s }.join("\n")
      example.exception.message << "\nConsole logs:\n#{s}"
    else
      new_logs.should eq [ ]
    end
  }
end
Share:
14,917

Related videos on Youtube

Andrew De Andrade
Author by

Andrew De Andrade

Updated on June 04, 2022

Comments

  • Andrew De Andrade
    Andrew De Andrade almost 2 years

    When I run rspec, is it possible to have capybara/selenium report any javascript console.errors and other exceptions back to rspec?

    I have a whole bunch of tests failing, but my application is working when I manually test it. Without knowing the javascript errors that are likely blocking my single-page web app only during testing, it's really hard to figure out why the tests are failing.

    I've looked around and haven't really been able to find a solution to this.

  • Andrew De Andrade
    Andrew De Andrade about 12 years
    A bit too complicated. I figured that someone had already done this. Thanks though.
  • Abe Petrillo
    Abe Petrillo almost 12 years
    I use the evergreen gem with capybara-webkit. Aside from some parsing issues it seems to be working ok.
  • Julie
    Julie almost 7 years
    another variant of this that I found helpful: expect(page.driver.browser.manage.logs.get(:browser).select {|m| m.level == 'SEVERE'}.length).to eq(0)
  • steve
    steve over 5 years
    No longer working in recent versions, see here :(
  • BrunoF
    BrunoF over 5 years
    Yes, apparently it no longer works with Firefox. Maybe it still works with Chrome?
  • map7
    map7 over 5 years
    It is still working in chrome, I'm using chromeheadless 2.41 and it works