1
votes

After finishing RailsTutorial.org i have decided to i18n my application and suddently my tests started failing with the following,

Failures:

1) User pages index Failure/Error: sign_in user Capybara::ElementNotFound: Unable to find field "Email" # ./spec/support/utilities.rb:5:in sign_in' # ./spec/requests/user_pages_spec.rb:11:inblock (3 levels)

The only changes i have made where,

routes.rb

SampleApp::Application.routes.draw do
  scope '(:locale)' do
    resources :users
    resources :sessions, only: [:new, :create, :destroy]
    root to: 'static_pages#home'
    match '/signup',    to: 'users#new',              via: 'get'
    match '/signin',    to: 'sessions#new',           via: 'get'
    match '/signout',   to: 'sessions#destroy',       via: 'delete'
    match '/help',      to: 'static_pages#help',      via: 'get'
    match '/about',     to: 'static_pages#about',     via: 'get'
    match '/contact',   to: 'static_pages#contact',   via: 'get'
  end

And config/initializers/i18n.rb

I18n.default_locale = :en

LANGUAGES = [
  ['English',               'en'],
  ['Portuguese',        'pt']
]

Before the i18n the routes looked like the following,

users_path  GET     /users(.:format)    users#index
    POST    /users(.:format)    users#create
new_user_path   GET     /users/new(.:format)    users#new
edit_user_path  GET     /users/:id/edit(.:format)   users#edit
user_path   GET     /users/:id(.:format)    users#show
    PATCH   /users/:id(.:format)    users#update
    PUT     /users/:id(.:format)    users#update
    DELETE  /users/:id(.:format)    users#destroy
sessions_path   POST    /sessions(.:format)     sessions#create
new_session_path    GET     /sessions/new(.:format)     sessions#new
session_path    DELETE  /sessions/:id(.:format)     sessions#destroy
root_path   GET     /   static_pages#home
signup_path     GET     /signup(.:format)   users#new
signin_path     GET     /signin(.:format)   sessions#new
signout_path    DELETE  /signout(.:format)  sessions#destroy
help_path   GET     /help(.:format)     static_pages#help
about_path  GET     /about(.:format)    static_pages#about
contact_path    GET     /contact(.:format)  static_pages#contact 

And now,

users_path  GET     (/:locale)/users(.:format)  users#index
    POST    (/:locale)/users(.:format)  users#create
new_user_path   GET     (/:locale)/users/new(.:format)  users#new
edit_user_path  GET     (/:locale)/users/:id/edit(.:format)     users#edit
user_path   GET     (/:locale)/users/:id(.:format)  users#show
    PATCH   (/:locale)/users/:id(.:format)  users#update
    PUT     (/:locale)/users/:id(.:format)  users#update
    DELETE  (/:locale)/users/:id(.:format)  users#destroy
sessions_path   POST    (/:locale)/sessions(.:format)   sessions#create
new_session_path    GET     (/:locale)/sessions/new(.:format)   sessions#new
session_path    DELETE  (/:locale)/sessions/:id(.:format)   sessions#destroy
root_path   GET     /(:locale)(.:format)    static_pages#home
signup_path     GET     (/:locale)/signup(.:format)     users#new
signin_path     GET     (/:locale)/signin(.:format)     sessions#new
signout_path    DELETE  (/:locale)/signout(.:format)    sessions#destroy
help_path   GET     (/:locale)/help(.:format)   static_pages#help
about_path  GET     (/:locale)/about(.:format)  static_pages#about
contact_path    GET     (/:locale)/contact(.:format)    static_pages#contact 

user_pages_spec.rb

require 'spec_helper'

