19

そのページをテストしようとしています<title>My Title</title>:

# spec/features/reports_spec.rb
require 'spec_helper'

feature "Archive Management" do
  subject { page }

  describe "Index Page" do
    before(:all) { 10.times { FactoryGirl.create(:randomreport) } }
    after(:all) { Report.delete_all }

    describe "when no search terms present" do
      before { visit reports_path }

      it { should have_selector('title', text: 'My Title') } # <= Fails w/Capybara 2.0
      it { should have_selector('title') }                   # <= passes
      it { should have_text('My Title') }                    # <= passes
      it { should have_selector('h2', text: "Welcome") }     # <= passes
    end
  end
end

エラーメッセージ:

 Failure/Error: it { should have_selector('title', text: base_title) }
 Capybara::ExpectationNotMet:
   expected to find css "title" with text "My Title" but there were no matches. Also found "", which matched the selector but not all filters.

私は痛いほど明白なことを見落としていることを知っていますが、それが何であるかを理解できませんか? <title>タグは「セレクター」と見なされなくなりましたか?! ? または...?!?

編集(デバッガ情報)

@shioyama が巧みに提案したようにデバッガーにドロップダウンすると、page.body に含まれていることが明らかです<title>My Title</title>。同じ page.body が含まれており<h2>Welcome to My Title Project</h2>、渡されます!

<title>...</title>タグを見つけたように見えますが、その中にはありませんMy Title。しかしMy Title、ページ内<a href=\"/\" class=\"brand\">My Title</a>および/または内の後半で見つかります<h2>Welcome to The My Title Project</h2>:

(rdb:1) p page
#<Capybara::Session>
(rdb:1) p page.body
"<!DOCTYPE html>\n<html>\n<head>\n<title>My Title</title>\n
<meta content='research, report, technology' name='keywords'>\n<meta 
content='Some Project' name='description'>\n<link href=\"/assets/application.css\"
...
</head>\n<body>\n<header class='navbar navbar-fixed-top 
navbar-inverse'>\n<div class='navbar-inner'>\n<div class='container'>\n
<a href=\"/\" class=\"brand\">My Title</a>\n<div class='pull-right'>\n
<ul class='nav'>\n<li><a href=\"/about\">About</a></li>\n<li><a href=\"/help\">Help</a>
</li>\n</ul>\n<form accept-charset=\"UTF-8\" action=\"/reports\" 
class=\"navbar-search\" method=\"get\"><div style=\"margin:0;padding:0;display:inline\">
<input name=\"utf8\" type=\"hidden\" value=\"&#x2713;\" /></div>\n
<input class=\"search-query\" id=\"query\" name=\"query\" 
placeholder=\"Search\" type=\"text\" />\n</form>\n\n</div>\n</div>\n</div>\n</header>\n\n
<div class='container'>\n<div class='hero-unit center'>\n<h1>My Title</h1>\n
<h2>Welcome to The My Title Project</h2>\n<p>Lorem ipsum dolor sit amet, consectetur 
adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
...

have_selector?('title', text: ...) が失敗する理由を理解するために、デバッガーで他に何を試すことができますか?

では、Capybara 2.0 でタイトルをテストする適切な方法は何ですか?

4

6 に答える 6

35

Capybara 2.0 にアップグレードしたときに同じ問題が発生し、次のカスタム RSpec マッチャーを使用してそれらを解決することができましたCapybara.string

仕様/サポート/utilities.rb

RSpec::Matchers::define :have_title do |text|
  match do |page|
    Capybara.string(page.body).has_selector?('title', text: text)
  end
end

さて、仕様ファイルでsubject { page }、次を使用できます。

it { should have_title("My Title") }
it { should_not have_title("My Title") }

余談ですが、この質問に関する会話は、この回答にたどり着くのに非常に役立ちました。ありがとうございます!

更新 1:

カスタム RSpec マッチャーを作成したくない場合は、ユーザーdimuchによるこの StackOverflow の回答のおかげで、非表示の DOM 要素をテストするために( aliased ) を直接呼び出すことができることがわかりました。have_selectorpage.sourcepage.body

it "should show the correct title" do
  page.source.should have_selector('title', text: 'My Title')
end

またはどこでsubject { page }

its(:source) { should have_selector('title', text: 'My Title') }

更新 2:

Capybara 2.1 から、組み込みのhave_title/has_title?マッチャーがあり、この回答でカスタム RSpec マッチャーの必要性がなくなりました。さらに、its(:source) { ... }Update 1 で説明されているテストは、Capybara 2.1 では壊れているようです。have_title/が期待どおりに機能することを確認したhas_title?ので、アップグレードを計画している場合は、次の構文を使用することをお勧めします。

時期subject { page }

it { should have_title("My Title") }
it { should_not have_title("My Title") }

/ブロックexpect内で構文を使用する場合:itscenario

expect(page).to have_title("My Title")
expect(page).to_not have_title("My Title")
于 2012-12-07T01:49:16.577 に答える
1

ここには、次の 2 つの問題が考えられます。

  1. <title>タグはページにありますが、テキストはタグ内ではなく、ページのMy Title別の場所にあります。これは、他のテストがパスする理由を説明します。<title>ページにタグがあるのでhave_selector('title')パスMy Titleし、ページにテキストがあるのでhave_text(base_title)パスします。
  2. <title>タグにはテキストと他のMy Title何かが含まれており、表示される結果も説明<title>されます。ページにタグがあるのでhave_selector('title')合格し、テキストがあるMy Titleので合格しますhave_text(base_title)が、textオプションhave_selectorは厳密であるため、正確に等しくない文字列が見つかった場合は失敗しますMy Title

xpath セレクターを使用して、これら 2 つの可能性のうち後者を確認できますshould have_xpath("//title[contains(.,'#{base_title}')]")。それが成功した場合、タイトル テキストの周りに空白や改行が含まれている可能性がありますhave_selector(それらは無視されたと思っていましたが、間違っている可能性があります)。

それが役立つことを願っています。

于 2012-11-26T23:08:15.277 に答える
0

これにはすでに受け入れられている回答があることは知っていますが、それだけの価値があるため、より少ないコード行で次のことができます。

title = first("head title").native.text
expect(title).to == "What you expect it to match"

これにより、ネイティブ ドライバー要素にアクセスできます。さらに、Capybara 2.0 は目に見えないテキストを無視するため (タイトルはブラウザ以外には見えない)、このケースを満たすにはこれ (または同様の回避策) が必要です。( https://github.com/jnicklas/capybara/issues/863を参照)

于 2013-04-15T14:50:30.267 に答える