airborne 0.0.23 → 0.1.1
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 +25 -2
- data/airborne.gemspec +2 -2
- data/lib/airborne/path_matcher.rb +2 -2
- data/lib/airborne/request_expectations.rb +76 -36
- data/spec/airborne/expectations/expect_json_types_date.rb +29 -0
- data/spec/test_responses/date_response.json +3 -0
- metadata +26 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e39fcf812c0db731f927d6d8d3958af460d32d45
|
4
|
+
data.tar.gz: 0d57d02c7d3ab02be5043c454b6a77cffc44a234
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 413820ceb078ed9d209c7fe1cd746222bae68b18453102194a75be1929cba97a01868eaf3d699d7b8491841947cd01e7e330d2a9c4321352a790422e9e0fa540
|
7
|
+
data.tar.gz: ac22937b6c71ab214c89fa778d7c255433cc08c96c1d401d84b2b859142e86ce835086046473f3f7678c3b122a5ad67bf4178832514506b147b08378fc1f2d2b
|
data/README.md
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
[](https://travis-ci.org/brooklynDev/airborne)
|
4
4
|
[](https://coveralls.io/r/brooklynDev/airborne?branch=master)
|
5
|
+
[](https://codeclimate.com/github/brooklynDev/airborne)
|
5
6
|
[](http://rubygems.org/gems/airborne)
|
6
7
|
[](http://rubygems.org/gems/airborne)
|
7
8
|
[](http://rubygems.org/gems/airborne)
|
@@ -42,6 +43,7 @@ When calling expect_json_types, these are the valid types that can be tested aga
|
|
42
43
|
* `:float`
|
43
44
|
* `:bool` or `:boolean`
|
44
45
|
* `:string`
|
46
|
+
* `:date`
|
45
47
|
* `:object`
|
46
48
|
* `:array`
|
47
49
|
* `:array_of_integers` or `:array_of_ints`
|
@@ -288,13 +290,34 @@ it 'should check all nested arrays for specified elements' do
|
|
288
290
|
end
|
289
291
|
```
|
290
292
|
|
293
|
+
##Dates
|
294
|
+
JSON has no support for dates, however airborne gives you the ability to check for dates using the following. For `expect_json_types` you would use it as you would for any of the other types:
|
295
|
+
|
296
|
+
```ruby
|
297
|
+
it 'should verify date type' do
|
298
|
+
get '/get_date' #api that returns {createdAt: "Mon Oct 20 2014 16:10:42 GMT-0400 (EDT)"}
|
299
|
+
expect_json_types({createdAt: :date})
|
300
|
+
end
|
301
|
+
```
|
302
|
+
However if you want to check the actual date data with `expect_json`, you need to call the `date` function:
|
303
|
+
|
304
|
+
```ruby
|
305
|
+
it 'should verify correct date value' do
|
306
|
+
get '/get_date' #api that returns {createdAt: "Mon Oct 20 2014 16:10:42 GMT-0400 (EDT)"}
|
307
|
+
prev_day = DateTime.new(2014,10,19)
|
308
|
+
next_day = DateTime.new(2014,10,21)
|
309
|
+
#within the date callback, you can use regular RSpec expectations that work with dates
|
310
|
+
expect_json({createdAt: date {|value| expect(value).to be_between(prev_day, next_day)}})
|
311
|
+
end
|
312
|
+
```
|
313
|
+
|
291
314
|
##Configuration
|
292
315
|
|
293
316
|
When setting up Airborne, you can call `configure` just like you would with `rspec`:
|
294
317
|
|
295
318
|
```ruby
|
296
319
|
#config is the RSpec configuration and can be used just like it
|
297
|
-
Airborne.configure
|
320
|
+
Airborne.configure do |config|
|
298
321
|
config.include MyModule
|
299
322
|
end
|
300
323
|
```
|
@@ -302,7 +325,7 @@ end
|
|
302
325
|
Additionally, you can specify a `base_url` and default `headers` to be used on every request (unless overridden in the actual request):
|
303
326
|
|
304
327
|
```ruby
|
305
|
-
Airborne.configure
|
328
|
+
Airborne.configure do |config|
|
306
329
|
config.base_url = 'http://example.com/api/v1'
|
307
330
|
config.headers = {'x-auth-token' => 'my_token'}
|
308
331
|
end
|
data/airborne.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'airborne'
|
3
|
-
s.version = '0.
|
4
|
-
s.date = '2014-
|
3
|
+
s.version = '0.1.1'
|
4
|
+
s.date = '2014-10-20'
|
5
5
|
s.summary = "RSpec driven API testing framework"
|
6
6
|
s.authors = ["Alex Friedman", "Seth Pollack"]
|
7
7
|
s.email = ['a.friedman07@gmail.com', 'teampollack@gmail.com']
|
@@ -82,7 +82,7 @@ module Airborne
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def ensure_match_one(path, item_count, error_count)
|
85
|
-
raise "Expected one object in path #{path} to match provided JSON values" if item_count == error_count
|
85
|
+
raise RSpec::Expectations::ExpectationNotMetError, "Expected one object in path #{path} to match provided JSON values" if item_count == error_count
|
86
86
|
end
|
87
87
|
|
88
88
|
def ensure_match_all(error)
|
@@ -90,7 +90,7 @@ module Airborne
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def ensure_array(path, json)
|
93
|
-
raise "Expected #{path} to be array got #{json.class} from JSON response" unless json.class == Array
|
93
|
+
raise RSpec::Expectations::ExpectationNotMetError, "Expected #{path} to be array got #{json.class} from JSON response" unless json.class == Array
|
94
94
|
end
|
95
95
|
|
96
96
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rspec'
|
2
|
+
require 'date'
|
2
3
|
|
3
4
|
module Airborne
|
4
5
|
module RequestExpectations
|
@@ -28,21 +29,11 @@ module Airborne
|
|
28
29
|
end
|
29
30
|
|
30
31
|
def expect_header(key, content)
|
31
|
-
|
32
|
-
if header
|
33
|
-
expect(header.downcase).to eq(content.downcase)
|
34
|
-
else
|
35
|
-
raise "Header #{key} not present in HTTP response"
|
36
|
-
end
|
32
|
+
expect_header_impl(key, content)
|
37
33
|
end
|
38
34
|
|
39
35
|
def expect_header_contains(key, content)
|
40
|
-
|
41
|
-
if header
|
42
|
-
expect(header.downcase).to include(content.downcase)
|
43
|
-
else
|
44
|
-
raise "Header #{key} not present in HTTP response"
|
45
|
-
end
|
36
|
+
expect_header_impl(key, content, true)
|
46
37
|
end
|
47
38
|
|
48
39
|
def optional(hash)
|
@@ -53,6 +44,10 @@ module Airborne
|
|
53
44
|
Regexp.new(reg)
|
54
45
|
end
|
55
46
|
|
47
|
+
def date
|
48
|
+
lambda {|value| yield DateTime.parse(value)}
|
49
|
+
end
|
50
|
+
|
56
51
|
[:expect_json_types, :expect_json, :expect_json_keys, :expect_status, :expect_header, :expect_header_contains].each do |method_name|
|
57
52
|
method = instance_method(method_name)
|
58
53
|
define_method(method_name) do |*args, &block|
|
@@ -63,6 +58,19 @@ module Airborne
|
|
63
58
|
|
64
59
|
private
|
65
60
|
|
61
|
+
def expect_header_impl(key, content, contains = nil)
|
62
|
+
header = headers[key]
|
63
|
+
if header
|
64
|
+
if contains
|
65
|
+
expect(header.downcase).to include(content.downcase)
|
66
|
+
else
|
67
|
+
expect(header.downcase).to eq(content.downcase)
|
68
|
+
end
|
69
|
+
else
|
70
|
+
raise RSpec::Expectations::ExpectationNotMetError, "Header #{key} not present in HTTP response"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
66
74
|
def set_rails_response
|
67
75
|
set_response(@response) if @json_body.nil?
|
68
76
|
end
|
@@ -94,7 +102,8 @@ module Airborne
|
|
94
102
|
object: [Hash],
|
95
103
|
array_of_objects: [Hash],
|
96
104
|
array: [Array],
|
97
|
-
array_of_arrays: [Array]
|
105
|
+
array_of_arrays: [Array],
|
106
|
+
date: [DateTime]
|
98
107
|
}
|
99
108
|
|
100
109
|
mapper = base_mapper.clone
|
@@ -105,41 +114,72 @@ module Airborne
|
|
105
114
|
end
|
106
115
|
|
107
116
|
def expect_json_types_impl(expectations, hash)
|
108
|
-
return if expectations
|
117
|
+
return if is_nil_optional_hash?(expectations, hash)
|
109
118
|
@mapper ||= get_mapper
|
110
|
-
|
119
|
+
hash = convert_to_date(hash) if expectations == :date
|
120
|
+
return expect_type(expectations, hash.class) if expectations.class == Symbol
|
111
121
|
expectations.each do |prop_name, expected_type|
|
112
|
-
value = hash[prop_name]
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
value.each do |val|
|
120
|
-
expect(@mapper[expected_type].include?(val.class)).to eq(true), "Expected #{prop_name} to be of type #{expected_type}, got #{val.class} instead"
|
121
|
-
end
|
122
|
+
value = expected_type == :date ? convert_to_date(hash[prop_name]) : hash[prop_name]
|
123
|
+
expected_class = expected_type.class
|
124
|
+
value_class = value.class
|
125
|
+
next expect_json_types_impl(expected_type, value) if is_hash?(expected_class)
|
126
|
+
next expected_type.call(value) if expected_class == Proc
|
127
|
+
if expected_type.to_s.include?("array_of")
|
128
|
+
check_array_types(value, value_class, prop_name, expected_type)
|
122
129
|
else
|
123
|
-
|
130
|
+
expect_type(expected_type, value_class, prop_name)
|
124
131
|
end
|
125
132
|
end
|
126
133
|
end
|
127
134
|
|
135
|
+
def convert_to_date(value)
|
136
|
+
begin
|
137
|
+
value = DateTime.parse(value)
|
138
|
+
rescue
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def check_array_types(value, value_class, prop_name, expected_type)
|
143
|
+
expect_array(value_class, prop_name, expected_type)
|
144
|
+
value.each do |val|
|
145
|
+
expect_type(expected_type, val.class, prop_name)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def is_nil_optional_hash?(expectations, hash)
|
150
|
+
expectations.class == Airborne::OptionalHashTypeExpectations && hash.nil?
|
151
|
+
end
|
152
|
+
|
153
|
+
def expect_type(expected_type, value_class, prop_name = nil)
|
154
|
+
insert = prop_name.nil? ? "" : "#{prop_name} to be of type"
|
155
|
+
msg = "Expected #{insert} #{expected_type}\n, got #{value_class} instead"
|
156
|
+
expect(@mapper[expected_type].include?(value_class)).to eq(true), msg
|
157
|
+
end
|
158
|
+
|
159
|
+
def is_hash?(expected_class)
|
160
|
+
expected_class == Hash || expected_class == Airborne::OptionalHashTypeExpectations
|
161
|
+
end
|
162
|
+
|
163
|
+
def expect_array(value_class, prop_name, expected_type)
|
164
|
+
expect(value_class).to eq(Array), "Expected #{prop_name}\n to be of type #{expected_type}\n, got #{value_class} instead"
|
165
|
+
end
|
166
|
+
|
128
167
|
def expect_json_impl(expectations, hash)
|
129
168
|
hash = hash.to_s if expectations.class == Regexp
|
130
|
-
return expect(hash).to match(expectations) if
|
169
|
+
return expect(hash).to match(expectations) if is_property?(expectations)
|
131
170
|
expectations.each do |prop_name, expected_value|
|
132
171
|
actual_value = hash[prop_name]
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
expect(actual_value.to_s).to match(expected_value)
|
139
|
-
else
|
140
|
-
expect(actual_value).to eq(expected_value)
|
141
|
-
end
|
172
|
+
expected_class = expected_value.class
|
173
|
+
next expect_json_impl(expected_value, actual_value) if expected_class == Hash
|
174
|
+
next expected_value.call(actual_value) if expected_class == Proc
|
175
|
+
next expect(actual_value.to_s).to match(expected_value) if expected_class == Regexp
|
176
|
+
expect(actual_value).to eq(expected_value)
|
142
177
|
end
|
143
178
|
end
|
179
|
+
|
180
|
+
def is_property?(expectations)
|
181
|
+
[String, Regexp, Float, Fixnum, Bignum, TrueClass, FalseClass, NilClass].include?(expectations.class)
|
182
|
+
end
|
183
|
+
|
144
184
|
end
|
145
185
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
describe 'expect_json_types with date' do
|
5
|
+
it 'should verify correct date types' do
|
6
|
+
mock_get('date_response')
|
7
|
+
get '/date_response'
|
8
|
+
|
9
|
+
expect_json_types({createdAt: :date})
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should verify correct date types with path' do
|
13
|
+
mock_get('date_response')
|
14
|
+
get '/date_response'
|
15
|
+
|
16
|
+
expect_json_types("createdAt", :date)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'expect_json with date' do
|
21
|
+
it 'should verify correct date value' do
|
22
|
+
mock_get('date_response')
|
23
|
+
get '/date_response'
|
24
|
+
|
25
|
+
prev_day = DateTime.new(2014,10,19)
|
26
|
+
next_day = DateTime.new(2014,10,21)
|
27
|
+
expect_json({createdAt: date {|value| expect(value).to be_between(prev_day, next_day)}})
|
28
|
+
end
|
29
|
+
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.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Friedman
|
@@ -9,94 +9,94 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-10-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- - ~>
|
18
|
+
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: '3.1'
|
21
|
-
- -
|
21
|
+
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
23
|
version: 3.1.0
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
26
|
version_requirements: !ruby/object:Gem::Requirement
|
27
27
|
requirements:
|
28
|
-
- - ~>
|
28
|
+
- - "~>"
|
29
29
|
- !ruby/object:Gem::Version
|
30
30
|
version: '3.1'
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: 3.1.0
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
35
|
name: rest-client
|
36
36
|
requirement: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.7'
|
41
|
-
- -
|
41
|
+
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
version: 1.7.2
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
46
|
version_requirements: !ruby/object:Gem::Requirement
|
47
47
|
requirements:
|
48
|
-
- - ~>
|
48
|
+
- - "~>"
|
49
49
|
- !ruby/object:Gem::Version
|
50
50
|
version: '1.7'
|
51
|
-
- -
|
51
|
+
- - ">="
|
52
52
|
- !ruby/object:Gem::Version
|
53
53
|
version: 1.7.2
|
54
54
|
- !ruby/object:Gem::Dependency
|
55
55
|
name: rack-test
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
|
-
- - ~>
|
58
|
+
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '0.6'
|
61
|
-
- -
|
61
|
+
- - ">="
|
62
62
|
- !ruby/object:Gem::Version
|
63
63
|
version: 0.6.2
|
64
64
|
type: :runtime
|
65
65
|
prerelease: false
|
66
66
|
version_requirements: !ruby/object:Gem::Requirement
|
67
67
|
requirements:
|
68
|
-
- - ~>
|
68
|
+
- - "~>"
|
69
69
|
- !ruby/object:Gem::Version
|
70
70
|
version: '0.6'
|
71
|
-
- -
|
71
|
+
- - ">="
|
72
72
|
- !ruby/object:Gem::Version
|
73
73
|
version: 0.6.2
|
74
74
|
- !ruby/object:Gem::Dependency
|
75
75
|
name: activesupport
|
76
76
|
requirement: !ruby/object:Gem::Requirement
|
77
77
|
requirements:
|
78
|
-
- -
|
78
|
+
- - ">="
|
79
79
|
- !ruby/object:Gem::Version
|
80
80
|
version: 4.0.1
|
81
81
|
type: :runtime
|
82
82
|
prerelease: false
|
83
83
|
version_requirements: !ruby/object:Gem::Requirement
|
84
84
|
requirements:
|
85
|
-
- -
|
85
|
+
- - ">="
|
86
86
|
- !ruby/object:Gem::Version
|
87
87
|
version: 4.0.1
|
88
88
|
- !ruby/object:Gem::Dependency
|
89
89
|
name: webmock
|
90
90
|
requirement: !ruby/object:Gem::Requirement
|
91
91
|
requirements:
|
92
|
-
- - ~>
|
92
|
+
- - "~>"
|
93
93
|
- !ruby/object:Gem::Version
|
94
94
|
version: '0'
|
95
95
|
type: :development
|
96
96
|
prerelease: false
|
97
97
|
version_requirements: !ruby/object:Gem::Requirement
|
98
98
|
requirements:
|
99
|
-
- - ~>
|
99
|
+
- - "~>"
|
100
100
|
- !ruby/object:Gem::Version
|
101
101
|
version: '0'
|
102
102
|
description:
|
@@ -107,9 +107,9 @@ executables: []
|
|
107
107
|
extensions: []
|
108
108
|
extra_rdoc_files: []
|
109
109
|
files:
|
110
|
-
- .coveralls.yml
|
111
|
-
- .gitignore
|
112
|
-
- .travis.yml
|
110
|
+
- ".coveralls.yml"
|
111
|
+
- ".gitignore"
|
112
|
+
- ".travis.yml"
|
113
113
|
- Gemfile
|
114
114
|
- Gemfile.lock
|
115
115
|
- LICENSE
|
@@ -132,6 +132,7 @@ files:
|
|
132
132
|
- spec/airborne/expectations/expect_json_path_spec.rb
|
133
133
|
- spec/airborne/expectations/expect_json_regex_spec.rb
|
134
134
|
- spec/airborne/expectations/expect_json_spec.rb
|
135
|
+
- spec/airborne/expectations/expect_json_types_date.rb
|
135
136
|
- spec/airborne/expectations/expect_json_types_lambda_spec.rb
|
136
137
|
- spec/airborne/expectations/expect_json_types_optional_spec.rb
|
137
138
|
- spec/airborne/expectations/expect_json_types_path_spec.rb
|
@@ -148,6 +149,7 @@ files:
|
|
148
149
|
- spec/test_responses/array_with_index.json
|
149
150
|
- spec/test_responses/array_with_nested.json
|
150
151
|
- spec/test_responses/array_with_nested_bad_data.json
|
152
|
+
- spec/test_responses/date_response.json
|
151
153
|
- spec/test_responses/invalid_get.json
|
152
154
|
- spec/test_responses/simple_get.json
|
153
155
|
- spec/test_responses/simple_json.json
|
@@ -166,17 +168,17 @@ require_paths:
|
|
166
168
|
- lib
|
167
169
|
required_ruby_version: !ruby/object:Gem::Requirement
|
168
170
|
requirements:
|
169
|
-
- -
|
171
|
+
- - ">="
|
170
172
|
- !ruby/object:Gem::Version
|
171
173
|
version: '0'
|
172
174
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
173
175
|
requirements:
|
174
|
-
- -
|
176
|
+
- - ">="
|
175
177
|
- !ruby/object:Gem::Version
|
176
178
|
version: '0'
|
177
179
|
requirements: []
|
178
180
|
rubyforge_project:
|
179
|
-
rubygems_version: 2.
|
181
|
+
rubygems_version: 2.2.0
|
180
182
|
signing_key:
|
181
183
|
specification_version: 4
|
182
184
|
summary: RSpec driven API testing framework
|