rspec-api-expectations 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
[](https://travis-ci.org/rspec-api/rspec-api-expectations)
|
8
11
|
[](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
|