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.
@@ -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
- class NestedMessage < ::Protobuf::Message
11
- optional :int64, :number, 1
12
- end
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
- class ResourceQuery < ::Protobuf::Message
22
- optional :string, :param, 1
23
- end
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
- # Give these things a different structure than ResourceQuery,
26
- # just to avoid any possibility of decoding as the incorrect
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
- class ActionResponse < ::Protobuf::Message
32
- optional :string, :response, 3
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: ResourceMessage, converter: converter
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.class_eval do
70
- resource actions: [], message: ResourceMessage
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(NestedMessage).returns(false)
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(NestedMessage).returns(true)
106
- converter.expects(:to_message).once.with(6, NestedMessage).returns(NestedMessage.new number: 100)
107
- converter.expects(:to_object).once.with(NestedMessage.new number: 100).returns 'intern'
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 NestedMessage.new(number: 100), resource.message.nested_message, 'object was not converted'
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
- ResourceMessage.new(string: 'banjo', id: 1),
122
- ResourceMessage.new(string: 'kazooie', id: 2),
123
- ].map(&:encode)
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.class_eval do
133
- resource actions: [:show], message: ResourceMessage
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.class_eval do
141
- resource actions: [:index], message: ResourceMessage
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.class_eval do
186
- resource actions: [:index], message: ResourceMessage, query: ResourceQuery
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: ResourceQuery.new(param: 'val'), response_type: Protip::Messages::Array
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: ResourceQuery.new, response_type: Protip::Messages::Array)
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
- ResourceMessage.new(string: 'pitbull', id: 100)
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.class_eval do
220
- resource actions: [:index], message: ResourceMessage
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.class_eval do
228
- resource actions: [:show], message: ResourceMessage
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: ResourceMessage)
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.class_eval do
260
- resource actions: [:show], message: ResourceMessage, query: ResourceQuery
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: ResourceQuery.new(param: 'val'), response_type: ResourceMessage)
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: ResourceQuery.new, response_type: ResourceMessage)
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.class_eval do
294
- resource actions: [], message: ResourceMessage
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 ResourceMessage.new, resource_class.new.message
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 = ResourceMessage.new(id: 1)
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 ResourceMessage.new(attrs), resource_class.new(attrs).message
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.class_eval do
323
- resource actions: [], message: ResourceMessage
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
- ResourceMessage.new(string: 'pit', string2: 'bull', id: 200)
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.class_eval do
342
- resource actions: [:create], message: ResourceMessage
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: ResourceMessage.new(string: 'time', string2: 'flees'), response_type: ResourceMessage)
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.class_eval do
377
- resource actions: [:update], message: ResourceMessage
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: ResourceMessage.new(id: 4, string: 'pitbull'), response_type: ResourceMessage)
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.class_eval do
417
- resource actions: [:update, :create], message: ResourceMessage
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 = ['message1', 'message2']
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
- @errors.field_errors = [
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
- ResourceMessage.new(id: 5, string: 'deleted')
460
+ resource_message_class.new(id: 5, string: 'deleted')
451
461
  end
452
462
  before do
453
- resource_class.class_eval do
454
- resource actions: [:destroy], message: ResourceMessage
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: ResourceMessage)
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 `class_eval` block
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
- ActionResponse.new(response: 'bilbo')
499
+ action_response_class.new(response: 'bilbo')
490
500
  end
491
501
 
492
502
  before do
493
- resource_class.class_eval do
494
- resource actions: [], message: ResourceMessage
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.class_eval do
526
- send defining_method, action: :action, method: Net::HTTP::Post, request: ActionQuery
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: ActionQuery.new(param: 'tom cruise'), response_type: nil)
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: ActionQuery.new, response_type: nil)
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.class_eval do
552
- send defining_method, action: :action, method: Net::HTTP::Get, response: ActionResponse
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: ActionResponse)
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