Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save e0da/5580042 to your computer and use it in GitHub Desktop.
Save e0da/5580042 to your computer and use it in GitHub Desktop.
Testing REST APIs with Cucumber and Rack::Test

First attempting to use Capybara directly, you will ran into issues when trying to set HTTP header. Using Basic HTTP Authentication requires that we needed to set the header. Also we need to set the Content-Type and Accept headers to ensure that Rails handles the input and output correctly. When using Rack, Capybara delegates request and response handling down to Rack::Test. So I used Rack::Test directly in my step definitions, and it works. Rack::Test has a module called Rack::Test::Methods that can be mixed into a class to provide it with methods for get, post, put, delete as well as last_request, last_response, header and more. I mixed Rack::Test::Methods into the Cucumber world at the top of our API steps file like so:

World(Rack::Test::Methods)
Given /^I am a valid API user$/ do
@user = Factory(:user)
authorize(@user.email, @user.password)
end
Given /^I send and accept XML$/ do
header 'Accept', 'text/xml'
header 'Content-Type', 'text/xml'
end
Given /^I send and accept JSON$/ do
header 'Accept', 'application/json'
header 'Content-Type', 'application/json'
end
When /^I send a GET request for "([^\"]*)"$/ do |path|
get path
end
When /^I send a POST request to "([^\"]*)" with the following:$/ do |path, body|
post path, body
end
When /^I send a PUT request to "([^\"]*)" with the following:$/ do |path, body|
put path, body
end
When /^I send a DELETE request to "([^\"]*)"$/ do |path|
delete path
end
Then /^the response should be "([^\"]*)"$/ do |status|
last_response.status.should == status.to_i
end
Then /^the XML response should be a "([^\"]*)" array with (\d+) "([^\"]*)" elements$/ do |tag, number_of_children, child_tag|
page = Nokogiri::XML(last_response.body)
page.xpath("//#{tag}/#{child_tag}").length.should == number_of_children.to_i
end
Then /^the JSON response should be an array with (\d+) "([^\"]*)" elements$/ do |number_of_children, name|
page = JSON.parse(last_response.body)
page.map { |d| d[name] }.length.should == number_of_children.to_i
end
@api
Feature: List domains
As an API client
In order to do things with domains
I want to retrieve a list of domains
Scenario: retreive all domains as XML
Given I am a valid API user
And I send and accept XML
And I have 1 domain with 5 "A" records
When I send a GET request for "/domains"
Then the response should be "200"
And the XML response should be a "domains" array with 1 "domain" elements
Scenario: retreive all domains as JSON
Given I am a valid API user
And I send and accept JSON
And I have 1 domain with 5 "A" records
When I send a GET request for "/domains"
Then the response should be "200"
And the JSON response should be an array with 1 "domain" elements
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment