Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save keeperofthenecklace/3389416 to your computer and use it in GitHub Desktop.
Save keeperofthenecklace/3389416 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:
##############################
#features/list_domiain.feature
@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
##############################################
#features/step_definitions/list_domain_steps.rb
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment