web-dev-qa-db-fra.com

Capybara avec: js => true provoque l'échec du test

Je suis nouveau sur Capybara et je teste sur Rails en général, alors pardonnez-moi s'il s'agit d'une réponse simple.

J'ai ce test

it "should be able to edit an assignment" do
    visit dashboard_path
    select(@project.client + " - " + @project.name, :from => "assignment_project_id")
    select(@team_member.first_name + " " + @team_member.last_name, :from => "assignment_person_id")
    click_button "Create assignment"
    page.should have_content(@team_member.first_name)
end

il passe tel quel, mais si j'ajoute: js => true, il échoue avec

cannot select option, no option with text 'Test client - Test project' in select box 'assignment_project_id'

J'utilise FactoryGirl pour créer les données, et comme le test réussit sans JS, je sais que cette partie fonctionne.

J'ai essayé avec le pilote JS par défaut et avec le pilote: webkit (avec capybara-webkit installé)

Je suppose que je ne comprends pas assez ce que l'activation de JS pour Capybara fait.

Pourquoi le test échouerait avec JS activé?

50
evanmcd

J'ai lu le fichier Lisezmoi de Capybara sur https://github.com/jnicklas/capybara et cela a résolu mon problème.

Les appareils transactionnels ne fonctionnent que dans le pilote Rack :: Test par défaut, mais pas pour d'autres pilotes comme Selenium. Cucumber s'en charge automatiquement, mais avec Test :: Unit ou RSpec, vous devrez peut-être utiliser le gem database_cleaner. Voir cette explication (et code pour solution 2 et solution ) pour plus de détails.

Mais en gros, c'est un problème de thread qui implique que Capybara ait son propre thread lors de l'exécution du pilote non-Rack, ce qui fait que les appareils transactionnels disposent d'une deuxième connexion dans un autre contexte. Ainsi, le thread du pilote n'est jamais dans le même contexte que la rspec en cours d'exécution.

Heureusement, cela peut être facilement résolu (au moins cela a été résolu pour moi) en effectuant une commutation dynamique dans la stratégie DatabaseCleaner à utiliser:

RSpec.configure do |config|
  config.use_transactional_fixtures = false

  config.before :each do
    if Capybara.current_driver == :rack_test
      DatabaseCleaner.strategy = :transaction
    else
      DatabaseCleaner.strategy = :truncation
    end
    DatabaseCleaner.start
  end

  config.after do
    DatabaseCleaner.clean
  end
end
107
brutuscat

Une variation de réponse de brutuscat qui a corrigé nos spécifications de fonctionnalités (qui utilisent toutes Capybara):

config.before(:suite) do
  DatabaseCleaner.clean_with(:truncation)
end

config.before(:each) do
  # set the default
  DatabaseCleaner.strategy = :transaction
end

config.before(:each, type: :feature) do
  DatabaseCleaner.strategy = :truncation
end

config.before(:each) do
  DatabaseCleaner.start
end

config.append_after(:each) do
  DatabaseCleaner.clean
end
9
Aidan Feldman

Il existe une autre façon de résoudre ce problème maintenant décrit et discuté ici: Pourquoi ne pas utiliser les connexions ActiveRecord partagées pour Rspec + Selenium?

7
Lars Schirrmeister