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