Search code examples
ruby-on-railscapybaracancancapybara-webkitcancancan

Capybara::Webkit::InvalidResponseError: Javascript failed to execute


I converted an app from Rails 3.2 to 4.2 that was using the cancan gem. Googling around and checking on their github says it's enought to just replace gem cancan with gem cancancan without changing anything. This doesn't seem to work. My test fails:

Failures:

  1) Redactable fields Manual redaction Redacting selected text in body
     Failure/Error:
           page.execute_script <<-EOS
             document.getElementById('notice_#{@name}').focus();
             document.getElementById('notice_#{@name}').select();
           EOS
     
     Capybara::Webkit::InvalidResponseError:
       Javascript failed to execute
     # /Users/siaw23/.rvm/gems/ruby-2.1.9/gems/capybara-webkit-1.11.1/lib/capybara/webkit/browser.rb:305:in `check'
     # /Users/siaw23/.rvm/gems/ruby-2.1.9/gems/capybara-webkit-1.11.1/lib/capybara/webkit/browser.rb:211:in `command'
     # /Users/siaw23/.rvm/gems/ruby-2.1.9/gems/capybara-webkit-1.11.1/lib/capybara/webkit/browser.rb:232:in `execute_script'
     # /Users/siaw23/.rvm/gems/ruby-2.1.9/gems/capybara-webkit-1.11.1/lib/capybara/webkit/driver.rb:80:in `execute_script'
     # /Users/siaw23/.rvm/gems/ruby-2.1.9/gems/capybara-2.7.1/lib/capybara/session.rb:524:in `execute_script'
     # ./spec/support/page_objects/redactable_field_on_page.rb:15:in `select'
     # ./spec/support/page_objects/redactable_field_on_page.rb:22:in `select_and_redact'
     # ./spec/integration/redaction_spec.rb:37:in `block (4 levels) in <top (required)>'

  2) Redactable fields Manual redaction Restoring body from original
     Failure/Error: page.find("#notice_#{@name}").click
     
     Capybara::ElementNotFound:
       Unable to find css "#notice_body"
     # /Users/siaw23/.rvm/gems/ruby-2.1.9/gems/capybara-2.7.1/lib/capybara/node/finders.rb:44:in `block in find'
     # /Users/siaw23/.rvm/gems/ruby-2.1.9/gems/capybara-2.7.1/lib/capybara/node/base.rb:85:in `synchronize'
     # /Users/siaw23/.rvm/gems/ruby-2.1.9/gems/capybara-2.7.1/lib/capybara/node/finders.rb:33:in `find'
     # /Users/siaw23/.rvm/gems/ruby-2.1.9/gems/capybara-2.7.1/lib/capybara/session.rb:699:in `block (2 levels) in <class:Session>'
     # ./spec/support/page_objects/redactable_field_on_page.rb:9:in `unredact'
     # ./spec/integration/redaction_spec.rb:46:in `block (4 levels) in <top (required)>'

The elements being searched for can be reached manually after loggin in. This means neither cancancan nor cancan successfully applies :admin permission to my user that's created in the test. I used You are not authorized to access this page. and I get "You are not authorized to access this page."

The spec itself looks like this:

require 'rails_helper'
require 'support/notice_actions'

      #lots of irrelevant code

      private

      def visit_redact_notice
        user = create(:user, :admin)
        visit '/users/sign_in'
        fill_in "Email", with: user.email
        fill_in "Password", with: user.password
        click_on "Log in"

        notice = create(:dmca, :redactable)

        visit "/admin/notice/#{notice.id}/redact_notice"

        notice
      end
    end
  end
end

The visit_redact_notice method in the above spec is where everything is happening. I need help :). This is my repo if it might help: https://github.com/siaw23/lumendatabase

ability.rb

class Ability
  include CanCan::Ability

  def initialize(user)
    return unless user

    if user.has_role?(Role.submitter)
      can :submit, Notice
    end

    if user.has_role?(Role.redactor)
      grant_admin_access
      grant_redact
    end

    if user.has_role?(Role.publisher)
      grant_admin_access
      grant_redact

      can :publish, Notice
    end

    if user.has_role?(Role.admin)
      grant_admin_access
      grant_redact

      can :edit, :all
      cannot :edit, [User, Role]

      can :publish, Notice
      can :rescind, Notice

      can :pdf_requests, :all
    end

    if user.has_role?(Role.super_admin)
      can :manage, :all
    end
    
    if user.has_role?(Role.researcher)
      can :read, Notice
    end
  end

  def grant_admin_access
    can :read, :all
    can :access, :rails_admin
    can :dashboard
    can :search, Entity
    can :access, :original_files
  end

  def grant_redact
    can :edit, Notice
    can :redact_notice, Notice
    can :redact_queue, Notice
  end
end

Solution

  • A couple issues you might want to check out...

    1. There's a new version of Devise out that allows authentication via feature / integration tests. I've always spent hours debugging actually getting step-by-step login functionality to work. With Devise 4.2, logging in via integration tests is now supported. You'll have to make some changes to the RSpec configuration for Devise, as noted in the documentation above for the sign_in method to work.
    2. If at this point logging in as an admin still does not work, I would check to see if your RSpec configuration has use_transactional_fixtures set to true. If it does, I would strongly encourage you to let the database_cleaner gem manage your test database, and set use_transactional_fixtures to false.

    One or both of those should get you around your authentication issue. My guess is that it's most likely an issue with the transactional fixtures, as Rails is likely cleaning up a transaction before you're fully authenticated (thus why I'd suspect #1 above won't work).