2016-09-22 2 views
0

Я работаю над своим первым сложным тестом, и мне нужна помощь. Мне нужно создать пользователя, подписать его и заполнить форму как он. Страница выдает ошибку: undefined method first_name for nil:nilClassОтправить переменную для просмотра по запросу spec

Обе функции являются довольно легко, вот тест:

it "simulates creator onboard" do 
@user = FactoryGirl.create(:user) 
puts @user.onboard_token.size 
visit onboard_path(:token => @user.onboard_token) 
puts @user.nil? 
expect(@user.active).to eq(false) 
click_on('step-forward') 
find('input[name="user[password"]').set "12345678" 
find('input[name="user[password_confirmation"]').set "12346578" 
find('input[name="commit"]').click 
expect(response).to redirect_to(root_path) 
expect(@user.active).to eq(true) 

конец

А вот функция регулятора:

def onboard 
authorize(:user, :onboard?) 
if params[:token].present? 
    if params[:token] != nil && params[:token].size == 40 && !User.where(onboard_token: params[:token]).empty? 
    @user = User.find_by_onboard_token(params[:token]) 
    end 
    if [email protected]? 
    sign_in(:user, @user) 
    @brand = @user.profile 
    sign_out(:user) 
    end 
else 
    sign_out(:user) 
    redirect_to root_path 
end 

конец

По какой-то причине, похоже, что @user переменная не передается в представление. Я убедился, что это не ноль, убедитесь, что вы используете правильные функции capybara, но все же, @user - это нуль.

Я что-то пропустил?

+0

Пробовали ли вы отладки это? Удостоверьтесь, что ваши 'params [: token]! = Nil && params [: token] .size == 40 &&! User.where (onboard_token: params [: token]). Empty?' Оценивается как true, а @user присваивается начните с, дайте мне знать, если это не проблема. – IKA

+0

Одна из проблем заключается в том, что переменную '@ user' в вашем тесте нужно перезагрузить с помощью' @ user.reload', чтобы просмотреть изменения, внесенные в базу данных вашим приложением , '@ vars' - это переменные экземпляра, а не глобальные, и даже если это ваш тест, а тестируемое приложение часто выполняется в разных потоках. – max

+0

Аплодисменты из этого рода беспорядок. Если вы можете сказать нам в простых выражениях («Когда пользователь нажимает X - Y должен произойти»), то, что должно выполнить ваше действие контроллера, мы можем вам помочь. – max

ответ

0

Поскольку вы используете Selenium с Капибарой этого тест имеет ряд вопросов

  1. Объекты, созданные в тестовой нити не видны в приложении нити, если вы используете транзакционное тестирование - https://github.com/jnicklas/capybara#transactions-and-database-setup
  2. Действия в Capybara являются асинхронными, поэтому при попытке проверить значения на объекте сразу же после запуска действия (без какой-либо экспрессии на отображаемом контенте, чтобы убедиться, что действие завершено) будет flaky
  3. Вы не можете использовать visit и «ответ» в то же время
  4. Объект, present? не может быть нулевым
  5. Если есть знак, но ни один пользователь не соответствует его код с еще пытаются вынести мнение, но без @user и не @brand

Чтобы решить эту проблему, вам необходимо настроить что-то вроде DatabaseCleaner и убедиться, что вы используете стратегию усечения или удаления для тестов с использованием драйвера селена. Это позволит видимым в приложении объектам, созданным в тестовом потоке (в вашем случае пользователю). Тогда ваше испытание должно быть что-то больше похоже на

it "simulates creator onboard" do 
    @user = FactoryGirl.create(:user) 
    visit onboard_path(:token => @user.onboard_token) 
    #You need to expect for something that should be on the screen before checking user.active - since this can occur before the visit has actually done anything 
    #expect(@user.reload.active).to eq(false) 
    click_on('step-forward') 
    find('input[name="user[password"]').set "12345678" 
    find('input[name="user[password_confirmation"]').set "12346578" 
    find('input[name="commit"]').click 
    expect(page).to have_current_path(root_path) 
    expect(@user.reload.active).to eq(true) 
end 

с контроллером больше как

def onboard 
    authorize(:user, :onboard?) 
    if params[:token].present? && params[:token].size == 40 
    @user = User.find_by_onboard_token(params[:token]) 
    if [email protected]? 
    sign_in(:user, @user) 
    @brand = @user.profile 
    sign_out(:user) 
    else 
    # do something here because it means the token was invalid 
    end 
    else 
    sign_out(:user) 
    redirect_to root_path 
    end