heroics 0.0.17 → 0.0.18

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,35 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'helper'
3
- require 'netrc'
4
- require 'stringio'
5
-
6
- class GenerateClientTest < MiniTest::Unit::TestCase
7
- include ExconHelper
8
-
9
- # generate_client takes a module, schema, API URL and options and returns a
10
- # string containing generated Ruby client code.
11
- def test_generate_client
12
- Excon.stub(method: :get) do |request|
13
- assert_equal('example.com', request[:host])
14
- assert_equal('/schema', request[:path])
15
- assert_equal('application/vnd.example+json; version=3',
16
- request[:headers]['Accept'])
17
- Excon.stubs.pop
18
- {status: 200, headers: {'Content-Type' => 'application/json'},
19
- body: MultiJson.dump(SAMPLE_SCHEMA)}
20
- end
21
-
22
- netrc = Netrc.read
23
- username, token = netrc['example.com']
24
- schema_url = "https://example.com/schema"
25
- options = {
26
- default_headers: {'Accept' => 'application/vnd.example+json; version=3'},
27
- cache: 'Moneta.new(:File, dir: "#{Dir.home}/.heroics/example")'
28
- }
29
- schema = Heroics.download_schema(schema_url, options)
30
- client_source = Heroics.generate_client("ExampleAPI", schema,
31
- "api.example.com", options)
32
- # Ensure the generated code is syntactically valid.
33
- eval(client_source)
34
- end
35
- end
@@ -1,275 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'helper'
3
-
4
- class ClientTest < MiniTest::Unit::TestCase
5
- include ExconHelper
6
-
7
- # Client.to_s returns a simple human-readable description of the client
8
- # instance with the URL embedded in it. A password, if present in the URL,
9
- # is redacted to avoid leaking credentials.
10
- def test_to_s
11
- client = Heroics::Client.new({}, 'http://foo:bar@example.com')
12
- assert_equal('#<Heroics::Client url="http://foo:REDACTED@example.com">',
13
- client.to_s)
14
- end
15
-
16
- # Client.<resource> raises a NoMethodError when a method is invoked
17
- # without a matching resource.
18
- def test_invalid_resource
19
- client = Heroics::Client.new({}, 'http://example.com')
20
- error = assert_raises NoMethodError do
21
- client.unknown
22
- end
23
- assert_equal("undefined method `unknown' for " +
24
- '#<Heroics::Client url="http://example.com">',
25
- error.message)
26
- end
27
-
28
- # Client.<resource>.<link> finds the appropriate link and invokes it.
29
- def test_resource
30
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
31
- link = Heroics::Link.new('https://username:secret@example.com',
32
- schema.resource('resource').link('list'))
33
- resource = Heroics::Resource.new({'link' => link})
34
- client = Heroics::Client.new({'resource' => resource},
35
- 'http://example.com')
36
- Excon.stub(method: :get) do |request|
37
- assert_equal('Basic dXNlcm5hbWU6c2VjcmV0',
38
- request[:headers]['Authorization'])
39
- assert_equal('example.com', request[:host])
40
- assert_equal(443, request[:port])
41
- assert_equal('/resource', request[:path])
42
- Excon.stubs.pop
43
- {status: 200, body: 'Hello, world!'}
44
- end
45
- assert_equal('Hello, world!', client.resource.link)
46
- end
47
-
48
- # Client.<resource>.<link> finds the appropriate link and invokes it with
49
- # query params, since it is a GET resource
50
- def test_resource_with_query_param
51
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
52
- link = Heroics::Link.new('https://username:secret@example.com',
53
- schema.resource('resource').link('list'))
54
- resource = Heroics::Resource.new({'link' => link})
55
- client = Heroics::Client.new({'resource' => resource},
56
- 'http://example.com')
57
- Excon.stub(method: :get) do |request|
58
- assert_equal({:limit => '50', :page => '25'}, request[:query])
59
- Excon.stubs.pop
60
- {status: 200, body: 'Hello, world!'}
61
- end
62
- assert_equal('Hello, world!', client.resource.link(limit: '50', page: '25'))
63
- end
64
-
65
- # Client converts underscores in resource method names to dashes to match
66
- # names specified in the schema.
67
- def test_resource_with_dashed_name
68
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
69
- link = Heroics::Link.new('https://username:secret@example.com',
70
- schema.resource('another-resource').link('list'))
71
- resource = Heroics::Resource.new({'link' => link})
72
- client = Heroics::Client.new({'another-resource' => resource},
73
- 'http://example.com')
74
- Excon.stub(method: :get) do |request|
75
- assert_equal('Basic dXNlcm5hbWU6c2VjcmV0',
76
- request[:headers]['Authorization'])
77
- assert_equal('example.com', request[:host])
78
- assert_equal(443, request[:port])
79
- assert_equal('/another-resource', request[:path])
80
- Excon.stubs.pop
81
- {status: 200, body: 'Hello, world!'}
82
- end
83
- assert_equal('Hello, world!', client.another_resource.link)
84
- end
85
-
86
- # Client.<resource>.<link> finds the appropriate link and invokes it, even if
87
- # the resource has an underscore in its name
88
- def test_resource_with_underscored_name
89
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
90
- link = Heroics::Link.new('https://username:secret@example.com',
91
- schema.resource('underscored_resource').link('list'))
92
- resource = Heroics::Resource.new({'link' => link})
93
- client = Heroics::Client.new({'underscored_resource' => resource},
94
- 'http://example.com')
95
- Excon.stub(method: :get) do |request|
96
- assert_equal('Basic dXNlcm5hbWU6c2VjcmV0',
97
- request[:headers]['Authorization'])
98
- assert_equal('example.com', request[:host])
99
- assert_equal(443, request[:port])
100
- assert_equal('/underscored_resource', request[:path])
101
- Excon.stubs.pop
102
- {status: 200, body: 'Hello, world!'}
103
- end
104
- assert_equal('Hello, world!', client.underscored_resource.link)
105
- end
106
- end
107
-
108
- class ClientFromSchemaTest < MiniTest::Unit::TestCase
109
- include ExconHelper
110
-
111
- # client_from_schema returns a Client generated from the specified schema.
112
- def test_client_from_schema
113
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
114
- client = Heroics::client_from_schema(schema, 'https://example.com')
115
- body = {'Hello' => 'World!'}
116
- Excon.stub(method: :post) do |request|
117
- assert_equal('/resource', request[:path])
118
- Excon.stubs.pop
119
- {status: 200, headers: {'Content-Type' => 'application/json'},
120
- body: MultiJson.dump(body)}
121
- end
122
- assert_equal(body, client.resource.create)
123
- end
124
-
125
- # client_from_schema returns a Client that can make requests to APIs mounted
126
- # under a prefix, such as http://example.com/api, for example.
127
- def test_client_from_schema_with_url_prefix
128
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
129
- client = Heroics::client_from_schema(schema, 'https://example.com/api')
130
- body = {'Hello' => 'World!'}
131
- Excon.stub(method: :post) do |request|
132
- assert_equal('/api/resource', request[:path])
133
- Excon.stubs.pop
134
- {status: 200, headers: {'Content-Type' => 'application/json'},
135
- body: MultiJson.dump(body)}
136
- end
137
- assert_equal(body, client.resource.create)
138
- end
139
-
140
- # client_from_schema optionally accepts custom headers to pass with every
141
- # request made by the generated client.
142
- def test_client_from_schema_with_custom_headers
143
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
144
- client = Heroics::client_from_schema(
145
- schema, 'https://example.com',
146
- default_headers: {'Accept' => 'application/vnd.heroku+json; version=3'})
147
- Excon.stub(method: :post) do |request|
148
- assert_equal('application/vnd.heroku+json; version=3',
149
- request[:headers]['Accept'])
150
- Excon.stubs.pop
151
- {status: 200}
152
- end
153
- client.resource.create
154
- end
155
-
156
- # client_from_schema takes an optional :cache parameter which it uses when
157
- # constructing Link instances.
158
- def test_client_from_schema_with_cache
159
- body = {'Hello' => 'World!'}
160
- Excon.stub(method: :get) do |request|
161
- Excon.stubs.pop
162
- {status: 201, headers: {'Content-Type' => 'application/json',
163
- 'ETag' => 'etag-contents'},
164
- body: MultiJson.dump(body)}
165
- end
166
-
167
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
168
- client = Heroics::client_from_schema(schema, 'https://example.com',
169
- cache: Moneta.new(:Memory))
170
- assert_equal(body, client.resource.list)
171
-
172
- Excon.stub(method: :get) do |request|
173
- assert_equal('etag-contents', request[:headers]['If-None-Match'])
174
- Excon.stubs.pop
175
- {status: 304, headers: {'Content-Type' => 'application/json'}}
176
- end
177
- assert_equal(body, client.resource.list)
178
- end
179
- end
180
-
181
- class OAuthClientFromSchemaTest < MiniTest::Unit::TestCase
182
- include ExconHelper
183
-
184
- # oauth_client_from_schema injects an Authorization header, built from the
185
- # specified OAuth token, into the default header options.
186
- def test_oauth_client_from_schema
187
- body = {'Hello' => 'World!'}
188
- Excon.stub(method: :get) do |request|
189
- assert_equal(
190
- 'Bearer c55ef0d8-40b6-4759-b1bf-4a6f94190a66',
191
- request[:headers]['Authorization'])
192
- Excon.stubs.pop
193
- {status: 200, headers: {'Content-Type' => 'application/json'},
194
- body: MultiJson.dump(body)}
195
- end
196
-
197
- oauth_token = 'c55ef0d8-40b6-4759-b1bf-4a6f94190a66'
198
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
199
- client = Heroics.oauth_client_from_schema(oauth_token, schema,
200
- 'https://example.com')
201
- assert_equal(body, client.resource.list)
202
- end
203
-
204
- # oauth_client_from_schema doesn't mutate the options object, and in
205
- # particular, it doesn't mutate the :default_headers Hash in that object.
206
- def test_oauth_client_from_schema_with_options
207
- body = {'Hello' => 'World!'}
208
- Excon.stub(method: :get) do |request|
209
- assert_equal('application/vnd.heroku+json; version=3',
210
- request[:headers]['Accept'])
211
- assert_equal(
212
- 'Bearer c55ef0d8-40b6-4759-b1bf-4a6f94190a66',
213
- request[:headers]['Authorization'])
214
- Excon.stubs.pop
215
- {status: 200, headers: {'Content-Type' => 'application/json'},
216
- body: MultiJson.dump(body)}
217
- end
218
-
219
- oauth_token = 'c55ef0d8-40b6-4759-b1bf-4a6f94190a66'
220
- options = {
221
- default_headers: {'Accept' => 'application/vnd.heroku+json; version=3'}}
222
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
223
- client = Heroics.oauth_client_from_schema(oauth_token, schema,
224
- 'https://example.com', options)
225
- assert_equal(body, client.resource.list)
226
- end
227
- end
228
-
229
- class TokenClientFromSchemaTest < MiniTest::Unit::TestCase
230
- include ExconHelper
231
-
232
- # token_client_from_schema injects an Authorization header, built from the
233
- # specified token, into the default header options.
234
- def test_token_client_from_schema
235
- body = {'Hello' => 'World!'}
236
- Excon.stub(method: :get) do |request|
237
- assert_equal(
238
- 'Token token=c55ef0d8-40b6-4759-b1bf-4a6f94190a66',
239
- request[:headers]['Authorization'])
240
- Excon.stubs.pop
241
- {status: 200, headers: {'Content-Type' => 'application/json'},
242
- body: MultiJson.dump(body)}
243
- end
244
-
245
- token = 'c55ef0d8-40b6-4759-b1bf-4a6f94190a66'
246
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
247
- client = Heroics.token_client_from_schema(token, schema,
248
- 'https://example.com')
249
- assert_equal(body, client.resource.list)
250
- end
251
-
252
- # token_client_from_schema doesn't mutate the options object, and in
253
- # particular, it doesn't mutate the :default_headers Hash in that object.
254
- def test_token_client_from_schema_with_options
255
- body = {'Hello' => 'World!'}
256
- Excon.stub(method: :get) do |request|
257
- assert_equal('application/vnd.heroku+json; version=3',
258
- request[:headers]['Accept'])
259
- assert_equal(
260
- 'Token token=c55ef0d8-40b6-4759-b1bf-4a6f94190a66',
261
- request[:headers]['Authorization'])
262
- Excon.stubs.pop
263
- {status: 200, headers: {'Content-Type' => 'application/json'},
264
- body: MultiJson.dump(body)}
265
- end
266
-
267
- token = 'c55ef0d8-40b6-4759-b1bf-4a6f94190a66'
268
- options = {
269
- default_headers: {'Accept' => 'application/vnd.heroku+json; version=3'}}
270
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
271
- client = Heroics.token_client_from_schema(token, schema,
272
- 'https://example.com', options)
273
- assert_equal(body, client.resource.list)
274
- end
275
- end
@@ -1,215 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'helper'
3
- require 'stringio'
4
-
5
- class CommandTest < MiniTest::Unit::TestCase
6
- include ExconHelper
7
-
8
- # Command.name returns the name of the command, which is made up by joining
9
- # the resource name and link title with a colon.
10
- def test_name
11
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
12
- client = Heroics::client_from_schema(schema, 'https://example.com')
13
- output = StringIO.new
14
- command = Heroics::Command.new(
15
- 'cli', schema.resource('resource').link('list'), client, output)
16
- assert_equal('resource:list', command.name)
17
- end
18
-
19
- # Command.description returns a description for the command.
20
- def test_description
21
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
22
- client = Heroics::client_from_schema(schema, 'https://example.com')
23
- output = StringIO.new
24
- command = Heroics::Command.new(
25
- 'cli', schema.resource('resource').link('list'), client, output)
26
- assert_equal('Show all sample resources', command.description)
27
- end
28
-
29
- # Command.run calls the correct method on the client when no link parameters
30
- # are provided.
31
- def test_run_without_parameters
32
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
33
- client = Heroics::client_from_schema(schema, 'https://example.com')
34
- output = StringIO.new
35
- command = Heroics::Command.new(
36
- 'cli', schema.resource('resource').link('list'), client, output)
37
-
38
- body = ['Hello', 'World!']
39
- Excon.stub(method: :get) do |request|
40
- assert_equal('/resource', request[:path])
41
- Excon.stubs.pop
42
- {status: 200, headers: {'Content-Type' => 'application/json'},
43
- body: MultiJson.dump(body)}
44
- end
45
-
46
- command.run
47
- assert_equal(MultiJson.dump(body, pretty: true) + "\n", output.string)
48
- end
49
-
50
- # Command.run calls the correct method on the client and passes link
51
- # parameters when they're provided.
52
- def test_run_with_parameters
53
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
54
- client = Heroics::client_from_schema(schema, 'https://example.com')
55
- output = StringIO.new
56
- command = Heroics::Command.new(
57
- 'cli', schema.resource('resource').link('info'), client, output)
58
-
59
- uuid = '1ab1c589-df46-40aa-b786-60e83b1efb10'
60
- body = {'Hello' => 'World!'}
61
- Excon.stub(method: :get) do |request|
62
- assert_equal("/resource/#{uuid}", request[:path])
63
- Excon.stubs.pop
64
- {status: 200, headers: {'Content-Type' => 'application/json'},
65
- body: MultiJson.dump(body)}
66
- end
67
-
68
- command.run(uuid)
69
- assert_equal(MultiJson.dump(body, pretty: true) + "\n", output.string)
70
- end
71
-
72
- # Command.run calls the correct method on the client and passes a request
73
- # body to the link when it's provided.
74
- def test_run_with_request_body_and_text_response
75
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
76
- client = Heroics::client_from_schema(schema, 'https://example.com')
77
- output = StringIO.new
78
- command = Heroics::Command.new(
79
- 'cli', schema.resource('resource').link('create'), client, output)
80
-
81
- body = {'Hello' => 'World!'}
82
- Excon.stub(method: :post) do |request|
83
- assert_equal('/resource', request[:path])
84
- assert_equal('application/json', request[:headers]['Content-Type'])
85
- assert_equal(body, MultiJson.load(request[:body]))
86
- Excon.stubs.pop
87
- {status: 201}
88
- end
89
-
90
- command.run(body)
91
- assert_equal('', output.string)
92
- end
93
-
94
- # Command.run calls the correct method on the client and converts the result
95
- # to an array, if a range response is received, before writing it out.
96
- def test_run_with_range_response
97
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
98
- client = Heroics::client_from_schema(schema, 'https://example.com')
99
- output = StringIO.new
100
- command = Heroics::Command.new(
101
- 'cli', schema.resource('resource').link('list'), client, output)
102
-
103
- Excon.stub(method: :get) do |request|
104
- Excon.stubs.shift
105
- {status: 206, headers: {'Content-Type' => 'application/json',
106
- 'Content-Range' => 'id 1..2; max=200'},
107
- body: MultiJson.dump([2])}
108
- end
109
-
110
- Excon.stub(method: :get) do |request|
111
- Excon.stubs.shift
112
- {status: 206, headers: {'Content-Type' => 'application/json',
113
- 'Content-Range' => 'id 0..1; max=200',
114
- 'Next-Range' => '201'},
115
- body: MultiJson.dump([1])}
116
- end
117
-
118
- command.run
119
- assert_equal(MultiJson.dump([1, 2], pretty: true) + "\n", output.string)
120
- end
121
-
122
- # Command.run calls the correct method on the client and passes parameters
123
- # and a request body to the link when they're provided.
124
- def test_run_with_request_body_and_parameters
125
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
126
- client = Heroics::client_from_schema(schema, 'https://example.com')
127
- output = StringIO.new
128
- command = Heroics::Command.new(
129
- 'cli', schema.resource('resource').link('update'), client, output)
130
-
131
- uuid = '1ab1c589-df46-40aa-b786-60e83b1efb10'
132
- body = {'Hello' => 'World!'}
133
- result = {'Goodbye' => 'Universe!'}
134
- Excon.stub(method: :patch) do |request|
135
- assert_equal("/resource/#{uuid}", request[:path])
136
- assert_equal('application/json', request[:headers]['Content-Type'])
137
- assert_equal(body, MultiJson.load(request[:body]))
138
- Excon.stubs.pop
139
- {status: 200, headers: {'Content-Type' => 'application/json'},
140
- body: MultiJson.dump(result)}
141
- end
142
-
143
- command.run(uuid, body)
144
- assert_equal(MultiJson.dump(result, pretty: true) + "\n", output.string)
145
- end
146
-
147
- # Command.run raises an ArgumentError if too few parameters are provided.
148
- def test_run_with_too_few_parameters
149
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
150
- client = Heroics::client_from_schema(schema, 'https://example.com')
151
- output = StringIO.new
152
- command = Heroics::Command.new(
153
- 'cli', schema.resource('resource').link('info'), client, output)
154
- assert_raises ArgumentError do
155
- command.run
156
- end
157
- end
158
-
159
- # Command.run raises an ArgumentError if too many parameters are provided.
160
- def test_run_with_too_many_parameters
161
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
162
- client = Heroics::client_from_schema(schema, 'https://example.com')
163
- output = StringIO.new
164
- command = Heroics::Command.new(
165
- 'cli', schema.resource('resource').link('info'), client, output)
166
- assert_raises ArgumentError do
167
- command.run('too', 'many', 'parameters')
168
- end
169
- end
170
-
171
- # Command.usage displays usage information.
172
- def test_usage
173
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
174
- client = Heroics::client_from_schema(schema, 'https://example.com')
175
- output = StringIO.new
176
- command = Heroics::Command.new(
177
- 'cli', schema.resource('resource').link('update'), client, output)
178
- command.usage
179
- expected = <<-USAGE
180
- Usage: cli resource:update <uuid_field> <body>
181
-
182
- Description:
183
- Update a sample resource
184
-
185
- Body example:
186
- {
187
- "date_field": "2013-10-19 22:10:29Z",
188
- "string_field": "Sample text.",
189
- "boolean_field": true,
190
- "uuid_field": "44724831-bf66-4bc2-865f-e2c4c2b14c78",
191
- "email_field": "username@example.com"
192
- }
193
- USAGE
194
- assert_equal(expected, output.string)
195
- end
196
-
197
- # Command.usage correctly handles parameters that are described by 'oneOf'
198
- # and 'anyOf' sub-parameter lists.
199
- def test_usage_with_one_of_field
200
- schema = Heroics::Schema.new(SAMPLE_SCHEMA)
201
- client = Heroics::client_from_schema(schema, 'https://example.com')
202
- output = StringIO.new
203
- command = Heroics::Command.new(
204
- 'cli', schema.resource('resource').link('identify_resource'), client,
205
- output)
206
- command.usage
207
- expected = <<-USAGE
208
- Usage: cli resource:identify-resource <uuid_field|email_field>
209
-
210
- Description:
211
- Show a sample resource
212
- USAGE
213
- assert_equal(expected, output.string)
214
- end
215
- end