Last active
November 30, 2018 19:19
-
-
Save bosskovic/091a8dfbfa41d5e9a49a to your computer and use it in GitHub Desktop.
Developing rails REST API with Cucumber
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
Given /^I send and accept JSON$/ do | |
header 'Accept', 'application/json' | |
header 'Content-Type', 'application/json' | |
end | |
Given /^I send and accept JSON using version (\d+) of the (\w+) API$/ do |version, model| | |
header 'Accept', "application/vnd.#{model}+json; version=#{version}" | |
header 'Content-Type', 'application/json' | |
end | |
When(/^I authenticate via auth_token "([^"]*)" and email "([^"]*)" in header$/) do |auth_token, email| | |
header('X-User-Email', email) | |
header('X-User-Token', auth_token) | |
end |
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
When (/^I authenticate as (user|admin)$/) do |user_type| | |
@authenticated_user = find_user_by_type(user_type) | |
token = @authenticated_user.authentication_token | |
email = @authenticated_user.email | |
steps %{ | |
When I authenticate via auth_token "#{token}" and email "#{email}" in header | |
} | |
end |
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
# features/support/custom_env.rb | |
require 'json_spec/cucumber' | |
def last_json | |
last_response.body | |
end |
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: Fruit list | |
In order to make a great smoothie | |
I need some fruit. | |
Scenario: List fruit | |
Given the system knows about the following fruit: banana, strawberry | |
When the client requests GET /fruits | |
Then the response status should be "OK" | |
And the JSON response at "users" should have 2 fruits | |
And fruits array should include banana and strawberry with name and color | |
And the response should include last href |
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
# source: http://media.pragprog.com/titles/hwcuc/code/rest_web_services/00/features/fruit_list.feature | |
Feature: Fruit list | |
In order to make a great smoothie | |
I need some fruit. | |
Scenario: List fruit | |
Given the system knows about the following fruit: | |
| name | color | | |
| banana | yellow | | |
| strawberry | red | | |
When the client requests GET /fruits | |
Then the response should be JSON: | |
""" | |
[ | |
{"name": "banana", "color": "yellow"}, | |
{"name": "strawberry", "color": "red"} | |
] | |
""" |
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
CAPTURE_FRUIT_NAMES = Transformation /^(?:(?:apple|banana|pear|strawberry)(?:,\s|\sand\s)?)+$/ do |fruit_names| | |
fruit_names.gsub('and', ',').split(',').map { |e| e.strip.gsub(' ', '_').to_sym } | |
end | |
# using faker gem: https://github.com/stympy/faker | |
def create_fruit_by_name(name) | |
Fruit.create name: name, color: Faker::Commerce.color | |
end | |
Given(/^Given the system knows about the following fruit(?::)? (#{CAPTURE_FRUIT_NAMES})$/) do |user_types| | |
fruit_names.each { |name| create_fruit_by_name name } | |
end | |
When /^the client requests (GET|POST|PUT|DELETE) (.*?)$/ do |request_type, path| | |
request_opts = { method: request_type.downcase.to_sym } | |
@last_href = "http://example.org#{path}" | |
request(path, request_opts).inspect | |
end | |
CAPTURE_RECOGNIZED_STATUS = Transform /^OK|UNPROCESSABLE|FORBIDDEN|UNAUTHORIZED|CREATED$/ do |status| | |
status | |
end | |
Then /^the response status should be "(#{CAPTURE_RECOGNIZED_STATUS})"$/ do |status| | |
begin | |
case status | |
when 'OK' | |
expect(last_response.status).to eq 200 | |
last_json.should be_json_eql(JsonSpec.remember(200)).at_path('status') | |
last_json.should be_json_eql(JsonSpec.remember(true)).at_path('success') | |
when 'UNPROCESSABLE' | |
expect(last_response.status).to eq 422 | |
last_json.should be_json_eql(JsonSpec.remember(422)).at_path('status') | |
last_json.should be_json_eql(JsonSpec.remember(false)).at_path('success') | |
when 'FORBIDDEN' | |
expect(last_response.status).to eq 403 | |
last_json.should be_json_eql(JsonSpec.remember(403)).at_path('status') | |
last_json.should be_json_eql(JsonSpec.remember(false)).at_path('success') | |
when 'UNAUTHORIZED' | |
expect(last_response.status).to eq 401 | |
last_json.should be_json_eql(JsonSpec.remember(401)).at_path('status') | |
last_json.should be_json_eql(JsonSpec.remember(false)).at_path('success') | |
when 'CREATED' | |
expect(last_response.status).to eq 201 | |
last_json.should be_json_eql(JsonSpec.remember(201)).at_path('status') | |
last_json.should be_json_eql(JsonSpec.remember(true)).at_path('success') | |
end | |
rescue RSpec::Expectations::ExpectationNotMetError => e | |
puts 'Response body:' | |
puts last_response.body | |
raise e | |
end | |
end | |
# this one is dealt with json_spec cucumber steps directly | |
# (https://github.com/collectiveidea/json_spec/blob/master/lib/json_spec/cucumber.rb) | |
# it checks if response is a JSON array and if it has specified size | |
# And /^the (?:JSON|json)(?: response)?(?: at "(.*)")? should( not)? have (\d+)/ do |path, negative, size| | |
CAPTURE_FIELD_NAMES = Transformation /^(.*?)$/ do |fields| | |
fields.gsub('and', ',').split(',').map { |e| e.strip.to_sym } | |
end | |
def compare_json_with_record(json, record, fields) | |
field.each do |field| | |
expect(json).to be_json_eql(JsonSpec.remember(record[field])).at_path(field) | |
end | |
end | |
And(/^fruits array should include (#{CAPTURE_FRUIT_NAMES}) with (#{CAPTURE_FIELD_NAMES})$/) do |fruit_names, fields| | |
fruit_names.each do |fruit_name| | |
fruit = Fruit.where(name: fruit_name).pluck(fields).first | |
compare_json_with_record(last_json, fruit, fields) | |
end | |
end | |
And(/^the response should include last href$/) do | |
expect(last_json).to be_json_eql(JsonSpec.remember(@last_href.to_json)).at_path('href') | |
end | |
# this is how the response to GET /fruits would look like: | |
# { "href" : "http://example.org/fruits", | |
# "success" : true, | |
# "status" : 200, | |
# "count" : 2, | |
# "fruits" : [ | |
# { "name" : "banana", "color" : "random color name" }, | |
# { "name" : "strawberry", "color" : "random color name" } ] |
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
. . . | |
group :test do | |
gem 'cucumber-rails', '1.4.1', :require => false | |
gem 'json_spec', '1.1.2' | |
. . . |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment