Created
June 24, 2010 17:55
-
-
Save guenter/451730 to your computer and use it in GitHub Desktop.
Snippets for testing REST APIs with Cucumber and friends
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Feature: API | |
In order to use the service from third party apps | |
As a user | |
I want to be able to use an API | |
Background: | |
Given a user exists # Pickle | |
And I login as the user using basic auth | |
Scenario Outline: Get a ticket | |
Given a ticket exists with title: "The network is down!", description: "Nothing works!" # Pickle | |
When I GET "/tickets/{the ticket}" using <format> | |
Then the response code should be 200 | |
And I should see the following ticket in <format> format | |
| title | description | | |
| The network is down! | Nothing works! | | |
Examples: | |
| format | | |
| JSON | | |
| XML | | |
Scenario: Accept a ticket | |
Given a ticket exists | |
When I POST to "/tickets/{the ticket}/accept" using JSON | |
Then the response code should be 200 | |
And the ticket should be accepted # Pickle | |
And the user should be the ticket's engineer # Pickle | |
Scenario: Requeue a ticket to an invalid technology | |
Given a ticket exists | |
When I POST to "/tickets/{the ticket}/requeue" using JSON | |
""" | |
{"ticket":{"technology":"Wireless Power"}} | |
""" | |
Then the response code should be 422 | |
And the ticket's status should not be "requeued" # Pickle | |
And the response body should be | |
""" | |
[["technology","is invalid"]] | |
""" | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def decode_api_response_as(model_name, format) | |
if format == 'JSON' | |
decoded = ActiveSupport::JSON.decode(response.body) | |
if decoded.is_a?(Array) | |
decoded.map { |inst| inst[model_name] } | |
else | |
decoded[model_name] | |
end | |
elsif format == 'XML' | |
decoded = Hash.from_xml(response.body) | |
decoded[model_name] || decoded[model_name.pluralize] | |
else | |
raise "Unsopported response format: #{format}" | |
end | |
end | |
Given /^I login as #{capture_model} using basic auth$/ do |model_name| | |
user_name = model(model_name).email | |
password = 't35tp455w0rd' | |
basic_auth(user_name, password) | |
end | |
When /^I (GET|POST|PUT|DELETE)(?: to)? "(.+)" using (JSON|XML)$/ do |method, path, format, *body| | |
method = method.downcase.to_sym | |
# Replace {the model} with the corresponding id | |
path = path.gsub(/\{#{capture_model}\}/) { |match| model!($1).to_param } | |
format = format.downcase | |
# HAxx to make this arg. optional | |
body = body.first | |
header('Accept', "application/#{format}") | |
header('Content-Type', "application/#{format}") | |
visit(path, method, body) | |
end | |
Then /^the response code should be (\d+)$/ do |response_code| | |
response.response_code.should == response_code.to_i | |
end | |
Then /^the response body should be$/ do |body| | |
response.body.should == body | |
end | |
Then /^the "([^\"]*)" header should be "(.*)"$/ do |key, value| | |
response.headers[key].should == value | |
end | |
Then /^I should see the following #{capture_plural_factory} in (JSON|XML) format$/ do |plural_factory, format, table| | |
content_type = "application/#{format.downcase}" | |
model_name = plural_factory.singularize.gsub(' ', '_') | |
response_data = decode_api_response_as(model_name, format) | |
# Check content type | |
response.content_type.should == content_type | |
attributes = table.headers | |
expected = table.rows.sort | |
actual = response_data.map { |row| row.values_at(*attributes).map(&:to_s) }.sort | |
actual.should == expected | |
end | |
Then /^I should see the following #{capture_factory} in (JSON|XML) format$/ do |singular_factory, format, table| | |
content_type = "application/#{format.downcase}" | |
model_name = singular_factory.gsub(' ', '_') | |
response_data = decode_api_response_as(model_name, format) | |
# Check content type | |
response.content_type.should == content_type | |
attributes = table.headers | |
expected = table.rows.first | |
actual = response_data.values_at(*attributes).map(&:to_s) | |
actual.should == expected | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment