Skip to content

Commit

Permalink
Bump version to 0.7.0
Browse files Browse the repository at this point in the history
  • Loading branch information
claudiob committed Nov 25, 2013
1 parent 6f3403f commit cc2f1ff
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 70 deletions.
10 changes: 5 additions & 5 deletions Gemfile.lock
@@ -1,12 +1,12 @@
PATH
remote: .
specs:
rspec-api-requests (0.6.2)
rspec-api-requests (0.7.0)
activesupport
faraday
faraday_middleware
rspec
rspec-api-expectations (~> 0.6.2)
rspec-api-expectations (~> 0.7.0)

GEM
remote: https://rubygems.org/
Expand Down Expand Up @@ -46,13 +46,13 @@ GEM
rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0)
rspec-mocks (~> 2.14.0)
rspec-api-expectations (0.6.2)
rspec-api-expectations (0.7.0)
activesupport
faraday
rack
rspec
rspec-api-matchers (~> 0.6.1)
rspec-api-matchers (0.6.1)
rspec-api-matchers (~> 0.7.0)
rspec-api-matchers (0.7.0)
activesupport
rack
rspec
Expand Down
200 changes: 137 additions & 63 deletions README.md
@@ -1,7 +1,7 @@
RSpec API Requests
==================

RSpecApi::Requests lets make requests to web APIs and verify their expectations:
RSpecApi::Requests lets you make requests to web APIs and verify their expectations:

