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,214 @@
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
@@ -0,0 +1,204 @@
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
+ }