4

CapybaraHaveSelectorは RSpecexpectで期待どおりに動作しません。私は Capybara と RSpec を初めて使用するので、これは RSpec または Capybara に関する私の誤解であるか、または Capybara (バージョン 2.0.2) の欠陥である可能性があります。私の間違いを理解するか、バグレポート/機能リクエストを作成するのを手伝ってください.

私のRSpecで私は書いた:

expect { click('.special-div .submit') }.to have_css('.submitted')

これは機能的に同等であると予想していました

click('.special-div .submit')
page.should have_css('.submitted')

そうではありません。代わりに、マッチャーhave_cssは、proc オブジェクトを呼び出した結果ではなく、proc オブジェクトの文字列変換に対して照合を試みます。(つまり、click('.special-div .submit')決して実行されません。)

カピバラの振る舞いは次のとおりです。

  • かなり合理的
  • Capybara に欠けている機能の例
  • カピバラ 2.0.2 のバグ
  • 他の何か?

expect {}また、上記の 2 行バージョンを使用することで明らかにやりたいことを実行できますが、私たちのチームは で標準化しようとしexpect {}ています。

編集

私は作業中のコードを継承したので、Andrey Botalov が指摘したように、それclickが Capybara の標準部分ではないことに気づきませんでした。そうあるべきだと思われますが、これもclickすでに他の用途で多用されているため、Capybara がさらに別の定義を追加しない方がよい場合があります。

一部の人々は懐疑的であるように見えるので、このコードが正常に機能していることを保証させてください:

click('.special-div .submit')
page.should have_css('.submitted')

について疑問に思っている人にとってhave_css()は、これが の RSpec マジックですhas_css?。について疑問に思っている人のためclickに、私のプロジェクトでは、誰かが次のように便利にclick関数を作成しました:

  def click(css)
    page.execute_script("$('#{css}').first().trigger('click');")
  end

なんで?明らかな代替手段がどれも機能しなかったためです。

click_on('.special-div .submit')  # Fails because click_on does not take CSS
# Cannot use click_button() because we are clicking on a <div>
find('.special-div .submit').click # Raises exception because there are more than one
first('.special-div .submit').click # Fails because the div is not visible

続けて、@zetetic が尋ねた

expect(click('.special-div .submit')).to have_css('.submitted')

動作します。いいえ、私たちはまだ RSpec 2.9 を使用しており、その構文は 2.11 で導入されたので機能しませんが、アップグレードしてもclickオブジェクトを返さないため機能しません。click2.11 にアップグレードして returnに変更すればおそらく動作するでしょうpage

4

2 に答える 2

2

いくつかの問題があり、expect { click('.special-div .submit') }.to have_css('.submitted')それが私がとても混乱した理由です。

私にとって最も紛らわしいのは、RSpec のexpect {...}.to ...構文です。この構文により、マッチャーが でコードを実行し{}、マッチャーを結果などに適用するようになると思いました。を考えると理にかなっているようです:

expect { something }.to raise_error(SomeError)

これは一般的に正しくないことがわかりました。特定のマッチャーのみが、「実際の」(「expect」と「.to」の間にあるもの) が a であると想定しProc、それを呼び出します。ほとんどのマッチャーは、「実際の」オブジェクトがオブジェクトであることを期待しています。そう:

expect { 1 + 1 }.to eq(2)

Procaと aを比較しようとすると、例外が発生しFixnumます。

したがって、カピバラのhas_css?マッチャーは、「実際の」has_selector?Proc. それが本当に私の主な質問でした。それで、カピバラはフックから外れました。

私の混乱をさらに助長したのは、Capybara が役立つように DSL を提供しているため、私の例 has_css?では が と同等であり、が に対して魔法のように動作し続けることpage.has_css?を期待したことです。have_css(css)page

テストを書くためのより良い方法に進みます。@deviousdodoはほとんど正しいので、その答えにボーナスを与えています。私が欲しかったのは

expect {
  click('.special-div .submit') 
}.to change { page.has_css?('.submitted') }.from(false).to(true)

実は、元の質問の範囲を超えていますが、私が本当に欲しいのは

expect { 
  click('.special-div .submit')
  page.should have_css('.submitted')
}.to change { Click.count }.by 1

これが必要な理由は、最もチェックしたいのは、クリックがデータベースに記録される (Click.countインクリメント) ことですが、クリックによってトリガーされた AJAX 呼び出しが終了するのを待たなければならないためhas_css?です。

于 2013-04-08T01:51:29.627 に答える
1

編集:答えの最初の部分が間違っていたので、変更しました。

私は最初にこのコードと言いました

expect { click('.special-div .submit') }.to have_css('.submitted')

次と同等です。

click('.special-div .submit').should have_css('.submitted')

しかし、渡された procexpectは実際には評価されないため、これは正しくありません (詳細については @OldPro の回答を読むことができます)。

解決策は次のexpect changeとおりです。

expect {
  click_button('Button label')
}.to change { page.has_css?('.submitted') }.from(false).to(true)

詳細については、rspec の Web サイトを参照してください。

于 2013-04-06T23:11:26.310 に答える