rspec-api-expectations 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +107 -47
- data/lib/rspec-api/expectations.rb +26 -2
- data/lib/rspec-api/expectations/body.rb +29 -30
- data/lib/rspec-api/expectations/body/attributes.rb +25 -0
- data/lib/rspec-api/expectations/body/collection.rb +29 -0
- data/lib/rspec-api/expectations/body/filter.rb +25 -0
- data/lib/rspec-api/expectations/body/jsonp.rb +25 -0
- data/lib/rspec-api/expectations/body/sort.rb +25 -0
- data/lib/rspec-api/expectations/headers.rb +15 -11
- data/lib/rspec-api/expectations/headers/content_type.rb +25 -0
- data/lib/rspec-api/expectations/headers/page_links.rb +29 -0
- data/lib/rspec-api/expectations/response.rb +43 -0
- data/lib/rspec-api/expectations/status.rb +11 -4
- data/lib/rspec-api/expectations/status/code.rb +25 -0
- data/lib/rspec-api/expectations/version.rb +1 -1
- metadata +13 -9
- data/lib/rspec-api/configure.rb +0 -8
- data/lib/rspec-api/resourceful.rb +0 -34
- data/lib/rspec-api/resourceful/body.rb +0 -27
- data/lib/rspec-api/resourceful/headers.rb +0 -20
- data/lib/rspec-api/resourceful/status.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fdb96efa9b4427fe2fd324119952bf272f20db25
|
4
|
+
data.tar.gz: d84e07314ec0cbeed9246ae39a0a09d45cb3f9bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 23adb51e77acc3689557ef246ee4e4e683d55211ccc34546f14b535e3f31fff676e7e38135622b9e7dfb4459c1458cb0a0c979f8b3d15dd1baacab07f6a3904a
|
7
|
+
data.tar.gz: 973f03448725f9132f58c5ece33acabd56802353b7115cef3461d4e984f45ebbe36444fbceeaad4099ffa575eb41b583eb20755bbebd1b163b2cfb69043c79ee
|
data/README.md
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
RSpec API Expectations
|
2
2
|
======================
|
3
3
|
|
4
|
-
RSpecApi::Expectations
|
5
|
-
|
4
|
+
RSpecApi::Expectations lets you express expectations on the response of web APIs:
|
5
|
+
|
6
|
+
expect_response response, status: :ok, type: :json, collection: true
|
7
|
+
|
8
|
+
More documentation and examples about RSpecApi are available at [http://rspec-api.github.io](http://rspec-api.github.io)
|
6
9
|
|
7
10
|
[![Build Status](https://travis-ci.org/rspec-api/rspec-api-expectations.png?branch=master)](https://travis-ci.org/rspec-api/rspec-api-expectations)
|
8
11
|
[![Code Climate](https://codeclimate.com/github/rspec-api/rspec-api-expectations.png)](https://codeclimate.com/github/rspec-api/rspec-api-expectations)
|
@@ -12,92 +15,149 @@ RSpec example group tagged as `:rspec_api_resource`.
|
|
12
15
|
Basic example
|
13
16
|
-------------
|
14
17
|
|
15
|
-
|
16
|
-
response = Faraday.new('http://example.com/').get('/concerts')
|
18
|
+
# 1. Make a request to the GitHub API:
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
+
require 'faraday'
|
21
|
+
conn = Faraday.new 'https://api.github.com/' do |c|
|
22
|
+
c.use Faraday::Adapter::NetHttp
|
20
23
|
end
|
24
|
+
conn.headers[:user_agent] = 'RSpec API'
|
25
|
+
conn.authorization :token, ENV['RSPEC_API_GITHUB_TOKEN']
|
26
|
+
response = conn.get '/repositories'
|
27
|
+
|
28
|
+
# 2. Expect the response to be successful and to return a JSON collection,
|
29
|
+
# where each object has an ID key/value (number), a name key/value
|
30
|
+
# (string) and a url key/value (string in URL format)
|
31
|
+
|
32
|
+
require 'rspec-api/expectations'
|
33
|
+
|
34
|
+
describe 'List all public repositories', rspec_api: true do
|
35
|
+
expect_response response, status: :ok, type: :json, collection: true,
|
36
|
+
attributes: {id: {type: :number}, name: {type: :string},
|
37
|
+
url: {type: {string: :url}}}
|
38
|
+
|
39
|
+
Running the example above returns the following successful output:
|
21
40
|
|
22
|
-
|
23
|
-
|
41
|
+
GET https://api.github.com/repositories
|
42
|
+
responds with a status code that
|
43
|
+
should be 200
|
44
|
+
responds with headers that
|
45
|
+
should include 'Content-Type': 'application/json; charset=utf-8'
|
46
|
+
responds with a body that
|
47
|
+
should be a collection
|
48
|
+
should have attributes {:id=>{:type=>:number}, :name=>{:type=>:string}, :url=>{:type=>{:string=>:url}}}
|
24
49
|
|
25
|
-
|
26
|
-
|
27
|
-
* has a JSON Array of Hashes (also called 'objects') in the body
|
50
|
+
Finished in 0.13086 seconds
|
51
|
+
4 examples, 0 failures
|
28
52
|
|
29
|
-
|
53
|
+
Note that, in order run the example, above, you need to get a GitHub Personal Access Token:
|
54
|
+
|
55
|
+
* Browse to your [GitHub settings](https://github.com/settings/applications)
|
56
|
+
* Click on 'Create new token' under 'Personal Access Token' (name it as you want)
|
57
|
+
* Copy the generated token and store it on your machine as the environment variable called `RSPEC_API_GITHUB_TOKEN`:
|
58
|
+
* On OSX and bash, accomplish this by running the command `export RSPEC_API_GITHUB_TOKEN=` followed by your pasted key (no spaces after `=`)
|
30
59
|
|
31
|
-
...
|
32
60
|
|
33
61
|
Available expectations
|
34
62
|
======================
|
35
63
|
|
36
64
|
The purpose of RSpecApi::Expectations is to give developers a tool to quickly
|
37
|
-
test that API endpoints respect some best practices
|
38
|
-
RESTful resourceful web APIs.
|
39
|
-
|
40
|
-
A list of best practices is available in [this great article by ...]; they
|
41
|
-
span from something as simple as "the status of a successful GET request should
|
42
|
-
be 200 OK" to something more complex as "the headers of a GET request for a
|
43
|
-
paginated list should include a link to the previous page".
|
44
|
-
|
45
|
-
RSpecApi::Expectations makes it easy to test whether any web API respects these
|
46
|
-
best practices by means of the `expect_resourceful` method. Here are all the
|
47
|
-
available expectations that can be tested with this method:
|
65
|
+
test that API endpoints respect some [best practices](http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api)
|
66
|
+
that are common to RESTful resourceful web APIs.
|
48
67
|
|
49
68
|
Status
|
50
69
|
------
|
51
70
|
|
52
|
-
|
71
|
+
expect_response response, status: :ok
|
53
72
|
|
54
73
|
Expects a specific HTTP status code in the response.
|
55
|
-
The status can be specified either as a number or as a
|
74
|
+
The status can be specified either as a number (200) or as a symbol (:ok).
|
56
75
|
|
57
76
|
Content Type
|
58
77
|
------------
|
59
78
|
|
60
|
-
|
79
|
+
expect_response response, type: :json
|
61
80
|
|
62
81
|
Expects a specific 'Content-Type' header in the response.
|
63
|
-
The status can be specified either as a string or as a
|
64
|
-
|
65
|
-
|
66
|
-
|
82
|
+
The status can be specified either as a string or as a symbol.
|
83
|
+
The expectation always passes when the response does not have a content
|
84
|
+
(e.g. if the status is '204 No Content').
|
85
|
+
|
86
|
+
|
87
|
+
Page Links
|
88
|
+
----------
|
89
|
+
|
90
|
+
expect_response response, page_links: true
|
91
|
+
|
92
|
+
Expects a 'Link' header in the response to denote pagination, in accordance to [RFC 5988](http://tools.ietf.org/html/rfc5988#page-6).
|
93
|
+
The expectation passes if a link with rel="prev" is found.
|
67
94
|
|
68
95
|
Collection
|
69
96
|
----------
|
70
97
|
|
71
|
-
|
98
|
+
expect_response response, collection: true
|
99
|
+
|
100
|
+
Expects a collection of JSON objects in the response body.
|
101
|
+
For example, the expectation above passes if the body is
|
102
|
+
`[{"name":"foo"},{"name":"bar"}]`.
|
103
|
+
|
104
|
+
JSONP Callback
|
105
|
+
--------------
|
106
|
+
|
107
|
+
expect_response response, callback: 'alert'
|
72
108
|
|
73
|
-
Expects
|
74
|
-
|
109
|
+
Expects a response body with a JSON wrapped in the given JSONP callback.
|
110
|
+
For example, the expectation above passes if the body is
|
111
|
+
`alert({"name": "foo"})`.
|
75
112
|
|
76
|
-
|
77
|
-
|
78
|
-
An example of a JSON response with a collection of resources is:
|
79
|
-
`[{"id": 1, "name": "foo"}, {"id": 2, "name": "bar"}]`.
|
113
|
+
Sort
|
114
|
+
----
|
80
115
|
|
81
|
-
|
82
|
-
-----------
|
116
|
+
expect_response response, sort: {by: :id, verse: :desc}
|
83
117
|
|
84
|
-
|
118
|
+
Expects a response body with a JSON collection sorted by the given option.
|
119
|
+
For example, the expectation above passes if the body is
|
120
|
+
`[{"id": 2, "foo"},{"id": 1, "bar"}]`.
|
121
|
+
|
122
|
+
Filter
|
123
|
+
------
|
124
|
+
|
125
|
+
expect_response response, filter: {by: :name, value: "foo"}
|
126
|
+
|
127
|
+
Expects a response body with a JSON collection filtered by the given option.
|
128
|
+
For example, the expectation above passes if the body is
|
129
|
+
`[{"id": 1, "foo"},{"id": 2, "foo"}]`.
|
130
|
+
|
131
|
+
Filter
|
132
|
+
------
|
133
|
+
|
134
|
+
expect_response response, attributes: [:id, name: {type: :string}]
|
135
|
+
|
136
|
+
Expects a response body that includes the given attributes.
|
137
|
+
For example, the expectation above passes if the body is
|
138
|
+
`[{"id": 1, "foo"},{"id": 2, "bar"}]`.
|
85
139
|
|
86
140
|
|
87
141
|
How to install
|
88
142
|
==============
|
89
143
|
|
90
|
-
|
91
|
-
|
144
|
+
To install on your system, run `gem install rspec-api-expectations`.
|
145
|
+
To use inside a bundled Ruby project, add this line to the Gemfile:
|
92
146
|
|
93
|
-
|
94
|
-
|
95
|
-
|
147
|
+
gem 'rspec-api-expectations', '~> 0.6.0'
|
148
|
+
|
149
|
+
The rspec-api-expectations gem follows [Semantic Versioning](http://semver.org).
|
150
|
+
Any new release that is fully backward-compatible bumps the *patch* version (0.0.x).
|
151
|
+
Any new version that breaks compatibility bumps the *minor* version (0.x.0)
|
152
|
+
|
153
|
+
Indicating the full version in your Gemfile (*major*.*minor*.*patch*) guarantees
|
154
|
+
that your project won’t occur in any error when you `bundle update` and a new
|
155
|
+
version of RSpecApi::Expectations is released.
|
96
156
|
|
97
|
-
gem 'rspec-api-expectations', '~> 0.5.0'
|
98
157
|
|
99
158
|
How to contribute
|
100
159
|
=================
|
101
160
|
|
102
161
|
Don’t hesitate to send me code comments, issues or pull requests through GitHub!
|
162
|
+
|
103
163
|
All feedback is appreciated. Thanks :)
|
@@ -1,2 +1,26 @@
|
|
1
|
-
require 'rspec
|
2
|
-
require 'rspec-api/
|
1
|
+
require 'rspec/core'
|
2
|
+
require 'rspec-api/expectations/response'
|
3
|
+
|
4
|
+
module RSpecApi
|
5
|
+
module Expectations
|
6
|
+
include Response
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# RSpecApi::Matchers adds matchers to test RESTful APIs.
|
11
|
+
#
|
12
|
+
# To have these matchers available inside of an RSpec `describe` block, tag that
|
13
|
+
# block with the `:rspec_api` metadata:
|
14
|
+
#
|
15
|
+
# describe "Artists", rspec_api: true do
|
16
|
+
# ... # here you can write `expect(response).to have_status :ok`, etc.
|
17
|
+
# end
|
18
|
+
RSpec.configuration.extend RSpecApi::Expectations, rspec_api: true
|
19
|
+
|
20
|
+
# You can also explicitly include the RSpec::Api module inside the example group:
|
21
|
+
#
|
22
|
+
# describe "Artists" do
|
23
|
+
# include RSpecApi::Matchers
|
24
|
+
# ... # here you can write `expect(response).to have_status :ok`, etc.
|
25
|
+
# end
|
26
|
+
#
|
@@ -1,37 +1,36 @@
|
|
1
|
-
require 'rspec-api/
|
2
|
-
require '
|
1
|
+
require 'rspec-api/expectations/body/collection'
|
2
|
+
require 'rspec-api/expectations/body/jsonp'
|
3
|
+
require 'rspec-api/expectations/body/sort'
|
4
|
+
require 'rspec-api/expectations/body/filter'
|
5
|
+
require 'rspec-api/expectations/body/attributes'
|
3
6
|
|
4
7
|
module RSpecApi
|
5
8
|
module Expectations
|
6
|
-
module
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
9
|
+
module Response
|
10
|
+
# Creates an example group for expectations on the response body of the
|
11
|
+
# last API request and runs it to verify that it matches best practices:
|
12
|
+
# * if response is succesful and has a body
|
13
|
+
# - the body should be a JSON-marshalled Array or Hash
|
14
|
+
# - if request has a callback parameter, the body should be JSONP
|
15
|
+
# - if request has a sort parameter, the body should be sorted
|
16
|
+
# - if request has a filter parameter, the body should be filtered
|
17
|
+
# - if some attributes are expected, the body should include them
|
18
|
+
module Body
|
19
|
+
def expect_body(response, expectations = {})
|
20
|
+
context 'responds with a body that' do
|
21
|
+
extend Collection
|
22
|
+
extend Jsonp
|
23
|
+
extend Sort
|
24
|
+
extend Filter
|
25
|
+
extend Attributes
|
22
26
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def successful?(response)
|
34
|
-
response.status < 400 && !Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(response.status)
|
27
|
+
expect_a_collection response, expectations
|
28
|
+
expect_a_callback_wrapped response, expectations
|
29
|
+
expect_a_sorted response, expectations
|
30
|
+
expect_a_filtered response, expectations
|
31
|
+
expect_attributes response, expectations
|
32
|
+
end if expectations.any?
|
33
|
+
end
|
35
34
|
end
|
36
35
|
end
|
37
36
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rspec-api/matchers'
|
2
|
+
|
3
|
+
module RSpecApi
|
4
|
+
module Expectations
|
5
|
+
module Response
|
6
|
+
module Body
|
7
|
+
module Attributes
|
8
|
+
def expect_attributes(response, expectations = {})
|
9
|
+
include RSpecApi::Matchers
|
10
|
+
|
11
|
+
if should_check_attributes(response, expectations)
|
12
|
+
it { expect(response).to have_attributes expectations[:attributes] }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def should_check_attributes(response, expectations)
|
19
|
+
expectations.key?(:attributes) && success?(response) && has_entity_body?(response)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rspec-api/matchers'
|
2
|
+
|
3
|
+
module RSpecApi
|
4
|
+
module Expectations
|
5
|
+
module Response
|
6
|
+
module Body
|
7
|
+
module Collection
|
8
|
+
def expect_a_collection(response, expectations = {})
|
9
|
+
include RSpecApi::Matchers
|
10
|
+
|
11
|
+
if should_check_collection(response, expectations)
|
12
|
+
if expectations[:collection]
|
13
|
+
it { expect(response).to be_a_collection }
|
14
|
+
else
|
15
|
+
it { expect(response).not_to be_a_collection }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def should_check_collection(response, expectations)
|
23
|
+
expectations.key?(:collection) && success?(response) && has_entity_body?(response)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rspec-api/matchers'
|
2
|
+
|
3
|
+
module RSpecApi
|
4
|
+
module Expectations
|
5
|
+
module Response
|
6
|
+
module Body
|
7
|
+
module Filter
|
8
|
+
def expect_a_filtered(response, expectations = {})
|
9
|
+
include RSpecApi::Matchers
|
10
|
+
|
11
|
+
if should_check_filtered(response, expectations)
|
12
|
+
it { expect(response).to be_filtered expectations[:filter] }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def should_check_filtered(response, expectations)
|
19
|
+
expectations.key?(:filter)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rspec-api/matchers'
|
2
|
+
|
3
|
+
module RSpecApi
|
4
|
+
module Expectations
|
5
|
+
module Response
|
6
|
+
module Body
|
7
|
+
module Jsonp
|
8
|
+
def expect_a_callback_wrapped(response, expectations = {})
|
9
|
+
include RSpecApi::Matchers
|
10
|
+
|
11
|
+
if should_check_callback_wrapped(response, expectations)
|
12
|
+
it { expect(response).to be_wrapped_in_callback expectations[:callback] }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def should_check_callback_wrapped(response, expectations)
|
19
|
+
expectations.key?(:callback)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rspec-api/matchers'
|
2
|
+
|
3
|
+
module RSpecApi
|
4
|
+
module Expectations
|
5
|
+
module Response
|
6
|
+
module Body
|
7
|
+
module Sort
|
8
|
+
def expect_a_sorted(response, expectations = {})
|
9
|
+
include RSpecApi::Matchers
|
10
|
+
|
11
|
+
if should_check_sorted(response, expectations)
|
12
|
+
it { expect(response).to be_sorted expectations[:sort] }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def should_check_sorted(response, expectations)
|
19
|
+
expectations.key?(:sort)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,18 +1,22 @@
|
|
1
|
-
require 'rspec-api/
|
2
|
-
require '
|
1
|
+
require 'rspec-api/expectations/headers/content_type'
|
2
|
+
require 'rspec-api/expectations/headers/page_links'
|
3
3
|
|
4
4
|
module RSpecApi
|
5
5
|
module Expectations
|
6
|
-
module
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
module Response
|
7
|
+
# Creates an example group for expectations on the response headers of
|
8
|
+
# last API request and runs it to verify that it matches best practices:
|
9
|
+
# * if request has entity body, the Content-Type header should be JSON
|
10
|
+
# * if request has pages, the Link header should have a 'rel=prev' link
|
11
|
+
module Headers
|
12
|
+
def expect_headers(response, expectations = {})
|
13
|
+
context 'responds with headers that' do
|
14
|
+
extend ContentType
|
15
|
+
extend PageLinks
|
10
16
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
else
|
15
|
-
expect(response).to have_prev_page_link
|
17
|
+
expect_content_type response, expectations
|
18
|
+
expect_page_links response, expectations
|
19
|
+
end if expectations.any?
|
16
20
|
end
|
17
21
|
end
|
18
22
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rspec-api/matchers'
|
2
|
+
|
3
|
+
module RSpecApi
|
4
|
+
module Expectations
|
5
|
+
module Response
|
6
|
+
module Headers
|
7
|
+
module ContentType
|
8
|
+
def expect_content_type(response, expectations = {})
|
9
|
+
include RSpecApi::Matchers
|
10
|
+
|
11
|
+
if should_check_content_type(response, expectations)
|
12
|
+
it { expect(response).to have_content_type expectations[:type] }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def should_check_content_type(response, expectations)
|
19
|
+
expectations.key?(:type) && has_entity_body?(response)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rspec-api/matchers'
|
2
|
+
|
3
|
+
module RSpecApi
|
4
|
+
module Expectations
|
5
|
+
module Response
|
6
|
+
module Headers
|
7
|
+
module PageLinks
|
8
|
+
def expect_page_links(response, expectations = {})
|
9
|
+
include RSpecApi::Matchers
|
10
|
+
|
11
|
+
if should_check_page_links(response, expectations)
|
12
|
+
if expectations[:page_links]
|
13
|
+
it { expect(response).to have_page_links }
|
14
|
+
else
|
15
|
+
it { expect(response).not_to have_page_links }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def should_check_page_links(response, expectations)
|
23
|
+
expectations.key?(:page_links)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'active_support/core_ext/hash/slice'
|
2
|
+
require 'rack/utils'
|
3
|
+
require 'rspec-api/expectations/status'
|
4
|
+
require 'rspec-api/expectations/headers'
|
5
|
+
require 'rspec-api/expectations/body'
|
6
|
+
|
7
|
+
module RSpecApi
|
8
|
+
module Expectations
|
9
|
+
module Response
|
10
|
+
include Status
|
11
|
+
include Headers
|
12
|
+
include Body
|
13
|
+
|
14
|
+
def expect_response(response, expectations)
|
15
|
+
expect_status response, expectations.slice(*on_status)
|
16
|
+
expect_headers response, expectations.slice(*on_headers)
|
17
|
+
expect_body response, expectations.slice(*on_body)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def on_status
|
23
|
+
[:status]
|
24
|
+
end
|
25
|
+
|
26
|
+
def on_headers
|
27
|
+
[:type, :page_links]
|
28
|
+
end
|
29
|
+
|
30
|
+
def on_body
|
31
|
+
[:collection, :callback, :sort, :filter, :attributes]
|
32
|
+
end
|
33
|
+
|
34
|
+
def success?(response)
|
35
|
+
response.status && response.status < 400
|
36
|
+
end
|
37
|
+
|
38
|
+
def has_entity_body?(response)
|
39
|
+
!Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(response.status)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -1,10 +1,17 @@
|
|
1
|
-
require 'rspec-api/
|
1
|
+
require 'rspec-api/expectations/status/code'
|
2
2
|
|
3
3
|
module RSpecApi
|
4
4
|
module Expectations
|
5
|
-
module
|
6
|
-
|
7
|
-
|
5
|
+
module Response
|
6
|
+
# Creates an example group for expectations on the HTTP status code of the
|
7
|
+
# last API request and runs it to verify that it matches +status+.
|
8
|
+
module Status
|
9
|
+
def expect_status(response, expectations = {})
|
10
|
+
context 'responds with a status code that' do
|
11
|
+
extend Code
|
12
|
+
expect_status_code response, expectations
|
13
|
+
end if expectations.any?
|
14
|
+
end
|
8
15
|
end
|
9
16
|
end
|
10
17
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rspec-api/matchers'
|
2
|
+
|
3
|
+
module RSpecApi
|
4
|
+
module Expectations
|
5
|
+
module Response
|
6
|
+
module Status
|
7
|
+
module Code
|
8
|
+
def expect_status_code(response, expectations = {})
|
9
|
+
include RSpecApi::Matchers
|
10
|
+
|
11
|
+
if should_check_status_code(response, expectations)
|
12
|
+
it { expect(response).to have_status expectations[:status] }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def should_check_status_code(response, expectations)
|
19
|
+
expectations.key?(:status)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-api-expectations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- claudiob
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-11-
|
11
|
+
date: 2013-11-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.
|
47
|
+
version: 0.6.1
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.
|
54
|
+
version: 0.6.1
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rack
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -129,16 +129,20 @@ executables: []
|
|
129
129
|
extensions: []
|
130
130
|
extra_rdoc_files: []
|
131
131
|
files:
|
132
|
-
- lib/rspec-api/
|
132
|
+
- lib/rspec-api/expectations/body/attributes.rb
|
133
|
+
- lib/rspec-api/expectations/body/collection.rb
|
134
|
+
- lib/rspec-api/expectations/body/filter.rb
|
135
|
+
- lib/rspec-api/expectations/body/jsonp.rb
|
136
|
+
- lib/rspec-api/expectations/body/sort.rb
|
133
137
|
- lib/rspec-api/expectations/body.rb
|
138
|
+
- lib/rspec-api/expectations/headers/content_type.rb
|
139
|
+
- lib/rspec-api/expectations/headers/page_links.rb
|
134
140
|
- lib/rspec-api/expectations/headers.rb
|
141
|
+
- lib/rspec-api/expectations/response.rb
|
142
|
+
- lib/rspec-api/expectations/status/code.rb
|
135
143
|
- lib/rspec-api/expectations/status.rb
|
136
144
|
- lib/rspec-api/expectations/version.rb
|
137
145
|
- lib/rspec-api/expectations.rb
|
138
|
-
- lib/rspec-api/resourceful/body.rb
|
139
|
-
- lib/rspec-api/resourceful/headers.rb
|
140
|
-
- lib/rspec-api/resourceful/status.rb
|
141
|
-
- lib/rspec-api/resourceful.rb
|
142
146
|
- lib/rspec-api-expectations.rb
|
143
147
|
- MIT-LICENSE
|
144
148
|
- README.md
|
data/lib/rspec-api/configure.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/hash/slice'
|
2
|
-
require 'rspec-api/resourceful/status'
|
3
|
-
require 'rspec-api/resourceful/headers'
|
4
|
-
require 'rspec-api/resourceful/body'
|
5
|
-
|
6
|
-
module RSpecApi
|
7
|
-
module Expectations
|
8
|
-
module Resourceful
|
9
|
-
include ResourcefulStatus
|
10
|
-
include ResourcefulHeaders
|
11
|
-
include ResourcefulBody
|
12
|
-
|
13
|
-
def expect_resourceful(response, expectations)
|
14
|
-
expect_resourceful_status response, expectations.slice(*on_status)
|
15
|
-
expect_resourceful_headers response, expectations.slice(*on_headers)
|
16
|
-
expect_resourceful_body response, expectations.slice(*on_body)
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def on_status
|
22
|
-
[:status]
|
23
|
-
end
|
24
|
-
|
25
|
-
def on_headers
|
26
|
-
[:type, :has_prev_page]
|
27
|
-
end
|
28
|
-
|
29
|
-
def on_body
|
30
|
-
[:collection, :callback, :sort, :filter, :attributes]
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
require 'rspec-api/expectations/body'
|
2
|
-
require 'rack/utils'
|
3
|
-
|
4
|
-
module RSpecApi
|
5
|
-
module Expectations
|
6
|
-
module ResourcefulBody
|
7
|
-
# Creates an example group for expectations on the response body of the
|
8
|
-
# last API request and runs it to verify that it matches best practices:
|
9
|
-
# * if response is succesful and has a body
|
10
|
-
# - the body should be a JSON-marshalled Array or Hash
|
11
|
-
# - if request has a callback parameter, the body should be JSONP
|
12
|
-
# - if request has a sort parameter, the body should be sorted
|
13
|
-
# - if request has a filter parameter, the body should be filtered
|
14
|
-
# - if some attributes are expected, the body should include them
|
15
|
-
def expect_resourceful_body(response, expectations = {})
|
16
|
-
include BodyExpectations
|
17
|
-
context 'responds with a body that' do
|
18
|
-
it { expect_a_collection response, expectations[:collection] } if expectations.key?(:collection) && response.status && response.status < 400 && !Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(response.status)
|
19
|
-
it { expect_callback_wrapped response, expectations[:callback] } if expectations[:callback]
|
20
|
-
it { expect_a_sorted response, expectations[:sort] } if expectations[:sort]
|
21
|
-
it { expect_a_filtered response, expectations[:filter] } if expectations[:filter]
|
22
|
-
it { expect_attributes response, expectations[:attributes] } if expectations[:attributes] && response.status && response.status < 400 && !Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(response.status)
|
23
|
-
end if expectations.any?
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
require 'rspec-api/expectations/headers'
|
2
|
-
|
3
|
-
module RSpecApi
|
4
|
-
module Expectations
|
5
|
-
module ResourcefulHeaders
|
6
|
-
# Creates an example group for expectations on the response headers of
|
7
|
-
# last API request and runs it to verify that it matches best practices:
|
8
|
-
# * if request has entity body, the Content-Type header should be JSON
|
9
|
-
# * if request has pages, the Link header should have a 'rel=prev' link
|
10
|
-
def expect_resourceful_headers(response, expectations = {})
|
11
|
-
include HeadersExpectations
|
12
|
-
|
13
|
-
context 'responds with headers that' do
|
14
|
-
it { expect_content_type_header response, expectations[:type] } if expectations[:type] && !Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(response.status)
|
15
|
-
it { expect_prev_page_link_header response, expectations[:has_prev_page] } if expectations.key?(:has_prev_page)
|
16
|
-
end if expectations.any?
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
require 'rspec-api/expectations/status'
|
2
|
-
|
3
|
-
module RSpecApi
|
4
|
-
module Expectations
|
5
|
-
module ResourcefulStatus
|
6
|
-
# Creates an example group for expectations on the HTTP status code of the
|
7
|
-
# last API request and runs it to verify that it matches +status+.
|
8
|
-
def expect_resourceful_status(response, expectations = {})
|
9
|
-
include StatusExpectations
|
10
|
-
|
11
|
-
context 'responds with a status code that' do
|
12
|
-
it { expect_status response, expectations[:status] } if expectations[:status]
|
13
|
-
end if expectations.any?
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|