params = {host: 'http://api.example.com', route: '/concerts', attributes: {where: {type: :string}}

Expand All @@ -17,91 +17,165 @@ More documentation and examples about RSpecApi are available at [http://rspec-ap
[![Dependency Status](https://gemnasium.com/rspec-api/rspec-api-requests.png)](https://gemnasium.com/rspec-api/rspec-api-requests)


Basic example
-------------

# 1. Specify how to connect to the API and what to expect:
gists_params = {
host: 'https://api.github.com',
action: 'get',
authorize_with: {token: YOUR-GITHUB-TOKEN-HERE},
route: '/gists',
collection: true,
attributes: {url: {type: {string: :url}}},
extra_requests: [{
expect: {filter: {by: :updated_at, compare_with: :>=, value: '2012-10-10T00:00:00Z'}},
params: {since: '2012-10-10T00:00:00Z'}
}]
}

# 2. Use `respond_to` to send the request and verify the expectations
describe 'GitHub Gists', rspec_api_params: gists_params do
respond_with :ok
end

Running the example above returns the following successful output:

Examples from GitHub API
GitHub Gists
GET /gists with {:since=>"2012-10-10T00:00:00Z"}
responds with a body that
should be a collection
should have attributes {:url=>{:type=>{:string=>:url}}}
should be filtered by updated_at>=2012-10-10T00:00:00Z
responds with a status code that
should be 200
GET /gists
responds with a body that
should have attributes {:url=>{:type=>{:string=>:url}}}
should be a collection
responds with a status code that
should be 200

**DRAFT! Work in Progress! Caution!**
Finished in 0.01056 seconds
7 examples, 0 failures

Remember how RSpecApi::Expectations let you write something like this?
Note that, in order run the example, above, you need to replace
`YOUR-GITHUB-TOKEN-HERE` with your [GitHub Personal Access Token](https://github.com/settings/applications).

# 1. Make a request to the GitHub API:

require 'faraday'
conn = Faraday.new 'https://api.github.com/' do |c|
c.use Faraday::Adapter::NetHttp
end
conn.headers[:user_agent] = 'RSpec API'
conn.authorization :token, ENV['RSPEC_API_GITHUB_TOKEN']
response = conn.get '/repositories'
Available request options
=========================

# 2. Expect the response to be successful and to return a JSON collection,
# where each object has an ID key/value (number), a name key/value
# (string) and a url key/value (string in URL format)
RSpecApi::Requests makes available one method `respond_to`, which sends the
request to the API and verify the expectations specified using RSpec metadata
`rspec_api_params` in the surrounding `describe` block, as shown above.
The following are the valid request options for `rspec_api_params`.

require 'rspec-api/requests'
:host and :adapter (*either one or the other is required*)
----------------------------------------------------------

describe 'List all public repositories', rspec_api: true do
expect_response response, status: :ok, type: :json, collection: true,
attributes: {id: {type: :number}, name: {type: :string},
url: {type: {string: :url}}}
Respectively the URL where the API is hosted and the adapter to connect to it.
By default, RSpecApi::Requests uses `Net::HTTP`, e.g:

host: 'http://example.com' # => connect via Net::HTTP

Well, it would make sense for that request and that expectation to go together,
not to be separate. RSpecApi::Requests let you do that, and write:
This behavior can be overridden specifying a different adapter:

describe 'List all public repositories', rspec_api: true do
get '/repositories',
host: 'https://api.github.com/',
authorize_with: ENV['RSPEC_API_GITHUB_TOKEN'],
attributes: {id: {type: :number}, name: {type: :string}, url: {type: {string: :url}}} do
respond_with :ok
end
end
adapter: [:rack, app] # => connect via Rack::Test to a local Rack app

or even this:
Therefore, RSpecApi::Requests can be used both to send requests to **remote**
and to **local** web API, making API development easier.

describe 'List all public repositories', rspec_api: true do
host 'https://api.github.com/'
authorize_with: {token: ENV['RSPEC_API_GITHUB_TOKEN']}
:route (*required*)
-------------------

has_attribute :id, {type: :number}
has_attribute :name, {type: :string}, url: {type: {string: :url}}}
The API route to access a resource, e.g.:

get '/repositories' do
respond_with :ok
end
end
host: 'http://example.com', route: '/concerts'
# => connect to 'http://example.com/concerts'

:action (*required*)
--------------------

The HTTP method to access a resource, e.g.:

action: :delete, route: '/concerts'
# => sends 'DELETE /concerts'

:authorize_with (*optional*)
----------------------------

The HTTP authentication payload to send with the request, e.g.:

authorize_with: {token: 'foo'}
# => sends [:token, 'foo'] as the HTTP authentication


Available expectations
======================

The following are the valid expectations for `rspec_api_params`.

:collection (*optional*)
------------------------

Whether the response body will include a *single* JSON object
(`collection: false`) or a *collection* of objects (`collection: true`), e.g.:

action: :get, route: '/concerts', collection: true
# => expect `GET /concerts' to return a collection

action: :get, route: '/concerts/1', collection: false
# => expect `GET /concerts/1' to return an object

:attributes (*optional*)
------------------------

Which attributes the JSON object or collection in the response body will contain, e.g.:

action: :get, route: '/concerts/1', attributes: {url: {type: {string: :url}}}
# => expect `GET /concerts/1' to return an object with a 'url' field
# that should contain a URL-formatted string

Extra requests
==============

The last option of `rspec_api_params` allows to send multiple API requests:

:extra_requests (*optional*)
----------------------------

Which extra requests should be sent and what to expect from them, e.g.:

action: :get, route: '/concerts', extra_requests: [{
expect: {filter: {by: :created_at, compare_with: :>=, value: '2012-10-10T00:00:00Z'}},
params: {since: '2012-10-10T00:00:00Z'}
}]
# => expect `GET /concerts/1?since=2012-10-10T00:00:00Z' to only return
# concerts created after October 10th, 2012.

And all of these are equivalent. But this syntax hides the real requests, making
you focus more on the expectations, and also allows you to make many requests
with the same expectations on the attributes, which is a best practice of
an API. For instance if you get ONE repo, ALL the repos or FILTERED repos,
you should still get a result with those attributes:

get '/repositories?since=1234' do
respond_with :ok
end
How to install
==============

get '/repos/:owner/:repo' do
respond_with :ok, owner: 'rspec-api', repo: 'rspec-api-requests'
end
To install on your system, run `gem install rspec-api-requests`.
To use inside a bundled Ruby project, add this line to the Gemfile:

get '/repos/:owner/:repo' do
respond_with :not_found, owner: 'not-an-owner', repo: 'not-a-repo'
end
gem 'rspec-api-requests', '~> 0.7.0'

So in short, rspec-api-requests adds methods to RSpec's ExampleGroups tagged
as :rspec_api:
The rspec-api-requests gem follows [Semantic Versioning](http://semver.org).
Any new release that is fully backward-compatible bumps the *patch* version (0.0.x).
Any new version that breaks compatibility bumps the *minor* version (0.x.0)

* the most important methods are the actions: get, put, post, patch,
delete -- they make the request to the API
Indicating the full version in your Gemfile (*major*.*minor*.*patch*) guarantees
that your project won’t occur in any error when you `bundle update` and a new
version of RSpecApi::Requests is released.

* inside those methods, `respond_with`, which checks that the expectations on
that endpoint are met. By default, we expect JSON and we indicate the status.
Also, `respond_with` gets the values to replace the placeholders in the route

* more expectations on the attributes can be set with `has_attribute`
How to contribute
=================

* configuration about the requests can be set with `host` and `authorize_with`
Don’t hesitate to send me code comments, issues or pull requests through GitHub!

* extra requests can be run with `accepts`
All feedback is appreciated. Thanks :)
2 changes: 1 addition & 1 deletion lib/rspec-api/requests/version.rb
@@ -1,5 +1,5 @@
module RSpecApi
module Requests
VERSION = '0.6.2'
VERSION = '0.7.0'
end
end
2 changes: 1 addition & 1 deletion rspec-api-requests.gemspec
Expand Up @@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
spec.required_rubygems_version = ">= 1.3.6"

spec.add_dependency 'rspec'
spec.add_dependency 'rspec-api-expectations', '~> 0.6.2' # expect(200).to match_status(200)
spec.add_dependency 'rspec-api-expectations', '~> 0.7.0' # expect(200).to match_status(200)

spec.add_dependency 'activesupport' # to .slice, etc
spec.add_dependency 'faraday' # to send remote HTTP requests
Expand Down

0 comments on commit cc2f1ff

Please sign in to comment.