B Seven
B Seven

Reputation: 45943

How to check Capybara AJAX response from Rails?

Given a controller that responds with:

render json:{ errors: [] }

How to test an AJAX call for this response?

expect( page.body ).to have_content { errors:[] }.to_json

This does not work because it seems to be checking the page before it makes the AJAX call, not the response from the AJAX call.

Is there a way to check the body of the response from an AJAX call?

Upvotes: 0

Views: 1423

Answers (2)

Alexis
Alexis

Reputation: 4499

As far as I know, there's no easy way to do what you want.

When you test your AJAX features with Capybara, it is normally supposed that your AJAX request does something with your HTML page, and you're expected to check for changes on the page, not for the response of the request.

If you want to check the response directly, you should be able to test it separately by directly sending and checking your AJAX request from your test.

That said, you should be able to use some trick to achieve your initial goals. For example, you may want to try the execute_script method. Honestly though I don't think it's worth the effort.

Upvotes: 3

jayands
jayands

Reputation: 133

Thoughtbot has an excellent answer on how to do this:

First, add json-schema gem to the Gemfile:

# Gemfile
gem 'json-schema', groups: [:test]

Next, we load our custom matchers:

# spec/support/api/json_schema_matcher.rb
RSpec::Matchers.define :match_response_schema do |schema|
  match do |response|
    schema_directory = "#{Dir.pwd}/spec/support/api/schemas"
    schema_path = "#{schema_directory}/#{schema}.json"
    JSON::Validator.validate!(schema_path, response.body, strict: true)
  end
end

Then we define our schema (spec/support/api/schema/empty_errors.json):

{
  "type": "object",
  "required": ["errors"],
  "properties": {
    "errors": {
      "type": "array",
      "properties": {"items":[],"minItems": 0, "additionalItems": false}
    }
  }
}

Finally, we can add the matcher to our tests (TB uses RSpec, adjust accordingly):

  expect(response.status).to eq 200
  expect(response).to match_response_schema("empty_errors") # or whatever the bigger schema you define is called

Visit the JSON Schema site for the complete technical definition, but between the thoughtbot site and googling, you should be able to find out how to customize it to your needs. Good luck!

Upvotes: 1

Related Questions