komoju 0.0.4 → 0.0.7

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.
@@ -1,214 +0,0 @@
1
- require 'helper'
2
- require 'stringio'
3
-
4
- class CommandTest < MiniTest::Unit::TestCase
5
- include ExconHelper
6
-
7
- # Command.name returns the name of the command, which is made up by joining
8
- # the resource name and link title with a colon.
9
- def test_name
10
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
11
- client = Heroics::client_from_schema(schema, 'https://example.com')
12
- output = StringIO.new
13
- command = Heroics::Command.new(
14
- 'cli', schema.resource('resource').link('list'), client, output)
15
- assert_equal('resource:list', command.name)
16
- end
17
-
18
- # Command.description returns a description for the command.
19
- def test_description
20
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
21
- client = Heroics::client_from_schema(schema, 'https://example.com')
22
- output = StringIO.new
23
- command = Heroics::Command.new(
24
- 'cli', schema.resource('resource').link('list'), client, output)
25
- assert_equal('Show all sample resources', command.description)
26
- end
27
-
28
- # Command.run calls the correct method on the client when no link parameters
29
- # are provided.
30
- def test_run_without_parameters
31
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
32
- client = Heroics::client_from_schema(schema, 'https://example.com')
33
- output = StringIO.new
34
- command = Heroics::Command.new(
35
- 'cli', schema.resource('resource').link('list'), client, output)
36
-
37
- body = ['Hello', 'World!']
38
- Excon.stub(method: :get) do |request|
39
- assert_equal('/resource', request[:path])
40
- Excon.stubs.pop
41
- {status: 200, headers: {'Content-Type' => 'application/json'},
42
- body: MultiJson.dump(body)}
43
- end
44
-
45
- command.run
46
- assert_equal(MultiJson.dump(body, pretty: true) + "\n", output.string)
47
- end
48
-
49
- # Command.run calls the correct method on the client and passes link
50
- # parameters when they're provided.
51
- def test_run_with_parameters
52
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
53
- client = Heroics::client_from_schema(schema, 'https://example.com')
54
- output = StringIO.new
55
- command = Heroics::Command.new(
56
- 'cli', schema.resource('resource').link('info'), client, output)
57
-
58
- uuid = '1ab1c589-df46-40aa-b786-60e83b1efb10'
59
- body = {'Hello' => 'World!'}
60
- Excon.stub(method: :get) do |request|
61
- assert_equal("/resource/#{uuid}", request[:path])
62
- Excon.stubs.pop
63
- {status: 200, headers: {'Content-Type' => 'application/json'},
64
- body: MultiJson.dump(body)}
65
- end
66
-
67
- command.run(uuid)
68
- assert_equal(MultiJson.dump(body, pretty: true) + "\n", output.string)
69
- end
70
-
71
- # Command.run calls the correct method on the client and passes a request
72
- # body to the link when it's provided.
73
- def test_run_with_request_body_and_text_response
74
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
75
- client = Heroics::client_from_schema(schema, 'https://example.com')
76
- output = StringIO.new
77
- command = Heroics::Command.new(
78
- 'cli', schema.resource('resource').link('create'), client, output)
79
-
80
- body = {'Hello' => 'World!'}
81
- Excon.stub(method: :post) do |request|
82
- assert_equal('/resource', request[:path])
83
- assert_equal('application/json', request[:headers]['Content-Type'])
84
- assert_equal(body, MultiJson.load(request[:body]))
85
- Excon.stubs.pop
86
- {status: 201}
87
- end
88
-
89
- command.run(body)
90
- assert_equal('', output.string)
91
- end
92
-
93
- # Command.run calls the correct method on the client and converts the result
94
- # to an array, if a range response is received, before writing it out.
95
- def test_run_with_range_response
96
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
97
- client = Heroics::client_from_schema(schema, 'https://example.com')
98
- output = StringIO.new
99
- command = Heroics::Command.new(
100
- 'cli', schema.resource('resource').link('list'), client, output)
101
-
102
- Excon.stub(method: :get) do |request|
103
- Excon.stubs.shift
104
- {status: 206, headers: {'Content-Type' => 'application/json',
105
- 'Content-Range' => 'id 1..2; max=200'},
106
- body: MultiJson.dump([2])}
107
- end
108
-
109
- Excon.stub(method: :get) do |request|
110
- Excon.stubs.shift
111
- {status: 206, headers: {'Content-Type' => 'application/json',
112
- 'Content-Range' => 'id 0..1; max=200',
113
- 'Next-Range' => '201'},
114
- body: MultiJson.dump([1])}
115
- end
116
-
117
- command.run
118
- assert_equal(MultiJson.dump([1, 2], pretty: true) + "\n", output.string)
119
- end
120
-
121
- # Command.run calls the correct method on the client and passes parameters
122
- # and a request body to the link when they're provided.
123
- def test_run_with_request_body_and_parameters
124
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
125
- client = Heroics::client_from_schema(schema, 'https://example.com')
126
- output = StringIO.new
127
- command = Heroics::Command.new(
128
- 'cli', schema.resource('resource').link('update'), client, output)
129
-
130
- uuid = '1ab1c589-df46-40aa-b786-60e83b1efb10'
131
- body = {'Hello' => 'World!'}
132
- result = {'Goodbye' => 'Universe!'}
133
- Excon.stub(method: :patch) do |request|
134
- assert_equal("/resource/#{uuid}", request[:path])
135
- assert_equal('application/json', request[:headers]['Content-Type'])
136
- assert_equal(body, MultiJson.load(request[:body]))
137
- Excon.stubs.pop
138
- {status: 200, headers: {'Content-Type' => 'application/json'},
139
- body: MultiJson.dump(result)}
140
- end
141
-
142
- command.run(uuid, body)
143
- assert_equal(MultiJson.dump(result, pretty: true) + "\n", output.string)
144
- end
145
-
146
- # Command.run raises an ArgumentError if too few parameters are provided.
147
- def test_run_with_too_few_parameters
148
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
149
- client = Heroics::client_from_schema(schema, 'https://example.com')
150
- output = StringIO.new
151
- command = Heroics::Command.new(
152
- 'cli', schema.resource('resource').link('info'), client, output)
153
- assert_raises ArgumentError do
154
- command.run
155
- end
156
- end
157
-
158
- # Command.run raises an ArgumentError if too many parameters are provided.
159
- def test_run_with_too_many_parameters
160
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
161
- client = Heroics::client_from_schema(schema, 'https://example.com')
162
- output = StringIO.new
163
- command = Heroics::Command.new(
164
- 'cli', schema.resource('resource').link('info'), client, output)
165
- assert_raises ArgumentError do
166
- command.run('too', 'many', 'parameters')
167
- end
168
- end
169
-
170
- # Command.usage displays usage information.
171
- def test_usage
172
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
173
- client = Heroics::client_from_schema(schema, 'https://example.com')
174
- output = StringIO.new
175
- command = Heroics::Command.new(
176
- 'cli', schema.resource('resource').link('update'), client, output)
177
- command.usage
178
- expected = <<-USAGE
179
- Usage: cli resource:update <uuid_field> <body>
180
-
181
- Description:
182
- Update a sample resource
183
-
184
- Body example:
185
- {
186
- "date_field": "2013-10-19 22:10:29Z",
187
- "string_field": "Sample text.",
188
- "boolean_field": true,
189
- "uuid_field": "44724831-bf66-4bc2-865f-e2c4c2b14c78",
190
- "email_field": "username@example.com"
191
- }
192
- USAGE
193
- assert_equal(expected, output.string)
194
- end
195
-
196
- # Command.usage correctly handles parameters that are described by 'oneOf'
197
- # and 'anyOf' sub-parameter lists.
198
- def test_usage_with_one_of_field
199
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
200
- client = Heroics::client_from_schema(schema, 'https://example.com')
201
- output = StringIO.new
202
- command = Heroics::Command.new(
203
- 'cli', schema.resource('resource').link('identify_resource'), client,
204
- output)
205
- command.usage
206
- expected = <<-USAGE
207
- Usage: cli resource:identify-resource <uuid_field|email_field>
208
-
209
- Description:
210
- Show a sample resource
211
- USAGE
212
- assert_equal(expected, output.string)
213
- end
214
- end
@@ -1,204 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'time'
3
-
4
- require 'heroics'
5
-
6
- module ExconHelper
7
- def setup
8
- super
9
- Excon.stubs.clear
10
- Excon.defaults[:mock] = true
11
- end
12
-
13
- def teardown
14
- # FIXME This is a bit ugly, but Excon doesn't provide a builtin way to
15
- # ensure that a request was invoked, so we have to do it ourselves.
16
- # Without this, and the Excon.stubs.pop calls in the tests that use this
17
- # helper, tests will pass if request logic is completely removed from
18
- # application code. -jkakar
19
- assert(Excon.stubs.empty?, 'Expected HTTP requests were not made.')
20
- super
21
- end
22
- end
23
-
24
- # A simple JSON schema for testing purposes.
25
- SAMPLE_SCHEMA = {
26
- 'description' => 'Sample schema for use in tests.',
27
- 'definitions' => {
28
- 'resource' => {
29
- 'description' => 'A sample resource to use in tests.',
30
- 'id' => 'schema/resource',
31
- '$schema' => 'http://json-schema.org/draft-04/hyper-schema',
32
- 'title' => 'Sample resource title',
33
- 'type' => ['object'],
34
-
35
- 'definitions' => {
36
- 'date_field' => {
37
- 'description' => 'A sample date field',
38
- 'example' => '2013-10-19 22:10:29Z',
39
- 'format' => 'date-time',
40
- 'readOnly' => true,
41
- 'type' => ['string']
42
- },
43
-
44
- 'string_field' => {
45
- 'description' => 'A sample string field',
46
- 'example' => 'Sample text.',
47
- 'readOnly' => true,
48
- 'type' => ['string']
49
- },
50
-
51
- 'boolean_field' => {
52
- 'description' => 'A sample boolean field',
53
- 'example' => true,
54
- 'type' => ['boolean']
55
- },
56
-
57
- 'uuid_field' => {
58
- 'description' => 'A sample UUID field',
59
- 'example' => '44724831-bf66-4bc2-865f-e2c4c2b14c78',
60
- 'format' => 'uuid',
61
- 'readOnly' => true,
62
- 'type' => ['string']
63
- },
64
-
65
- 'email_field' => {
66
- 'description' => 'A sample email address field',
67
- 'example' => 'username@example.com',
68
- 'format' => 'email',
69
- 'readOnly' => true,
70
- 'type' => ['string']
71
- },
72
-
73
- 'identity' => {
74
- 'oneOf' => [
75
- {'$ref' => '#/definitions/resource/definitions/uuid_field'},
76
- {'$ref' => '#/definitions/resource/definitions/email_field'}]
77
- }
78
- },
79
-
80
- 'properties' => {
81
- 'date_field' => {
82
- '$ref' => '#/definitions/resource/definitions/date_field'},
83
- 'string_field' => {
84
- '$ref' => '#/definitions/resource/definitions/string_field'},
85
- 'boolean_field' => {
86
- '$ref' => '#/definitions/resource/definitions/boolean_field'},
87
- 'uuid_field' => {
88
- '$ref' => '#/definitions/resource/definitions/uuid_field'},
89
- 'email_field' => {
90
- '$ref' => '#/definitions/resource/definitions/email_field'},
91
- },
92
-
93
- 'links' => [
94
- {'description' => 'Show all sample resources',
95
- 'href' => '/resource',
96
- 'method' => 'GET',
97
- 'rel' => 'instances',
98
- 'title' => 'List'},
99
-
100
- {'description' => 'Show a sample resource',
101
- 'href' => '/resource/{(%23%2Fdefinitions%2Fresource%2Fdefinitions%2Fuuid_field)}',
102
- 'method' => 'GET',
103
- 'rel' => 'self',
104
- 'title' => 'Info'},
105
-
106
- {'description' => 'Show a sample resource',
107
- 'href' => '/resource/{(%23%2Fdefinitions%2Fresource%2Fdefinitions%2Fidentity)}',
108
- 'method' => 'GET',
109
- 'rel' => 'self',
110
- 'title' => 'Identify resource'},
111
-
112
- {'description' => 'Create a sample resource',
113
- 'href' => '/resource',
114
- 'method' => 'POST',
115
- 'rel' => 'create',
116
- 'title' => 'Create',
117
- 'schema' => {
118
- 'properties' => {
119
- 'date_field' => {
120
- '$ref' => '#/definitions/resource/definitions/date_field'},
121
- 'string_field' => {
122
- '$ref' => '#/definitions/resource/definitions/string_field'},
123
- 'boolean_field' => {
124
- '$ref' => '#/definitions/resource/definitions/boolean_field'},
125
- 'uuid_field' => {
126
- '$ref' => '#/definitions/resource/definitions/uuid_field'},
127
- 'email_field' => {
128
- '$ref' => '#/definitions/resource/definitions/email_field'}}}},
129
-
130
- {'description' => 'Submit a sample resource as form data',
131
- 'encType' => 'application/x-www-form-urlencoded',
132
- 'href' => '/resource',
133
- 'method' => 'POST',
134
- 'rel' => 'submit',
135
- 'title' => 'Submit',
136
- 'schema' => {
137
- 'properties' => {
138
- 'date_field' => {
139
- '$ref' => '#/definitions/resource/definitions/date_field'},
140
- 'string_field' => {
141
- '$ref' => '#/definitions/resource/definitions/string_field'},
142
- 'boolean_field' => {
143
- '$ref' => '#/definitions/resource/definitions/boolean_field'},
144
- 'uuid_field' => {
145
- '$ref' => '#/definitions/resource/definitions/uuid_field'},
146
- 'email_field' => {
147
- '$ref' => '#/definitions/resource/definitions/email_field'}}}},
148
-
149
- {'description' => 'Update a sample resource',
150
- 'href' => '/resource/{(%23%2Fdefinitions%2Fresource%2Fdefinitions%2Fuuid_field)}',
151
- 'method' => 'PATCH',
152
- 'rel' => 'update',
153
- 'title' => 'Update',
154
- 'schema' => {
155
- 'properties' => {
156
- 'date_field' => {
157
- '$ref' => '#/definitions/resource/definitions/date_field'},
158
- 'string_field' => {
159
- '$ref' => '#/definitions/resource/definitions/string_field'},
160
- 'boolean_field' => {
161
- '$ref' => '#/definitions/resource/definitions/boolean_field'},
162
- 'uuid_field' => {
163
- '$ref' => '#/definitions/resource/definitions/uuid_field'},
164
- 'email_field' => {
165
- '$ref' => '#/definitions/resource/definitions/email_field'}}}},
166
-
167
- {'description' => 'Delete an existing sample resource at specific time',
168
- 'href' => '/resource/{(%23%2Fdefinitions%2Fresource%2Fdefinitions%2Fdate_field)}',
169
- 'method' => 'DELETE',
170
- 'rel' => 'destroy',
171
- 'title' => 'Delete'}
172
- ]
173
- },
174
-
175
- 'another-resource' => {
176
- 'description' => 'Another sample resource to use in tests.',
177
- 'id' => 'schema/another-resource',
178
- '$schema' => 'http://json-schema.org/draft-04/hyper-schema',
179
- 'title' => 'Another sample resource title',
180
- 'type' => ['object'],
181
-
182
- 'definitions' => {},
183
-
184
- 'properties' => {},
185
-
186
- 'links' => [
187
- {'description' => 'Create another resource',
188
- 'href' => '/another-resource',
189
- 'method' => 'POST',
190
- 'rel' => 'self',
191
- 'title' => 'Create'},
192
- {'description' => 'Show all sample resources',
193
- 'href' => '/another-resource',
194
- 'method' => 'GET',
195
- 'rel' => 'instances',
196
- 'title' => 'List'}
197
- ]
198
- },
199
- },
200
- 'properties' => {
201
- 'resource' => { '$ref' => '#/definitions/resource' },
202
- 'another-resource' => { '$ref' => '#/definitions/another-resource' }
203
- }
204
- }
@@ -1,398 +0,0 @@
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 URL-escapes special characters in parameters.
42
- def test_run_with_parameters_needing_escaping
43
- Excon.stub(method: :get) do |request|
44
- assert_equal('/resource/foo%23bar', request[:path])
45
- Excon.stubs.pop
46
- {status: 200, body: ''}
47
- end
48
-
49
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
50
- link = Heroics::Link.new('https://example.com',
51
- schema.resource('resource').link('info'))
52
- assert_equal(nil, link.run('foo#bar'))
53
- end
54
-
55
- # Link.run converts Time parameters to UTC before sending them to the
56
- # server.
57
- def test_run_converts_time_parameters_to_utc
58
- Excon.stub(method: :delete) do |request|
59
- assert_equal("/resource/2013-01-01T08:00:00Z", request[:path])
60
- Excon.stubs.pop
61
- {status: 200, body: ''}
62
- end
63
-
64
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
65
- link = Heroics::Link.new('https://example.com',
66
- schema.resource('resource').link('delete'))
67
- assert_equal(nil, link.run(Time.parse('2013-01-01 00:00:00-0800')))
68
- end
69
-
70
- # Link.run optionally takes an extra parameter to send in the request body.
71
- # It automatically converts the specified object to JSON and includes a
72
- # Content-Type header in the request.
73
- def test_run_without_parameters_and_with_request_body
74
- body = {'Hello' => 'world!'}
75
- Excon.stub(method: :post) do |request|
76
- assert_equal('application/json', request[:headers]['Content-Type'])
77
- assert_equal(body, MultiJson.load(request[:body]))
78
- Excon.stubs.pop
79
- {status: 200, body: ''}
80
- end
81
-
82
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
83
- link = Heroics::Link.new('https://example.com',
84
- schema.resource('resource').link('create'))
85
- assert_equal(nil, link.run(body))
86
- end
87
-
88
- # Link.run optionally takes an extra parameter to send in the request body.
89
- # It automatically converts the specified object to the specified encoding
90
- # type and includes a Content-Type header in the request
91
- def test_run_without_parameters_and_with_non_json_request_body
92
- body = {'Hello' => 'world!'}
93
- Excon.stub(method: :post) do |request|
94
- assert_equal('application/x-www-form-urlencoded', request[:headers]['Content-Type'])
95
- assert_equal('Hello=world%21', request[:body])
96
- Excon.stubs.pop
97
- {status: 200, body: ''}
98
- end
99
-
100
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
101
- link = Heroics::Link.new('https://example.com',
102
- schema.resource('resource').link('submit'))
103
- assert_equal(nil, link.run(body))
104
- end
105
-
106
-
107
- # Link.run passes custom headers to the server when they've been provided.
108
- def test_run_with_custom_request_headers
109
- Excon.stub(method: :get) do |request|
110
- assert_equal('application/vnd.heroku+json; version=3',
111
- request[:headers]['Accept'])
112
- Excon.stubs.pop
113
- {status: 200}
114
- end
115
-
116
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
117
- link = Heroics::Link.new(
118
- 'https://example.com', schema.resource('resource').link('list'),
119
- {default_headers: {'Accept' => 'application/vnd.heroku+json; version=3'}})
120
- assert_equal(nil, link.run())
121
- end
122
-
123
- # Link.run passes custom headers to the server when they've been provided.
124
- # It merges in the Content-Type when a body is included in the request.
125
- def test_run_with_custom_request_headers_and_with_request_body
126
- body = {'Hello' => 'world!'}
127
- Excon.stub(method: :post) do |request|
128
- assert_equal('application/json', request[:headers]['Content-Type'])
129
- assert_equal('application/vnd.heroku+json; version=3',
130
- request[:headers]['Accept'])
131
- assert_equal(body, MultiJson.load(request[:body]))
132
- Excon.stubs.pop
133
- {status: 200}
134
- end
135
-
136
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
137
- link = Heroics::Link.new(
138
- 'https://example.com', schema.resource('resource').link('create'),
139
- default_headers: {'Accept' => 'application/vnd.heroku+json; version=3'})
140
- assert_equal(nil, link.run(body))
141
- end
142
-
143
- # Link.run doesn't mutate the default headers.
144
- def test_run_never_overwrites_default_headers
145
- body = {'Hello' => 'world!'}
146
- Excon.stub(method: :post) do |request|
147
- assert_equal('application/json', request[:headers]['Content-Type'])
148
- assert_equal('application/vnd.heroku+json; version=3',
149
- request[:headers]['Accept'])
150
- assert_equal(body, MultiJson.load(request[:body]))
151
- Excon.stubs.pop
152
- {status: 200}
153
- end
154
-
155
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
156
- link = Heroics::Link.new(
157
- 'https://example.com', schema.resource('resource').link('create'),
158
- {default_headers: {'Accept' => 'application/vnd.heroku+json; version=3'}})
159
- assert_equal(nil, link.run(body))
160
-
161
- # The second time we use the link, without providing a request body, the
162
- # Content-Type set during the first run is not present, as expected.
163
- Excon.stub(method: :post) do |request|
164
- assert_equal(nil, request[:headers]['Content-Type'])
165
- assert_equal('application/vnd.heroku+json; version=3',
166
- request[:headers]['Accept'])
167
- Excon.stubs.pop
168
- {status: 200}
169
- end
170
- assert_equal(nil, link.run)
171
- end
172
-
173
- # Link.run returns text responses sent by the server without processing them
174
- # in any way.
175
- def test_run_with_text_response
176
- Excon.stub(method: :get) do |request|
177
- assert_equal('/resource', request[:path])
178
- Excon.stubs.pop
179
- {status: 200, headers: {'Content-Type' => 'application/text'},
180
- body: "Hello, world!\r\n"}
181
- end
182
-
183
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
184
- link = Heroics::Link.new('https://example.com',
185
- schema.resource('resource').link('list'))
186
- assert_equal("Hello, world!\r\n", link.run)
187
- end
188
-
189
- # Link.run automatically decodes JSON responses sent by the server into Ruby
190
- # objects.
191
- def test_run_with_json_response
192
- body = {'Hello' => 'World!'}
193
- Excon.stub(method: :post) do |request|
194
- assert_equal('/resource', request[:path])
195
- Excon.stubs.pop
196
- {status: 201, headers: {'Content-Type' => 'application/json'},
197
- body: MultiJson.dump(body)}
198
- end
199
-
200
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
201
- link = Heroics::Link.new('https://example.com',
202
- schema.resource('resource').link('create'))
203
- assert_equal(body, link.run)
204
- end
205
-
206
- # Link.run automatically decodes JSON responses with a complex Content-Type
207
- # header sent by the server into Ruby objects.
208
- def test_run_with_json_response_and_complex_content_type
209
- body = {'Hello' => 'World!'}
210
- Excon.stub(method: :get) do |request|
211
- assert_equal('/resource', request[:path])
212
- Excon.stubs.pop
213
- {status: 200,
214
- headers: {'Content-Type' => 'application/vnd.api+json;charset=utf-8'},
215
- body: MultiJson.dump(body)}
216
- end
217
-
218
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
219
- link = Heroics::Link.new('https://example.com',
220
- schema.resource('resource').link('list'))
221
- assert_equal(body, link.run)
222
- end
223
-
224
- # Link.run considers HTTP 202 Accepted responses as successful.
225
- def test_run_with_accepted_request
226
- body = {'Hello' => 'World!'}
227
- Excon.stub(method: :post) do |request|
228
- assert_equal('/resource', request[:path])
229
- Excon.stubs.pop
230
- {status: 202, headers: {'Content-Type' => 'application/json'},
231
- body: MultiJson.dump(body)}
232
- end
233
-
234
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
235
- link = Heroics::Link.new('https://example.com',
236
- schema.resource('resource').link('create'))
237
- assert_equal(body, link.run)
238
- end
239
-
240
- # Link.run considers HTTP 204 No Content responses as successful.
241
- def test_run_with_no_content_response
242
- Excon.stub(method: :delete) do |request|
243
- assert_equal("/resource/2013-01-01T08:00:00Z", request[:path])
244
- Excon.stubs.pop
245
- {status: 204, body: ''}
246
- end
247
-
248
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
249
- link = Heroics::Link.new('https://example.com',
250
- schema.resource('resource').link('delete'))
251
- assert_equal(nil, link.run(Time.parse('2013-01-01 00:00:00-0800')))
252
- end
253
-
254
- # Link.run raises an Excon error if anything other than a 200 or 201 HTTP
255
- # status code was returned by the server.
256
- def test_run_with_failed_request
257
- Excon.stub(method: :get) do |request|
258
- assert_equal('/resource', request[:path])
259
- Excon.stubs.pop
260
- {status: 400}
261
- end
262
-
263
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
264
- link = Heroics::Link.new('https://example.com',
265
- schema.resource('resource').link('list'))
266
- assert_raises Excon::Errors::BadRequest do
267
- link.run
268
- end
269
- end
270
-
271
- # Link.run raises an ArgumentError if too few parameters are provided.
272
- def test_run_with_missing_parameters
273
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
274
- link = Heroics::Link.new('https://example.com',
275
- schema.resource('resource').link('info'))
276
- error = assert_raises ArgumentError do
277
- link.run
278
- end
279
- assert_equal('wrong number of arguments (0 for 1)', error.message)
280
- end
281
-
282
- # Link.run raises an ArgumentError if too many parameters are provided.
283
- def test_run_with_too_many_parameters
284
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
285
- link = Heroics::Link.new('https://example.com',
286
- schema.resource('resource').link('info'))
287
- error = assert_raises ArgumentError do
288
- link.run('too', 'many', 'parameters')
289
- end
290
- assert_equal('wrong number of arguments (3 for 1)', error.message)
291
- end
292
-
293
- # Link.run passes ETags from the cache to the server with GET requests.
294
- def test_run_passes_cached_etags_in_get_requests
295
- Excon.stub(method: :get) do |request|
296
- assert_equal('etag-contents', request[:headers]['If-None-Match'])
297
- Excon.stubs.pop
298
- {status: 200}
299
- end
300
-
301
- headers = {}
302
- cache = Moneta.new(:Memory)
303
- cache["etag:/resource:#{headers.hash}"] = 'etag-contents'
304
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
305
- link = Heroics::Link.new('https://example.com',
306
- schema.resource('resource').link('list'),
307
- cache: cache)
308
- link.run
309
- end
310
-
311
- # Link.run will not pas ETags from the cache for non-GET requests.
312
- def test_run_ignores_etags_for_non_get_requests
313
- Excon.stub(method: :post) do |request|
314
- assert_equal(nil, request[:headers]['If-None-Match'])
315
- Excon.stubs.pop
316
- {status: 201}
317
- end
318
-
319
- cache = Moneta.new(:Memory)
320
- cache['etag:/resource:0'] = 'etag-contents'
321
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
322
- link = Heroics::Link.new('https://example.com',
323
- schema.resource('resource').link('create'),
324
- cache: cache)
325
- link.run({'Hello' => 'World'})
326
- end
327
-
328
- # Link.run returns JSON content loaded from the cache when a GET request
329
- # with an ETag yields a 304 Not Modified response.
330
- def test_run_returns_cached_json_content_for_not_modified_response
331
- body = {'Hello' => 'World!'}
332
- Excon.stub(method: :get) do |request|
333
- assert_equal('etag-contents', request[:headers]['If-None-Match'])
334
- Excon.stubs.pop
335
- {status: 304, headers: {'Content-Type' => 'application/json'}}
336
- end
337
-
338
- headers = {}
339
- cache = Moneta.new(:Memory)
340
- cache["etag:/resource:#{headers.hash}"] = 'etag-contents'
341
- cache["data:/resource:#{headers.hash}"] = MultiJson.dump(body)
342
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
343
- link = Heroics::Link.new('https://example.com',
344
- schema.resource('resource').link('list'),
345
- cache: cache)
346
- assert_equal(body, link.run)
347
- end
348
-
349
- # Link.run caches JSON content received from the server when an ETag is
350
- # included in the response.
351
- def test_run_caches_json_body_when_an_etag_is_received
352
- body = {'Hello' => 'World!'}
353
- Excon.stub(method: :get) do |request|
354
- Excon.stubs.pop
355
- {status: 200, headers: {'Content-Type' => 'application/json',
356
- 'ETag' => 'etag-contents'},
357
- body: MultiJson.dump(body)}
358
- end
359
-
360
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
361
- link = Heroics::Link.new('https://example.com',
362
- schema.resource('resource').link('list'),
363
- cache: Moneta.new(:Memory))
364
- assert_equal(body, link.run)
365
-
366
- Excon.stub(method: :get) do |request|
367
- assert_equal('etag-contents', request[:headers]['If-None-Match'])
368
- Excon.stubs.pop
369
- {status: 304, headers: {'Content-Type' => 'application/json'}}
370
- end
371
- assert_equal(body, link.run)
372
- end
373
-
374
- # Link.run returns an enumerator when a 206 Partial Content status code and
375
- # Content-Range header is included in a server response. The enumerator
376
- # makes requests to fetch missing pages as its iterated.
377
- def test_run_with_range_response
378
- Excon.stub(method: :get) do |request|
379
- Excon.stubs.shift
380
- {status: 206, headers: {'Content-Type' => 'application/json',
381
- 'Content-Range' => 'id 1..2; max=200'},
382
- body: MultiJson.dump([2])}
383
- end
384
-
385
- Excon.stub(method: :get) do |request|
386
- Excon.stubs.shift
387
- {status: 206, headers: {'Content-Type' => 'application/json',
388
- 'Content-Range' => 'id 0..1; max=200',
389
- 'Next-Range' => '201'},
390
- body: MultiJson.dump([1])}
391
- end
392
-
393
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
394
- link = Heroics::Link.new('https://example.com',
395
- schema.resource('resource').link('list'))
396
- assert_equal([1, 2], link.run.to_a)
397
- end
398
- end