23296


# 前提・実現したいこと

rails+capybara(+Poltergeist)でスクレイピングをしようとしています。  
aタグをクリックして次のページに移動する動きしようとしているのですがうまく動きません。

# 発生している問題・エラーメッセージ

[code]

    Failures:
    
      1) test next20
         Failure/Error: click_on "次の20件"
    
         Capybara::ElementNotFound:
           Unable to find link or button "次の20件"
         # ~/vendor/bundler/ruby/2.3.0/gems/capybara-2.6.2/lib/capybara/node/finders.rb:43:in `block in find'
         # ~/vendor/bundler/ruby/2.3.0/gems/capybara-2.6.2/lib/capybara/node/base.rb:84:in `synchronize'
         # ~/vendor/bundler/ruby/2.3.0/gems/capybara-2.6.2/lib/capybara/node/finders.rb:32:in `find'
         # ~/vendor/bundler/ruby/2.3.0/gems/capybara-2.6.2/lib/capybara/node/actions.rb:13:in `click_link_or_button'
         # ~/vendor/bundler/ruby/2.3.0/gems/capybara-2.6.2/lib/capybara/session.rb:686:in `block (2 levels) in <class:Session>'
         # ~/vendor/bundler/ruby/2.3.0/gems/capybara-2.6.2/lib/capybara/dsl.rb:51:in `block (2 levels) in <module:DSL>'
         # ./test3.rb:30:in `block (3 levels) in <top (required)>'
         # ~/vendor/bundler/ruby/2.3.0/gems/capybara-2.6.2/lib/capybara/session.rb:290:in `within'
         # ~/vendor/bundler/ruby/2.3.0/gems/capybara-2.6.2/lib/capybara/dsl.rb:51:in `block (2 levels) in <module:DSL>'
         # ./test3.rb:28:in `block (2 levels) in <top (required)>'
    
    Finished in 7.06 seconds (files took 0.4783 seconds to load)
    1 example, 1 failure
    
    Failed examples:
    
[/code]

# ソースコード（test3.rb）

[code]

    require 'capybara/rspec' 
    require 'capybara/poltergeist' 
    require 'capybara/dsl'
    
    Capybara.javascript_driver = :poltergeist 
    Capybara.register_driver :poltergeist do |app| 
      Capybara::Poltergeist::Driver.new(app, { 
                        js_errors: false, 
                        timeout: 1000, 
                        debug: true, 
                        phantomjs_options: [ 
                                  '--load-images=no', 
                                  '--ignore-ssl-errors=yes', 
                                  '--ssl-protocol=any']}) 
    end
    
    Capybara.configure do |config| 
        config.run_server = false 
        config.default_driver = :poltergeist 
        config.app_host = 'http://www.mansion-review.jp/prefecture/20.html' 
    end
    
    describe "test", :type => :feature do 
      subject{ page } 
      before { visit('/') }
    
      it "next20", js: true do 
        within ('#saleHistorySoubaBlock') do 
          have_text "次の20件" 
          click_on "次の20件" 
        end 
      end 
    end
    
[/code]

# 補足情報

  * capybara (2.6.2)
  * globalid (0.3.6)
  * rails (4.2.6)
  * rspec-rails (3.4.2)

# 追記

広く意見を求めたい為,Stack Overflowとteratailにて同様の質問をしております。  
解決しましたら、両方にて共有したいと思いますので、ご容赦ください。

* * *

コメントは改行できないのですね、教えていただきありがとうございます。  
エラーメッセージが若干違うようですので、貼っておきます。

# エラーメッセージ

[code]

    Failures:
    
      1) test next20
         Failure/Error: click_on "次の20件"
    
         Capybara::ElementNotFound:
           Unable to find link or button "次の20件"
         # ~/vendor/bundler/ruby/2.3.0/gems/capybara-2.6.2/lib/capybara/node/finders.rb:43:in `block in find'
         # ~/vendor/bundler/ruby/2.3.0/gems/capybara-2.6.2/lib/capybara/node/base.rb:84:in `synchronize'
         # ~/vendor/bundler/ruby/2.3.0/gems/capybara-2.6.2/lib/capybara/node/finders.rb:32:in `find'
         # ~/vendor/bundler/ruby/2.3.0/gems/capybara-2.6.2/lib/capybara/node/actions.rb:13:in `click_link_or_button'
         # ~/vendor/bundler/ruby/2.3.0/gems/capybara-2.6.2/lib/capybara/session.rb:686:in `block (2 levels) in <class:Session>'
         # ~/vendor/bundler/ruby/2.3.0/gems/capybara-2.6.2/lib/capybara/dsl.rb:51:in `block (2 levels) in <module:DSL>'
         # ./test3.rb:31:in `block (4 levels) in <top (required)>'
         # ~/vendor/bundler/ruby/2.3.0/gems/capybara-2.6.2/lib/capybara/session.rb:290:in `within'
         # ~/vendor/bundler/ruby/2.3.0/gems/capybara-2.6.2/lib/capybara/dsl.rb:51:in `block (2 levels) in <module:DSL>'
         # ./test3.rb:29:in `block (3 levels) in <top (required)>'
         # ~/vendor/bundler/ruby/2.3.0/gems/capybara-2.6.2/lib/capybara/session.rb:290:in `within'
         # ~/vendor/bundler/ruby/2.3.0/gems/capybara-2.6.2/lib/capybara/dsl.rb:51:in `block (2 levels) in <module:DSL>'
         # ./test3.rb:28:in `block (2 levels) in <top (required)>'
    
    Finished in 7.67 seconds (files took 1.44 seconds to load)
    1 example, 1 failure
    
    Failed examples:
    
[/code]

# 修正部分

[code]

    describe "test", :type => :feature do
      subject{ page }
      before { visit('/') }
    
      it "next20", js: true do
        within first('#resultBlock div p') do
          within all('a').last do
            should have_text '次の20件'
            click_on "次の20件"
          end
        end
      end
    end
    
[/code]


CC BY-SA 3.0
2016-03-20T03:47:12.763
23290
2016-03-22T05:15:12.873
2016-03-22T04:42:07.757
8000
14858
question
ruby-on-rails ruby capybara phantomjs poltergeist
capybara（+ Poltergeist）でaタグがclick_on出来ない


そのページをブラウザで見てみましたが、エラーメッセージの通り、 `#saleHistorySoubaBlock` の中に `次の20件`
はありません。というか、`#saleHistorySoubaBlock` は空っぽの `<div>` ですね。

それなら `click_on` じゃなくて `have_text`
でエラーになりそうですが、これは「対象が指定した文字列を含むかどうかを検査するMatcher」を返すメソッドで、呼びだしただけでは何も起きません。RSpecの
`should` や `expect(...).to` に渡して初めて実際の検査が行われます。

例えば次のようにすると、`should have_text` の時点でFailureになります。

[code]

    describe "test", :type => :feature do 
      subject{ page } 
      before { visit('/') }
    
      it "next20", js: true do 
        within ('#saleHistorySoubaBlock') do 
          should have_text "次の20件" 
          click_on "次の20件" 
        end 
      end 
    end
    
[/code]

* * *

例えば `<a id="hoge">link text</a>` というリンクがあり、ここで `within('#hoge')` とすると、

  * `should have_text 'link text'`： **そのリンクの中に** `link text` という文字列を含む  
⇒ OK

  * `click_on 'link text'`： **そのリンクの中で** `link text` と書かれたリンク・ボタンをクリック  
⇒ `<a id="hoge">link text</a>` の中にリンク・ボタンは存在しないのでエラー

となります。それ自身をクリックするという意味にはなりません。

withinで選択した要素自体をクリックする方法はちょっとわからなかったので、have_textも省略してこんな感じでいかがでしょう。

[code]

    describe "test", :type => :feature do 
      subject{ page } 
      before { visit('/') }
    
      it "next20", js: true do 
        within ('#resultBlock div p') do 
          first(:link, "次の20件").click
          # あるいは
          # click_on "次の20件", :match => :first
        end 
      end 
    end
    
[/code]

一応firstと指定していますが、capybara2.6.2で試す限りでは単にclick_onとだけ書いても最初にマッチしたものをクリックしてくれるようですね。

参考

  * [Capybaraでクリックできない場合の対処法 - harublog](http://hrt0kmt.hatenablog.com/entry/2015/11/17/210904)
  * [How to click first link in list of items after upgrading to Capybara 2.0? - Stack Overflow](https://stackoverflow.com/questions/14513377/how-to-click-first-link-in-list-of-items-after-upgrading-to-capybara-2-0)


CC BY-SA 3.0
2016-03-20T07:47:03.470
23296
2016-03-22T05:15:12.873
2017-05-23T12:38:55.250
-1
8000
23290
answer