kylewelsby
kylewelsby

Reputation: 4109

XHR request stubbing for Capybara JavaScript Testing

I'm trying to write a request_spec that tests the functionality of a page with a form that does a ajax autocomplete lookup and returns valid results to then activate the submit button.

I'm wondering if anybody has has the same issue and found someway or references to get this test passing.

Gemfile

gem 'rake', '0.8.7'
gem 'rails', '2.3.5'
group :test do
  gem "capybara", :git => "git://github.com/jnicklas/capybara.git"
  gem 'rspec', '1.3.1'
  gem 'rspec-core'
  gem 'rspec-rails', '1.3.2'
  gem 'webmock', '1.4.0'
end

HTML

    ...
    <fieldset>
      <label>Enter a Destination</label>
      <%= text_field_tag :reviewable_name, nil, :id => "destination_autocomplete", :class => 'textfield'  %>
      <ul>
        <li>
          <h3 class="disabled">
            <%= submit_tag "Read reviews", :id => "read_a_destination_review", :name => "agree", :class => "read_review", :disabled => false %>
          </h3>
        </li>
        <li class="or">or</li>
        <li>
          <h3>
            <%= submit_tag "Write review", :id => "write_a_destination_review", :name => "agree", :class => "write_review", :disabled => false %>
          </h3>
        </li>
      </ul>
    </fieldset>
    ...

JavaScript (jQuery 1.4.4)

  ...
  $("#hotel_autocomplete, #destination_autocomplete").autocomplete({
    source: function(request, response){
      $.getJSON('/ajax/search_reviewable?type=destination&q=' + request.term,
        function(results, status){
          if(status == 'success'){
            //make it regex safe
            var term = request.term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1");
            term = term.split(' ').join('|');
            for(var i = 0; i < results.length; i++){
              results[i].value = results[i].label;
              results[i].label = results[i].value.replace(new RegExp("("+term+")", "gi"),'<strong>$1</strong>');
            }
            response(results);
          }
        }
      );
    },
    minLength: 3,
    delay: 500,
    select: function( event, ui ) {...}
  });
  ...

JSON Response

/ajax/search_reviewable?type=destination&q=florida

[{"label":"Florida","id":124}]

RSpec Test

    it "should activate submit button", :js => true do
      stub_request(:get, "/ajax/search_reviewable/type=destination&q=florida").to_return(:body => %Q{[{"label":"Florida","id":124}]}, :headers => {"Content-Type" => "applicaation/json; charset=utf-8", "Accept" => "*/*"})
      fill_in("destination_autocomplete", :with => "florida")
      page.execute_script(%Q{$("#destination_autocomplete").trigger("keyup");})
      find(".ui-menu-item a").click
      # should post to '/review/new', :id => 124
      page.should have_content("Write a Destination Review")
    end

The test fails because this spec is unable to stub the XHR request within the JavaScript.

I thank you for your comments responses and help.

Upvotes: 4

Views: 3039

Answers (1)

kylewelsby
kylewelsby

Reputation: 4109

I manage to find a solution to this issue.

What was actually happening, The AJAX requested page /ajax/search_reviewable?type=destination&q=$1 was doing a Net::HTTP request to another service.

This request needed to be stubbed with the response I was needing.

stub_request(:get, ".../all_by_partial_name/Florida/").to_return({
  :body => %Q{[{"label":"Florida","id":124}]}, 
  :headers => {"Content-Type" => "applicaation/json; charset=utf-8", "Accept" => "*/*"}
})

After some major research, I found that you have to trigger a event in JavaScript to pass the test.

Source. Clicking AutoComplete Options Gist

Now the spec example looks like this

before(:each) do
  stub_request(:get, ".../all_by_partial_name/Florida/").to_return({
    :body => %Q{[{"label":"Florida","id":124}]}, 
    :headers => {"Content-Type" => "applicaation/json; charset=utf-8", "Accept" => "*/*"}
  })
end

it "should activate submit button and direct to new review", :js => true do
  fill_in("destination_autocomplete", :with => "florida")
  sleep 2
  page.execute_script(%Q{$(".ui-menu-item a:eq(0)").trigger("mouseenter").click();})
  find_button("write_a_destination_review").click
  page.should have_content("Write a Destination Review")
end

I hope this helps you with resolving your RSpec JQuery issues.

Upvotes: 0

Related Questions