路由错误 I18n 和 rspec

Route error I18n and rspec

在应用程序中,我使用 gem "I18n" 进行国际化。一切正常,但在验收测试中,我收到一个错误:

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

测试:

  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

现场一切正常。我该如何解决?

当使用支持 JS 的驱动程序(capybara-webkit 是)时,Capybara 操作异步发生。这意味着对访问的调用可能 return 在浏览器的 URL 实际发生变化之前,这也是为什么大多数水豚动作都有内置的等待行为。在这种情况下,您可能会在浏览器从旧路径更改为新路径之前获得 current_path。有几个解决方案

  1. 如果使用 Capybara 2.5+ 更改为使用具有内置等待行为的 have_current_path 匹配器

    期待(页面).to have_current_path(profile_path)

  2. 为页面上应有的内容添加内容检查 - 将触发等待行为并确保在获取 current_path

    [=26= 之前加载页面]
  3. 访问后添加一两秒的休眠,这将使浏览器有时间更改到新路径

显然 #1 是更好的解决方案,除非你有某些原因不能使用 Capybara 2.5+

既然你说问题只出现在 RSpec 测试中并且应用程序运行良好,那么我假设你希望 URL 的形式为 /:locale/profile(.:format) .因此,如果您的应用程序中有类似以下路由范围的内容...

config/routes.rb

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

  # other routes
end

...并且您的控制器中有如下内容(可能是 ApplicationController),它会自动将 locale 注入 url 选项...

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

(以上也可以是 default_url_options 作为 的覆盖)

...然后,您还需要将 locale 作为参数传递给规范中的路径:

  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

假设以上是正确的,您甚至可以在 rails 控制台中对此进行测试并(可能)获得类似于以下内容的输出:

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"