简体   繁体   中英

Route error I18n and rspec

In app I use gem "I18n" for internationalization. All worck ok, but in aceptance tests, I receive an error:

    Failure/Error: expect(current_path).to eq profile_path
     expected: "/profile"
     got: "/en/profile"
   (compared using ==)

Test:

  describe 'User go to profile' do
    before do
      page.driver.header 'Accept-Language', locale
      I18n.locale = locale

      sign_in (user)
    end

    context 'locale EN' do
      let(:locale) { :en }

      scenario 'and view see profile page' do
        visit profile_path

        expect(current_path).to eq profile_path
      end
    end
  end

On site all work good. How can I fix it?

When using JS capable drivers (which capybara-webkit is) with Capybara actions occur asynchronously. This means the call to visit may return before the URL of the browser has actually changed, and why most capybara actions have waiting behavior built-in. In this case its probably you're getting the current_path before the browser has changed from the old path to the new. There are a couple of solutions

  1. If using Capybara 2.5+ change to using the have_current_path matcher which has waiting behavior built-in

    expect(page).to have_current_path(profile_path)

  2. Add a content check for something that should on the page - will trigger the waiting behavior and make sure the page is loaded before getting current_path

  3. add a sleep of a second or two after visit, which will give the browser time to change to the new path

Obviously #1 is the better solution unless you have some reason you can't be on Capybara 2.5+

Since you're saying that the problems are only in the RSpec tests and the app is working fine, then I assume you're expecting the URLs to be in the form of /:locale/profile(.:format) . So, if you have something like the following route scope in your app...

config/routes.rb

scope ":locale", locale: /#{I18n.available_locales.join("|")}/ do
  get 'profile',  to: 'users#profile'

  # other routes
end

...and you have something like the following in your controller (probably ApplicationController ) that automatically injects the locale into the url options...

def url_options
  { locale: I18n.locale }.merge(super)
end

(The above could also be an override of default_url_options as Tom Walpole mentioned )

...then, you'll need to pass that locale in as a parameter to your paths in the spec as well:

  describe 'User go to profile' do
    before do
      page.driver.header 'Accept-Language', locale
      I18n.locale = locale

      sign_in (user)
    end

    context 'locale EN' do
      let(:locale) { :en }

      scenario 'and view see profile page' do
        visit profile_path

        expect(current_path).to eq profile_path(locale: locale)
      end
    end
  end

Assuming the above is correct, you could even test this in a rails console and (probably) get output similar to the following:

irb> app.profile_path
ActionController::UrlGenerationError: No route matches {:action=>"profile", :controller=>"users"} missing required keys: [:locale]
irb> app.profile_path(locale: :en)
"/en/profile"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM