airborne 0.0.17 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
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