describe "User pages" do

    subject { page }

    describe "index" do
        let(:user) { FactoryGirl.create(:user) }

        before (:each) do
            sign_in user
            visit users_path
        end

        it { should have_title('All users') }
        it { should have_content('All users') }

        describe "pagination" do
            before(:all) { 30.times { FactoryGirl.create(:user) } }
            after(:all) { User.delete_all }

            it { should have_selector('div.pagination') }

            it "should list each user" do
                User.paginate(page: 1).each do |user|
                    expect(page).to have_selector('li', text: user.name)
                end
            end
        end

        describe "delete links" do

            it { should_not have_link('delete') }

            describe "as an admin user" do
                let(:admin) { FactoryGirl.create(:admin) }
                before do
                  sign_in admin
                  visit users_path
                end

                it { should have_link('delete', href: user_path(User.first)) }
                it "should be able to delete another user" do
                    expect{ click_link('delete') }.to change(User, :count).by(-1)
                end
                it { should_not have_link('delete', href: user_path(admin)) }
            end
        end
    end

    describe "profile page" do
        let(:user) { FactoryGirl.create(:user) }
        before { visit user_path(user) }

        it { should have_content(user.name) }
        it { should have_title(user.name) }
    end

    describe "signup page" do
        before { visit signup_path }

        it { should have_content('Sign up') }
        it { should have_title(full_title('Sign up')) }
    end

    describe "signup" do

        before { visit signup_path }

        let(:submit) { "Create my account" }

        describe "with invalid information" do
            it "should not create a user" do
                expect { click_button submit }.not_to change(User, :count)              
            end

            describe "after submission" do
                before { click_button submit }

                it { should have_title('Sign up') }
                it { should have_content('error') }
            end
        end

        describe "with valid information" do
            before do
              fill_in "Name",           with: "Example User"
              fill_in "Email",          with: "[email protected]"
              fill_in "Password",       with: "password"
              fill_in "Confirm Password",   with: "password"
            end

            it "should create a user" do
                expect { click_button submit }.to change(User, :count).by(1)
            end

            describe "after saving the user" do
                before { click_button submit }
                let(:user) { User.find_by(email: '[email protected]') }

                it { should have_link('Sign out') }
                it { should have_title(user.name) }
                it { should have_selector('div.alert.alert-success', text: 'Welcome') }
            end
        end
    end

    describe "edit" do
        let(:user) { FactoryGirl.create(:user) }
        before do
          sign_in user
          visit edit_user_path(user)
        end

        describe "page" do
            it { should have_content("Update your profile") }
            it { should have_title("Edit user") }
        end

        describe "with invalid information" do
            before { click_button "Save changes" }

            it { should have_content('error') }
        end

        describe "with valid information" do
            let(:new_name) { "New Name" }
            let(:new_email) { "[email protected]" }
            before do
              fill_in "Name",               with: new_name
              fill_in "Email",              with: new_email
              fill_in "Password",           with: user.password
              fill_in "Confirm Password",   with: user.password
              click_button "Save changes"
            end

            it { should have_title(new_name) }
            it { should have_selector('div.alert.alert-success') }
            it { should have_link('Sign out', href: signout_path) }
            specify { expect(user.reload.name).to eql(new_name) }
            specify { expect(user.reload.email).to eql(new_email) }
        end

        describe "forbidden attributes" do
            let(:params) do
                { user: { admin: true, password: user.password, password_confirmation: user.password } }
            end
            before { patch user_path(user), params }
            specify { expect(user.reload).not_to be_admin }
        end
    end
end

utilities.rb

include ApplicationHelper

def sign_in(user)
    visit signin_path
    fill_in "Email",        with: user.email
    fill_in "Password",     with: user.password
    click_button "Sign in"
    #Sign in when not using Capybara as well.
    cookies[:remember_token] = user.remember_token
end

Could someone please provide some tips for beginners? Thanks for all the support.

1
Hi Miguel, did you understand what the error message is saying? could you please paste your test here?Kleber S.
Yes field Email cannot be found.Miguel Silva

1 Answers

2
votes

If you're going to scope all your routes to include a locale, you'll need to pass in a locale into your paths when you test them (as you can see in the new output to rake routes, a :locale is expected), so where you would put, say, visit users_path, you would put
visit users_path(locale). You would get your locale from your list of I18n.available_locales. You'll also need to change the strings that you're using to find fields to their i18n equivalent eg
fill_in "Email" becomes fill_in I18n.t('sessions.new.email')

I i18n-ized my Sample App, so here's my user_pages_spec.rb which will hopefully give you an idea on what kind of changes you'll probably need to make.