ページをロードした後、xhrによって返されたデータに基づいてさまざまなアイテムを実行および非表示および表示するコードがあります。
私の統合テストは次のようになります。
it "should not show the blah" do
page.find('#blah').visible?.should be_true
end
このテストが実行されるコンテキストで手動でページに移動すると、#blahはnot予想どおりに表示されます。 Capybaraはページの初期状態(この場合は見えない)を見て、DOMの状態を評価し、JSが実行される前にテストに失敗していると思われます。
はい、含む記述ブロックに:js => true
を設定します:)
どんなアイデアでも大歓迎です!ここに意図的な遅延を入れる必要がないことを望んでいます。
ここでのfind
ステートメントは暗黙的な待機を伴うものであるため、Capybaraは要素がページに表示されるまで待機しますが、表示されるまで待機しません。
ここでは、可視要素が表示されるまでCapybaraが待機するようにします。これは、visible
オプションを指定することで実現できます。
expect(page).to have_selector('#blah', visible: true)
試したことはありませんが、find
が常に表示される要素を待機するようにしたい場合は、ignore_hidden_elements
構成オプションも役立ちます。
これは私にとって完璧に機能する別の方法です:
find(:css, "#some_element").should be_visible
特に次のようなより複雑な検索の場合
find(:css, "#comment_stream_list li[data-id='#{@id3}']").should_not be_visible
要素が隠されていると断言します。
要素がページ上にあるが表示されていないことを確認する場合は、visible: false
は期待どおりに機能しません。私は少し困惑していました。
方法は次のとおりです。
# assert element is present, regardless of visibility
page.should have_css('#some_element', :visible => false)
# assert visible element is not present
page.should have_no_css('#some_element', :visible => true)
を使用して:
Ruby: Ruby 1.9.3dev (2011-09-23 revision 33323) [i686-linux]
Rails: 3.2.9
Capybara: 2.0.3
Railsアプリケーションがあります。このアプリケーションには、クリックするとAJAXリクエストを送信してJSレスポンスを返すリンクがあります。
リンクコード:
link_to("Send Notification", notification_path(user_id: user_id), remote: true, method: :post)
JSレスポンス(.js.hamlファイル)は、リンクが存在するページで次の非表示divを切り替える必要があります。
#notification_status(style='display:none')
js.hamlファイルの内容:
:plain
var notificationStatusContainer = $('#notification_status');
notificationStatusContainer.val("#{@notification_status_msg}");
notificationStatusContainer.show();
通知を送信し、Cucumber(cucumber-Rails gem with Capybara support)を使用して通知ステータスメッセージをユーザーに表示するシナリオをテストしていました
Id:notification_statusを持つ要素がステップ定義の成功応答で表示されることをテストしようとしていたため、次のステートメントを試しました:
page.find('#notification_status').should be_visible
page.should have_selector('#notification_status', visible: true)
page.should have_css('#notification_status', visible: true)
page.find('#notification_status', visible: true)
page.find(:css, 'div#notification_status', visible: true)
上記のいずれも機能せず、私のステップに失敗しました。上記の5つのスニペットのうち、最後の4つは次のエラーで失敗しました。
'expected to find css "#notification_status" but there were no matches. Also found "", which matched the selector but not all filters. (Capybara::ExpectationNotMet)'
次の文が正しく渡されたため、これは奇妙でした。
page.has_selector?('#notification_status')
実際、私は以下を使用してページソースを検査しました
print page.html
現れた
<div style='' id='notification_status'></div>
予想された。
最後に、このリンクを見つけました capybara asserting a elements of elements これは、要素の属性を生の方法で検査する方法を示しました。
また、Capybaraのドキュメントで目に見えるものを見つけましたか?メソッド( http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Element#visible%3F-instance_method )以下の情報:
Not all drivers support CSS, so the result may be inaccurate.
したがって、要素の可視性をテストするとき、カピバラの可視性の結果に依存しないという結論に達しましたか? CSSセレクターを使用し、リンクで提案されているソリューションを使用する場合のメソッド capybara assert element of attributes of element
私は次のことを思いつきました:
module CustomMatchers
def should_be_visible(css_selector)
find(css_selector)['style'].should_not include('display:none', 'display: none')
end
end
World(CustomMatchers)
使用法:
should_be_visible('#notification_status')
目に見える意味は明らかではありません
この失敗は、目に見えていると考えられているもの、またはドライバーの移植性がなく、文書化されていないものと見なされるものの誤解から生じる場合があります。いくつかのテスト:
HTML:
<div id="visible-empty" ></div>
<div id="visible-empty-background" style="width:10px; height:10px; background:black;"></div>
<div id="visible-empty-background-same" style="width:10px; height:10px; background:white;"></div>
<div id="visible-visibility-hidden" style="visibility:hidden;" >a</div>
<div id="visible-display-none" style="display:none;" >a</div>
Rackテストで不可視と見なされるのはインラインdisplay: none
のみです(セレクターを実行しないため、内部CSSではありません):
!all('#visible-empty', visible: true).empty? or raise
!all('#visible-empty-background', visible: true).empty? or raise
!all('#visible-empty-background-same', visible: true).empty? or raise
!all('#visible-visibiility-hidden', visible: true).empty? or raise
all('#visible-display-none', visible: true).empty? or raise
Poltergeistも同様の動作をしますが、内部CSSおよびJs style.display
操作を処理できます。
Capybara.current_driver = :poltergeist
!all('#visible-empty', visible: true).empty? or raise
!all('#visible-empty-background', visible: true).empty? or raise
!all('#visible-empty-background-same', visible: true).empty? or raise
!all('#visible-visibiility-hidden', visible: true).empty? or raise
all('#visible-display-none', visible: true).empty? or raise
Seleniumの動作はまったく異なります。空の要素を非表示にし、visibility-hidden
およびdisplay: none
を考慮する場合:
Capybara.current_driver = :Selenium
all('#visible-empty', visible: true).empty? or raise
!all('#visible-empty-background', visible: true).empty? or raise
!all('#visible-empty-background-same', visible: true).empty? or raise
all('#visible-visibiility-hidden', visible: true).empty? or raise
all('#visible-display-none', visible: true).empty? or raise
もう1つの一般的な問題は、visible
のデフォルト値です。
false
でした(both可視および不可視要素を参照)、true
ですCapybara.ignore_hidden_elements
オプションによって制御されます。参照 。
完全に実行可能なテスト 私のGitHubで 。
this post をご覧ください。これは、すべてのajaxリクエストが完了するまで待機するためのサンプルメソッドを提供します。
def wait_for_ajax(timeout = Capybara.default_wait_time)
page.wait_until(timeout) do
page.evaluate_script 'jQuery.active == 0'
end
end
'should'は非推奨の構文であるため、受け入れられた答えは少し時代遅れです。最近では、expect(page).not_to have_css('#blah', visible: :hidden)
の行に沿って何かをする方が良いでしょう。
ここでの他の答えは、要素を「待つ」ための最良の方法です。しかし、作業中のサイトではこれが機能しないことがわかりました。基本的に、クリックする必要がある要素は、その背後の関数が完全にロードされる前に表示されていました。これはほんの一瞬ですが、テストが非常に速く実行され、ボタンをクリックしても何も起こらないことがわかりました。私はこの仮のブール式を実行することでそれを回避することができました:
if page.has_selector?('<css-that-appears-after-click>')
puts ('<Some-message-you-want-printed-in-the-output>')
else
find('<css-for-the-button-to-click-again>', :match == :first).trigger('click')
end
基本的に、表示されるべきものを探すためにカピバラのデフォルトの待機時間を使用し、存在しない場合はクリックを再試行します。
繰り返しますが、should have_selector
メソッドを最初に試す必要がありますが、うまくいかない場合はこれを試してください