101

カピバラのあいまいさを解決するにはどうすればよいですか? 何らかの理由でページに同じ値のリンクが必要ですが、エラーが発生するためテストを作成できません

Failure/Error: click_link("#tag1")
     Capybara::Ambiguous:
       Ambiguous match, found 2 elements matching link "#tag1"

これが避けられないのは、設計上の理由によるものです。ツイート/タグが右側にあり、タグがページの左側にある Twitter ページを再作成しようとしています。そのため、同じページに同じリンク先のページが表示されることは避けられません。

4

9 に答える 9

149

私の解決策は

first(:link, link).click

それ以外の

click_link(link)
于 2012-11-14T21:08:15.653 に答える
77

このようなカピバラの動作は意図的なものであり、他のほとんどの回答で示唆されているように修正すべきではないと思います。

2.0 より前のバージョンの Capybara は、例外を発生させる代わりに最初の要素を返しましたが、後の Capybara のメンテナーは、それは悪い考えであり、発生させる方がよいと判断しました。多くの場合、最初の要素を返すと、開発者が返したいと思っていた要素が返されないことが判明しました。

ここで最も支持された回答では、 butの代わりにfirstorを使用することをお勧めします。allfind

  1. allそのfirstようなロケータを持つ要素がページに表示されるまで待たfindないでください
  2. all(...).firstfirst将来、そのようなロケーターを持つ別の要素がページに表示され、その結果、間違った要素が見つかる可能性があるという状況からあなたを保護しません

したがって、あいまいさの少ない別のロケーターを選択することをお勧めします。たとえば、ID、クラス、またはその他の css/xpath ロケーターで要素を選択して、1 つの要素のみが一致するようにします。


注意として、あいまいさを解決するときに私が通常役立つと考えるいくつかのロケーターを次に示します。

  • find('ul > li:first-child')

    first('ul > li')最初にページに表示されるまで待つよりも便利ですli

  • click_link('Create Account', match: :first)

    first(:link, 'Create Account').click少なくとも 1 つの [アカウントの作成] リンクがページに表示されるまで待つよりはましです。ただし、ページに 2 回表示されない一意のロケーターを選択する方がよいと思います。

  • fill_in('Password', with: 'secret', exact: true)

    exact: trueCapybara に完全一致のみを検索するように指示します。つまり、「パスワードの確認」は検索しません。

于 2013-10-15T08:12:18.483 に答える
28

上記のソリューションはうまく機能しますが、興味のある方は次の構文を使用することもできます。

click_link(link_name, match: :first)

詳細については、次を参照してください。

http://taimoorchangaizpucitian.wordpress.com/2013/09/06/capybara-click-link-different-cases-and-solutions/

于 2014-03-20T19:22:23.410 に答える
24

新しい答え:

次のようなものを試すことができます

all('a').select {|elt| elt.text == "#tag1" }.first.click

利用可能な Capybara 構文をより有効に利用する方法があるかもしれall("a[text='#tag1']").first.clickません。とは言っても、同じ、、 のテキストを持つ 2 つの<a>タグがあるというのは、そもそも少し奇妙な状況です。DOM の適切なセグメントを実行できるため、それらが異なる div の子である可能性はありますか。(HTML ソースを少し見ると役に立ちます)。idclassfind within


OLD ANSWER: (「#tag1」は、要素idに「tag1」が含まれていることを意味していると思いました)

どのリンクをクリックしますか? それが最初の場合(または問題ではない場合)、次のことができます

find('#tag1').click

そうでなければあなたができる

all('#tag1')[1].click

2 つ目をクリックします。

于 2012-10-30T05:52:04.473 に答える
11

次を使用して、最初のものを確実に見つけることができますmatch

find('.selector', match: :first).click

しかし、重要なことは、おそらくこれを実行したくないということです。なぜなら、重複出力コードの臭いを無視する脆弱なテストにつながるためです。これにより、失敗するはずのときに誤検知が発生し続ける可能性があります。要素ですが、テストは喜んで他の要素を見つけました。

より良い賭けは、使用することwithinです:

within('#sidebar') do
  find('.selector).click
end

これにより、Capybara の自動待機機能と自動再試行機能 ( を使用すると失われる) を活用しながら、見つけたい要素を確実に見つけることができfind('.selector').click、意図がより明確になります。

于 2015-11-05T23:17:26.847 に答える
10

ここで既存の知識体系に追加するには:

JS テストの場合、Capybara は 2 つのスレッド (1 つは RSpec 用、もう 1 つは Rails 用) と 2 つ目のプロセス (ブラウザー) を同期させておく必要があります。これは、ほとんどのマッチャーとノード検索メソッドで (構成された最大待機時間まで) 待機することによって行われます。

カピバラには、主に待機しないメソッドもありますNode#all。それらを使用することは、断続的に失敗することを仕様に伝えるようなものです。

受け入れられた答えは示唆してpage.first('selector')います。Node#firstこれはNode#all、少なくとも JS 仕様では望ましくありません。

つまり、次のように Capybara を構成Node#first すると待機します。

# rails_helper.rb
Capybara.wait_on_first_by_default = true

このオプションはCapybara 2.5.0で追加され、デフォルトでは false です。

アンドレイが述べたように、代わりに使用する必要があります

find('selector', match: :first)

またはセレクターを変更します。構成やドライバーに関係なく、どちらもうまく機能します。

さらに複雑なことに、古いバージョンの Capybara (または構成オプションが有効になっている) では、#findあいまいさを喜んで無視し、最初に一致したセレクターを返すだけです。これも、仕様が明確でなくなるため、あまり良くありません。これが、デフォルトの動作ではなくなった理由だと思います。詳細については既に説明済みであるため、ここでは省略します。

その他のリソース:

于 2016-03-03T19:52:58.173 に答える
5

この投稿により、「一致」オプションを使用して修正できます。

Capybara.configure do |config|
  config.match = :prefer_exact
end
于 2013-10-12T18:22:05.637 に答える
0

キュウリのあいまいなエラーを回避するため。

解決策 1

first("#tag1").click

解決策 2

Cucumber features/filename.feature --guess
于 2015-11-25T06:23:14.923 に答える