protip 0.10.7 → 0.11.0

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