I'm trying to test that a link to a destroy action throws a native browser confirm
box with the correct message.
The link is being generated using rails' link_to
:
link_to 'Delete', user_path, method: :delete, data: { confirm: "Are you sure?" }
And generates the following html:
<a data-confirm="Are you sure?" data-method="delete" href="/users/6" rel="nofollow">Delete</a>
The functionality is working correctly in the browser, but I want to test for it in my rspec
feature spec.
I'm trying to stub out the browser's confirm
function as described here and in this gist, however I can't get it to work.
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
Gives the following error from rspec
:
Failure/Error: expect(page.evaluate_script('window.confirmMsg')).to eq('Are you sure?')
expected: "Are you sure?"
got: nil
(compared using ==)
However, if I call a confirm
directly 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
Then the test passes.
Also clicking the Delete link will cause the test to fail, even if confirm
has been called directly for 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
Gives the same error from rspec
:
Failure/Error: expect(page.evaluate_script('window.confirmMsg')).to eq('Are you sure?')
expected: "Are you sure?"
got: nil
(compared using ==)
Why is the test failing? And, how can I test confirm dialogues correctly?
Context:
I'm running my tests from a Vagrant virtual machine, which is Ubuntu 12.04.4 LTS
and running ruby 2.1.2p95
.
My Gemfile.lock
shows that I have the following versions:
rails (4.1.4)
poltergeist (1.5.1)
capybara (2.4.1)
page.driver.browser.accept_js_confirms is deprecated. Instead use
page.accept_confirm do
click_link 'Delete'
end
Unfortunately, you cannot do this, because Poltergeist does work only in one window.
For that specific test you will need to use Selenium and this API:
page.driver.browser.switch_to.alert.accept
If you are concerned about wanting to run your tests headless, you can use Xvfb (X Virtual Framebuffer) like this:
Xvfb :1 -screen 0 1024x768x24+32
Alternatively you can also use capybara-webkit:
page.driver.browser.accept_js_confirms
page.driver.browser.reject_js_confirms
However, I have made the best experience using a mixture of (mostly) Poltergeist and Selenium where necessary.
To expand on the above, when using Selenium you can test the actual text of the confirm dialog using the following:
click_link 'Delete'
a = page.driver.browser.switch_to.alert
expect(a.text).to eq("Are you sure?")
a.accept
Also, just found a good test for whether the alert is present here: selenium 2.4.0, how to check for presence of an alert I slightly modified it, put in my spec_helper file as:
def alert_present?
begin
page.driver.browser.switch_to.alert
return true
rescue
return false
end
end
And then in your test just do:
click_link 'Delete'
expect(alert_present?).to eq(true)
Given this Javascript:
confirm('You have unsaved changes, do you want to continue?')
For Poltergiest I found the following to work:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With