Ruby on Rails Tutorial (13)

昨晩の続き、ということにて。

8.3.3 Counterpoint: RSpec custom matchers

例えば以下な部分とか
features/step_definitions/authentication_steps.rb

Then /^he should see an error message$/ do
  page.should have_selector('div.alert.alert-error')
end

あるいは以下な部分とかの
spec/requests/authentication_spec.rb

  describe "signin" do
    before { visit signin_path }

    describe "with invalid information" do
      before { click_button "Sign in" }

      it { should have_selector('title', text: 'Sign in') }
      it { should have_selector('div.alert.alert-error', text: 'Invalid') }

should have_selector なソレを should have_error_message('Invalid') と書ければ分かりやすいよね的カスタマイズが云々、らしい。
あるいは signin な以下の記述とかも

      before do
        fill_in "Email",    with: user.email
        fill_in "Password", with: user.password
        click_button "Sign in"
      end

手続きとして括り出せれば云々ですね。これを spec/support/utilities.rb に以下のように書けば OK とのこと。

include ApplicationHelper

def valid_signin(user)
  fill_in "Email",    with: user.email
  fill_in "Password", with: user.password
  click_button "Sign in"
end

RSpec::Matchers.define :have_error_message do |message|
  match do |page|
    page.should have_selector('div.alert.alert-error', text: message)
  end
end

こうすることで

      it { should have_selector('div.alert.alert-error', text: 'Invalid') }

      it { should have_error_message('Invalid') }

と書けるし

      before do
        fill_in "Email",    with: user.email
        fill_in "Password", with: user.password
        click_button "Sign in"
      end

      before { valid_signin(user) }

と書けるとのこと。
週末で最後までなんとかできるのかどうか。とりあえずここから先の exercise はスルーの方向でヤッツケてみます。

盛り込んでなかった

で、盛り込んで試験実行してみたんですが NoMethodError になるな。あ、spec/support/utilities.rb だった。再度 spec/helpers/utilities.rb に盛り込んで試験 green 終了を確認しております。

  describe "signin" do
    before { visit signin_path }

    describe "with invalid information" do
      before { click_button "Sign in" }

      it { should have_selector('title', text: 'Sign in') }
      it { should have_error_message('Invalid') }

あるいは spec/requests/authentication_steps.rb に盛り込んでみたんですが

    Then he should see an error message        # features/step_definitions/authentication_steps.rb:9
      undefined method `has_error_message?' for #<Capybara::Session> (NoMethodError)
      ./features/step_definitions/authentication_steps.rb:10:in `/^he should see an error message$/'
      features/signing_in.feature:6:in `Then he should see an error message'

て言われるな。custom matcher が cucumber な世界では読みこめていない模様。どうも cucumber では若干作法が異なるらしい。
support/general_helpers.rb を作って以下を盛り込んでみました。

module GeneralHelpers
  def have_error_message(message)
    have_selector('div.alert.alert-error', text:message)
  end
end

World(GeneralHelpers)

を、試験 green になりました。成程。

もう少し

以下を云々。

$ git commit -a -m "Finish sign in"
$ git checkout master
$ git merge sign-in-out --no-ff
$ git push origin master

あるいは heroku 方面にも。

$ git push heroku
$ heroku run rake db:migrate

以下も、とのこと。

$ heroku run console
>> User.all.each { |user| user.save(validate: false) }

あらら、動かんな。これは先方の問題なのかどうなのか。