airborne 0.0.17 → 0.0.18

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 617736e61c4229477118c5e4c6f9b36e6a84ba3a
4
- data.tar.gz: 4fa7413cdb076f955e9710dd04f1ebc5cb722f29
3
+ metadata.gz: c02499ba105b2a0cf64b2b3f66b3cb0603cdecff
4
+ data.tar.gz: 80406ace55d569bbabfd7a103f0135e4a37357b5
5
5
  SHA512:
6
- metadata.gz: 81987ab36bcf03af95ccb687409c83df3debec95ce9981c7113320c981936ad27099f5dcc5816fdec2c156e1d635d3b23c37887e9e8edb6ec5e8a994f827dd76
7
- data.tar.gz: 4144d3be1dee4d53e318ed696c4fa7ef8f97652ce5462fe631e42c9f9458d2ac2c8375ca27c71847342268fca866a12f63058cdca23f526e60ec983173c8ab4a
6
+ metadata.gz: 2a1e7465a8e9b57cd98b8ac94c93f6cf0c890cf660905da806c3a768ef36a0f897a143c35afa52a704b6a2ed9bf8b0e4b3a87825e7c47e4b134ae74baf8caadd
7
+ data.tar.gz: 4bbccbf924040c02119972fab3582cab6b71119d8696e0a385f8840389f3023b8ceb23af6d91606d34a50fa98416a081b015b9901573fe04c665d2a257e49993
data/README.md CHANGED
@@ -8,25 +8,32 @@
8
8
  RSpec driven API testing framework inspired by [frisby.js](https://github.com/vlucas/frisby)
9
9
 
10
10
  ## Installation
11
+
11
12
  Install Airborne:
12
13
 
13
14
  gem install airborne
15
+
16
+ Or add it to your Gemfile:
17
+
18
+ gem 'airborne'
14
19
 
15
20
  ##Creating Tests
16
21
 
17
- require 'airborne'
18
-
19
- describe 'sample spec' do
20
- it 'should validate types' do
21
- get 'http://example.com/api/v1/simple_get' #json api that returns { "name" : "John Doe" }
22
- expect_json_types({name: :string})
23
- end
24
-
25
- it 'should validate values' do
26
- get 'http://example.com/api/v1/simple_get' #json api that returns { "name" : "John Doe" }
27
- expect_json({:name => "John Doe"})
28
- end
29
- end
22
+ ```ruby
23
+ require 'airborne'
24
+
25
+ describe 'sample spec' do
26
+ it 'should validate types' do
27
+ get 'http://example.com/api/v1/simple_get' #json api that returns { "name" : "John Doe" }
28
+ expect_json_types({name: :string})
29
+ end
30
+
31
+ it 'should validate values' do
32
+ get 'http://example.com/api/v1/simple_get' #json api that returns { "name" : "John Doe" }
33
+ expect_json({:name => "John Doe"})
34
+ end
35
+ end
36
+ ```
30
37
 
31
38
  When calling expect_json_types, these are the valid types that can be tested against:
32
39
 
@@ -45,31 +52,37 @@ When calling expect_json_types, these are the valid types that can be tested aga
45
52
 
46
53
  If the properties are optional and may not appear in the response, you can append `_or_null` to the types above.
47
54
 
48
- describe 'sample spec' do
49
- it 'should validate types' do
50
- get 'http://example.com/api/v1/simple_get' #json api that returns { "name" : "John Doe" } or { "name" : "John Doe", "age" : 45 }
51
- expect_json_types({name: :string, age: :int_or_null})
52
- end
53
- end
55
+ ```ruby
56
+ describe 'sample spec' do
57
+ it 'should validate types' do
58
+ get 'http://example.com/api/v1/simple_get' #json api that returns { "name" : "John Doe" } or { "name" : "John Doe", "age" : 45 }
59
+ expect_json_types({name: :string, age: :int_or_null})
60
+ end
61
+ end
62
+ ```
54
63
 
55
64
  Additionally, if an entire object could be null, but you'd still want to test the types if it does exist, you can wrap the expectations in a call to `optional`:
56
65
 
57
- it 'should allow optional nested hash' do
58
- get '/simple_path_get' #may or may not return coordinates
59
- expect_json_types("address.coordinates", optional({lattitude: :float, longitutde: :float}))
60
- end
66
+ ```ruby
67
+ it 'should allow optional nested hash' do
68
+ get '/simple_path_get' #may or may not return coordinates
69
+ expect_json_types("address.coordinates", optional({lattitude: :float, longitutde: :float}))
70
+ end
71
+ ```
61
72
 
62
- When calling `expect_json`, you can optionally provide a block and run your own `rspec` expectations:
73
+ When calling `expect_json` or `expect_json_types`, you can optionally provide a block and run your own `rspec` expectations:
63
74
 
64
- describe 'sample spec' do
65
- it 'should validate types' do
66
- get 'http://example.com/api/v1/simple_get' #json api that returns { "name" : "John Doe" }
67
- expect_json({name: lambda |name| expect(name.length).to eq(8)})
68
- end
69
- end
70
-
75
+ ```ruby
76
+ describe 'sample spec' do
77
+ it 'should validate types' do
78
+ get 'http://example.com/api/v1/simple_get' #json api that returns { "name" : "John Doe" }
79
+ expect_json({name: -> (name){expect(name.length).to eq(8)}})
80
+ end
81
+ end
82
+ ```
71
83
 
72
84
  ##Making requests
85
+
73
86
  Airborne uses `rest_client` to make the HTTP request, and supports all HTTP verbs. When creating a test, you can call any of the following methods: `get`, `post`, `put`, `patch`, `delete`. This will then give you access the following properties:
74
87
 
75
88
  * `response` - The HTTP response returned from the request
@@ -79,22 +92,28 @@ Airborne uses `rest_client` to make the HTTP request, and supports all HTTP verb
79
92
 
80
93
  Fo example:
81
94
 
82
- it 'should validate types' do
83
- get 'http://example.com/api/v1/simple_get' #json api that returns { "name" : "John Doe" }
84
- name = json_body[:name] #name will equal "John Doe"
85
- body_as_string = body
86
- end
87
-
95
+ ```ruby
96
+ it 'should validate types' do
97
+ get 'http://example.com/api/v1/simple_get' #json api that returns { "name" : "John Doe" }
98
+ name = json_body[:name] #name will equal "John Doe"
99
+ body_as_string = body
100
+ end
101
+ ```
88
102
 
89
103
  When calling any of the methods above, you can pass request headers to be used.
90
104
 
91
- get 'http://example.com/api/v1/my_api', {'x-auth-token' => 'my_token'}
105
+ ```ruby
106
+ get 'http://example.com/api/v1/my_api', {'x-auth-token' => 'my_token'}
107
+ ```
92
108
 
93
109
  For requests that require a body (`post`, `put`, `patch`) you can pass the body as a hash as well:
94
110
 
95
- post 'http://example.com/api/v1/my_api', {:name => 'John Doe'}, {'x-auth-token' => 'my_token'}
96
-
111
+ ```ruby
112
+ post 'http://example.com/api/v1/my_api', {:name => 'John Doe'}, {'x-auth-token' => 'my_token'}
113
+ ```
114
+
97
115
  ##API
116
+
98
117
  * `expect_json_types` - Tests the types of the JSON property values returned
99
118
  * `expect_json` - Tests the values of the JSON property values returned
100
119
  * `expect_json_keys` - Tests the existence of the specified keys in the JSON object
@@ -103,114 +122,148 @@ For requests that require a body (`post`, `put`, `patch`) you can pass the body
103
122
  * `expect_header_contains` - Partial match test on a specified header
104
123
 
105
124
  ##Path Matching
125
+
106
126
  When calling `expect_json_types`, `expect_json` or `expect_json_keys` you can optionaly specify a path as a first parameter.
107
127
 
108
128
  For example, if our API returns the following JSON:
109
129
 
110
- {
111
- "name": "Alex",
112
- "address": {
113
- "street": "Area 51",
114
- "city": "Roswell",
115
- "state": "NM",
116
- "coordinates":{
117
- "lattitude": 33.3872,
118
- "longitude": 104.5281
119
- }
120
- }
130
+ ```json
131
+ {
132
+ "name": "Alex",
133
+ "address": {
134
+ "street": "Area 51",
135
+ "city": "Roswell",
136
+ "state": "NM",
137
+ "coordinates": {
138
+ "lattitude": 33.3872,
139
+ "longitude": 104.5281
121
140
  }
141
+ }
142
+ }
143
+ ```
122
144
 
123
145
  This test would only test the address object:
124
146
 
125
- describe 'path spec' do
126
- it 'should allow simple path and verify only that path' do
127
- get 'http://example.com/api/v1/simple_path_get'
128
- expect_json_types('address', {street: :string, city: :string, state: :string, coordinates: :object })
129
- #or this
130
- expect_json_types('address', {street: :string, city: :string, state: :string, coordinates: { lattitude: :float, longitude: :float } })
131
- end
132
- end
147
+ ```ruby
148
+ describe 'path spec' do
149
+ it 'should allow simple path and verify only that path' do
150
+ get 'http://example.com/api/v1/simple_path_get'
151
+ expect_json_types('address', {street: :string, city: :string, state: :string, coordinates: :object })
152
+ #or this
153
+ expect_json_types('address', {street: :string, city: :string, state: :string, coordinates: { lattitude: :float, longitude: :float } })
154
+ end
155
+ end
156
+ ```
133
157
 
134
158
  Alternativley, if we only want to test `coordinates` we can dot into just the `coordinates`:
135
159
 
136
- it 'should allow nested paths' do
137
- get 'http://example.com/api/v1/simple_path_get'
138
- expect_json('address.coordinates', {lattitude: 33.3872, longitutde: 104.5281} )
139
- end
160
+ ```ruby
161
+ it 'should allow nested paths' do
162
+ get 'http://example.com/api/v1/simple_path_get'
163
+ expect_json('address.coordinates', {lattitude: 33.3872, longitutde: 104.5281} )
164
+ end
165
+ ```
140
166
 
141
167
  When dealing with `arrays`, we can optionally test all (`*`) or a single (`?` - any, `0` - index) element of the array:
142
168
 
143
169
  Given the following JSON:
144
170
 
171
+ ```json
172
+ {
173
+ "cars": [
174
+ {
175
+ "make": "Tesla",
176
+ "model": "Model S"
177
+ },
145
178
  {
146
- "cars":[
147
- {"make": "Tesla", "model": "Model S"},
148
- {"make": "Lamborghini", "model": "Aventador"}
149
- ]
179
+ "make": "Lamborghini",
180
+ "model": "Aventador"
150
181
  }
182
+ ]
183
+ }
184
+ ```
151
185
 
152
186
  We can test against just the first car like this:
153
187
 
154
- it 'should index into array and test against specific element' do
155
- get '/array_api'
156
- expect_json('cars.0', {make: "Tesla", model: "Model S"})
157
- end
188
+ ```ruby
189
+ it 'should index into array and test against specific element' do
190
+ get '/array_api'
191
+ expect_json('cars.0', {make: "Tesla", model: "Model S"})
192
+ end
193
+ ```
158
194
 
159
195
  To test the types of all elements in the array:
160
196
 
161
- it 'should test all elements of the array' do
162
- get 'http://example.com/api/v1/array_api
163
- expect_json('cars.?', {make: "Tesla", model: "Model S"}) # tests that one car in array matches the tesla
164
- expect_json_types('cars.*', {make: :string, model: :string}) # tests all cars in array for make and model of type string
165
- end
197
+ ```ruby
198
+ it 'should test all elements of the array' do
199
+ get 'http://example.com/api/v1/array_api'
200
+ expect_json('cars.?', {make: "Tesla", model: "Model S"}) # tests that one car in array matches the tesla
201
+ expect_json_types('cars.*', {make: :string, model: :string}) # tests all cars in array for make and model of type string
202
+ end
203
+ ```
166
204
 
167
205
  `*` and `?` work for nested arrays as well. Given the following JSON:
168
206
 
207
+ ```json
208
+ {
209
+ "cars": [
169
210
  {
170
- "cars": [{
171
- "make": "Tesla",
172
- "model": "Model S",
173
- "owners": [{
174
- "name": "Bart Simpson"
175
- }]
176
- }, {
177
- "make": "Lamborghini",
178
- "model": "Aventador",
179
- "owners": [{
180
- "name": "Peter Griffin"
181
- }]
182
- }]
211
+ "make": "Tesla",
212
+ "model": "Model S",
213
+ "owners": [
214
+ {
215
+ "name": "Bart Simpson"
216
+ }
217
+ ]
218
+ },
219
+ {
220
+ "make": "Lamborghini",
221
+ "model": "Aventador",
222
+ "owners": [
223
+ {
224
+ "name": "Peter Griffin"
225
+ }
226
+ ]
183
227
  }
228
+ ]
229
+ }
230
+ ```
184
231
 
185
232
  ===
186
233
 
187
- it 'should check all nested arrays for specified elements' do
188
- get 'http://example.com/api/v1/array_with_nested'
189
- expect_json_types('cars.*.owners.*', {name: :string})
190
- end
191
-
234
+ ```ruby
235
+ it 'should check all nested arrays for specified elements' do
236
+ get 'http://example.com/api/v1/array_with_nested'
237
+ expect_json_types('cars.*.owners.*', {name: :string})
238
+ end
239
+ ```
192
240
 
193
241
  ##Configuration
194
242
 
195
243
  When setting up Airborne, you can call `configure` just like you would with `rspec`:
196
244
 
197
- Airborne.configure.do |config| #config is the RSpec configuration and can be used just like it
198
- config.include MyModule
199
- end
245
+ ```ruby
246
+ #config is the RSpec configuration and can be used just like it
247
+ Airborne.configure.do |config|
248
+ config.include MyModule
249
+ end
250
+ ```
200
251
 
201
252
  Additionally, you can specify a `base_url` and default `headers` to be used on every request (unless overriden in the actual request):
202
253
 
203
- Airborne.configure.do |config|
204
- config.base_url = 'http://example.com/api/v1'
205
- config.headers = {'x-auth-token' => 'my_token'}
206
- end
207
-
208
- describe 'spec' do
209
- it 'now we no longer need the full url' do
210
- get '/simple_get'
211
- expect_json_types({name: :string})
212
- end
213
- end
254
+ ```ruby
255
+ Airborne.configure.do |config|
256
+ config.base_url = 'http://example.com/api/v1'
257
+ config.headers = {'x-auth-token' => 'my_token'}
258
+ end
259
+
260
+ describe 'spec' do
261
+ it 'now we no longer need the full url' do
262
+ get '/simple_get'
263
+ expect_json_types({name: :string})
264
+ end
265
+ end
266
+ ```
214
267
 
215
268
  ## License
216
269
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'airborne'
3
- s.version = '0.0.17'
3
+ s.version = '0.0.18'
4
4
  s.date = '2014-09-12'
5
5
  s.summary = "RSpec driven API testing framework"
6
6
  s.authors = ["Alex Friedman", "Seth Pollack"]
@@ -7,9 +7,9 @@ module Airborne
7
7
  if part == '*' || part == '?'
8
8
  type = part
9
9
  raise "Expected #{path} to be array got #{json.class} from JSON response" unless json.class == Array
10
- if index < parts.length - 1
10
+ if index < parts.length.pred
11
11
  json.each do |element|
12
- sub_path = parts[(index + 1)..(parts.length-1)].join('.')
12
+ sub_path = parts[(index.next)...(parts.length)].join('.')
13
13
  get_by_path(sub_path, element, &block)
14
14
  end
15
15
  return
@@ -21,7 +21,7 @@ module Airborne
21
21
  json = json[part]
22
22
  else
23
23
  json = json[part.to_sym]
24
- raise "Expected #{path} to be object or array got #{json.class} from JSON response" unless json.class == Array || json.class == Hash || json.nil?
24
+ raise "Expected #{path} to be object or array got #{json.class} from JSON response" unless [Array, Hash, NilClass].include?(json.class)
25
25
  end
26
26
  end
27
27
  if type == '*'
@@ -97,6 +97,8 @@ module Airborne
97
97
  value = hash[prop_name]
98
98
  if expected_type.class == Hash || expected_type.class == Airborne::OptionalHashTypeExpectations
99
99
  expect_json_types_impl(expected_type, value)
100
+ elsif expected_type.class == Proc
101
+ expected_type.call(value)
100
102
  elsif expected_type.to_s.include?("array_of")
101
103
  expect(value.class).to eq(Array), "Expected #{prop_name} to be of type #{expected_type}, got #{value.class} instead"
102
104
  value.each do |val|
@@ -111,9 +113,9 @@ module Airborne
111
113
  def expect_json_impl(expectations, hash)
112
114
  expectations.each do |prop_name, expected_value|
113
115
  actual_value = hash[prop_name]
114
- if(expected_value.class == Hash)
116
+ if expected_value.class == Hash
115
117
  expect_json_impl(expected_value, actual_value)
116
- elsif(expected_value.class == Proc)
118
+ elsif expected_value.class == Proc
117
119
  expected_value.call(actual_value)
118
120
  else
119
121
  expect(expected_value).to eq(actual_value)
@@ -96,4 +96,10 @@ describe 'expect_json_types' do
96
96
  get '/simple_path_get'
97
97
  expect_json_types("address.coordinates", optional({lattitude: :float, longitutde: :float}))
98
98
  end
99
+
100
+ it 'should invoke proc passed in' do
101
+ mock_get('simple_get')
102
+ get '/simple_get'
103
+ expect_json_types({name: -> (name){expect(name.length).to eq(4)}})
104
+ end
99
105
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: airborne
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.17
4
+ version: 0.0.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Friedman