rspec-api-expectations 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fda99c3899642eb3cfc68d5be22833ec6608111b
4
+ data.tar.gz: b30aa6e5fc91427c927090f942874034ba466267
5
+ SHA512:
6
+ metadata.gz: 43a66db64f8b79f52fffd84116419779e09202f154033a1d4261c13bbc6cedf72c2aa8f643c4d178acb897f8a308198e293b5ea67eacf29cd8e13928b1893c5f
7
+ data.tar.gz: 4c6a318a4b16cc27086e9abd70830a9e1395048fc68e2f57ab72f44e36afeed8a6e2d54c28b8069c5b636e1950ae41b297a2b8501f727201197083f9804ba444
@@ -0,0 +1,20 @@
1
+ Copyright 2013 claudiob
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,103 @@
1
+ RSpec API Expectations
2
+ ======================
3
+
4
+ RSpecApi::Expectations provides the `expect_resourceful` helper to any
5
+ RSpec example group tagged as `:rspec_api_resource`.
6
+
7
+ [![Build Status](https://travis-ci.org/rspec-api/rspec-api-expectations.png?branch=master)](https://travis-ci.org/rspec-api/rspec-api-expectations)
8
+ [![Code Climate](https://codeclimate.com/github/rspec-api/rspec-api-expectations.png)](https://codeclimate.com/github/rspec-api/rspec-api-expectations)
9
+ [![Coverage Status](https://coveralls.io/repos/rspec-api/rspec-api-expectations/badge.png)](https://coveralls.io/r/rspec-api/rspec-api-expectations)
10
+ [![Dependency Status](https://gemnasium.com/rspec-api/rspec-api-expectations.png)](https://gemnasium.com/rspec-api/rspec-api-expectations)
11
+
12
+ Basic example
13
+ -------------
14
+
15
+ require 'faraday'
16
+ response = Faraday.new('http://example.com/').get('/concerts')
17
+
18
+ describe 'GET http://example.com/concerts', :rspec_api_resource do
19
+ expect_resourceful response, status: :ok, type: :json, array: true
20
+ end
21
+
22
+ The example above makes a `GET `'http://example.com/concerts'` request, then
23
+ check that the response:
24
+
25
+ * has a status code of 200 OK
26
+ * has the 'Content-Type' header set to 'application/json'
27
+ * has a JSON Array of Hashes (also called 'objects') in the body
28
+
29
+ Running the test above in RSpec produces the following output:
30
+
31
+ ...
32
+
33
+ Available expectations
34
+ ======================
35
+
36
+ The purpose of RSpecApi::Expectations is to give developers a tool to quickly
37
+ test that API endpoints respect some best practices that are common to
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:
48
+
49
+ Status
50
+ ------
51
+
52
+ expect_resourceful response, status: :ok
53
+
54
+ Expects a specific HTTP status code in the response.
55
+ The status can be specified either as a number or as a [symbol](...)
56
+
57
+ Content Type
58
+ ------------
59
+
60
+ expect_resourceful response, type: :json
61
+
62
+ Expects a specific 'Content-Type' header in the response.
63
+ The status can be specified either as a string or as a [symbol](...).
64
+ By default, the expectation (best practice) is 'application/json'.
65
+ Note that this expectation always passes if the response status indicates
66
+ that there is no content at all (e.g. if the status is '204 No Content').
67
+
68
+ Collection
69
+ ----------
70
+
71
+ expect_resourceful response, collection: true
72
+
73
+ Expects the response body to either contain one or a collection of resources.
74
+ By default, the expectation is `collection: false`.
75
+
76
+ An example of a JSON response with one resource is:
77
+ `{"id": 1, "name": "foo"}`.
78
+ An example of a JSON response with a collection of resources is:
79
+ `[{"id": 1, "name": "foo"}, {"id": 2, "name": "bar"}]`.
80
+
81
+ More to add
82
+ -----------
83
+
84
+ ....
85
+
86
+
87
+ How to install
88
+ ==============
89
+
90
+ Add `gem 'rspec-api-expectations'` to your `Gemfile` and run `bundle`.
91
+ Or install yourself by running `gem install rspec-api-expectations`.
92
+
93
+ Version changes respect [Semantic Versioning](http://semver.org).
94
+ To ensure `bundle update` won't cause problems in your repository,
95
+ always indicate the patch version until version 1.0.0 is released, e.g.:
96
+
97
+ gem 'rspec-api-expectations', '~> 0.5.0'
98
+
99
+ How to contribute
100
+ =================
101
+
102
+ Don’t hesitate to send me code comments, issues or pull requests through GitHub!
103
+ All feedback is appreciated. Thanks :)
@@ -0,0 +1 @@
1
+ require 'rspec-api/expectations'
@@ -0,0 +1,8 @@
1
+ require 'rspec'
2
+ require 'rspec-api/resourceful'
3
+
4
+ # Make `expect_resourceful` available in every RSpec ExampleGroup tagged
5
+ # as `rspec_api_resource`
6
+ RSpec.configure do |c|
7
+ c.extend(RSpecApi::Expectations::Resourceful, rspec_api_resource: true)
8
+ end
@@ -0,0 +1,2 @@
1
+ require 'rspec-api/resourceful'
2
+ require 'rspec-api/configure'
@@ -0,0 +1,38 @@
1
+ require 'rspec-api/matchers'
2
+ require 'rack/utils'
3
+
4
+ module RSpecApi
5
+ module Expectations
6
+ module BodyExpectations
7
+ def expect_a_collection(response, is_collection)
8
+ if is_collection
9
+ expect(response).to be_a_collection
10
+ else
11
+ expect(response).not_to be_a_collection
12
+ end
13
+ end
14
+
15
+ def expect_callback_wrapped(response, callback)
16
+ expect(response).to be_a_jsonp callback
17
+ end
18
+
19
+ def expect_a_sorted(response, sort = {})
20
+ expect(response).to be_sorted sort
21
+ end
22
+
23
+ def expect_a_filtered(response, filter = {})
24
+ expect(response).to be_filtered filter[:value], filter.except(:value)
25
+ end
26
+
27
+ def expect_attributes(response, attributes)
28
+ expect(response).to have_attributes attributes
29
+ end
30
+
31
+ private
32
+
33
+ def successful?(response)
34
+ response.status < 400 && !Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(response.status)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,20 @@
1
+ require 'rspec-api/matchers'
2
+ require 'rack/utils'
3
+
4
+ module RSpecApi
5
+ module Expectations
6
+ module HeadersExpectations
7
+ def expect_content_type_header(response, type)
8
+ expect(response).to include_content_type type
9
+ end
10
+
11
+ def expect_prev_page_link_header(response, has_prev_page)
12
+ if has_prev_page == false
13
+ expect(response).not_to have_prev_page_link
14
+ else
15
+ expect(response).to have_prev_page_link
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ require 'rspec-api/matchers'
2
+
3
+ module RSpecApi
4
+ module Expectations
5
+ module StatusExpectations
6
+ def expect_status(response, status)
7
+ expect(response).to have_status status
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ module RSpecApi
2
+ module Expectations
3
+ VERSION = '0.5.0'
4
+ end
5
+ end
@@ -0,0 +1,34 @@
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
@@ -0,0 +1,27 @@
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
@@ -0,0 +1,20 @@
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
@@ -0,0 +1,17 @@
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
metadata ADDED
@@ -0,0 +1,170 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rspec-api-expectations
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ platform: ruby
6
+ authors:
7
+ - claudiob
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec-api-matchers
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 0.5.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.5.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: rack
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: faraday
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '1.3'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '1.3'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: coveralls
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: RSpec expectations useful to test web APIs.
126
+ email:
127
+ - claudiob@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - lib/rspec-api/configure.rb
133
+ - lib/rspec-api/expectations/body.rb
134
+ - lib/rspec-api/expectations/headers.rb
135
+ - lib/rspec-api/expectations/status.rb
136
+ - lib/rspec-api/expectations/version.rb
137
+ - 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
+ - lib/rspec-api-expectations.rb
143
+ - MIT-LICENSE
144
+ - README.md
145
+ homepage: https://github.com/rspec-api/rspec-api-expectations
146
+ licenses:
147
+ - MIT
148
+ metadata: {}
149
+ post_install_message:
150
+ rdoc_options: []
151
+ require_paths:
152
+ - lib
153
+ required_ruby_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - '>='
156
+ - !ruby/object:Gem::Version
157
+ version: 1.9.3
158
+ required_rubygems_version: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - '>='
161
+ - !ruby/object:Gem::Version
162
+ version: 1.3.6
163
+ requirements: []
164
+ rubyforge_project:
165
+ rubygems_version: 2.1.10
166
+ signing_key:
167
+ specification_version: 4
168
+ summary: Expectations extracted from rspec-api to chech response of pragmatic RESTful
169
+ web APIs.
170
+ test_files: []