hyperspec 0.0.2 → 0.0.3
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.
- data/.travis.yml +10 -0
- data/README.md +2 -0
- data/hyperspec.gemspec +20 -15
- data/lib/hyperspec.rb +100 -16
- data/lib/hyperspec/version.rb +1 -1
- data/spec/hyperspec_spec.rb +73 -3
- metadata +74 -59
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -10,6 +10,8 @@ A full stack testing framework for HTTP APIs.
|
|
10
10
|
By extending `minitest/spec` HyperSpec provides a Ruby DSL for testing
|
11
11
|
HTTP APIs from the outside.
|
12
12
|
|
13
|
+
[](http://travis-ci.org/hannestyden/hyperspec)
|
14
|
+
|
13
15
|
## Example
|
14
16
|
|
15
17
|
```ruby
|
data/hyperspec.gemspec
CHANGED
@@ -3,22 +3,27 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
require "hyperspec/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
|
-
s.name
|
7
|
-
s.version
|
8
|
-
s.authors
|
9
|
-
s.email
|
10
|
-
s.homepage
|
11
|
-
s.summary
|
6
|
+
s.name = "hyperspec"
|
7
|
+
s.version = HyperSpec::VERSION
|
8
|
+
s.authors = [ "Hannes Tydén" ]
|
9
|
+
s.email = [ "hannes@soundcloud.com" ]
|
10
|
+
s.homepage = "http://github.com/hannestyden/hyperspec"
|
11
|
+
s.summary = "Full stack HTTP API testing DSL."
|
12
|
+
|
12
13
|
s.description = <<-DESCRIPTION
|
13
|
-
By extending minitest/spec HyperSpec provides a Ruby DSL for testing
|
14
|
+
By extending minitest/spec HyperSpec provides a Ruby DSL for testing
|
15
|
+
HTTP APIs from the "outside".
|
14
16
|
DESCRIPTION
|
15
17
|
|
16
18
|
# Required for validation.
|
17
19
|
s.rubyforge_project = "hyperspec"
|
18
20
|
|
19
|
-
s.files
|
20
|
-
s.test_files
|
21
|
-
|
21
|
+
s.files = `git ls-files`.split("\n")
|
22
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
23
|
+
|
24
|
+
s.executables = `git ls-files -- bin/*`.
|
25
|
+
split("\n").map { |f| File.basename(f) }
|
26
|
+
|
22
27
|
s.require_paths = [ "lib" ]
|
23
28
|
|
24
29
|
dependencies =
|
@@ -28,17 +33,17 @@ Gem::Specification.new do |s|
|
|
28
33
|
|
29
34
|
developement_dependencies =
|
30
35
|
[
|
31
|
-
[ "vcr",
|
32
|
-
[ "
|
36
|
+
[ "vcr", "~> 1.6" ],
|
37
|
+
[ "fakeweb" ],
|
33
38
|
]
|
34
39
|
|
35
|
-
runtime_dependencies
|
40
|
+
runtime_dependencies = []
|
36
41
|
|
37
42
|
(dependencies + developement_dependencies).each do |dependency|
|
38
|
-
s.add_development_dependency
|
43
|
+
s.add_development_dependency(*dependency)
|
39
44
|
end
|
40
45
|
|
41
46
|
(dependencies + runtime_dependencies).each do |dependency|
|
42
|
-
s.add_runtime_dependency
|
47
|
+
s.add_runtime_dependency(*dependency)
|
43
48
|
end
|
44
49
|
end
|
data/lib/hyperspec.rb
CHANGED
@@ -61,18 +61,32 @@ module HyperSpec
|
|
61
61
|
|
62
62
|
# HTTP method selection
|
63
63
|
#
|
64
|
-
|
65
|
-
|
66
|
-
'
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
64
|
+
# Hard coded method definitions is required for 1.8.7 compatibility.
|
65
|
+
def get(additional_desc = nil, &block)
|
66
|
+
_request('get', Net::HTTP::Get, additional_desc, &block)
|
67
|
+
end
|
68
|
+
|
69
|
+
def head(additional_desc = nil, &block)
|
70
|
+
_request('head', Net::HTTP::Head, additional_desc, &block)
|
71
|
+
end
|
72
|
+
|
73
|
+
def post(additional_desc = nil, &block)
|
74
|
+
_request('post', Net::HTTP::Post, additional_desc, &block)
|
75
|
+
end
|
76
|
+
|
77
|
+
def put(additional_desc = nil, &block)
|
78
|
+
_request('put', Net::HTTP::Put, additional_desc, &block)
|
79
|
+
end
|
80
|
+
|
81
|
+
def delete(additional_desc = nil, &block)
|
82
|
+
_request('delete', Net::HTTP::Delete, additional_desc, &block)
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
def _request(http_method, request_class, additional_desc, &block)
|
87
|
+
describe(http_method.upcase, additional_desc, &block).tap do |cls|
|
88
|
+
cls.class_eval do
|
89
|
+
define_method(:request_class) { request_class }
|
76
90
|
end
|
77
91
|
end
|
78
92
|
end
|
@@ -85,7 +99,7 @@ module HyperSpec
|
|
85
99
|
end
|
86
100
|
|
87
101
|
def responds_with
|
88
|
-
|
102
|
+
RespondsWith.new(response)
|
89
103
|
end
|
90
104
|
|
91
105
|
private
|
@@ -120,18 +134,77 @@ module HyperSpec
|
|
120
134
|
end
|
121
135
|
end
|
122
136
|
|
137
|
+
class UnkownStatusCodeError < StandardError; end
|
138
|
+
|
123
139
|
Response = Struct.new(:status_code, :headers, :body) do
|
124
140
|
STATI = {
|
125
|
-
#
|
141
|
+
# RFC 2616 - HTTP 1.1
|
142
|
+
## Informational
|
143
|
+
100 => :continue,
|
144
|
+
101 => :switching_protocols,
|
145
|
+
|
146
|
+
## Successful 2xx
|
126
147
|
200 => :ok,
|
127
148
|
201 => :created,
|
149
|
+
202 => :accepted,
|
150
|
+
203 => :non_authoritative_information,
|
151
|
+
204 => :no_content,
|
152
|
+
205 => :reset_content,
|
153
|
+
206 => :partial_content,
|
128
154
|
|
129
|
-
|
155
|
+
## Redirection 3xx
|
156
|
+
300 => :multiple_choices,
|
157
|
+
301 => :moved_permanently,
|
158
|
+
302 => :found,
|
159
|
+
303 => :see_other,
|
160
|
+
304 => :not_modified,
|
161
|
+
305 => :use_proxy,
|
162
|
+
# 306 => :(Unused),
|
163
|
+
307 => :temporary_redirect,
|
164
|
+
|
165
|
+
## Client Error 4xx,
|
166
|
+
400 => :bad_request,
|
130
167
|
401 => :unauthorized,
|
168
|
+
402 => :payment_required,
|
169
|
+
403 => :forbidden,
|
170
|
+
404 => :not_found,
|
171
|
+
405 => :method_not_allowed,
|
172
|
+
406 => :not_acceptable,
|
173
|
+
407 => :proxy_authentication_required,
|
174
|
+
408 => :request_timeout,
|
175
|
+
409 => :conflict,
|
176
|
+
410 => :gone,
|
131
177
|
411 => :length_required,
|
178
|
+
412 => :precondition_failed,
|
179
|
+
413 => :request_entity_too_large,
|
180
|
+
414 => :request_uri_too_long,
|
181
|
+
415 => :unsupported_media_type,
|
182
|
+
416 => :requested_range_not_satisfiable,
|
183
|
+
417 => :expectation_failed,
|
184
|
+
|
185
|
+
## Server Error 5xx
|
186
|
+
500 => :internal_server_error,
|
187
|
+
501 => :not_implemented,
|
188
|
+
502 => :bad_gateway,
|
189
|
+
503 => :service_unavailable,
|
190
|
+
504 => :gateway_timeout,
|
191
|
+
505 => :http_version_not_supported,
|
192
|
+
|
193
|
+
# RFC 2324
|
194
|
+
418 => :im_a_teapot,
|
132
195
|
|
133
|
-
# WebDav
|
196
|
+
# RFC 4918 - WebDav
|
197
|
+
207 => :multi_status,
|
134
198
|
422 => :unprocessable_entity,
|
199
|
+
423 => :locked,
|
200
|
+
424 => :failed_dependency,
|
201
|
+
507 => :insufficient_storage,
|
202
|
+
|
203
|
+
# RFC 6585 - Additional HTTP Status Codes
|
204
|
+
428 => :precondition_required,
|
205
|
+
429 => :too_many_requests,
|
206
|
+
431 => :request_header_fields_too_large,
|
207
|
+
511 => :network_authentication_required,
|
135
208
|
}
|
136
209
|
|
137
210
|
def self.from_net_http_response(http)
|
@@ -179,6 +252,17 @@ module HyperSpec
|
|
179
252
|
proxy.send(method_name).must_equal(*arguments)
|
180
253
|
end
|
181
254
|
end
|
255
|
+
|
256
|
+
class RespondsWith < Have
|
257
|
+
def status(status_code_symbol)
|
258
|
+
if STATI.has_value?(status_code_symbol)
|
259
|
+
proxy.status.must_equal(status_code_symbol)
|
260
|
+
else
|
261
|
+
raise UnkownStatusCodeError,
|
262
|
+
"Status code #{status_code_symbol.inspect} is unkown."
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
182
266
|
end
|
183
267
|
|
184
268
|
::Object.send(:include, HyperSpec::ObjectExtensions)
|
data/lib/hyperspec/version.rb
CHANGED
data/spec/hyperspec_spec.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'uri'
|
2
2
|
|
3
|
-
|
3
|
+
# Ensure gem is used over 1.9.x built in.
|
4
|
+
gem 'minitest' if RUBY_VERSION =~ /1.9.\d/
|
5
|
+
|
4
6
|
require 'minitest/spec'
|
5
7
|
require 'minitest/autorun'
|
6
8
|
|
@@ -21,8 +23,8 @@ describe HyperSpec do
|
|
21
23
|
|
22
24
|
use_vcr_cassette('localhost')
|
23
25
|
|
24
|
-
it "should be of version 0.0.
|
25
|
-
HyperSpec::VERSION.must_equal "0.0.
|
26
|
+
it "should be of version 0.0.2" do
|
27
|
+
HyperSpec::VERSION.must_equal "0.0.2"
|
26
28
|
end
|
27
29
|
|
28
30
|
describe "MiniTest::Spec extensions" do
|
@@ -161,11 +163,73 @@ describe HyperSpec do
|
|
161
163
|
|
162
164
|
describe "status" do
|
163
165
|
{
|
166
|
+
# RFC 2616 - HTTP 1.1
|
167
|
+
## Informational
|
168
|
+
100 => :continue,
|
169
|
+
101 => :switching_protocols,
|
170
|
+
|
171
|
+
## Successful 2xx
|
164
172
|
200 => :ok,
|
165
173
|
201 => :created,
|
174
|
+
202 => :accepted,
|
175
|
+
203 => :non_authoritative_information,
|
176
|
+
204 => :no_content,
|
177
|
+
205 => :reset_content,
|
178
|
+
206 => :partial_content,
|
179
|
+
|
180
|
+
## Redirection 3xx
|
181
|
+
300 => :multiple_choices,
|
182
|
+
301 => :moved_permanently,
|
183
|
+
302 => :found,
|
184
|
+
303 => :see_other,
|
185
|
+
304 => :not_modified,
|
186
|
+
305 => :use_proxy,
|
187
|
+
# 306 => :(Unused),
|
188
|
+
307 => :temporary_redirect,
|
189
|
+
|
190
|
+
## Client Error 4xx,
|
191
|
+
400 => :bad_request,
|
166
192
|
401 => :unauthorized,
|
193
|
+
402 => :payment_required,
|
194
|
+
403 => :forbidden,
|
195
|
+
404 => :not_found,
|
196
|
+
405 => :method_not_allowed,
|
197
|
+
406 => :not_acceptable,
|
198
|
+
407 => :proxy_authentication_required,
|
199
|
+
408 => :request_timeout,
|
200
|
+
409 => :conflict,
|
201
|
+
410 => :gone,
|
167
202
|
411 => :length_required,
|
203
|
+
412 => :precondition_failed,
|
204
|
+
413 => :request_entity_too_large,
|
205
|
+
414 => :request_uri_too_long,
|
206
|
+
415 => :unsupported_media_type,
|
207
|
+
416 => :requested_range_not_satisfiable,
|
208
|
+
417 => :expectation_failed,
|
209
|
+
|
210
|
+
## Server Error 5xx
|
211
|
+
500 => :internal_server_error,
|
212
|
+
501 => :not_implemented,
|
213
|
+
502 => :bad_gateway,
|
214
|
+
503 => :service_unavailable,
|
215
|
+
504 => :gateway_timeout,
|
216
|
+
505 => :http_version_not_supported,
|
217
|
+
|
218
|
+
# RFC 2324
|
219
|
+
418 => :im_a_teapot,
|
220
|
+
|
221
|
+
# RFC 4918 - WebDav
|
222
|
+
207 => :multi_status,
|
168
223
|
422 => :unprocessable_entity,
|
224
|
+
423 => :locked,
|
225
|
+
424 => :failed_dependency,
|
226
|
+
507 => :insufficient_storage,
|
227
|
+
|
228
|
+
# RFC 6585 - Additional HTTP Status Codes
|
229
|
+
428 => :precondition_required,
|
230
|
+
429 => :too_many_requests,
|
231
|
+
431 => :request_header_fields_too_large,
|
232
|
+
511 => :network_authentication_required,
|
169
233
|
}.each do |code, status|
|
170
234
|
it do
|
171
235
|
subject.status_code = code
|
@@ -203,6 +267,12 @@ describe HyperSpec do
|
|
203
267
|
|
204
268
|
it { subject.status_code 200 }
|
205
269
|
it { subject.status :ok }
|
270
|
+
|
271
|
+
it do
|
272
|
+
lambda do
|
273
|
+
subject.status :this_is_not_known
|
274
|
+
end.must_raise HyperSpec::UnkownStatusCodeError
|
275
|
+
end
|
206
276
|
end
|
207
277
|
|
208
278
|
describe "basic auth" do
|
metadata
CHANGED
@@ -1,72 +1,90 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: hyperspec
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
4
5
|
prerelease:
|
5
|
-
version: 0.0.2
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
8
|
-
-
|
7
|
+
authors:
|
8
|
+
- Hannes Tydén
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-08-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
16
15
|
name: minitest
|
17
|
-
|
18
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
19
17
|
none: false
|
20
|
-
requirements:
|
18
|
+
requirements:
|
21
19
|
- - ~>
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version:
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.11'
|
24
22
|
type: :development
|
25
|
-
version_requirements: *id001
|
26
|
-
- !ruby/object:Gem::Dependency
|
27
|
-
name: vcr
|
28
23
|
prerelease: false
|
29
|
-
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
25
|
none: false
|
31
|
-
requirements:
|
26
|
+
requirements:
|
32
27
|
- - ~>
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version:
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.11'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: vcr
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '1.6'
|
35
38
|
type: :development
|
36
|
-
version_requirements: *id002
|
37
|
-
- !ruby/object:Gem::Dependency
|
38
|
-
name: webmock
|
39
39
|
prerelease: false
|
40
|
-
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.6'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: fakeweb
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
41
49
|
none: false
|
42
|
-
requirements:
|
43
|
-
- -
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version:
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
46
54
|
type: :development
|
47
|
-
version_requirements: *id003
|
48
|
-
- !ruby/object:Gem::Dependency
|
49
|
-
name: minitest
|
50
55
|
prerelease: false
|
51
|
-
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: minitest
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
52
65
|
none: false
|
53
|
-
requirements:
|
66
|
+
requirements:
|
54
67
|
- - ~>
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
version:
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '2.11'
|
57
70
|
type: :runtime
|
58
|
-
|
59
|
-
|
60
|
-
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '2.11'
|
78
|
+
description: ! " By extending minitest/spec HyperSpec provides a Ruby DSL for testing\n
|
79
|
+
\ HTTP APIs from the \"outside\".\n"
|
80
|
+
email:
|
61
81
|
- hannes@soundcloud.com
|
62
82
|
executables: []
|
63
|
-
|
64
83
|
extensions: []
|
65
|
-
|
66
84
|
extra_rdoc_files: []
|
67
|
-
|
68
|
-
files:
|
85
|
+
files:
|
69
86
|
- .gitignore
|
87
|
+
- .travis.yml
|
70
88
|
- Gemfile
|
71
89
|
- README.md
|
72
90
|
- Rakefile
|
@@ -82,32 +100,29 @@ files:
|
|
82
100
|
- spec/support/vcr.rb
|
83
101
|
homepage: http://github.com/hannestyden/hyperspec
|
84
102
|
licenses: []
|
85
|
-
|
86
103
|
post_install_message:
|
87
104
|
rdoc_options: []
|
88
|
-
|
89
|
-
require_paths:
|
105
|
+
require_paths:
|
90
106
|
- lib
|
91
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
108
|
none: false
|
93
|
-
requirements:
|
94
|
-
- -
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version:
|
97
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ! '>='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
114
|
none: false
|
99
|
-
requirements:
|
100
|
-
- -
|
101
|
-
- !ruby/object:Gem::Version
|
102
|
-
version:
|
115
|
+
requirements:
|
116
|
+
- - ! '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
103
119
|
requirements: []
|
104
|
-
|
105
120
|
rubyforge_project: hyperspec
|
106
|
-
rubygems_version: 1.8.
|
121
|
+
rubygems_version: 1.8.24
|
107
122
|
signing_key:
|
108
123
|
specification_version: 3
|
109
124
|
summary: Full stack HTTP API testing DSL.
|
110
|
-
test_files:
|
125
|
+
test_files:
|
111
126
|
- spec/fixtures/vcr_cassettes/localhost.yml
|
112
127
|
- spec/hyperspec_spec.rb
|
113
128
|
- spec/support/meta_spec.rb
|