protip 0.10.7 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/definitions/google/protobuf/wrappers.proto +99 -0
- data/definitions/protip/messages/array.proto +3 -2
- data/definitions/protip/messages/errors.proto +5 -4
- data/definitions/protip/messages/types.proto +6 -4
- data/lib/google/protobuf/wrappers.rb +48 -0
- data/lib/protip/client.rb +3 -4
- data/lib/protip/error.rb +2 -3
- data/lib/protip/messages/array.rb +16 -0
- data/lib/protip/messages/errors.rb +22 -0
- data/lib/protip/messages/types.rb +18 -0
- data/lib/protip/resource.rb +11 -9
- data/lib/protip/standard_converter.rb +12 -41
- data/lib/protip/wrapper.rb +48 -26
- data/test/functional/protip/resource_test.rb +173 -138
- data/test/unit/protip/resource_test.rb +107 -85
- data/test/unit/protip/standard_converter_test.rb +14 -11
- data/test/unit/protip/wrapper_test.rb +105 -37
- metadata +12 -12
- data/definitions/protip/messages/wrappers.proto +0 -60
- data/lib/protip/messages/array.pb.rb +0 -27
- data/lib/protip/messages/errors.pb.rb +0 -34
- data/lib/protip/messages/types.pb.rb +0 -26
- data/lib/protip/messages/wrappers.pb.rb +0 -64
@@ -6,32 +6,41 @@ require 'protip/resource'
|
|
6
6
|
|
7
7
|
module Protip::ResourceTest # Namespace for internal constants
|
8
8
|
describe Protip::Resource do
|
9
|
+
let :pool do
|
10
|
+
pool = Google::Protobuf::DescriptorPool.new
|
11
|
+
pool.build do
|
12
|
+
add_message 'nested_message' do
|
13
|
+
optional :number, :int64, 1
|
14
|
+
end
|
15
|
+
add_message 'resource_message' do
|
16
|
+
optional :id, :int64, 1
|
17
|
+
optional :string, :string, 2
|
18
|
+
optional :string2, :string, 3
|
19
|
+
optional :nested_message, :message, 4, 'nested_message'
|
20
|
+
end
|
9
21
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
class ResourceMessage < ::Protobuf::Message
|
15
|
-
optional :int64, :id, 1
|
16
|
-
optional :string, :string, 2
|
17
|
-
optional :string, :string2, 3
|
18
|
-
optional NestedMessage, :nested_message, 4
|
19
|
-
end
|
22
|
+
add_message 'resource_query' do
|
23
|
+
optional :param, :string, 1
|
24
|
+
end
|
20
25
|
|
21
|
-
|
22
|
-
|
23
|
-
|
26
|
+
# Give these things a different structure than resource_query_class,
|
27
|
+
# just to avoid any possibility of decoding as the incorrect
|
28
|
+
# type but still yielding correct results.
|
29
|
+
add_message 'action_query' do
|
30
|
+
optional :param, :string, 4
|
31
|
+
end
|
32
|
+
add_message 'action_response' do
|
33
|
+
optional :response, :string, 3
|
34
|
+
end
|
24
35
|
|
25
|
-
|
26
|
-
|
27
|
-
# type but still yielding correct results.
|
28
|
-
class ActionQuery < ::Protobuf::Message
|
29
|
-
optional :string, :param, 4
|
36
|
+
end
|
37
|
+
pool
|
30
38
|
end
|
31
|
-
|
32
|
-
|
39
|
+
%w(nested_message resource_message resource_query action_query action_response).each do |name|
|
40
|
+
let(:"#{name}_class") do
|
41
|
+
pool.lookup(name).msgclass
|
42
|
+
end
|
33
43
|
end
|
34
|
-
|
35
44
|
# Stubbed API client
|
36
45
|
let :client do
|
37
46
|
mock.responds_like_instance_of(Class.new { include Protip::Client })
|
@@ -59,15 +68,16 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
59
68
|
end
|
60
69
|
|
61
70
|
before do
|
62
|
-
resource_class.class_exec(converter) do |converter|
|
63
|
-
resource actions: [], message:
|
71
|
+
resource_class.class_exec(converter, resource_message_class) do |converter, message|
|
72
|
+
resource actions: [], message: message
|
73
|
+
self.converter = converter
|
64
74
|
end
|
65
75
|
end
|
66
76
|
|
67
77
|
it 'can only be invoked once' do
|
68
78
|
assert_raises RuntimeError do
|
69
|
-
resource_class.
|
70
|
-
resource actions: [], message:
|
79
|
+
resource_class.class_exec(resource_message_class) do |message|
|
80
|
+
resource actions: [], message: message
|
71
81
|
end
|
72
82
|
end
|
73
83
|
end
|
@@ -94,7 +104,7 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
94
104
|
end
|
95
105
|
|
96
106
|
it 'checks with the converter when setting message types' do
|
97
|
-
converter.expects(:convertible?).once.with(
|
107
|
+
converter.expects(:convertible?).once.with(nested_message_class).returns(false)
|
98
108
|
resource = resource_class.new
|
99
109
|
assert_raises(ArgumentError) do
|
100
110
|
resource.nested_message = 5
|
@@ -102,14 +112,14 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
102
112
|
end
|
103
113
|
|
104
114
|
it 'converts message types to and from their Ruby values when the converter allows' do
|
105
|
-
converter.expects(:convertible?).times(2).with(
|
106
|
-
converter.expects(:to_message).once.with(6,
|
107
|
-
converter.expects(:to_object).once.with(
|
115
|
+
converter.expects(:convertible?).times(2).with(nested_message_class).returns(true)
|
116
|
+
converter.expects(:to_message).once.with(6, nested_message_class).returns(nested_message_class.new number: 100)
|
117
|
+
converter.expects(:to_object).once.with(nested_message_class.new number: 100).returns 'intern'
|
108
118
|
|
109
119
|
resource = resource_class.new
|
110
120
|
resource.nested_message = 6
|
111
121
|
|
112
|
-
assert_equal
|
122
|
+
assert_equal nested_message_class.new(number: 100), resource.message.nested_message, 'object was not converted'
|
113
123
|
assert_equal 'intern', resource.nested_message, 'message was not converted'
|
114
124
|
end
|
115
125
|
end
|
@@ -118,9 +128,9 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
118
128
|
let :response do
|
119
129
|
Protip::Messages::Array.new({
|
120
130
|
messages: [
|
121
|
-
|
122
|
-
|
123
|
-
].map(
|
131
|
+
resource_message_class.new(string: 'banjo', id: 1),
|
132
|
+
resource_message_class.new(string: 'kazooie', id: 2),
|
133
|
+
].map{|m| resource_message_class.encode(m).encode('UTF-8')}
|
124
134
|
})
|
125
135
|
end
|
126
136
|
|
@@ -129,16 +139,16 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
129
139
|
end
|
130
140
|
|
131
141
|
it 'does not exist if the resource is defined without the index action' do
|
132
|
-
resource_class.
|
133
|
-
resource actions: [:show], message:
|
142
|
+
resource_class.class_exec(resource_message_class) do |message|
|
143
|
+
resource actions: [:show], message: message
|
134
144
|
end
|
135
145
|
refute_respond_to resource_class, :all
|
136
146
|
end
|
137
147
|
|
138
148
|
describe 'without a query' do
|
139
149
|
before do
|
140
|
-
resource_class.
|
141
|
-
resource actions: [:index], message:
|
150
|
+
resource_class.class_exec(resource_message_class) do |message|
|
151
|
+
resource actions: [:index], message: message
|
142
152
|
end
|
143
153
|
end
|
144
154
|
|
@@ -182,8 +192,8 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
182
192
|
|
183
193
|
describe 'with a query' do
|
184
194
|
before do
|
185
|
-
resource_class.
|
186
|
-
resource actions: [:index], message:
|
195
|
+
resource_class.class_exec(resource_message_class, resource_query_class) do |message, query|
|
196
|
+
resource actions: [:index], message: message, query: query
|
187
197
|
end
|
188
198
|
end
|
189
199
|
|
@@ -191,7 +201,7 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
191
201
|
client.expects(:request)
|
192
202
|
.once
|
193
203
|
.with(method: Net::HTTP::Get, path: 'base_path',
|
194
|
-
message:
|
204
|
+
message: resource_query_class.new(param: 'val'), response_type: Protip::Messages::Array
|
195
205
|
).returns(response)
|
196
206
|
resource_class.all(param: 'val')
|
197
207
|
end
|
@@ -199,7 +209,7 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
199
209
|
it 'allows a request with an empty query' do
|
200
210
|
client.expects(:request)
|
201
211
|
.with(method: Net::HTTP::Get, path: 'base_path',
|
202
|
-
message:
|
212
|
+
message: resource_query_class.new, response_type: Protip::Messages::Array)
|
203
213
|
.returns(response)
|
204
214
|
resource_class.all
|
205
215
|
end
|
@@ -208,7 +218,7 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
208
218
|
|
209
219
|
describe '.find' do
|
210
220
|
let :response do
|
211
|
-
|
221
|
+
resource_message_class.new(string: 'pitbull', id: 100)
|
212
222
|
end
|
213
223
|
|
214
224
|
it 'does not exist if the resource has not been defined' do
|
@@ -216,23 +226,23 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
216
226
|
end
|
217
227
|
|
218
228
|
it 'does not exist if the resource is defined without the show action' do
|
219
|
-
resource_class.
|
220
|
-
resource actions: [:index], message:
|
229
|
+
resource_class.class_exec(resource_message_class) do |message|
|
230
|
+
resource actions: [:index], message: message
|
221
231
|
end
|
222
232
|
refute_respond_to resource_class, :find
|
223
233
|
end
|
224
234
|
|
225
235
|
describe 'without a query' do
|
226
236
|
before do
|
227
|
-
resource_class.
|
228
|
-
resource actions: [:show], message:
|
237
|
+
resource_class.class_exec(resource_message_class) do |message|
|
238
|
+
resource actions: [:show], message: message
|
229
239
|
end
|
230
240
|
end
|
231
241
|
|
232
242
|
it 'requests its message type from the show URL' do
|
233
243
|
client.expects(:request)
|
234
244
|
.once
|
235
|
-
.with(method: Net::HTTP::Get, path: 'base_path/3', message: nil, response_type:
|
245
|
+
.with(method: Net::HTTP::Get, path: 'base_path/3', message: nil, response_type: resource_message_class)
|
236
246
|
.returns(response)
|
237
247
|
resource_class.find 3
|
238
248
|
end
|
@@ -256,8 +266,8 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
256
266
|
|
257
267
|
describe 'with a query' do
|
258
268
|
before do
|
259
|
-
resource_class.
|
260
|
-
resource actions: [:show], message:
|
269
|
+
resource_class.class_exec(resource_message_class, resource_query_class) do |message, query|
|
270
|
+
resource actions: [:show], message: message, query: query
|
261
271
|
end
|
262
272
|
end
|
263
273
|
|
@@ -265,7 +275,7 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
265
275
|
client.expects(:request)
|
266
276
|
.once
|
267
277
|
.with(method: Net::HTTP::Get, path: 'base_path/5',
|
268
|
-
message:
|
278
|
+
message: resource_query_class.new(param: 'val'), response_type: resource_message_class)
|
269
279
|
.returns(response)
|
270
280
|
resource_class.find 5, param: 'val'
|
271
281
|
end
|
@@ -274,7 +284,7 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
274
284
|
client.expects(:request)
|
275
285
|
.once
|
276
286
|
.with(method: Net::HTTP::Get, path: 'base_path/6',
|
277
|
-
message:
|
287
|
+
message: resource_query_class.new, response_type: resource_message_class)
|
278
288
|
.returns(response)
|
279
289
|
resource_class.find 6
|
280
290
|
end
|
@@ -290,23 +300,23 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
290
300
|
end
|
291
301
|
describe 'when a message is given' do
|
292
302
|
before do
|
293
|
-
resource_class.
|
294
|
-
resource actions: [], message:
|
303
|
+
resource_class.class_exec(resource_message_class) do |message|
|
304
|
+
resource actions: [], message: message
|
295
305
|
end
|
296
306
|
end
|
297
307
|
|
298
308
|
it 'creates a resource with an empty message if no attributes are provided' do
|
299
|
-
assert_equal
|
309
|
+
assert_equal resource_message_class.new, resource_class.new.message
|
300
310
|
end
|
301
311
|
|
302
312
|
it 'allows a message to be provided directly' do
|
303
|
-
message =
|
313
|
+
message = resource_message_class.new(id: 1)
|
304
314
|
assert_equal message, resource_class.new(message).message
|
305
315
|
end
|
306
316
|
|
307
317
|
it 'sets attributes when a hash is given' do
|
308
318
|
attrs = {id: 2}
|
309
|
-
assert_equal
|
319
|
+
assert_equal resource_message_class.new(attrs), resource_class.new(attrs).message
|
310
320
|
end
|
311
321
|
|
312
322
|
it 'delegates to #assign_attributes on its wrapper object when a hash is given' do
|
@@ -319,8 +329,8 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
319
329
|
|
320
330
|
describe '#assign_attributes' do
|
321
331
|
before do
|
322
|
-
resource_class.
|
323
|
-
resource actions: [], message:
|
332
|
+
resource_class.class_exec(resource_message_class) do |resource_message_class|
|
333
|
+
resource actions: [], message: resource_message_class
|
324
334
|
end
|
325
335
|
end
|
326
336
|
it 'delegates to #assign_attributes on its wrapper object' do
|
@@ -333,13 +343,13 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
333
343
|
|
334
344
|
describe '#save' do
|
335
345
|
let :response do
|
336
|
-
|
346
|
+
resource_message_class.new(string: 'pit', string2: 'bull', id: 200)
|
337
347
|
end
|
338
348
|
|
339
349
|
describe 'for a new record' do
|
340
350
|
before do
|
341
|
-
resource_class.
|
342
|
-
resource actions: [:create], message:
|
351
|
+
resource_class.class_exec(resource_message_class) do |resource_message_class|
|
352
|
+
resource actions: [:create], message: resource_message_class
|
343
353
|
end
|
344
354
|
resource_class.any_instance.stubs(:persisted?).returns(false)
|
345
355
|
end
|
@@ -348,7 +358,7 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
348
358
|
client.expects(:request)
|
349
359
|
.once
|
350
360
|
.with(method: Net::HTTP::Post, path: 'base_path',
|
351
|
-
message:
|
361
|
+
message: resource_message_class.new(string: 'time', string2: 'flees'), response_type: resource_message_class)
|
352
362
|
.returns(response)
|
353
363
|
|
354
364
|
# Set via initializer and direct setter
|
@@ -373,8 +383,8 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
373
383
|
|
374
384
|
describe 'for an existing record' do
|
375
385
|
before do
|
376
|
-
resource_class.
|
377
|
-
resource actions: [:update], message:
|
386
|
+
resource_class.class_exec(resource_message_class) do |resource_message_class|
|
387
|
+
resource actions: [:update], message: resource_message_class
|
378
388
|
end
|
379
389
|
resource_class.any_instance.stubs(:persisted?).returns(true)
|
380
390
|
end
|
@@ -383,7 +393,7 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
383
393
|
client.expects(:request)
|
384
394
|
.once
|
385
395
|
.with(method: Net::HTTP::Put, path: 'base_path/4',
|
386
|
-
message:
|
396
|
+
message: resource_message_class.new(id: 4, string: 'pitbull'), response_type: resource_message_class)
|
387
397
|
.returns(response)
|
388
398
|
|
389
399
|
resource = resource_class.new(id: 4, string: 'pitbull')
|
@@ -413,25 +423,25 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
413
423
|
exception.stubs(:errors).returns @errors
|
414
424
|
client.stubs(:request).raises(exception)
|
415
425
|
|
416
|
-
resource_class.
|
417
|
-
resource actions: [:update, :create], message:
|
426
|
+
resource_class.class_exec(resource_message_class) do |resource_message_class|
|
427
|
+
resource actions: [:update, :create], message: resource_message_class
|
418
428
|
end
|
419
429
|
@resource = resource_class.new
|
420
430
|
end
|
421
431
|
|
422
432
|
it 'parses base errors' do
|
423
|
-
@errors.messages
|
433
|
+
@errors.messages += ['message1', 'message2']
|
424
434
|
@resource.save
|
425
435
|
|
426
436
|
assert_equal ['message1', 'message2'], @resource.errors['base']
|
427
437
|
end
|
428
438
|
|
429
439
|
it 'parses field errors' do
|
430
|
-
|
440
|
+
[
|
431
441
|
Protip::Messages::FieldError.new(field: 'string', message: 'message1'),
|
432
442
|
Protip::Messages::FieldError.new(field: 'id', message: 'message2'),
|
433
443
|
Protip::Messages::FieldError.new(field: 'string', message: 'message3'),
|
434
|
-
]
|
444
|
+
].each{|field_error| @errors.field_errors.push field_error}
|
435
445
|
@resource.save
|
436
446
|
|
437
447
|
assert_equal ['message1', 'message3'], @resource.errors['string']
|
@@ -447,11 +457,11 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
447
457
|
describe '#destroy' do
|
448
458
|
describe 'for an existing record' do
|
449
459
|
let :response do
|
450
|
-
|
460
|
+
resource_message_class.new(id: 5, string: 'deleted')
|
451
461
|
end
|
452
462
|
before do
|
453
|
-
resource_class.
|
454
|
-
resource actions: [:destroy], message:
|
463
|
+
resource_class.class_exec(resource_message_class) do |resource_message_class|
|
464
|
+
resource actions: [:destroy], message: resource_message_class
|
455
465
|
end
|
456
466
|
resource_class.any_instance.stubs(:persisted?).returns(true)
|
457
467
|
end
|
@@ -459,7 +469,7 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
459
469
|
it 'sends a delete request to the server' do
|
460
470
|
client.expects(:request)
|
461
471
|
.once
|
462
|
-
.with(method: Net::HTTP::Delete, path: 'base_path/79', message: nil, response_type:
|
472
|
+
.with(method: Net::HTTP::Delete, path: 'base_path/79', message: nil, response_type: resource_message_class)
|
463
473
|
.returns(response)
|
464
474
|
resource_class.new(id: 79).destroy
|
465
475
|
end
|
@@ -478,7 +488,7 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
478
488
|
# called. We assume that a `let(:target)` block has already been defined, which will yield the receiver
|
479
489
|
# of the non-resourceful method to be defined (e.g. a resource instance or resource class).
|
480
490
|
#
|
481
|
-
# @param defining_method [String] member or collection, e.g. the method to call in a `
|
491
|
+
# @param defining_method [String] member or collection, e.g. the method to call in a `class_val` block
|
482
492
|
# @param path [String] the URI that the client should expect to receive for an action of this type
|
483
493
|
# named 'action'
|
484
494
|
def self.describe_non_resourceful_action(defining_method, path)
|
@@ -486,12 +496,12 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
486
496
|
# let(:target) is assumed to have been defined
|
487
497
|
|
488
498
|
let :response do
|
489
|
-
|
499
|
+
action_response_class.new(response: 'bilbo')
|
490
500
|
end
|
491
501
|
|
492
502
|
before do
|
493
|
-
resource_class.
|
494
|
-
resource actions: [], message:
|
503
|
+
resource_class.class_exec(resource_message_class) do |resource_message_class|
|
504
|
+
resource actions: [], message: resource_message_class
|
495
505
|
end
|
496
506
|
end
|
497
507
|
describe 'without a request or response type' do
|
@@ -522,8 +532,8 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
522
532
|
end
|
523
533
|
describe 'with a request type' do
|
524
534
|
before do
|
525
|
-
resource_class.
|
526
|
-
send defining_method, action: :action, method: Net::HTTP::Post, request:
|
535
|
+
resource_class.class_exec(action_query_class) do |request|
|
536
|
+
send defining_method, action: :action, method: Net::HTTP::Post, request: request
|
527
537
|
end
|
528
538
|
end
|
529
539
|
|
@@ -531,7 +541,7 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
531
541
|
client.expects(:request)
|
532
542
|
.once
|
533
543
|
.with(method: Net::HTTP::Post, path: path,
|
534
|
-
message:
|
544
|
+
message: action_query_class.new(param: 'tom cruise'), response_type: nil)
|
535
545
|
.returns(nil)
|
536
546
|
target.action param: 'tom cruise'
|
537
547
|
end
|
@@ -540,7 +550,7 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
540
550
|
client.expects(:request)
|
541
551
|
.once
|
542
552
|
.with(method: Net::HTTP::Post, path: path,
|
543
|
-
message:
|
553
|
+
message: action_query_class.new, response_type: nil)
|
544
554
|
.returns(nil)
|
545
555
|
target.action
|
546
556
|
end
|
@@ -548,8 +558,8 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
548
558
|
|
549
559
|
describe 'with a response type' do
|
550
560
|
before do
|
551
|
-
resource_class.
|
552
|
-
send defining_method, action: :action, method: Net::HTTP::Get, response:
|
561
|
+
resource_class.class_exec(action_response_class) do |response|
|
562
|
+
send defining_method, action: :action, method: Net::HTTP::Get, response: response
|
553
563
|
end
|
554
564
|
end
|
555
565
|
|
@@ -557,7 +567,7 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
557
567
|
client.expects(:request)
|
558
568
|
.once
|
559
569
|
.with(method: Net::HTTP::Get, path: path,
|
560
|
-
message: nil, response_type:
|
570
|
+
message: nil, response_type: action_response_class)
|
561
571
|
.returns(response)
|
562
572
|
target.action
|
563
573
|
end
|
@@ -582,5 +592,17 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
582
592
|
end
|
583
593
|
describe_non_resourceful_action 'collection', 'base_path/action'
|
584
594
|
end
|
595
|
+
|
596
|
+
describe '.converter' do
|
597
|
+
describe 'default value' do
|
598
|
+
it 'defaults to the standard converter' do
|
599
|
+
assert_instance_of Protip::StandardConverter, resource_class.converter
|
600
|
+
end
|
601
|
+
|
602
|
+
it 're-uses the same converter on repeated accesses' do
|
603
|
+
assert_same resource_class.converter, resource_class.converter
|
604
|
+
end
|
605
|
+
end
|
606
|
+
end
|
585
607
|
end
|
586
608
|
end
|