In Rails 5.2 with Capybara, it doesn't seem like my assets are being loaded

398 Views Asked by At

I am attempting to run integration tests on Rails using RSpec Capybara and selenium-chrome driver.

I am also using the capybara-angular gem.

I'm a little confused about exactly whats going on as I don't see my scripts when I sleep my rspec test inspect the the sources tab in the chrome debugger it doesn't seem like my assets are loaded, although it does appear that the ng-if statements are working as the page is hidden.

So I'm not quite sure what's going on. The page works as expected in development, but variables on the $scope are not set in test.

This my set up in "system.rb

   RSpec.configure do |config|
  config.before(:each, type: :system) do
    driven_by :rack_test
  end
  config.before(:each, type: :system, js: true) do
    driven_by :selenium_chrome
  end
end

require "capybara-screenshot/rspec"
include Capybara::Angular::DSL

Here is the test I am running:

it "shows changes to the budget when the budget is changed", :js do
    visit(root_path)
    sleep 0.5
    fill_in "inputEmail", with: "[email protected]"
    fill_in "password", with: "test"
    click_on("Log In")
    sleep 0.25
    click_on("Budgeting")

    sleep 10
     expect(page).to  have_selector("#current_project_name", text: "Project A")
     expect(page).to have_selector("#budgetInput1")

    fill_in "#budgetInput1", with: "100"
    # Fail on next line with 'expected to find visible css "#budgetInput1" but there were no matches'
    page.should have_selector("#budgetInput1", text: "100") # <--test fails with
  end

From what I can tell, the reason it is not found is because the element appears in a div with ng-if="showBudget". $scope.showBudget=true is set in the controller, but the controller doesn't appear to be loading and {{showBudget==unknown}} returns true, which suggests that AngularJS is loading but the scripts loaded by the manifest for the page are not.

How to fix this?

2

There are 2 best solutions below

1
Thomas Walpole On

It looks like you're not using the correct expectation. Since you're able to call fill_in on the element with id budgetInput1 then expecting (not sure why you're mixing expect and should syntax) with the text option isn't going to work. What you probably want is

expect(page).to have_field('budgetInput1', with: '100')

If instead you're expecting the fill_in to trigger an update on the page that replaces the input element with id 'budgetInput1' with a different element, then you probably need to be sending an enter, a tab, or clicking outside the initial element to trigger the change.

On another note, I'm not sure why you have the sleeps in your test - fill_in will wait for the matching element to exist, so there really should be no need to sleep half a second after calling visit -- For the 10 second sleep (does your app really take 10 seconds to respond???) you could just use the wait option on expect(page).to have_selector("#current_project_name", text: "Project A", wait: 10) instead so that the test continues as soon as the element exists, rather than waiting all 10 seconds if it's not necessary.

0
GGizmos On

The problem turned out to be a little different than I thought. When I looked at the sources tab, in development I am used a big list of files including everything in my manifest listed. In the capybara test, all those files including jquery and angular are concatenated into a single file. jquery is at the top, and way down at the bottom, which was about line 40000 were my angular controller files. The problem was that that the file it created were not the based on the latest versions of my javascript assets.

rake assets:clean
rake assets:precompile

This was not normally necessary in development, the changes I make in my js files are picked up immediately, but I guess it is required when running Capybara tests with selenium chrome.