2015-04-03 2 views
1

У меня возникла странная проблема, когда я создаю пользователя для теста Rspec/Capybara, и пользователь таинственно удален после входа в систему. Когда я запускаю свой тест, пользователь создается и успешно вошел в систему. Однако, когда Capybara посещает admin_categories_path, тест терпит неудачу. Rails вызывает исключение, потому что current_user не определен. Когда я вставляю binding.pry, я вижу, что пользователь существует до тех пор, пока он не войдет в систему, и в этот момент пользователь исчезнет из тестовой базы данных, в результате чего current_user будет неопределенным и тем самым инициирует исключение. Я не понимаю, как это происходит.Rspec/Capybara: Уберите пользователя «исчезает» после входа в систему

ОБНОВЛЕНИЕ: У меня проблема с удалением пользователя. Теперь, когда Capybara видит страницу admin_categories_path, category не отображается. Вставка binding.pry показывает, что категория присутствует в базе данных.

Когда я запускаю приложение и регистрируюсь вручную, у меня нет проблем с доступом к admin_categories_path.

Вот мой спецификации файла:

require 'rails_helper' 

feature 'admin edits category', %Q{ 
    As an admin, I want to edit a category or subcategory, so that it better 
    represents the content under it. 
    Acceptance Criteria: 
    * [X] - I can edit the name of a category inline. 
    * [X] - I can edit the name of a subcategory inline. 
    } do 

    let(:admin) do 
    FactoryGirl.create(:user, admin: true) 
    end 

    let(:category) do 
    FactoryGirl.create(:category) 
    end 

    scenario 'admin edits category title', js: true, focus: true do 
    login_as(admin) 
    visit admin_categories_path 

    bip_area category, :name, 'Test Category' 
    expect(page).to have_content 'Test Category' 
    end 
end 

Вот мой помощник файл authentication.rd:

module Helpers 
    module Authentication 
    def log_in_as(user) 
     visit new_user_session_path 

     within "#new_user" do 
     fill_in 'user[email]', with: user.email 
     fill_in 'user[password]', with: user.password 
     click_on "Log in" 
     end 
    end 
    end 

    RSpec.configure do |config| 
    config.include Authentication, :type => :feature 
    end 
end 

Вот мой user завод:

require 'factory_girl' 

FactoryGirl.define do 
    factory :user do 
    sequence(:email) {|n| "lafiel.abriel#{n}@abhnation.com" } 
    username 
    password 'password' 
    password_confirmation 'password' 
    end 

    factory :category do 
    sequence(:name) { |n| "Category ##{n}" } 
    parent_id nil 
    display_index 1 
    user 
    end 

    sequence :username do |n| 
    "Lafiel_Abriel_#{n}" 
    end 
end 

А вот мой application_controller.rd где инициируется исключение:

module Admin 
    class ApplicationController < ActionController::Base 
    before_action :configure_permitted_parameters, if: :devise_controller? 
    before_action :reject_unless_admin 
    layout 'admin/layouts/application' 

    protect_from_forgery with: :exception 
    helper :avatar, :devise, :admin 

    protected 

    def reject_unless_admin 
     unless current_user && current_user.admin? 
     raise ActionController::RoutingError.new('404: Not Found') 
     end 
    end 

    def configure_permitted_parameters 
     devise_parameter_sanitizer.for(:sign_up) << [ 
     :avatar, 
     :remote_avatar_url, 
     :email, 
     :username, 
     :first_name, 
     :last_name, 
     :age, 
     :website, 
     :password, 
     :password_confirmation, 
     :current_password 
     ] 
    end 
    end 
end 

Любая помощь/понимание очень ценится. Благодарю.

+0

У меня возникла такая же проблема, когда current_user не присутствовал после успешного входа в систему. Самое страшное в том, что это происходит только в некоторых тестах: особенно, когда куча работает корректно, то внезапно последний тест не удается с этим поведением. В любом случае, было бы здорово, если бы вы могли поделиться, если и как вы решили свою проблему! Благодарю. –

+0

Проверьте мой ответ ниже. Надеюсь, что это поможет! – ACIDSTEALTH

ответ

0

Если я правильно помню, эта проблема имела какое-то отношение к схеме тестовой базы данных, которая не синхронизируется с базой данных разработки. Попробуйте запустить rake db:test:prepare, чтобы ваша схема тестирования соответствовала вашей схеме разработки.

В моем конкретном случае у меня было две проблемы для преодоления.

Первая проблема возникла, когда я создал category и admin в блоке let. Те, которые должны были быть размещены в блоке before, чтобы они были созданы до выполнения теста. Когда я разместил эти переменные в блоках let, они не создавались до первого вызова в тесте. Поэтому, когда я вошел в систему как администратор, переменная admin передавалась в мой login_as вспомогательный метод до того, как она была сохранена в базе данных. То же самое относится к переменной category.

Этот код не работает для меня:

let(:admin) do 
    FactoryGirl.create(:user, admin: true) 
end 

let(:category) do 
    FactoryGirl.create(:category) 
end 

scenario 'admin edits category title', js: true, focus: true do 
    login_as(admin) 
    visit admin_categories_path 

    bip_area category, :name, 'Test Category' 
    expect(page).to have_content 'Test Category' 
end 

Это решение, которое я использовал для преодоления первой проблемы:

before(:each) do 
    @admin = FactoryGirl.create(:user, admin: true) 
    @category = FactoryGirl.create(:category, user: @admin) 
end 

scenario 'admin edits category title', js: true do 
    skip "Doesn't work yet." 
    login_as(@admin) 
    visit admin_categories_path 

    wait_for_ajax 
    bip_text @category, :name, 'Test Category' 
    expect(page).to have_content 'Test Category' 
end 

Вторая проблема заключается в том, что, когда мой тест попадает в admin/categories_controller.rb, Category.all возвращает пустой массив, хотя @category.save! и @category.valid? верны, когда я тестирую свой блок before.Я так и не смог найти решение проблемы и закончил тестирование на льду.

Я думаю, что часть проблемы заключается в том, что документация на драгоценный камень Best-in-Place не очень хороша. Я использовал его в то время, потому что это было легким решением моей проблемы. Если идти вперед, я бы использовал что-то вроде углового для этого прецедента. Документация намного лучше, и это не черный ящик, как много драгоценных камней.

0

Я не уверен, что делает bip_area, но так как ваш тест говорит, что он редактирует категорию, я предполагаю, что вы ожидаете, что категория будет присутствовать на странице при посещении admin_categories_path. Когда вы посещаете этот путь, тем не менее категория еще не создана, так как вы используете «let», которая лениво оценивается (создается во время первого использования переменной), поэтому она не будет отображаться на экране для редактирования. Используя binding.pry, а затем посмотрев на эту переменную, на самом деле создадим ее, так что это может смутить вас в том, что он там. Вы можете использовать 'let!' вместо этого будет принудительно создавать переменную перед каждым тестом, а не лениво оценивать ее.

+0

«Пусть! Мне они кажутся одинаковыми. Теперь я знаю, что 'let' не оценивается до тех пор, пока он не будет вызван (не знал об этом в то время ...). – ACIDSTEALTH

+0

let! позволяет вам определять локальные переменные в отличие от переменных экземпляра (нет @ перед именем) –

Смежные вопросы