capybara-angular icon indicating copy to clipboard operation
capybara-angular copied to clipboard

capybara-angular does not wait for route changes

Open alexspark opened this issue 10 years ago • 2 comments

I am testing a login page, and after a successful login, I should be redirected to the dashboard page. I am using the ng-routes module, not the angular-ui-router. My test for asserting this route change always fails. my assertion looks like this:

expect(current_url).to eq("#{@app_host}/#/dashboard")

I see that the way capybara-angular checks to see if angular is ready is just by counting outstanding XHR requests.I think waiting for route changes should be a part of what this library covers.

alexspark avatar Feb 10 '15 20:02 alexspark

Agree this would be useful. Though it should only work in ngRoute or ui-router is being used.

This is what I do in my app currently:

# spec/support/route_changes.rb
module RouteChange
  def wait_for_route_changes
    page.evaluate_script <<-JS
      angular.element(document).ready(function() {
        var app = angular.element(document.querySelector('[ng-app], [data-ng-app]'));
        var injector = app.injector();

        injector.invoke(function($rootScope) {
          $rootScope.$on("$routeChangeStart", function() {
            window.angularReady = false;
          });

          var ready = function() { window.angularReady = true };

          $rootScope.$on("$routeChangeSuccess", ready);
          $rootScope.$on("$routeChangeError", ready);
        });
      });
    JS
  end
end

Then include it in spec_helper:

config.include Capybara::Angular::DSL
config.include RouteChange, type: :feature

And in my feature spec:

scenario "search for a product" do
  visit root_path
  wait_for_route_changes

  within :css, "form[name=SearchForm]" do
    fill_in "keywords", with: "shirt"
    click_on "Search"
  end

  expect(page.all('.product-listing .product').size).to eq(1)
end

joshnuss avatar Feb 12 '15 05:02 joshnuss

I agree with it as an option to opt-in for. I was thinking that one can check for the specific module in the page

if(angular.module('ngRoute')) then register the listeners

There might be a better way to check if the application is using ngRoute, and it would seem just as seamless as the Capybara::Angular::DSL

alexspark avatar Feb 12 '15 16:02 alexspark