grape 1.3.0 → 1.5.2
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/CHANGELOG.md +119 -1
- data/LICENSE +1 -1
- data/README.md +123 -29
- data/UPGRADING.md +265 -39
- data/lib/grape/api/instance.rb +32 -31
- data/lib/grape/api.rb +5 -5
- data/lib/grape/content_types.rb +34 -0
- data/lib/grape/dsl/callbacks.rb +1 -1
- data/lib/grape/dsl/helpers.rb +2 -1
- data/lib/grape/dsl/inside_route.rb +77 -43
- data/lib/grape/dsl/parameters.rb +12 -8
- data/lib/grape/dsl/routing.rb +12 -11
- data/lib/grape/dsl/validations.rb +18 -1
- data/lib/grape/eager_load.rb +1 -1
- data/lib/grape/endpoint.rb +8 -6
- data/lib/grape/exceptions/base.rb +0 -4
- data/lib/grape/exceptions/validation.rb +1 -1
- data/lib/grape/exceptions/validation_errors.rb +12 -13
- data/lib/grape/http/headers.rb +26 -0
- data/lib/grape/middleware/auth/base.rb +3 -3
- data/lib/grape/middleware/base.rb +4 -5
- data/lib/grape/middleware/error.rb +11 -13
- data/lib/grape/middleware/formatter.rb +3 -3
- data/lib/grape/middleware/stack.rb +10 -2
- data/lib/grape/middleware/versioner/header.rb +4 -4
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
- data/lib/grape/middleware/versioner/path.rb +1 -1
- data/lib/grape/namespace.rb +12 -2
- data/lib/grape/path.rb +13 -3
- data/lib/grape/request.rb +13 -8
- data/lib/grape/router/attribute_translator.rb +26 -5
- data/lib/grape/router/pattern.rb +17 -16
- data/lib/grape/router/route.rb +5 -24
- data/lib/grape/router.rb +26 -30
- data/lib/grape/{serve_file → serve_stream}/file_body.rb +1 -1
- data/lib/grape/{serve_file → serve_stream}/sendfile_response.rb +1 -1
- data/lib/grape/{serve_file/file_response.rb → serve_stream/stream_response.rb} +8 -8
- data/lib/grape/util/base_inheritable.rb +15 -8
- data/lib/grape/util/cache.rb +20 -0
- data/lib/grape/util/lazy_object.rb +43 -0
- data/lib/grape/util/lazy_value.rb +1 -0
- data/lib/grape/util/reverse_stackable_values.rb +2 -0
- data/lib/grape/util/stackable_values.rb +7 -20
- data/lib/grape/validations/attributes_iterator.rb +8 -0
- data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
- data/lib/grape/validations/params_scope.rb +10 -8
- data/lib/grape/validations/single_attribute_iterator.rb +1 -1
- data/lib/grape/validations/types/array_coercer.rb +14 -5
- data/lib/grape/validations/types/build_coercer.rb +5 -8
- data/lib/grape/validations/types/custom_type_coercer.rb +16 -2
- data/lib/grape/validations/types/dry_type_coercer.rb +36 -1
- data/lib/grape/validations/types/file.rb +15 -12
- data/lib/grape/validations/types/invalid_value.rb +24 -0
- data/lib/grape/validations/types/json.rb +40 -36
- data/lib/grape/validations/types/primitive_coercer.rb +15 -6
- data/lib/grape/validations/types/set_coercer.rb +6 -4
- data/lib/grape/validations/types/variant_collection_coercer.rb +1 -1
- data/lib/grape/validations/types.rb +7 -9
- data/lib/grape/validations/validator_factory.rb +1 -1
- data/lib/grape/validations/validators/as.rb +1 -1
- data/lib/grape/validations/validators/base.rb +8 -8
- data/lib/grape/validations/validators/coerce.rb +11 -15
- data/lib/grape/validations/validators/default.rb +3 -5
- data/lib/grape/validations/validators/exactly_one_of.rb +4 -2
- data/lib/grape/validations/validators/except_values.rb +1 -1
- data/lib/grape/validations/validators/multiple_params_base.rb +2 -1
- data/lib/grape/validations/validators/regexp.rb +1 -1
- data/lib/grape/validations/validators/values.rb +1 -1
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +5 -5
- data/spec/grape/api/instance_spec.rb +50 -0
- data/spec/grape/api_remount_spec.rb +9 -4
- data/spec/grape/api_spec.rb +82 -6
- data/spec/grape/dsl/inside_route_spec.rb +182 -33
- data/spec/grape/endpoint/declared_spec.rb +601 -0
- data/spec/grape/endpoint_spec.rb +0 -521
- data/spec/grape/entity_spec.rb +7 -1
- data/spec/grape/exceptions/validation_errors_spec.rb +2 -2
- data/spec/grape/integration/rack_sendfile_spec.rb +12 -8
- data/spec/grape/middleware/auth/strategies_spec.rb +1 -1
- data/spec/grape/middleware/error_spec.rb +1 -1
- data/spec/grape/middleware/formatter_spec.rb +3 -3
- data/spec/grape/middleware/stack_spec.rb +10 -0
- data/spec/grape/path_spec.rb +4 -4
- data/spec/grape/request_spec.rb +1 -1
- data/spec/grape/validations/instance_behaivour_spec.rb +1 -1
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +13 -3
- data/spec/grape/validations/params_scope_spec.rb +26 -0
- data/spec/grape/validations/single_attribute_iterator_spec.rb +17 -6
- data/spec/grape/validations/types/array_coercer_spec.rb +35 -0
- data/spec/grape/validations/types/primitive_coercer_spec.rb +135 -0
- data/spec/grape/validations/types/set_coercer_spec.rb +34 -0
- data/spec/grape/validations/types_spec.rb +1 -1
- data/spec/grape/validations/validators/coerce_spec.rb +366 -86
- data/spec/grape/validations/validators/default_spec.rb +170 -0
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +12 -12
- data/spec/grape/validations/validators/except_values_spec.rb +1 -0
- data/spec/grape/validations/validators/values_spec.rb +1 -1
- data/spec/grape/validations_spec.rb +298 -30
- data/spec/integration/eager_load/eager_load_spec.rb +15 -0
- data/spec/shared/versioning_examples.rb +20 -20
- data/spec/spec_helper.rb +3 -10
- data/spec/support/chunks.rb +14 -0
- data/spec/support/eager_load.rb +19 -0
- data/spec/support/versioned_helpers.rb +4 -6
- metadata +27 -10
- data/lib/grape/util/content_types.rb +0 -28
data/spec/grape/endpoint_spec.rb
CHANGED
@@ -280,527 +280,6 @@ describe Grape::Endpoint do
|
|
280
280
|
end
|
281
281
|
end
|
282
282
|
|
283
|
-
describe '#declared' do
|
284
|
-
before do
|
285
|
-
subject.format :json
|
286
|
-
subject.params do
|
287
|
-
requires :first
|
288
|
-
optional :second
|
289
|
-
optional :third, default: 'third-default'
|
290
|
-
optional :nested, type: Hash do
|
291
|
-
optional :fourth
|
292
|
-
optional :fifth
|
293
|
-
optional :nested_two, type: Hash do
|
294
|
-
optional :sixth
|
295
|
-
optional :nested_three, type: Hash do
|
296
|
-
optional :seventh
|
297
|
-
end
|
298
|
-
end
|
299
|
-
end
|
300
|
-
optional :nested_arr, type: Array do
|
301
|
-
optional :eighth
|
302
|
-
end
|
303
|
-
end
|
304
|
-
end
|
305
|
-
|
306
|
-
context 'when params are not built with default class' do
|
307
|
-
it 'returns an object that corresponds with the params class - hash with indifferent access' do
|
308
|
-
subject.params do
|
309
|
-
build_with Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder
|
310
|
-
end
|
311
|
-
subject.get '/declared' do
|
312
|
-
d = declared(params, include_missing: true)
|
313
|
-
{ declared_class: d.class.to_s }
|
314
|
-
end
|
315
|
-
|
316
|
-
get '/declared?first=present'
|
317
|
-
expect(JSON.parse(last_response.body)['declared_class']).to eq('ActiveSupport::HashWithIndifferentAccess')
|
318
|
-
end
|
319
|
-
|
320
|
-
it 'returns an object that corresponds with the params class - hashie mash' do
|
321
|
-
subject.params do
|
322
|
-
build_with Grape::Extensions::Hashie::Mash::ParamBuilder
|
323
|
-
end
|
324
|
-
subject.get '/declared' do
|
325
|
-
d = declared(params, include_missing: true)
|
326
|
-
{ declared_class: d.class.to_s }
|
327
|
-
end
|
328
|
-
|
329
|
-
get '/declared?first=present'
|
330
|
-
expect(JSON.parse(last_response.body)['declared_class']).to eq('Hashie::Mash')
|
331
|
-
end
|
332
|
-
|
333
|
-
it 'returns an object that corresponds with the params class - hash' do
|
334
|
-
subject.params do
|
335
|
-
build_with Grape::Extensions::Hash::ParamBuilder
|
336
|
-
end
|
337
|
-
subject.get '/declared' do
|
338
|
-
d = declared(params, include_missing: true)
|
339
|
-
{ declared_class: d.class.to_s }
|
340
|
-
end
|
341
|
-
|
342
|
-
get '/declared?first=present'
|
343
|
-
expect(JSON.parse(last_response.body)['declared_class']).to eq('Hash')
|
344
|
-
end
|
345
|
-
end
|
346
|
-
|
347
|
-
it 'should show nil for nested params if include_missing is true' do
|
348
|
-
subject.get '/declared' do
|
349
|
-
declared(params, include_missing: true)
|
350
|
-
end
|
351
|
-
|
352
|
-
get '/declared?first=present'
|
353
|
-
expect(last_response.status).to eq(200)
|
354
|
-
expect(JSON.parse(last_response.body)['nested']['fourth']).to be_nil
|
355
|
-
end
|
356
|
-
|
357
|
-
it 'does not work in a before filter' do
|
358
|
-
subject.before do
|
359
|
-
declared(params)
|
360
|
-
end
|
361
|
-
subject.get('/declared') { declared(params) }
|
362
|
-
|
363
|
-
expect { get('/declared') }.to raise_error(
|
364
|
-
Grape::DSL::InsideRoute::MethodNotYetAvailable
|
365
|
-
)
|
366
|
-
end
|
367
|
-
|
368
|
-
it 'has as many keys as there are declared params' do
|
369
|
-
subject.get '/declared' do
|
370
|
-
declared(params)
|
371
|
-
end
|
372
|
-
get '/declared?first=present'
|
373
|
-
expect(last_response.status).to eq(200)
|
374
|
-
expect(JSON.parse(last_response.body).keys.size).to eq(5)
|
375
|
-
end
|
376
|
-
|
377
|
-
it 'has a optional param with default value all the time' do
|
378
|
-
subject.get '/declared' do
|
379
|
-
declared(params)
|
380
|
-
end
|
381
|
-
get '/declared?first=one'
|
382
|
-
expect(last_response.status).to eq(200)
|
383
|
-
expect(JSON.parse(last_response.body)['third']).to eql('third-default')
|
384
|
-
end
|
385
|
-
|
386
|
-
it 'builds nested params' do
|
387
|
-
subject.get '/declared' do
|
388
|
-
declared(params)
|
389
|
-
end
|
390
|
-
|
391
|
-
get '/declared?first=present&nested[fourth]=1'
|
392
|
-
expect(last_response.status).to eq(200)
|
393
|
-
expect(JSON.parse(last_response.body)['nested'].keys.size).to eq 3
|
394
|
-
end
|
395
|
-
|
396
|
-
it 'builds nested params when given array' do
|
397
|
-
subject.get '/dummy' do
|
398
|
-
end
|
399
|
-
subject.params do
|
400
|
-
requires :first
|
401
|
-
optional :second
|
402
|
-
optional :third, default: 'third-default'
|
403
|
-
optional :nested, type: Array do
|
404
|
-
optional :fourth
|
405
|
-
end
|
406
|
-
end
|
407
|
-
subject.get '/declared' do
|
408
|
-
declared(params)
|
409
|
-
end
|
410
|
-
|
411
|
-
get '/declared?first=present&nested[][fourth]=1&nested[][fourth]=2'
|
412
|
-
expect(last_response.status).to eq(200)
|
413
|
-
expect(JSON.parse(last_response.body)['nested'].size).to eq 2
|
414
|
-
end
|
415
|
-
|
416
|
-
context 'sets nested objects when the param is missing' do
|
417
|
-
it 'to be a hash when include_missing is true' do
|
418
|
-
subject.get '/declared' do
|
419
|
-
declared(params, include_missing: true)
|
420
|
-
end
|
421
|
-
|
422
|
-
get '/declared?first=present'
|
423
|
-
expect(last_response.status).to eq(200)
|
424
|
-
expect(JSON.parse(last_response.body)['nested']).to be_a(Hash)
|
425
|
-
end
|
426
|
-
|
427
|
-
it 'to be an array when include_missing is true' do
|
428
|
-
subject.get '/declared' do
|
429
|
-
declared(params, include_missing: true)
|
430
|
-
end
|
431
|
-
|
432
|
-
get '/declared?first=present'
|
433
|
-
expect(last_response.status).to eq(200)
|
434
|
-
expect(JSON.parse(last_response.body)['nested_arr']).to be_a(Array)
|
435
|
-
end
|
436
|
-
|
437
|
-
it 'to be nil when include_missing is false' do
|
438
|
-
subject.get '/declared' do
|
439
|
-
declared(params, include_missing: false)
|
440
|
-
end
|
441
|
-
|
442
|
-
get '/declared?first=present'
|
443
|
-
expect(last_response.status).to eq(200)
|
444
|
-
expect(JSON.parse(last_response.body)['nested']).to be_nil
|
445
|
-
end
|
446
|
-
end
|
447
|
-
|
448
|
-
it 'filters out any additional params that are given' do
|
449
|
-
subject.get '/declared' do
|
450
|
-
declared(params)
|
451
|
-
end
|
452
|
-
get '/declared?first=one&other=two'
|
453
|
-
expect(last_response.status).to eq(200)
|
454
|
-
expect(JSON.parse(last_response.body).key?(:other)).to eq false
|
455
|
-
end
|
456
|
-
|
457
|
-
it 'stringifies if that option is passed' do
|
458
|
-
subject.get '/declared' do
|
459
|
-
declared(params, stringify: true)
|
460
|
-
end
|
461
|
-
|
462
|
-
get '/declared?first=one&other=two'
|
463
|
-
expect(last_response.status).to eq(200)
|
464
|
-
expect(JSON.parse(last_response.body)['first']).to eq 'one'
|
465
|
-
end
|
466
|
-
|
467
|
-
it 'does not include missing attributes if that option is passed' do
|
468
|
-
subject.get '/declared' do
|
469
|
-
error! 'expected nil', 400 if declared(params, include_missing: false).key?(:second)
|
470
|
-
''
|
471
|
-
end
|
472
|
-
|
473
|
-
get '/declared?first=one&other=two'
|
474
|
-
expect(last_response.status).to eq(200)
|
475
|
-
end
|
476
|
-
|
477
|
-
it 'does not include renamed missing attributes if that option is passed' do
|
478
|
-
subject.params do
|
479
|
-
optional :renamed_original, as: :renamed
|
480
|
-
end
|
481
|
-
subject.get '/declared' do
|
482
|
-
error! 'expected nil', 400 if declared(params, include_missing: false).key?(:renamed)
|
483
|
-
''
|
484
|
-
end
|
485
|
-
|
486
|
-
get '/declared?first=one&other=two'
|
487
|
-
expect(last_response.status).to eq(200)
|
488
|
-
end
|
489
|
-
|
490
|
-
it 'includes attributes with value that evaluates to false' do
|
491
|
-
subject.params do
|
492
|
-
requires :first
|
493
|
-
optional :boolean
|
494
|
-
end
|
495
|
-
|
496
|
-
subject.post '/declared' do
|
497
|
-
error!('expected false', 400) if declared(params, include_missing: false)[:boolean] != false
|
498
|
-
''
|
499
|
-
end
|
500
|
-
|
501
|
-
post '/declared', ::Grape::Json.dump(first: 'one', boolean: false), 'CONTENT_TYPE' => 'application/json'
|
502
|
-
expect(last_response.status).to eq(201)
|
503
|
-
end
|
504
|
-
|
505
|
-
it 'includes attributes with value that evaluates to nil' do
|
506
|
-
subject.params do
|
507
|
-
requires :first
|
508
|
-
optional :second
|
509
|
-
end
|
510
|
-
|
511
|
-
subject.post '/declared' do
|
512
|
-
error!('expected nil', 400) unless declared(params, include_missing: false)[:second].nil?
|
513
|
-
''
|
514
|
-
end
|
515
|
-
|
516
|
-
post '/declared', ::Grape::Json.dump(first: 'one', second: nil), 'CONTENT_TYPE' => 'application/json'
|
517
|
-
expect(last_response.status).to eq(201)
|
518
|
-
end
|
519
|
-
|
520
|
-
it 'includes missing attributes with defaults when there are nested hashes' do
|
521
|
-
subject.get '/dummy' do
|
522
|
-
end
|
523
|
-
|
524
|
-
subject.params do
|
525
|
-
requires :first
|
526
|
-
optional :second
|
527
|
-
optional :third, default: nil
|
528
|
-
optional :nested, type: Hash do
|
529
|
-
optional :fourth, default: nil
|
530
|
-
optional :fifth, default: nil
|
531
|
-
requires :nested_nested, type: Hash do
|
532
|
-
optional :sixth, default: 'sixth-default'
|
533
|
-
optional :seven, default: nil
|
534
|
-
end
|
535
|
-
end
|
536
|
-
end
|
537
|
-
|
538
|
-
subject.get '/declared' do
|
539
|
-
declared(params, include_missing: false)
|
540
|
-
end
|
541
|
-
|
542
|
-
get '/declared?first=present&nested[fourth]=&nested[nested_nested][sixth]=sixth'
|
543
|
-
json = JSON.parse(last_response.body)
|
544
|
-
expect(last_response.status).to eq(200)
|
545
|
-
expect(json['first']).to eq 'present'
|
546
|
-
expect(json['nested'].keys).to eq %w[fourth fifth nested_nested]
|
547
|
-
expect(json['nested']['fourth']).to eq ''
|
548
|
-
expect(json['nested']['nested_nested'].keys).to eq %w[sixth seven]
|
549
|
-
expect(json['nested']['nested_nested']['sixth']).to eq 'sixth'
|
550
|
-
end
|
551
|
-
|
552
|
-
it 'does not include missing attributes when there are nested hashes' do
|
553
|
-
subject.get '/dummy' do
|
554
|
-
end
|
555
|
-
|
556
|
-
subject.params do
|
557
|
-
requires :first
|
558
|
-
optional :second
|
559
|
-
optional :third
|
560
|
-
optional :nested, type: Hash do
|
561
|
-
optional :fourth
|
562
|
-
optional :fifth
|
563
|
-
end
|
564
|
-
end
|
565
|
-
|
566
|
-
subject.get '/declared' do
|
567
|
-
declared(params, include_missing: false)
|
568
|
-
end
|
569
|
-
|
570
|
-
get '/declared?first=present&nested[fourth]=4'
|
571
|
-
json = JSON.parse(last_response.body)
|
572
|
-
expect(last_response.status).to eq(200)
|
573
|
-
expect(json['first']).to eq 'present'
|
574
|
-
expect(json['nested'].keys).to eq %w[fourth]
|
575
|
-
expect(json['nested']['fourth']).to eq '4'
|
576
|
-
end
|
577
|
-
end
|
578
|
-
|
579
|
-
describe '#declared; call from child namespace' do
|
580
|
-
before do
|
581
|
-
subject.format :json
|
582
|
-
subject.namespace :parent do
|
583
|
-
params do
|
584
|
-
requires :parent_name, type: String
|
585
|
-
end
|
586
|
-
|
587
|
-
namespace ':parent_name' do
|
588
|
-
params do
|
589
|
-
requires :child_name, type: String
|
590
|
-
requires :child_age, type: Integer
|
591
|
-
end
|
592
|
-
|
593
|
-
namespace ':child_name' do
|
594
|
-
params do
|
595
|
-
requires :grandchild_name, type: String
|
596
|
-
end
|
597
|
-
|
598
|
-
get ':grandchild_name' do
|
599
|
-
{
|
600
|
-
'params' => params,
|
601
|
-
'without_parent_namespaces' => declared(params, include_parent_namespaces: false),
|
602
|
-
'with_parent_namespaces' => declared(params, include_parent_namespaces: true)
|
603
|
-
}
|
604
|
-
end
|
605
|
-
end
|
606
|
-
end
|
607
|
-
end
|
608
|
-
|
609
|
-
get '/parent/foo/bar/baz', child_age: 5, extra: 'hello'
|
610
|
-
end
|
611
|
-
|
612
|
-
let(:parsed_response) { JSON.parse(last_response.body, symbolize_names: true) }
|
613
|
-
|
614
|
-
it { expect(last_response.status).to eq 200 }
|
615
|
-
|
616
|
-
context 'with include_parent_namespaces: false' do
|
617
|
-
it 'returns declared parameters only from current namespace' do
|
618
|
-
expect(parsed_response[:without_parent_namespaces]).to eq(
|
619
|
-
grandchild_name: 'baz'
|
620
|
-
)
|
621
|
-
end
|
622
|
-
end
|
623
|
-
|
624
|
-
context 'with include_parent_namespaces: true' do
|
625
|
-
it 'returns declared parameters from every parent namespace' do
|
626
|
-
expect(parsed_response[:with_parent_namespaces]).to eq(
|
627
|
-
parent_name: 'foo',
|
628
|
-
child_name: 'bar',
|
629
|
-
grandchild_name: 'baz',
|
630
|
-
child_age: 5
|
631
|
-
)
|
632
|
-
end
|
633
|
-
end
|
634
|
-
|
635
|
-
context 'without declaration' do
|
636
|
-
it 'returns all requested parameters' do
|
637
|
-
expect(parsed_response[:params]).to eq(
|
638
|
-
parent_name: 'foo',
|
639
|
-
child_name: 'bar',
|
640
|
-
grandchild_name: 'baz',
|
641
|
-
child_age: 5,
|
642
|
-
extra: 'hello'
|
643
|
-
)
|
644
|
-
end
|
645
|
-
end
|
646
|
-
end
|
647
|
-
|
648
|
-
describe '#declared; from a nested mounted endpoint' do
|
649
|
-
before do
|
650
|
-
doubly_mounted = Class.new(Grape::API)
|
651
|
-
doubly_mounted.namespace :more do
|
652
|
-
params do
|
653
|
-
requires :y, type: Integer
|
654
|
-
end
|
655
|
-
route_param :y do
|
656
|
-
get do
|
657
|
-
{
|
658
|
-
params: params,
|
659
|
-
declared_params: declared(params)
|
660
|
-
}
|
661
|
-
end
|
662
|
-
end
|
663
|
-
end
|
664
|
-
|
665
|
-
mounted = Class.new(Grape::API)
|
666
|
-
mounted.namespace :another do
|
667
|
-
params do
|
668
|
-
requires :mount_space, type: Integer
|
669
|
-
end
|
670
|
-
route_param :mount_space do
|
671
|
-
mount doubly_mounted
|
672
|
-
end
|
673
|
-
end
|
674
|
-
|
675
|
-
subject.format :json
|
676
|
-
subject.namespace :something do
|
677
|
-
params do
|
678
|
-
requires :id, type: Integer
|
679
|
-
end
|
680
|
-
resource ':id' do
|
681
|
-
mount mounted
|
682
|
-
end
|
683
|
-
end
|
684
|
-
end
|
685
|
-
|
686
|
-
it 'can access parent attributes' do
|
687
|
-
get '/something/123/another/456/more/789'
|
688
|
-
expect(last_response.status).to eq 200
|
689
|
-
json = JSON.parse(last_response.body, symbolize_names: true)
|
690
|
-
|
691
|
-
# test all three levels of params
|
692
|
-
expect(json[:declared_params][:y]).to eq 789
|
693
|
-
expect(json[:declared_params][:mount_space]).to eq 456
|
694
|
-
expect(json[:declared_params][:id]).to eq 123
|
695
|
-
end
|
696
|
-
end
|
697
|
-
|
698
|
-
describe '#declared; mixed nesting' do
|
699
|
-
before do
|
700
|
-
subject.format :json
|
701
|
-
subject.resource :users do
|
702
|
-
route_param :id, type: Integer, desc: 'ID desc' do
|
703
|
-
# Adding this causes route_setting(:declared_params) to be nil for the
|
704
|
-
# get block in namespace 'foo' below
|
705
|
-
get do
|
706
|
-
end
|
707
|
-
|
708
|
-
namespace 'foo' do
|
709
|
-
get do
|
710
|
-
{
|
711
|
-
params: params,
|
712
|
-
declared_params: declared(params),
|
713
|
-
declared_params_no_parent: declared(params, include_parent_namespaces: false)
|
714
|
-
}
|
715
|
-
end
|
716
|
-
end
|
717
|
-
end
|
718
|
-
end
|
719
|
-
end
|
720
|
-
|
721
|
-
it 'can access parent route_param' do
|
722
|
-
get '/users/123/foo', bar: 'bar'
|
723
|
-
expect(last_response.status).to eq 200
|
724
|
-
json = JSON.parse(last_response.body, symbolize_names: true)
|
725
|
-
|
726
|
-
expect(json[:declared_params][:id]).to eq 123
|
727
|
-
expect(json[:declared_params_no_parent][:id]).to eq nil
|
728
|
-
end
|
729
|
-
end
|
730
|
-
|
731
|
-
describe '#declared; with multiple route_param' do
|
732
|
-
before do
|
733
|
-
mounted = Class.new(Grape::API)
|
734
|
-
mounted.namespace :albums do
|
735
|
-
get do
|
736
|
-
declared(params)
|
737
|
-
end
|
738
|
-
end
|
739
|
-
|
740
|
-
subject.format :json
|
741
|
-
subject.namespace :artists do
|
742
|
-
route_param :id, type: Integer do
|
743
|
-
get do
|
744
|
-
declared(params)
|
745
|
-
end
|
746
|
-
|
747
|
-
params do
|
748
|
-
requires :filter, type: String
|
749
|
-
end
|
750
|
-
get :some_route do
|
751
|
-
declared(params)
|
752
|
-
end
|
753
|
-
end
|
754
|
-
|
755
|
-
route_param :artist_id, type: Integer do
|
756
|
-
namespace :compositions do
|
757
|
-
get do
|
758
|
-
declared(params)
|
759
|
-
end
|
760
|
-
end
|
761
|
-
end
|
762
|
-
|
763
|
-
route_param :compositor_id, type: Integer do
|
764
|
-
mount mounted
|
765
|
-
end
|
766
|
-
end
|
767
|
-
end
|
768
|
-
|
769
|
-
it 'return only :id without :artist_id' do
|
770
|
-
get '/artists/1'
|
771
|
-
json = JSON.parse(last_response.body, symbolize_names: true)
|
772
|
-
|
773
|
-
expect(json.key?(:id)).to be_truthy
|
774
|
-
expect(json.key?(:artist_id)).not_to be_truthy
|
775
|
-
end
|
776
|
-
|
777
|
-
it 'return only :artist_id without :id' do
|
778
|
-
get '/artists/1/compositions'
|
779
|
-
json = JSON.parse(last_response.body, symbolize_names: true)
|
780
|
-
|
781
|
-
expect(json.key?(:artist_id)).to be_truthy
|
782
|
-
expect(json.key?(:id)).not_to be_truthy
|
783
|
-
end
|
784
|
-
|
785
|
-
it 'return :filter and :id parameters in declared for second enpoint inside route_param' do
|
786
|
-
get '/artists/1/some_route', filter: 'some_filter'
|
787
|
-
json = JSON.parse(last_response.body, symbolize_names: true)
|
788
|
-
|
789
|
-
expect(json.key?(:filter)).to be_truthy
|
790
|
-
expect(json.key?(:id)).to be_truthy
|
791
|
-
expect(json.key?(:artist_id)).not_to be_truthy
|
792
|
-
end
|
793
|
-
|
794
|
-
it 'return :compositor_id for mounter in route_param' do
|
795
|
-
get '/artists/1/albums'
|
796
|
-
json = JSON.parse(last_response.body, symbolize_names: true)
|
797
|
-
|
798
|
-
expect(json.key?(:compositor_id)).to be_truthy
|
799
|
-
expect(json.key?(:id)).not_to be_truthy
|
800
|
-
expect(json.key?(:artist_id)).not_to be_truthy
|
801
|
-
end
|
802
|
-
end
|
803
|
-
|
804
283
|
describe '#params' do
|
805
284
|
it 'is available to the caller' do
|
806
285
|
subject.get('/hey') do
|
data/spec/grape/entity_spec.rb
CHANGED
@@ -116,7 +116,7 @@ describe Grape::Entity do
|
|
116
116
|
expect(last_response.body).to eq('Auto-detect!')
|
117
117
|
end
|
118
118
|
|
119
|
-
it 'does not run autodetection for Entity when
|
119
|
+
it 'does not run autodetection for Entity when explicitly provided' do
|
120
120
|
entity = Class.new(Grape::Entity)
|
121
121
|
some_array = []
|
122
122
|
|
@@ -181,6 +181,7 @@ describe Grape::Entity do
|
|
181
181
|
subject.get '/example' do
|
182
182
|
c = Class.new do
|
183
183
|
attr_reader :id
|
184
|
+
|
184
185
|
def initialize(id)
|
185
186
|
@id = id
|
186
187
|
end
|
@@ -202,6 +203,7 @@ describe Grape::Entity do
|
|
202
203
|
subject.get '/examples' do
|
203
204
|
c = Class.new do
|
204
205
|
attr_reader :id
|
206
|
+
|
205
207
|
def initialize(id)
|
206
208
|
@id = id
|
207
209
|
end
|
@@ -226,6 +228,7 @@ describe Grape::Entity do
|
|
226
228
|
subject.get '/example' do
|
227
229
|
c = Class.new do
|
228
230
|
attr_reader :name
|
231
|
+
|
229
232
|
def initialize(args)
|
230
233
|
@name = args[:name] || 'no name set'
|
231
234
|
end
|
@@ -255,6 +258,7 @@ XML
|
|
255
258
|
subject.get '/example' do
|
256
259
|
c = Class.new do
|
257
260
|
attr_reader :name
|
261
|
+
|
258
262
|
def initialize(args)
|
259
263
|
@name = args[:name] || 'no name set'
|
260
264
|
end
|
@@ -284,6 +288,7 @@ XML
|
|
284
288
|
subject.get '/example' do
|
285
289
|
c = Class.new do
|
286
290
|
attr_reader :name
|
291
|
+
|
287
292
|
def initialize(args)
|
288
293
|
@name = args[:name] || 'no name set'
|
289
294
|
end
|
@@ -302,6 +307,7 @@ XML
|
|
302
307
|
it 'present with multiple entities using optional symbol' do
|
303
308
|
user = Class.new do
|
304
309
|
attr_reader :name
|
310
|
+
|
305
311
|
def initialize(args)
|
306
312
|
@name = args[:name] || 'no name set'
|
307
313
|
end
|
@@ -81,8 +81,8 @@ describe Grape::Exceptions::ValidationErrors do
|
|
81
81
|
expect(last_response.status).to eq(400)
|
82
82
|
expect(JSON.parse(last_response.body)).to eq(
|
83
83
|
[
|
84
|
-
'params' => %w[beer wine
|
85
|
-
'messages' => ['are
|
84
|
+
'params' => %w[beer wine],
|
85
|
+
'messages' => ['are mutually exclusive']
|
86
86
|
]
|
87
87
|
)
|
88
88
|
end
|
@@ -4,12 +4,16 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
describe Rack::Sendfile do
|
6
6
|
subject do
|
7
|
-
|
7
|
+
content_object = file_object
|
8
8
|
app = Class.new(Grape::API) do
|
9
9
|
use Rack::Sendfile
|
10
10
|
format :json
|
11
11
|
get do
|
12
|
-
|
12
|
+
if content_object.is_a?(String)
|
13
|
+
sendfile content_object
|
14
|
+
else
|
15
|
+
stream content_object
|
16
|
+
end
|
13
17
|
end
|
14
18
|
end
|
15
19
|
|
@@ -22,9 +26,9 @@ describe Rack::Sendfile do
|
|
22
26
|
app.call(env)
|
23
27
|
end
|
24
28
|
|
25
|
-
context do
|
26
|
-
let(:
|
27
|
-
|
29
|
+
context 'when calling sendfile' do
|
30
|
+
let(:file_object) do
|
31
|
+
'/accel/mapping/some/path'
|
28
32
|
end
|
29
33
|
|
30
34
|
it 'contains Sendfile headers' do
|
@@ -33,9 +37,9 @@ describe Rack::Sendfile do
|
|
33
37
|
end
|
34
38
|
end
|
35
39
|
|
36
|
-
context do
|
37
|
-
let(:
|
38
|
-
double(:
|
40
|
+
context 'when streaming non file content' do
|
41
|
+
let(:file_object) do
|
42
|
+
double(:file_object, each: nil)
|
39
43
|
end
|
40
44
|
|
41
45
|
it 'not contains Sendfile headers' do
|
@@ -36,7 +36,7 @@ describe Grape::Middleware::Auth::Strategies do
|
|
36
36
|
RSpec::Matchers.define :be_challenge do
|
37
37
|
match do |actual_response|
|
38
38
|
actual_response.status == 401 &&
|
39
|
-
actual_response['WWW-Authenticate']
|
39
|
+
actual_response['WWW-Authenticate'].start_with?('Digest ') &&
|
40
40
|
actual_response.body.empty?
|
41
41
|
end
|
42
42
|
end
|
@@ -380,7 +380,7 @@ describe Grape::Middleware::Formatter do
|
|
380
380
|
|
381
381
|
context 'send file' do
|
382
382
|
let(:file) { double(File) }
|
383
|
-
let(:file_body) { Grape::
|
383
|
+
let(:file_body) { Grape::ServeStream::StreamResponse.new(file) }
|
384
384
|
let(:app) { ->(_env) { [200, {}, file_body] } }
|
385
385
|
|
386
386
|
it 'returns a file response' do
|
@@ -402,10 +402,10 @@ describe Grape::Middleware::Formatter do
|
|
402
402
|
let(:app) { ->(_env) { [200, {}, ['']] } }
|
403
403
|
before do
|
404
404
|
Grape::Formatter.register :invalid, InvalidFormatter
|
405
|
-
Grape::ContentTypes
|
405
|
+
Grape::ContentTypes.register :invalid, 'application/x-invalid'
|
406
406
|
end
|
407
407
|
after do
|
408
|
-
Grape::ContentTypes
|
408
|
+
Grape::ContentTypes.default_elements.delete(:invalid)
|
409
409
|
Grape::Formatter.default_elements.delete(:invalid)
|
410
410
|
end
|
411
411
|
|
@@ -8,6 +8,7 @@ describe Grape::Middleware::Stack do
|
|
8
8
|
class BarMiddleware; end
|
9
9
|
class BlockMiddleware
|
10
10
|
attr_reader :block
|
11
|
+
|
11
12
|
def initialize(&block)
|
12
13
|
@block = block
|
13
14
|
end
|
@@ -111,6 +112,15 @@ describe Grape::Middleware::Stack do
|
|
111
112
|
expect(subject[1]).to eq(StackSpec::BlockMiddleware)
|
112
113
|
expect(subject[2]).to eq(StackSpec::BarMiddleware)
|
113
114
|
end
|
115
|
+
|
116
|
+
context 'middleware spec with proc declaration exists' do
|
117
|
+
let(:middleware_spec_with_proc) { [:use, StackSpec::FooMiddleware, proc] }
|
118
|
+
|
119
|
+
it 'properly forwards spec arguments' do
|
120
|
+
expect(subject).to receive(:use).with(StackSpec::FooMiddleware)
|
121
|
+
subject.merge_with([middleware_spec_with_proc])
|
122
|
+
end
|
123
|
+
end
|
114
124
|
end
|
115
125
|
|
116
126
|
describe '#build' do
|