komoju 0.0.0 → 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.
@@ -0,0 +1,236 @@
1
+ require 'helper'
2
+ require 'stringio'
3
+
4
+ class CLITest < MiniTest::Unit::TestCase
5
+ include ExconHelper
6
+
7
+ # CLI.run displays usage information when no arguments are provided.
8
+ def test_run_without_arguments
9
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
10
+ client = Heroics::client_from_schema(schema, 'https://example.com')
11
+ output = StringIO.new
12
+ command1 = Heroics::Command.new(
13
+ 'cli', schema.resource('resource').link('list'), client, output)
14
+ command2 = Heroics::Command.new(
15
+ 'cli', schema.resource('resource').link('info'), client, output)
16
+ cli = Heroics::CLI.new('cli', {'resource:list' => command1,
17
+ 'resource:info' => command2}, output)
18
+ cli.run
19
+ expected = <<-USAGE
20
+ Usage: cli <command> [<parameter> [...]] [<body>]
21
+
22
+ Help topics, type "cli help <topic>" for more details:
23
+
24
+ resource:info Show a sample resource
25
+ resource:list Show all sample resources
26
+ USAGE
27
+ assert_equal(expected, output.string)
28
+ end
29
+
30
+ # CLI.run displays usage information when the help command is specified.
31
+ def test_run_with_help_command
32
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
33
+ client = Heroics::client_from_schema(schema, 'https://example.com')
34
+ output = StringIO.new
35
+ command1 = Heroics::Command.new(
36
+ 'cli', schema.resource('resource').link('list'), client, output)
37
+ command2 = Heroics::Command.new(
38
+ 'cli', schema.resource('resource').link('info'), client, output)
39
+ cli = Heroics::CLI.new('cli', {'resource:list' => command1,
40
+ 'resource:info' => command2}, output)
41
+ cli.run('help')
42
+ expected = <<-USAGE
43
+ Usage: cli <command> [<parameter> [...]] [<body>]
44
+
45
+ Help topics, type "cli help <topic>" for more details:
46
+
47
+ resource:info Show a sample resource
48
+ resource:list Show all sample resources
49
+ USAGE
50
+ assert_equal(expected, output.string)
51
+ end
52
+
53
+ # CLI.run displays command-specific help when a command name is included
54
+ # with the 'help' command.
55
+ def test_run_with_help_command_and_explicit_command_name
56
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
57
+ client = Heroics::client_from_schema(schema, 'https://example.com')
58
+ output = StringIO.new
59
+ command1 = Heroics::Command.new(
60
+ 'cli', schema.resource('resource').link('list'), client, output)
61
+ command2 = Heroics::Command.new(
62
+ 'cli', schema.resource('resource').link('info'), client, output)
63
+ cli = Heroics::CLI.new('cli', {'resource:list' => command1,
64
+ 'resource:info' => command2}, output)
65
+ cli.run('help', 'resource:info')
66
+ expected = <<-USAGE
67
+ Usage: cli resource:info <uuid_field>
68
+
69
+ Description:
70
+ Show a sample resource
71
+ USAGE
72
+ assert_equal(expected, output.string)
73
+ end
74
+
75
+ # CLI.run displays an error message when no commands have been registered.
76
+ def test_run_without_commands
77
+ output = StringIO.new
78
+ cli = Heroics::CLI.new('cli', {}, output)
79
+ cli.run('help')
80
+ assert_equal('No commands are available.', output.string)
81
+ end
82
+
83
+ # CLI.run displays an error message when an unknown command name is used.
84
+ def test_run_with_unknown_name
85
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
86
+ client = Heroics::client_from_schema(schema, 'https://example.com')
87
+ output = StringIO.new
88
+ command = Heroics::Command.new(
89
+ 'cli', schema.resource('resource').link('list'), client, output)
90
+ cli = Heroics::CLI.new('cli', {'resource:list' => command}, output)
91
+ cli.run('unknown:command')
92
+ assert_equal("There is no command called 'unknown:command'.\n",
93
+ output.string)
94
+ end
95
+
96
+ # CLI.run runs the command matching the specified name.
97
+ def test_run_with_dashed_command_name
98
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
99
+ client = Heroics::client_from_schema(schema, 'https://example.com')
100
+ output = StringIO.new
101
+ command = Heroics::Command.new(
102
+ 'cli', schema.resource('resource').link('identify_resource'), client,
103
+ output)
104
+ cli = Heroics::CLI.new('cli', {'resource:identify-resource' => command},
105
+ output)
106
+
107
+ uuid = '1ab1c589-df46-40aa-b786-60e83b1efb10'
108
+ Excon.stub(method: :get) do |request|
109
+ assert_equal("/resource/#{uuid}", request[:path])
110
+ Excon.stubs.pop
111
+ {status: 200}
112
+ end
113
+
114
+ cli.run('resource:identify-resource', uuid)
115
+ assert_equal('', output.string)
116
+ end
117
+
118
+ # CLI.run runs the resource matching the specified name.
119
+ def test_run_with_dashed_resource_name
120
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
121
+ client = Heroics::client_from_schema(schema, 'https://example.com')
122
+ output = StringIO.new
123
+ command = Heroics::Command.new(
124
+ 'cli', schema.resource('another-resource').link('list'), client, output)
125
+ cli = Heroics::CLI.new('cli', {'another-resource:list' => command},
126
+ output)
127
+
128
+ result = {'Hello' => 'World!'}
129
+ Excon.stub(method: :get) do |request|
130
+ assert_equal("/another-resource", request[:path])
131
+ Excon.stubs.pop
132
+ {status: 200, headers: {'Content-Type' => 'application/json'},
133
+ body: MultiJson.dump(result)}
134
+ end
135
+
136
+ cli.run('another-resource:list')
137
+ assert_equal(MultiJson.dump(result, pretty: true) + "\n", output.string)
138
+ end
139
+
140
+ # CLI.run runs the command matching the specified name and passes parameters
141
+ # to it.
142
+ def test_run_with_parameters
143
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
144
+ client = Heroics::client_from_schema(schema, 'https://example.com')
145
+ output = StringIO.new
146
+ command = Heroics::Command.new(
147
+ 'cli', schema.resource('resource').link('update'), client, output)
148
+ cli = Heroics::CLI.new('cli', {'resource:update' => command}, output)
149
+
150
+ uuid = '1ab1c589-df46-40aa-b786-60e83b1efb10'
151
+ body = {'Hello' => 'World!'}
152
+ result = {'Goodbye' => 'Universe!'}
153
+ Excon.stub(method: :patch) do |request|
154
+ assert_equal("/resource/#{uuid}", request[:path])
155
+ assert_equal('application/json', request[:headers]['Content-Type'])
156
+ assert_equal(body, MultiJson.load(request[:body]))
157
+ Excon.stubs.pop
158
+ {status: 200, headers: {'Content-Type' => 'application/json'},
159
+ body: MultiJson.dump(result)}
160
+ end
161
+
162
+ cli.run('resource:update', uuid, body)
163
+ assert_equal(MultiJson.dump(result, pretty: true) + "\n", output.string)
164
+ end
165
+ end
166
+
167
+ class CLIFromSchemaTest < MiniTest::Unit::TestCase
168
+ include ExconHelper
169
+
170
+ # cli_from_schema returns a CLI generated from the specified schema.
171
+ def test_cli_from_schema
172
+ uuid = '1ab1c589-df46-40aa-b786-60e83b1efb10'
173
+ body = {'Hello' => 'World!'}
174
+ result = {'Goodbye' => 'Universe!'}
175
+ Excon.stub(method: :patch) do |request|
176
+ assert_equal("/resource/#{uuid}", request[:path])
177
+ assert_equal('application/json', request[:headers]['Content-Type'])
178
+ assert_equal(body, MultiJson.load(request[:body]))
179
+ Excon.stubs.pop
180
+ {status: 200, headers: {'Content-Type' => 'application/json'},
181
+ body: MultiJson.dump(result)}
182
+ end
183
+
184
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
185
+ output = StringIO.new
186
+ cli = Heroics.cli_from_schema('cli', output, schema, 'https://example.com')
187
+ cli.run('resource:update', uuid, body)
188
+ assert_equal(MultiJson.dump(result, pretty: true) + "\n", output.string)
189
+ end
190
+
191
+ # cli_from_schema returns a CLI that can make requests to APIs mounted under
192
+ # a prefix, such as http://example.com/api, for example.
193
+ def test_client_from_schema_with_url_prefix
194
+ uuid = '1ab1c589-df46-40aa-b786-60e83b1efb10'
195
+ body = {'Hello' => 'World!'}
196
+ result = {'Goodbye' => 'Universe!'}
197
+ Excon.stub(method: :patch) do |request|
198
+ assert_equal("/api/resource/#{uuid}", request[:path])
199
+ assert_equal('application/json', request[:headers]['Content-Type'])
200
+ assert_equal(body, MultiJson.load(request[:body]))
201
+ Excon.stubs.pop
202
+ {status: 200, headers: {'Content-Type' => 'application/json'},
203
+ body: MultiJson.dump(result)}
204
+ end
205
+
206
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
207
+ output = StringIO.new
208
+ cli = Heroics.cli_from_schema('cli', output, schema,
209
+ 'https://example.com/api')
210
+ cli.run('resource:update', uuid, body)
211
+ assert_equal(MultiJson.dump(result, pretty: true) + "\n", output.string)
212
+ end
213
+
214
+ # cli_from_schema optionally accepts custom headers to pass with every
215
+ # request made by the generated CLI.
216
+ def test_cli_from_schema_with_custom_headers
217
+ uuid = '1ab1c589-df46-40aa-b786-60e83b1efb10'
218
+ body = {'Hello' => 'World!'}
219
+ result = {'Goodbye' => 'Universe!'}
220
+ Excon.stub(method: :patch) do |request|
221
+ assert_equal('application/vnd.heroku+json; version=3',
222
+ request[:headers]['Accept'])
223
+ Excon.stubs.pop
224
+ {status: 200, headers: {'Content-Type' => 'application/json'},
225
+ body: MultiJson.dump(result)}
226
+ end
227
+
228
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
229
+ output = StringIO.new
230
+ cli = Heroics.cli_from_schema(
231
+ 'cli', output, schema, 'https://example.com',
232
+ default_headers: {'Accept' => 'application/vnd.heroku+json; version=3'})
233
+ cli.run('resource:update', uuid, body)
234
+ assert_equal(MultiJson.dump(result, pretty: true) + "\n", output.string)
235
+ end
236
+ end
@@ -0,0 +1,34 @@
1
+ require 'helper'
2
+ require 'netrc'
3
+ require 'stringio'
4
+
5
+ class GenerateClientTest < MiniTest::Unit::TestCase
6
+ include ExconHelper
7
+
8
+ # generate_client takes a module, schema, API URL and options and returns a
9
+ # string containing generated Ruby client code.
10
+ def test_generate_client
11
+ Excon.stub(method: :get) do |request|
12
+ assert_equal('example.com', request[:host])
13
+ assert_equal('/schema', request[:path])
14
+ assert_equal('application/vnd.example+json; version=3',
15
+ request[:headers]['Accept'])
16
+ Excon.stubs.pop
17
+ {status: 200, headers: {'Content-Type' => 'application/json'},
18
+ body: MultiJson.dump(SAMPLE_SCHEMA)}
19
+ end
20
+
21
+ netrc = Netrc.read
22
+ username, token = netrc['example.com']
23
+ schema_url = "https://example.com/schema"
24
+ options = {
25
+ default_headers: {'Accept' => 'application/vnd.example+json; version=3'},
26
+ cache: 'Moneta.new(:File, dir: "#{Dir.home}/.heroics/example")'
27
+ }
28
+ schema = Heroics.download_schema(schema_url, options)
29
+ client_source = Heroics.generate_client("ExampleAPI", schema,
30
+ "api.example.com", options)
31
+ # Ensure the generated code is syntactically valid.
32
+ eval(client_source)
33
+ end
34
+ end
@@ -0,0 +1,215 @@
1
+ require 'helper'
2
+
3
+ class ClientTest < MiniTest::Unit::TestCase
4
+ include ExconHelper
5
+
6
+ # Client.to_s returns a simple human-readable description of the client
7
+ # instance with the URL embedded in it. A password, if present in the URL,
8
+ # is redacted to avoid leaking credentials.
9
+ def test_to_s
10
+ client = Heroics::Client.new({}, 'http://foo:bar@example.com')
11
+ assert_equal('#<Heroics::Client url="http://foo:REDACTED@example.com">',
12
+ client.to_s)
13
+ end
14
+
15
+ # Client.<resource> raises a NoMethodError when a method is invoked
16
+ # without a matching resource.
17
+ def test_invalid_resource
18
+ client = Heroics::Client.new({}, 'http://example.com')
19
+ error = assert_raises NoMethodError do
20
+ client.unknown
21
+ end
22
+ assert_equal("undefined method `unknown' for " +
23
+ '#<Heroics::Client url="http://example.com">',
24
+ error.message)
25
+ end
26
+
27
+ # Client.<resource>.<link> finds the appropriate link and invokes it.
28
+ def test_resource
29
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
30
+ link = Heroics::Link.new('https://username:secret@example.com',
31
+ schema.resource('resource').link('list'))
32
+ resource = Heroics::Resource.new({'link' => link})
33
+ client = Heroics::Client.new({'resource' => resource},
34
+ 'http://example.com')
35
+ Excon.stub(method: :get) do |request|
36
+ assert_equal('Basic dXNlcm5hbWU6c2VjcmV0',
37
+ request[:headers]['Authorization'])
38
+ assert_equal('example.com', request[:host])
39
+ assert_equal(443, request[:port])
40
+ assert_equal('/resource', request[:path])
41
+ Excon.stubs.pop
42
+ {status: 200, body: 'Hello, world!'}
43
+ end
44
+ assert_equal('Hello, world!', client.resource.link)
45
+ end
46
+ end
47
+
48
+ class ClientFromSchemaTest < MiniTest::Unit::TestCase
49
+ include ExconHelper
50
+
51
+ # client_from_schema returns a Client generated from the specified schema.
52
+ def test_client_from_schema
53
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
54
+ client = Heroics::client_from_schema(schema, 'https://example.com')
55
+ body = {'Hello' => 'World!'}
56
+ Excon.stub(method: :post) do |request|
57
+ assert_equal('/resource', request[:path])
58
+ Excon.stubs.pop
59
+ {status: 200, headers: {'Content-Type' => 'application/json'},
60
+ body: MultiJson.dump(body)}
61
+ end
62
+ assert_equal(body, client.resource.create)
63
+ end
64
+
65
+ # client_from_schema returns a Client that can make requests to APIs mounted
66
+ # under a prefix, such as http://example.com/api, for example.
67
+ def test_client_from_schema_with_url_prefix
68
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
69
+ client = Heroics::client_from_schema(schema, 'https://example.com/api')
70
+ body = {'Hello' => 'World!'}
71
+ Excon.stub(method: :post) do |request|
72
+ assert_equal('/api/resource', request[:path])
73
+ Excon.stubs.pop
74
+ {status: 200, headers: {'Content-Type' => 'application/json'},
75
+ body: MultiJson.dump(body)}
76
+ end
77
+ assert_equal(body, client.resource.create)
78
+ end
79
+
80
+ # client_from_schema optionally accepts custom headers to pass with every
81
+ # request made by the generated client.
82
+ def test_client_from_schema_with_custom_headers
83
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
84
+ client = Heroics::client_from_schema(
85
+ schema, 'https://example.com',
86
+ default_headers: {'Accept' => 'application/vnd.heroku+json; version=3'})
87
+ Excon.stub(method: :post) do |request|
88
+ assert_equal('application/vnd.heroku+json; version=3',
89
+ request[:headers]['Accept'])
90
+ Excon.stubs.pop
91
+ {status: 200}
92
+ end
93
+ client.resource.create
94
+ end
95
+
96
+ # client_from_schema takes an optional :cache parameter which it uses when
97
+ # constructing Link instances.
98
+ def test_client_from_schema_with_cache
99
+ body = {'Hello' => 'World!'}
100
+ Excon.stub(method: :get) do |request|
101
+ Excon.stubs.pop
102
+ {status: 201, headers: {'Content-Type' => 'application/json',
103
+ 'ETag' => 'etag-contents'},
104
+ body: MultiJson.dump(body)}
105
+ end
106
+
107
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
108
+ client = Heroics::client_from_schema(schema, 'https://example.com',
109
+ cache: Moneta.new(:Memory))
110
+ assert_equal(body, client.resource.list)
111
+
112
+ Excon.stub(method: :get) do |request|
113
+ assert_equal('etag-contents', request[:headers]['If-None-Match'])
114
+ Excon.stubs.pop
115
+ {status: 304, headers: {'Content-Type' => 'application/json'}}
116
+ end
117
+ assert_equal(body, client.resource.list)
118
+ end
119
+ end
120
+
121
+ class OAuthClientFromSchemaTest < MiniTest::Unit::TestCase
122
+ include ExconHelper
123
+
124
+ # oauth_client_from_schema injects an Authorization header, built from the
125
+ # specified OAuth token, into the default header options.
126
+ def test_oauth_client_from_schema
127
+ body = {'Hello' => 'World!'}
128
+ Excon.stub(method: :get) do |request|
129
+ assert_equal(
130
+ 'Bearer c55ef0d8-40b6-4759-b1bf-4a6f94190a66',
131
+ request[:headers]['Authorization'])
132
+ Excon.stubs.pop
133
+ {status: 200, headers: {'Content-Type' => 'application/json'},
134
+ body: MultiJson.dump(body)}
135
+ end
136
+
137
+ oauth_token = 'c55ef0d8-40b6-4759-b1bf-4a6f94190a66'
138
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
139
+ client = Heroics.oauth_client_from_schema(oauth_token, schema,
140
+ 'https://example.com')
141
+ assert_equal(body, client.resource.list)
142
+ end
143
+
144
+ # oauth_client_from_schema doesn't mutate the options object, and in
145
+ # particular, it doesn't mutate the :default_headers Hash in that object.
146
+ def test_oauth_client_from_schema_with_options
147
+ body = {'Hello' => 'World!'}
148
+ Excon.stub(method: :get) do |request|
149
+ assert_equal('application/vnd.heroku+json; version=3',
150
+ request[:headers]['Accept'])
151
+ assert_equal(
152
+ 'Bearer c55ef0d8-40b6-4759-b1bf-4a6f94190a66',
153
+ request[:headers]['Authorization'])
154
+ Excon.stubs.pop
155
+ {status: 200, headers: {'Content-Type' => 'application/json'},
156
+ body: MultiJson.dump(body)}
157
+ end
158
+
159
+ oauth_token = 'c55ef0d8-40b6-4759-b1bf-4a6f94190a66'
160
+ options = {
161
+ default_headers: {'Accept' => 'application/vnd.heroku+json; version=3'}}
162
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
163
+ client = Heroics.oauth_client_from_schema(oauth_token, schema,
164
+ 'https://example.com', options)
165
+ assert_equal(body, client.resource.list)
166
+ end
167
+ end
168
+
169
+ class TokenClientFromSchemaTest < MiniTest::Unit::TestCase
170
+ include ExconHelper
171
+
172
+ # token_client_from_schema injects an Authorization header, built from the
173
+ # specified token, into the default header options.
174
+ def test_token_client_from_schema
175
+ body = {'Hello' => 'World!'}
176
+ Excon.stub(method: :get) do |request|
177
+ assert_equal(
178
+ 'Token token=c55ef0d8-40b6-4759-b1bf-4a6f94190a66',
179
+ request[:headers]['Authorization'])
180
+ Excon.stubs.pop
181
+ {status: 200, headers: {'Content-Type' => 'application/json'},
182
+ body: MultiJson.dump(body)}
183
+ end
184
+
185
+ token = 'c55ef0d8-40b6-4759-b1bf-4a6f94190a66'
186
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
187
+ client = Heroics.token_client_from_schema(token, schema,
188
+ 'https://example.com')
189
+ assert_equal(body, client.resource.list)
190
+ end
191
+
192
+ # token_client_from_schema doesn't mutate the options object, and in
193
+ # particular, it doesn't mutate the :default_headers Hash in that object.
194
+ def test_token_client_from_schema_with_options
195
+ body = {'Hello' => 'World!'}
196
+ Excon.stub(method: :get) do |request|
197
+ assert_equal('application/vnd.heroku+json; version=3',
198
+ request[:headers]['Accept'])
199
+ assert_equal(
200
+ 'Token token=c55ef0d8-40b6-4759-b1bf-4a6f94190a66',
201
+ request[:headers]['Authorization'])
202
+ Excon.stubs.pop
203
+ {status: 200, headers: {'Content-Type' => 'application/json'},
204
+ body: MultiJson.dump(body)}
205
+ end
206
+
207
+ token = 'c55ef0d8-40b6-4759-b1bf-4a6f94190a66'
208
+ options = {
209
+ default_headers: {'Accept' => 'application/vnd.heroku+json; version=3'}}
210
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
211
+ client = Heroics.token_client_from_schema(token, schema,
212
+ 'https://example.com', options)
213
+ assert_equal(body, client.resource.list)
214
+ end
215
+ end