破棄アクションへのリンクがネイティブブラウザのconfirm
ボックスに正しいメッセージを表示することをテストしようとしています。
リンクは、Railsのlink_to
を使用して生成されています。
link_to 'Delete', user_path, method: :delete, data: { confirm: "Are you sure?" }
そして、次のhtmlを生成します。
<a data-confirm="Are you sure?" data-method="delete" href="/users/6" rel="nofollow">Delete</a>
この機能はブラウザで正しく機能していますが、rspec
機能仕様でテストしたいと思います。
here および this Gist で説明されているように、ブラウザーのconfirm
関数をスタブ化しようとしていますが、動作させることができません。
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
rspec
から次のエラーが発生します。
Failure/Error: expect(page.evaluate_script('window.confirmMsg')).to eq('Are you sure?')
expected: "Are you sure?"
got: nil
(compared using ==)
ただし、page.execute_script
を介してconfirm
を直接呼び出す場合:
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
その後、テストに合格します。
また、[削除]リンクをクリックすると、confirm
が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
rspec
から同じエラーが発生します。
Failure/Error: expect(page.evaluate_script('window.confirmMsg')).to eq('Are you sure?')
expected: "Are you sure?"
got: nil
(compared using ==)
なぜテストが失敗するのですか?そして、どうすればダイアログを正しくテスト確認できますか?
コンテキスト:
Ubuntu 12.04.4 LTS
であるVagrant仮想マシンからテストを実行していてRuby 2.1.2p95
を実行しています。
私のGemfile.lock
は、次のバージョンがあることを示しています。
Rails (4.1.4)
poltergeist (1.5.1)
capybara (2.4.1)
page.driver.browser.accept_js_confirmsは非推奨です。代わりに使用する
page.accept_confirm do
click_link 'Delete'
end
残念ながら、あなたは これはできません ポルターガイストは1つのウィンドウでしか機能しないためです。
その特定のテストでは、SeleniumとこのAPIを使用する必要があります。
page.driver.browser.switch_to.alert.accept
テストをヘッドレスで実行する必要がある場合は、次のようにXvfb(X仮想フレームバッファー)を使用できます。
Xvfb :1 -screen 0 1024x768x24+32
または、capybara-webkitを使用することもできます。
page.driver.browser.accept_js_confirms
page.driver.browser.reject_js_confirms
しかし、私は必要に応じて(ほとんど)ポルターガイストとセレンの混合物を使用して最高の経験をしました。
上記を拡張するために、Seleniumを使用する場合、以下を使用して確認ダイアログの実際のテキストをテストできます。
click_link 'Delete'
a = page.driver.browser.switch_to.alert
expect(a.text).to eq("Are you sure?")
a.accept
また、ここにアラートが存在するかどうかの適切なテストが見つかりました: Selenium 2.4.0、アラートの存在を確認する方法 少し変更し、spec_helperファイルに次のように配置しました。
def alert_present?
begin
page.driver.browser.switch_to.alert
return true
rescue
return false
end
end
そして、あなたのテストでは、次のことを行ってください。
click_link 'Delete'
expect(alert_present?).to eq(true)
このJavascriptを考えると:
confirm('You have unsaved changes, do you want to continue?')
Poltergiestの場合、次のことが機能することがわかりました。
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
JavaScriptの動作をテストするのは難しいです。ただし、確認メッセージを確認したい場合は、ポルターガイストなしでのみリンク属性をテストしても問題ない場合があります。
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
代替手段は次のとおりです。
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
このテストでは、JSが正しく機能しているかどうかを確認できませんが、ほとんどの場合は十分です。 (そして速い!)