heroics 0.0.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.
data/test/link_test.rb ADDED
@@ -0,0 +1,349 @@
1
+ require 'helper'
2
+
3
+ class LinkTest < MiniTest::Unit::TestCase
4
+ include ExconHelper
5
+
6
+ # Link.run invokes a request against the service identified by the URL. The
7
+ # path is left unchanged when parameters aren't required and the username
8
+ # and password from the URL are passed using HTTP basic auth.
9
+ def test_run_without_parameters_and_with_empty_response
10
+ Excon.stub(method: :get) do |request|
11
+ assert_equal('Basic dXNlcm5hbWU6c2VjcmV0',
12
+ request[:headers]['Authorization'])
13
+ assert_equal('example.com', request[:host])
14
+ assert_equal(443, request[:port])
15
+ assert_equal('/resource', request[:path])
16
+ Excon.stubs.pop
17
+ {status: 200, body: ''}
18
+ end
19
+
20
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
21
+ link = Heroics::Link.new('https://username:secret@example.com',
22
+ schema.resource('resource').link('list'))
23
+ assert_equal(nil, link.run)
24
+ end
25
+
26
+ # Link.run injects parameters into the path in the order they were received.
27
+ def test_run_with_parameters_and_empty_response
28
+ Excon.stub(method: :get) do |request|
29
+ assert_equal('/resource/44724831-bf66-4bc2-865f-e2c4c2b14c78',
30
+ request[:path])
31
+ Excon.stubs.pop
32
+ {status: 200, body: ''}
33
+ end
34
+
35
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
36
+ link = Heroics::Link.new('https://example.com',
37
+ schema.resource('resource').link('info'))
38
+ assert_equal(nil, link.run('44724831-bf66-4bc2-865f-e2c4c2b14c78'))
39
+ end
40
+
41
+ # Link.run converts Time parameters to UTC before sending them to the
42
+ # server.
43
+ def test_run_converts_time_parameters_to_utc
44
+ Excon.stub(method: :delete) do |request|
45
+ assert_equal("/resource/2013-01-01T08:00:00Z", request[:path])
46
+ Excon.stubs.pop
47
+ {status: 200, body: ''}
48
+ end
49
+
50
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
51
+ link = Heroics::Link.new('https://example.com',
52
+ schema.resource('resource').link('delete'))
53
+ assert_equal(nil, link.run(Time.parse('2013-01-01 00:00:00-0800')))
54
+ end
55
+
56
+ # Link.run optionally takes an extra parameter to send in the request body.
57
+ # It automatically converts the specified object to JSON and includes a
58
+ # Content-Type header in the request.
59
+ def test_run_without_parameters_and_with_request_body
60
+ body = {'Hello' => 'world!'}
61
+ Excon.stub(method: :post) do |request|
62
+ assert_equal('application/json', request[:headers]['Content-Type'])
63
+ assert_equal(body, MultiJson.load(request[:body]))
64
+ Excon.stubs.pop
65
+ {status: 200, body: ''}
66
+ end
67
+
68
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
69
+ link = Heroics::Link.new('https://example.com',
70
+ schema.resource('resource').link('create'))
71
+ assert_equal(nil, link.run(body))
72
+ end
73
+
74
+ # Link.run passes custom headers to the server when they've been provided.
75
+ def test_run_with_custom_request_headers
76
+ Excon.stub(method: :get) do |request|
77
+ assert_equal('application/vnd.heroku+json; version=3',
78
+ request[:headers]['Accept'])
79
+ Excon.stubs.pop
80
+ {status: 200}
81
+ end
82
+
83
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
84
+ link = Heroics::Link.new(
85
+ 'https://example.com', schema.resource('resource').link('list'),
86
+ {default_headers: {'Accept' => 'application/vnd.heroku+json; version=3'}})
87
+ assert_equal(nil, link.run())
88
+ end
89
+
90
+ # Link.run passes custom headers to the server when they've been provided.
91
+ # It merges in the Content-Type when a body is included in the request.
92
+ def test_run_with_custom_request_headers_and_with_request_body
93
+ body = {'Hello' => 'world!'}
94
+ Excon.stub(method: :post) do |request|
95
+ assert_equal('application/json', request[:headers]['Content-Type'])
96
+ assert_equal('application/vnd.heroku+json; version=3',
97
+ request[:headers]['Accept'])
98
+ assert_equal(body, MultiJson.load(request[:body]))
99
+ Excon.stubs.pop
100
+ {status: 200}
101
+ end
102
+
103
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
104
+ link = Heroics::Link.new(
105
+ 'https://example.com', schema.resource('resource').link('create'),
106
+ default_headers: {'Accept' => 'application/vnd.heroku+json; version=3'})
107
+ assert_equal(nil, link.run(body))
108
+ end
109
+
110
+ # Link.run doesn't mutate the default headers.
111
+ def test_run_never_overwrites_default_headers
112
+ body = {'Hello' => 'world!'}
113
+ Excon.stub(method: :post) do |request|
114
+ assert_equal('application/json', request[:headers]['Content-Type'])
115
+ assert_equal('application/vnd.heroku+json; version=3',
116
+ request[:headers]['Accept'])
117
+ assert_equal(body, MultiJson.load(request[:body]))
118
+ Excon.stubs.pop
119
+ {status: 200}
120
+ end
121
+
122
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
123
+ link = Heroics::Link.new(
124
+ 'https://example.com', schema.resource('resource').link('create'),
125
+ {default_headers: {'Accept' => 'application/vnd.heroku+json; version=3'}})
126
+ assert_equal(nil, link.run(body))
127
+
128
+ # The second time we use the link, without providing a request body, the
129
+ # Content-Type set during the first run is not present, as expected.
130
+ Excon.stub(method: :post) do |request|
131
+ assert_equal(nil, request[:headers]['Content-Type'])
132
+ assert_equal('application/vnd.heroku+json; version=3',
133
+ request[:headers]['Accept'])
134
+ Excon.stubs.pop
135
+ {status: 200}
136
+ end
137
+ assert_equal(nil, link.run)
138
+ end
139
+
140
+ # Link.run returns text responses sent by the server without processing them
141
+ # in any way.
142
+ def test_run_with_text_response
143
+ Excon.stub(method: :get) do |request|
144
+ assert_equal('/resource', request[:path])
145
+ Excon.stubs.pop
146
+ {status: 200, headers: {'Content-Type' => 'application/text'},
147
+ body: "Hello, world!\r\n"}
148
+ end
149
+
150
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
151
+ link = Heroics::Link.new('https://example.com',
152
+ schema.resource('resource').link('list'))
153
+ assert_equal("Hello, world!\r\n", link.run)
154
+ end
155
+
156
+ # Link.run automatically decodes JSON responses sent by the server into Ruby
157
+ # objects.
158
+ def test_run_with_json_response
159
+ body = {'Hello' => 'World!'}
160
+ Excon.stub(method: :post) do |request|
161
+ assert_equal('/resource', request[:path])
162
+ Excon.stubs.pop
163
+ {status: 201, headers: {'Content-Type' => 'application/json'},
164
+ body: MultiJson.dump(body)}
165
+ end
166
+
167
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
168
+ link = Heroics::Link.new('https://example.com',
169
+ schema.resource('resource').link('create'))
170
+ assert_equal(body, link.run)
171
+ end
172
+
173
+ # Link.run automatically decodes JSON responses with a complex Content-Type
174
+ # header sent by the server into Ruby objects.
175
+ def test_run_with_json_response_and_complex_content_type
176
+ body = {'Hello' => 'World!'}
177
+ Excon.stub(method: :get) do |request|
178
+ assert_equal('/resource', request[:path])
179
+ Excon.stubs.pop
180
+ {status: 200,
181
+ headers: {'Content-Type' => 'application/json;charset=utf-8'},
182
+ body: MultiJson.dump(body)}
183
+ end
184
+
185
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
186
+ link = Heroics::Link.new('https://example.com',
187
+ schema.resource('resource').link('list'))
188
+ assert_equal(body, link.run)
189
+ end
190
+
191
+ # Link.run considers HTTP 202 Accepted responses as successful.
192
+ def test_run_with_accepted_request
193
+ body = {'Hello' => 'World!'}
194
+ Excon.stub(method: :post) do |request|
195
+ assert_equal('/resource', request[:path])
196
+ Excon.stubs.pop
197
+ {status: 202, headers: {'Content-Type' => 'application/json'},
198
+ body: MultiJson.dump(body)}
199
+ end
200
+
201
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
202
+ link = Heroics::Link.new('https://example.com',
203
+ schema.resource('resource').link('create'))
204
+ assert_equal(body, link.run)
205
+ end
206
+
207
+ # Link.run raises an Excon error if anything other than a 200 or 201 HTTP
208
+ # status code was returned by the server.
209
+ def test_run_with_failed_request
210
+ Excon.stub(method: :get) do |request|
211
+ assert_equal('/resource', request[:path])
212
+ Excon.stubs.pop
213
+ {status: 400}
214
+ end
215
+
216
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
217
+ link = Heroics::Link.new('https://example.com',
218
+ schema.resource('resource').link('list'))
219
+ assert_raises Excon::Errors::BadRequest do
220
+ link.run
221
+ end
222
+ end
223
+
224
+ # Link.run raises an ArgumentError if too few parameters are provided.
225
+ def test_run_with_missing_parameters
226
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
227
+ link = Heroics::Link.new('https://example.com',
228
+ schema.resource('resource').link('info'))
229
+ error = assert_raises ArgumentError do
230
+ link.run
231
+ end
232
+ assert_equal('wrong number of arguments (0 for 1)', error.message)
233
+ end
234
+
235
+ # Link.run raises an ArgumentError if too many parameters are provided.
236
+ def test_run_with_too_many_parameters
237
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
238
+ link = Heroics::Link.new('https://example.com',
239
+ schema.resource('resource').link('info'))
240
+ error = assert_raises ArgumentError do
241
+ link.run('too', 'many', 'parameters')
242
+ end
243
+ assert_equal('wrong number of arguments (3 for 1)', error.message)
244
+ end
245
+
246
+ # Link.run passes ETags from the cache to the server with GET requests.
247
+ def test_run_passes_cached_etags_in_get_requests
248
+ Excon.stub(method: :get) do |request|
249
+ assert_equal('etag-contents', request[:headers]['If-None-Match'])
250
+ Excon.stubs.pop
251
+ {status: 200}
252
+ end
253
+
254
+ cache = Moneta.new(:Memory)
255
+ cache['etag:/resource:0'] = 'etag-contents'
256
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
257
+ link = Heroics::Link.new('https://example.com',
258
+ schema.resource('resource').link('list'),
259
+ cache: cache)
260
+ link.run
261
+ end
262
+
263
+ # Link.run will not pas ETags from the cache for non-GET requests.
264
+ def test_run_ignores_etags_for_non_get_requests
265
+ Excon.stub(method: :post) do |request|
266
+ assert_equal(nil, request[:headers]['If-None-Match'])
267
+ Excon.stubs.pop
268
+ {status: 201}
269
+ end
270
+
271
+ cache = Moneta.new(:Memory)
272
+ cache['etag:/resource:0'] = 'etag-contents'
273
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
274
+ link = Heroics::Link.new('https://example.com',
275
+ schema.resource('resource').link('create'),
276
+ cache: cache)
277
+ link.run({'Hello' => 'World'})
278
+ end
279
+
280
+ # Link.run returns JSON content loaded from the cache when a GET request
281
+ # with an ETag yields a 304 Not Modified response.
282
+ def test_run_returns_cached_json_content_for_not_modified_response
283
+ body = {'Hello' => 'World!'}
284
+ Excon.stub(method: :get) do |request|
285
+ assert_equal('etag-contents', request[:headers]['If-None-Match'])
286
+ Excon.stubs.pop
287
+ {status: 304, headers: {'Content-Type' => 'application/json'}}
288
+ end
289
+
290
+ cache = Moneta.new(:Memory)
291
+ cache['etag:/resource:0'] = 'etag-contents'
292
+ cache['data:/resource:0'] = MultiJson.dump(body)
293
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
294
+ link = Heroics::Link.new('https://example.com',
295
+ schema.resource('resource').link('list'),
296
+ cache: cache)
297
+ assert_equal(body, link.run)
298
+ end
299
+
300
+ # Link.run caches JSON content received from the server when an ETag is
301
+ # included in the response.
302
+ def test_run_caches_json_body_when_an_etag_is_received
303
+ body = {'Hello' => 'World!'}
304
+ Excon.stub(method: :get) do |request|
305
+ Excon.stubs.pop
306
+ {status: 200, headers: {'Content-Type' => 'application/json',
307
+ 'ETag' => 'etag-contents'},
308
+ body: MultiJson.dump(body)}
309
+ end
310
+
311
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
312
+ link = Heroics::Link.new('https://example.com',
313
+ schema.resource('resource').link('list'),
314
+ cache: Moneta.new(:Memory))
315
+ assert_equal(body, link.run)
316
+
317
+ Excon.stub(method: :get) do |request|
318
+ assert_equal('etag-contents', request[:headers]['If-None-Match'])
319
+ Excon.stubs.pop
320
+ {status: 304, headers: {'Content-Type' => 'application/json'}}
321
+ end
322
+ assert_equal(body, link.run)
323
+ end
324
+
325
+ # Link.run returns an enumerator when a 206 Partial Content status code and
326
+ # Content-Range header is included in a server response. The enumerator
327
+ # makes requests to fetch missing pages as its iterated.
328
+ def test_run_with_range_response
329
+ Excon.stub(method: :get) do |request|
330
+ Excon.stubs.shift
331
+ {status: 206, headers: {'Content-Type' => 'application/json',
332
+ 'Content-Range' => 'id 1..2; max=200'},
333
+ body: MultiJson.dump([2])}
334
+ end
335
+
336
+ Excon.stub(method: :get) do |request|
337
+ Excon.stubs.shift
338
+ {status: 206, headers: {'Content-Type' => 'application/json',
339
+ 'Content-Range' => 'id 0..1; max=200',
340
+ 'Next-Range' => '201'},
341
+ body: MultiJson.dump([1])}
342
+ end
343
+
344
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
345
+ link = Heroics::Link.new('https://example.com',
346
+ schema.resource('resource').link('list'))
347
+ assert_equal([1, 2], link.run.to_a)
348
+ end
349
+ end
@@ -0,0 +1,45 @@
1
+ require 'helper'
2
+
3
+ class RubyNameTest < MiniTest::Unit::TestCase
4
+ # ruby_name is a no-op when an empty string is provided.
5
+ def test_ruby_name_with_empty_name
6
+ assert_equal('', Heroics.ruby_name(''))
7
+ end
8
+
9
+ # ruby_name converts capitals in a name to lowercase.
10
+ def test_ruby_name_with_capitals
11
+ assert_equal('capitalizedname', Heroics.ruby_name('CapitalizedName'))
12
+ end
13
+
14
+ # ruby_name converts dashes in a name to underscores.
15
+ def test_ruby_name_with_dashes
16
+ assert_equal('dashed_name', Heroics.ruby_name('dashed-name'))
17
+ end
18
+
19
+ # ruby_name converts spaces in a name to underscores.
20
+ def test_ruby_name_with_spaces
21
+ assert_equal('spaced_name', Heroics.ruby_name('spaced name'))
22
+ end
23
+ end
24
+
25
+ class PrettyNameTest < MiniTest::Unit::TestCase
26
+ # pretty_name is a no-op when an empty string is provided.
27
+ def test_pretty_name_with_empty_name
28
+ assert_equal('', Heroics.pretty_name(''))
29
+ end
30
+
31
+ # pretty_name converts capitals in a name to lowercase.
32
+ def test_pretty_name_with_capitals
33
+ assert_equal('capitalizedname', Heroics.pretty_name('CapitalizedName'))
34
+ end
35
+
36
+ # pretty_name converts underscores in a name to dashes.
37
+ def test_pretty_name_with_underscores
38
+ assert_equal('dashed-name', Heroics.pretty_name('dashed_name'))
39
+ end
40
+
41
+ # pretty_name converts spaces in a name to underscores.
42
+ def test_pretty_name_with_spaces
43
+ assert_equal('spaced-name', Heroics.pretty_name('spaced name'))
44
+ end
45
+ end
@@ -0,0 +1,35 @@
1
+ require 'helper'
2
+
3
+ class ResourceTest < MiniTest::Unit::TestCase
4
+ include ExconHelper
5
+
6
+ # Resource.<link> raises a NoMethodError when a method is invoked without a
7
+ # matching link.
8
+ def test_invalid_link
9
+ resource = Heroics::Resource.new({})
10
+ error = assert_raises NoMethodError do
11
+ resource.unknown
12
+ end
13
+ assert_match(
14
+ /undefined method `unknown' for #<Heroics::Resource:0x[0-9a-f]{14}>/,
15
+ error.message)
16
+ end
17
+
18
+ # Resource.<link> finds the appropriate link and invokes it.
19
+ def test_link
20
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
21
+ link = Heroics::Link.new('https://username:secret@example.com',
22
+ schema.resource('resource').link('list'))
23
+ resource = Heroics::Resource.new({'link' => link})
24
+ Excon.stub(method: :get) do |request|
25
+ assert_equal('Basic dXNlcm5hbWU6c2VjcmV0',
26
+ request[:headers]['Authorization'])
27
+ assert_equal('example.com', request[:host])
28
+ assert_equal(443, request[:port])
29
+ assert_equal('/resource', request[:path])
30
+ Excon.stubs.pop
31
+ {status: 200, body: 'Hello, world!'}
32
+ end
33
+ assert_equal('Hello, world!', resource.link)
34
+ end
35
+ end
@@ -0,0 +1,207 @@
1
+ require 'helper'
2
+
3
+ class SchemaTest < MiniTest::Unit::TestCase
4
+ # Schema.resource returns a ResourceSchema for the named resource.
5
+ def test_resource
6
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
7
+ assert_equal('resource', schema.resource('resource').name)
8
+ end
9
+
10
+ # Schema.resource raises a SchemaError is an unknown resource is requested.
11
+ def test_resource_with_unknown_name
12
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
13
+ error = assert_raises Heroics::SchemaError do
14
+ schema.resource('unknown-resource')
15
+ end
16
+ assert_equal("Unknown resource 'unknown-resource'.", error.message)
17
+ end
18
+
19
+ # Schema.resources returns a sequence of ResourceSchema children.
20
+ def test_resources
21
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
22
+ assert_equal(['resource', 'another-resource'],
23
+ schema.resources.map(&:name))
24
+ end
25
+ end
26
+
27
+ class ResourceSchemaTest < MiniTest::Unit::TestCase
28
+ # ResourceSchema.link returns a LinkSchema for the named link.
29
+ def test_link
30
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
31
+ link = schema.resource('resource').link('list')
32
+ assert_equal('list', link.name)
33
+ end
34
+
35
+ # ResourceSchema.link raises a SchemaError is an unknown link is requested.
36
+ def test_link_with_unknown_name
37
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
38
+ error = assert_raises Heroics::SchemaError do
39
+ schema.resource('resource').link('unknown-link')
40
+ end
41
+ assert_equal("Unknown link 'unknown-link'.", error.message)
42
+ end
43
+
44
+ # ResourceSchema.links returns a list of LinkSchema children.
45
+ def test_links
46
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
47
+ assert_equal(
48
+ ['list', 'info', 'identify_resource', 'create', 'update', 'delete'],
49
+ schema.resource('resource').links.map { |link| link.name })
50
+ end
51
+ end
52
+
53
+ class LinkSchemaTest < MiniTest::Unit::TestCase
54
+ # LinkSchema.name returns the sanitized link name.
55
+ def test_name
56
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
57
+ assert_equal('list', schema.resource('resource').link('list').name)
58
+ end
59
+
60
+ # LinkSchema.resource_name returns the parent resource name.
61
+ def test_resource_name
62
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
63
+ assert_equal('resource',
64
+ schema.resource('resource').link('list').resource_name)
65
+ end
66
+
67
+ # LinkSchema.description returns the link description.
68
+ def test_description
69
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
70
+ assert_equal('Show all sample resources',
71
+ schema.resource('resource').link('list').description)
72
+ end
73
+
74
+ # LinkSchema.parameters returns an empty list if the link doesn't require
75
+ # parameters.
76
+ def test_parameters_without_parameters
77
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
78
+ link = schema.resource('resource').link('list')
79
+ assert_equal([], link.parameters)
80
+ end
81
+
82
+ # LinkSchema.parameters returns a list of named parameter required to invoke
83
+ # the link correctly.
84
+ def test_parameters
85
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
86
+ link = schema.resource('resource').link('info')
87
+ assert_equal(['uuid_field'], link.parameters)
88
+ end
89
+
90
+ # LinkSchema.parameters returns a parameter name for multiple parameters
91
+ # when the parameter contains a 'oneOf' element that references more than
92
+ # one parameter.
93
+ def test_parameters_with_one_of_field
94
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
95
+ link = schema.resource('resource').link('identify_resource')
96
+ assert_equal(['uuid_field|email_field'], link.parameters)
97
+ end
98
+
99
+ # LinkSchema.body returns nil if the link doesn't accept a request body.
100
+ def test_example_body_without_body
101
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
102
+ link = schema.resource('resource').link('info')
103
+ assert_equal(nil, link.example_body)
104
+ end
105
+
106
+ # LinkSchema.body returns a sample body generated from the properties and
107
+ # embedded examples.
108
+ def test_example_body
109
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
110
+ link = schema.resource('resource').link('create')
111
+ assert_equal({'date_field' => '2013-10-19 22:10:29Z',
112
+ 'string_field' => 'Sample text.',
113
+ 'boolean_field' => true,
114
+ 'uuid_field' => '44724831-bf66-4bc2-865f-e2c4c2b14c78',
115
+ 'email_field' => 'username@example.com'},
116
+ link.example_body)
117
+ end
118
+
119
+ # LinkSchema.format_path converts a list of parameters into a path.
120
+ def test_format_path
121
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
122
+ link = schema.resource('resource').link('info')
123
+ assert_equal(['/resource/44724831-bf66-4bc2-865f-e2c4c2b14c78', nil],
124
+ link.format_path(['44724831-bf66-4bc2-865f-e2c4c2b14c78']))
125
+ end
126
+
127
+ # LinkSchema.format_path correctly returns a parameter as a body if a path
128
+ # doesn't have any parameters.
129
+ def test_format_path_with_body
130
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
131
+ link = schema.resource('resource').link('create')
132
+ assert_equal(['/resource', {'new' => 'resource'}],
133
+ link.format_path([{'new' => 'resource'}]))
134
+ end
135
+
136
+ # LinkSchema.format_path correctly returns a parameter as a body if a path
137
+ # doesn't have any parameters.
138
+ def test_format_path_with_path_and_body
139
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
140
+ link = schema.resource('resource').link('update')
141
+ assert_equal(['/resource/44724831-bf66-4bc2-865f-e2c4c2b14c78',
142
+ {'new' => 'resource'}],
143
+ link.format_path(['44724831-bf66-4bc2-865f-e2c4c2b14c78',
144
+ {'new' => 'resource'}]))
145
+ end
146
+
147
+ # LinkSchema.format_path raises an ArgumentError if too few parameters are
148
+ # provided
149
+ def test_format_path_with_too_few_parameters
150
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
151
+ link = schema.resource('resource').link('info')
152
+ error = assert_raises ArgumentError do
153
+ link.format_path([])
154
+ end
155
+ assert_equal('wrong number of arguments (0 for 1)', error.message)
156
+ end
157
+
158
+ # LinkSchema.format_path raises an ArgumentError if too many parameters are
159
+ # provided
160
+ def test_format_path_with_too_many_parameters
161
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
162
+ link = schema.resource('resource').link('info')
163
+ error = assert_raises ArgumentError do
164
+ link.format_path(['too', 'many', 'parameters'])
165
+ end
166
+ assert_equal('wrong number of arguments (3 for 1)', error.message)
167
+ end
168
+
169
+ # LinkSchema.pretty_resource_name returns the resource name in a pretty
170
+ # form, with underscores converted to dashes.
171
+ def test_pretty_resource_name
172
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
173
+ link = schema.resource('another-resource').link('list')
174
+ assert_equal('another-resource', link.pretty_resource_name)
175
+ end
176
+
177
+ # LinkSchema.pretty_name returns the link name in a pretty form, with
178
+ # underscores converted to dashes.
179
+ def test_pretty_resource_name
180
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
181
+ link = schema.resource('resource').link('identify_resource')
182
+ assert_equal('identify-resource', link.pretty_name)
183
+ end
184
+ end
185
+
186
+ class DownloadSchemaTest < MiniTest::Unit::TestCase
187
+ include ExconHelper
188
+
189
+ # download_schema makes a request to fetch the schema, decodes the
190
+ # downloaded JSON and returns a Ruby hash.
191
+ def test_download_schema
192
+ Excon.stub(method: :get) do |request|
193
+ assert_equal('example.com', request[:host])
194
+ assert_equal('/schema', request[:path])
195
+ assert_equal('application/vnd.heroku+json; version=3',
196
+ request[:headers]['Accept'])
197
+ Excon.stubs.pop
198
+ {status: 200, headers: {'Content-Type' => 'application/json'},
199
+ body: MultiJson.dump(SAMPLE_SCHEMA)}
200
+ end
201
+
202
+ schema = Heroics::download_schema(
203
+ 'https://username:token@example.com/schema',
204
+ default_headers: {'Accept' => 'application/vnd.heroku+json; version=3'})
205
+ assert_equal(SAMPLE_SCHEMA, schema.schema)
206
+ end
207
+ end