protip 0.10.7 → 0.11.0
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.
- 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
|