web-dev-qa-db-fra.com

Moyen correct d'attendre qu'une deuxième page soit chargée avec Capybara lorsque la première a le même champ que la deuxième

J'ai un problème avec une spécification qui visite deux formulaires avec le même champ ("Email") sur les deux formulaires. Si je ne dors pas manuellement, Capybara semble trouver le champ "Email" de la première visite dans la deuxième partie du test.

# visit the first form and fill out a subscription
visit new_front_form_subscription_path(@web_form_1.id)
fill_in "Email", with: "[email protected]"
fill_in "Field 1", with: "my first data"
click_button "Subscribe"

# visit the second form and fill out a subscription
visit new_front_form_subscription_path(@web_form_2.id)
sleep 1
fill_in "Email", with: "[email protected]"
fill_in "Field 2", with: "my second data"
click_button "Subscribe"

Avec le sommeil là-bas, la spécification passe avec brio. Sans la mise en veille, la deuxième soumission du formulaire génère une erreur de validation: une valeur "Email" vierge est blâmée.

Y a-t-il une bonne façon de gérer cela? Je déteste l'introduction de sommeil manuel dans nos spécifications. Je préférerais de loin dire à Capybara d’ignorer son concept de ce qui est déjà sur la page, ou quelque chose du genre.

Je vous remercie.

12
Alex

Voici quelques façons dont vous pouvez le résoudre:

  1. Utilisez un autre localisateur présent uniquement sur la deuxième page pour sélectionner le champ "Email":

    find('#second_page #email').set('[email protected]')
    
  2. Ecrivez une déclaration qui attendra qu'une deuxième page soit chargée au lieu de dormir:

    visit new_front_form_subscription_path(@web_form_2.id)
    expect(page).to have_css('locator_present_only_at_second_page')
    fill_in "Email", with: "[email protected]"
    
7
Andrei Botalov

Les réponses ci-dessus sont correctes, mais difficiles à mettre en œuvre si vous avez une grande suite de tests, car vous devez trouver un élément unique sur chaque page. Si vous êtes diplômé de l'école Michael Hartl of Rails, il existe un moyen simple de résoudre ce problème. Hartl enseigne la définition d'une variable d'instance @title différente pour chaque action du contrôleur. Ceci est ensuite utilisé dans application.html.erb pour définir un élément de titre html pour chaque page.

Certainement, et cela a permis de résoudre très facilement tous mes tests qui ont échoué parce que la page n’avait pas été chargée correctement. Vous ne pouvez pas trouver la balise de titre car elle n'est pas visible. Donc, ce que j'ai fait a été mis au bas de l'application.html.erb, le code suivant;

<%= content_tag :div, "[#{title}]", class: 'rspec_eyes_only' if Rails.env.test? %>

Cela insère, si vous êtes en mode test, un div avec un titre, entouré de crochets. Puis j'ai écrit une aide qui va dans Rails_helper.rb

def wait_for_page_load(title)
  find('div.rspec_eyes_only', text: title)
end

J'ai déjà un autre assistant pour tester le titre correct, je l'ai donc modifié pour ajouter wait_for_page_load i.e;

def title_is_correct(title)
  full_title = "#{BaseTitle} | #{title}"
  wait_for_page_load "[#{full_title}]"
  expect(page.title).to eq full_title
end

Ces changements simples ont permis de résoudre presque tous mes tests.

5
Obromios

Si vous avez eu recours au 2) d'Andrey ci-dessus, vous pouvez consulter le holdon gem , qui vous permettra d'écrire un bloc qui attendra le chargement d'un élément, puis de passer à la méthode fill_in une fois que cet élément sera chargé. .

1
aceofbassgreg

Généralement, cela peut être fait de cette façon. Par exemple, pour cliquer sur les boutons trouvés après le chargement d'une fenêtre contextuelle modale (ou d'une autre page), ajoutez le bloc suivant à votre fichier de macro.

def wait_until_modal
   page.has_css?('.modal')
end

Ici, la classe .modal se trouve sur la page contextuelle.

0
bir_ham