komoju 0.0.0 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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