J'essaie de tester qu'un lien vers une action de destruction jette une boîte confirm
de navigateur natif avec le message correct.
Le lien est généré à l'aide de link_to
:
link_to 'Delete', user_path, method: :delete, data: { confirm: "Are you sure?" }
Et génère le code HTML suivant:
<a data-confirm="Are you sure?" data-method="delete" href="/users/6" rel="nofollow">Delete</a>
La fonctionnalité fonctionne correctement dans le navigateur, mais je souhaite la tester dans ma spécification de fonctionnalité rspec
.
J'essaie de masquer la fonction confirm
du navigateur, comme décrit ici et dans ce Gist , mais je n'arrive pas à le faire fonctionner.
it 'requests confirmation', js: true do
visit user_path(user)
page.execute_script "
window.confirmMsg = null;
window.confirm = function(msg) { window.confirmMsg = msg; return true; };"
click_link 'Delete'
expect(page.evaluate_script('window.confirmMsg')).to eq('Are you sure?')
end
Donne l'erreur suivante de rspec
:
Failure/Error: expect(page.evaluate_script('window.confirmMsg')).to eq('Are you sure?')
expected: "Are you sure?"
got: nil
(compared using ==)
Cependant, si j'appelle une confirm
directement via page.execute_script
:
it 'requests confirmation', js: true do
visit user_path(user)
page.execute_script "
window.confirmMsg = null;
window.confirm = function(msg) { window.confirmMsg = msg; return true; };
window.confirm('Are you sure?');"
expect(page.evaluate_script('window.confirmMsg')).to eq('Are you sure?')
end
Ensuite, le test réussit.
Si vous cliquez également sur le lien Supprimer, le test échouera, même si confirm
a été appelé directement pour page.execute_script
:
it 'requests confirmation', js: true do
visit user_path(user)
page.execute_script "
window.confirmMsg = null;
window.confirm = function(msg) { window.confirmMsg = msg; return true; };
window.confirm('Are you sure?');"
click_link 'Delete'
expect(page.evaluate_script('window.confirmMsg')).to eq('Are you sure?')
end
Donne la même erreur de rspec
:
Failure/Error: expect(page.evaluate_script('window.confirmMsg')).to eq('Are you sure?')
expected: "Are you sure?"
got: nil
(compared using ==)
Pourquoi le test échoue-t-il? Et comment puis-je tester les dialogues de confirmation correctement?
Contexte:
J'exécute mes tests à partir d'une machine virtuelle Vagrant, qui s'appelle Ubuntu 12.04.4 LTS
et exécute Ruby 2.1.2p95
.
Mon Gemfile.lock
indique que j'ai les versions suivantes:
Rails (4.1.4)
poltergeist (1.5.1)
capybara (2.4.1)
page.driver.browser.accept_js_confirms est obsolète. Utilisez plutôt
page.accept_confirm do
click_link 'Delete'
end
Malheureusement, vous ne pouvez pas faire cela , car Poltergeist ne fonctionne que dans une seule fenêtre.
Pour ce test spécifique, vous devrez utiliser Selenium et cette API:
page.driver.browser.switch_to.alert.accept
Si vous souhaitez exécuter vos tests sans tête, vous pouvez utiliser Xvfb (X Virtual Framebuffer) comme ceci:
Xvfb :1 -screen 0 1024x768x24+32
Sinon, vous pouvez aussi utiliser capybara-webkit:
page.driver.browser.accept_js_confirms
page.driver.browser.reject_js_confirms
Cependant, j'ai fait la meilleure expérience en utilisant un mélange de Poltergeist (principalement) et de Sélénium si nécessaire.
Pour développer ce qui précède, lorsque vous utilisez Selenium, vous pouvez tester le texte réel de la boîte de dialogue de confirmation en utilisant les éléments suivants:
click_link 'Delete'
a = page.driver.browser.switch_to.alert
expect(a.text).to eq("Are you sure?")
a.accept
En outre, je viens de trouver un bon test pour savoir si l'alerte est présente ici: Selenium 2.4.0, comment vérifier la présence d'une alerte je l'ai légèrement modifié, mis dans mon fichier spec_helper de la manière suivante:
def alert_present?
begin
page.driver.browser.switch_to.alert
return true
rescue
return false
end
end
Et dans votre test, faites simplement:
click_link 'Delete'
expect(alert_present?).to eq(true)
Compte tenu de ce Javascript:
confirm('You have unsaved changes, do you want to continue?')
Pour Poltergiest j'ai trouvé ce qui suit fonctionner:
expect(page.driver.browser.modal_message).eq 'You have unsaved changes, do you want to contine?'
page.driver.browser.dismiss_confirm
page.driver.browser.accept_confirm
Il est difficile de tester le comportement de JavaScript. Mais si vous voulez vérifier le message de confirmation, vous pouvez peut-être tester l'attribut link uniquement sans Poltergeist:
it 'requests confirmation' do
visit user_path(user)
delete_link = find_link 'Delete', href: user_path(user)
expect(delete_link['data-confirm']).to eq 'Are you sure?'
end
Voici l'alternative:
it 'requests confirmation' do
visit user_path(user)
expect(page).to have_selector "a[data-confirm='Are you sure?'][href='#{user_path(user)}']", text: 'Delete'
end
Ce test ne peut pas vérifier si JS fonctionne correctement, mais il peut suffire dans la plupart des cas. (Et vite!)