grape 1.6.0 → 1.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/CONTRIBUTING.md +1 -0
- data/README.md +9 -1
- data/lib/grape/api.rb +12 -0
- data/lib/grape/dry_types.rb +12 -0
- data/lib/grape/dsl/headers.rb +5 -2
- data/lib/grape/dsl/helpers.rb +1 -1
- data/lib/grape/middleware/auth/dsl.rb +7 -1
- data/lib/grape/middleware/base.rb +1 -1
- data/lib/grape/util/json.rb +2 -0
- data/lib/grape/util/strict_hash_configuration.rb +1 -1
- data/lib/grape/validations/types/array_coercer.rb +0 -2
- data/lib/grape/validations/types/dry_type_coercer.rb +1 -10
- data/lib/grape/validations/types/json.rb +0 -2
- data/lib/grape/validations/types/primitive_coercer.rb +5 -7
- data/lib/grape/validations/types/set_coercer.rb +0 -3
- data/lib/grape/validations/types.rb +83 -9
- data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
- data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
- data/lib/grape/validations/validators/as_validator.rb +14 -0
- data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
- data/lib/grape/validations/validators/base.rb +73 -71
- data/lib/grape/validations/validators/coerce_validator.rb +75 -0
- data/lib/grape/validations/validators/default_validator.rb +51 -0
- data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
- data/lib/grape/validations/validators/except_values_validator.rb +24 -0
- data/lib/grape/validations/validators/multiple_params_base.rb +24 -22
- data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
- data/lib/grape/validations/validators/presence_validator.rb +15 -0
- data/lib/grape/validations/validators/regexp_validator.rb +16 -0
- data/lib/grape/validations/validators/same_as_validator.rb +29 -0
- data/lib/grape/validations/validators/values_validator.rb +88 -0
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +59 -24
- data/spec/grape/api/custom_validations_spec.rb +77 -46
- data/spec/grape/api/deeply_included_options_spec.rb +3 -3
- data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -1
- data/spec/grape/api/invalid_format_spec.rb +2 -0
- data/spec/grape/api/recognize_path_spec.rb +1 -1
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -15
- data/spec/grape/api_remount_spec.rb +16 -15
- data/spec/grape/api_spec.rb +317 -193
- data/spec/grape/dsl/callbacks_spec.rb +1 -0
- data/spec/grape/dsl/headers_spec.rb +39 -9
- data/spec/grape/dsl/helpers_spec.rb +3 -2
- data/spec/grape/dsl/inside_route_spec.rb +6 -4
- data/spec/grape/dsl/logger_spec.rb +16 -18
- data/spec/grape/dsl/middleware_spec.rb +1 -0
- data/spec/grape/dsl/parameters_spec.rb +1 -0
- data/spec/grape/dsl/request_response_spec.rb +1 -0
- data/spec/grape/dsl/routing_spec.rb +9 -6
- data/spec/grape/endpoint/declared_spec.rb +12 -12
- data/spec/grape/endpoint_spec.rb +59 -50
- data/spec/grape/entity_spec.rb +13 -13
- data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -0
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -22
- data/spec/grape/exceptions/validation_errors_spec.rb +13 -10
- data/spec/grape/exceptions/validation_spec.rb +5 -3
- data/spec/grape/extensions/param_builders/hash_spec.rb +7 -7
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -8
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -8
- data/spec/grape/integration/rack_sendfile_spec.rb +1 -1
- data/spec/grape/loading_spec.rb +8 -8
- data/spec/grape/middleware/auth/dsl_spec.rb +14 -5
- data/spec/grape/middleware/auth/strategies_spec.rb +60 -20
- data/spec/grape/middleware/base_spec.rb +24 -15
- data/spec/grape/middleware/error_spec.rb +1 -0
- data/spec/grape/middleware/exception_spec.rb +111 -161
- data/spec/grape/middleware/formatter_spec.rb +25 -4
- data/spec/grape/middleware/globals_spec.rb +7 -4
- data/spec/grape/middleware/stack_spec.rb +11 -11
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -1
- data/spec/grape/middleware/versioner/header_spec.rb +14 -13
- data/spec/grape/middleware/versioner/param_spec.rb +7 -1
- data/spec/grape/middleware/versioner/path_spec.rb +5 -1
- data/spec/grape/middleware/versioner_spec.rb +1 -1
- data/spec/grape/parser_spec.rb +4 -0
- data/spec/grape/path_spec.rb +52 -52
- data/spec/grape/presenters/presenter_spec.rb +7 -6
- data/spec/grape/request_spec.rb +6 -4
- data/spec/grape/util/inheritable_setting_spec.rb +7 -7
- data/spec/grape/util/inheritable_values_spec.rb +3 -2
- data/spec/grape/util/reverse_stackable_values_spec.rb +3 -1
- data/spec/grape/util/stackable_values_spec.rb +7 -5
- data/spec/grape/validations/instance_behaivour_spec.rb +9 -10
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -0
- data/spec/grape/validations/params_scope_spec.rb +9 -7
- data/spec/grape/validations/single_attribute_iterator_spec.rb +1 -0
- data/spec/grape/validations/types/primitive_coercer_spec.rb +2 -2
- data/spec/grape/validations/types_spec.rb +8 -8
- data/spec/grape/validations/validators/all_or_none_spec.rb +50 -56
- data/spec/grape/validations/validators/allow_blank_spec.rb +136 -140
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -56
- data/spec/grape/validations/validators/coerce_spec.rb +10 -12
- data/spec/grape/validations/validators/default_spec.rb +72 -78
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -77
- data/spec/grape/validations/validators/except_values_spec.rb +1 -1
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -77
- data/spec/grape/validations/validators/presence_spec.rb +16 -1
- data/spec/grape/validations/validators/regexp_spec.rb +25 -31
- data/spec/grape/validations/validators/same_as_spec.rb +14 -20
- data/spec/grape/validations/validators/values_spec.rb +172 -171
- data/spec/grape/validations_spec.rb +45 -16
- data/spec/integration/eager_load/eager_load_spec.rb +2 -2
- data/spec/integration/multi_json/json_spec.rb +1 -1
- data/spec/integration/multi_xml/xml_spec.rb +1 -1
- data/spec/shared/versioning_examples.rb +10 -7
- data/spec/spec_helper.rb +11 -1
- metadata +116 -116
- data/lib/grape/validations/types/build_coercer.rb +0 -94
- data/lib/grape/validations/validators/all_or_none.rb +0 -16
- data/lib/grape/validations/validators/allow_blank.rb +0 -18
- data/lib/grape/validations/validators/as.rb +0 -12
- data/lib/grape/validations/validators/at_least_one_of.rb +0 -15
- data/lib/grape/validations/validators/coerce.rb +0 -87
- data/lib/grape/validations/validators/default.rb +0 -49
- data/lib/grape/validations/validators/exactly_one_of.rb +0 -17
- data/lib/grape/validations/validators/except_values.rb +0 -22
- data/lib/grape/validations/validators/mutual_exclusion.rb +0 -16
- data/lib/grape/validations/validators/presence.rb +0 -13
- data/lib/grape/validations/validators/regexp.rb +0 -14
- data/lib/grape/validations/validators/same_as.rb +0 -27
- data/lib/grape/validations/validators/values.rb +0 -86
data/spec/grape/api_spec.rb
CHANGED
@@ -4,7 +4,10 @@ require 'spec_helper'
|
|
4
4
|
require 'shared/versioning_examples'
|
5
5
|
|
6
6
|
describe Grape::API do
|
7
|
-
subject
|
7
|
+
subject do
|
8
|
+
puts described_class
|
9
|
+
Class.new(described_class)
|
10
|
+
end
|
8
11
|
|
9
12
|
def app
|
10
13
|
subject
|
@@ -18,7 +21,7 @@ describe Grape::API do
|
|
18
21
|
end
|
19
22
|
|
20
23
|
get 'awesome/sauce/'
|
21
|
-
expect(last_response.status).to
|
24
|
+
expect(last_response.status).to be 200
|
22
25
|
expect(last_response.body).to eql 'Hello there.'
|
23
26
|
end
|
24
27
|
|
@@ -32,7 +35,7 @@ describe Grape::API do
|
|
32
35
|
expect(last_response.body).to eql 'Hello there.'
|
33
36
|
|
34
37
|
get '/hello'
|
35
|
-
expect(last_response.status).to
|
38
|
+
expect(last_response.status).to be 404
|
36
39
|
end
|
37
40
|
|
38
41
|
it 'supports OPTIONS' do
|
@@ -42,7 +45,7 @@ describe Grape::API do
|
|
42
45
|
end
|
43
46
|
|
44
47
|
options 'awesome/sauce'
|
45
|
-
expect(last_response.status).to
|
48
|
+
expect(last_response.status).to be 204
|
46
49
|
expect(last_response.body).to be_blank
|
47
50
|
end
|
48
51
|
|
@@ -51,7 +54,7 @@ describe Grape::API do
|
|
51
54
|
subject.get
|
52
55
|
|
53
56
|
post 'awesome/sauce'
|
54
|
-
expect(last_response.status).to
|
57
|
+
expect(last_response.status).to be 405
|
55
58
|
end
|
56
59
|
end
|
57
60
|
|
@@ -71,7 +74,7 @@ describe Grape::API do
|
|
71
74
|
end
|
72
75
|
|
73
76
|
describe '.version using path' do
|
74
|
-
|
77
|
+
it_behaves_like 'versioning' do
|
75
78
|
let(:macro_options) do
|
76
79
|
{
|
77
80
|
using: :path
|
@@ -81,7 +84,7 @@ describe Grape::API do
|
|
81
84
|
end
|
82
85
|
|
83
86
|
describe '.version using param' do
|
84
|
-
|
87
|
+
it_behaves_like 'versioning' do
|
85
88
|
let(:macro_options) do
|
86
89
|
{
|
87
90
|
using: :param,
|
@@ -92,7 +95,7 @@ describe Grape::API do
|
|
92
95
|
end
|
93
96
|
|
94
97
|
describe '.version using header' do
|
95
|
-
|
98
|
+
it_behaves_like 'versioning' do
|
96
99
|
let(:macro_options) do
|
97
100
|
{
|
98
101
|
using: :header,
|
@@ -120,7 +123,7 @@ describe Grape::API do
|
|
120
123
|
end
|
121
124
|
|
122
125
|
describe '.version using accept_version_header' do
|
123
|
-
|
126
|
+
it_behaves_like 'versioning' do
|
124
127
|
let(:macro_options) do
|
125
128
|
{
|
126
129
|
using: :accept_version_header
|
@@ -389,7 +392,7 @@ describe Grape::API do
|
|
389
392
|
end
|
390
393
|
end
|
391
394
|
|
392
|
-
before
|
395
|
+
before do
|
393
396
|
allow_any_instance_of(ApiSpec::DummyFormatClass).to receive(:to_json).and_return('abc')
|
394
397
|
allow_any_instance_of(ApiSpec::DummyFormatClass).to receive(:to_txt).and_return('def')
|
395
398
|
|
@@ -447,7 +450,7 @@ describe Grape::API do
|
|
447
450
|
end
|
448
451
|
|
449
452
|
%i[put post].each do |verb|
|
450
|
-
context verb do
|
453
|
+
context verb.to_s do
|
451
454
|
['string', :symbol, 1, -1.1, {}, [], true, false, nil].each do |object|
|
452
455
|
it "allows a(n) #{object.class} json object in params" do
|
453
456
|
subject.format :json
|
@@ -459,6 +462,7 @@ describe Grape::API do
|
|
459
462
|
expect(last_response.body).to eql ::Grape::Json.dump(object)
|
460
463
|
expect(last_request.params).to eql({})
|
461
464
|
end
|
465
|
+
|
462
466
|
it 'stores input in api.request.input' do
|
463
467
|
subject.format :json
|
464
468
|
subject.send(verb) do
|
@@ -468,6 +472,7 @@ describe Grape::API do
|
|
468
472
|
expect(last_response.status).to eq(verb == :post ? 201 : 200)
|
469
473
|
expect(last_response.body).to eql ::Grape::Json.dump(object).to_json
|
470
474
|
end
|
475
|
+
|
471
476
|
context 'chunked transfer encoding' do
|
472
477
|
it 'stores input in api.request.input' do
|
473
478
|
subject.format :json
|
@@ -562,7 +567,8 @@ describe Grape::API do
|
|
562
567
|
send(other_verb, '/example')
|
563
568
|
expected_rc = if other_verb == 'options' then 204
|
564
569
|
elsif other_verb == 'head' && verb == 'get' then 200
|
565
|
-
else
|
570
|
+
else
|
571
|
+
405
|
566
572
|
end
|
567
573
|
expect(last_response.status).to eql expected_rc
|
568
574
|
end
|
@@ -575,7 +581,7 @@ describe Grape::API do
|
|
575
581
|
end
|
576
582
|
|
577
583
|
post '/example'
|
578
|
-
expect(last_response.status).to
|
584
|
+
expect(last_response.status).to be 201
|
579
585
|
expect(last_response.body).to eql 'Created'
|
580
586
|
end
|
581
587
|
|
@@ -585,7 +591,7 @@ describe Grape::API do
|
|
585
591
|
'example'
|
586
592
|
end
|
587
593
|
put '/example'
|
588
|
-
expect(last_response.status).to
|
594
|
+
expect(last_response.status).to be 405
|
589
595
|
expect(last_response.body).to eql '405 Not Allowed'
|
590
596
|
expect(last_response.headers['X-Custom-Header']).to eql 'foo'
|
591
597
|
end
|
@@ -593,15 +599,17 @@ describe Grape::API do
|
|
593
599
|
it 'runs only the before filter on 405 bad method' do
|
594
600
|
subject.namespace :example do
|
595
601
|
before { header 'X-Custom-Header', 'foo' }
|
602
|
+
|
596
603
|
before_validation { raise 'before_validation filter should not run' }
|
597
604
|
after_validation { raise 'after_validation filter should not run' }
|
598
605
|
after { raise 'after filter should not run' }
|
606
|
+
|
599
607
|
params { requires :only_for_get }
|
600
608
|
get
|
601
609
|
end
|
602
610
|
|
603
611
|
post '/example'
|
604
|
-
expect(last_response.status).to
|
612
|
+
expect(last_response.status).to be 405
|
605
613
|
expect(last_response.headers['X-Custom-Header']).to eql 'foo'
|
606
614
|
end
|
607
615
|
|
@@ -614,26 +622,29 @@ describe Grape::API do
|
|
614
622
|
already_run = true
|
615
623
|
header 'X-Custom-Header', 'foo'
|
616
624
|
end
|
625
|
+
|
617
626
|
get
|
618
627
|
end
|
619
628
|
|
620
629
|
post '/example'
|
621
|
-
expect(last_response.status).to
|
630
|
+
expect(last_response.status).to be 405
|
622
631
|
expect(last_response.headers['X-Custom-Header']).to eql 'foo'
|
623
632
|
end
|
624
633
|
|
625
634
|
it 'runs all filters and body with a custom OPTIONS method' do
|
626
635
|
subject.namespace :example do
|
627
636
|
before { header 'X-Custom-Header-1', 'foo' }
|
637
|
+
|
628
638
|
before_validation { header 'X-Custom-Header-2', 'foo' }
|
629
639
|
after_validation { header 'X-Custom-Header-3', 'foo' }
|
630
640
|
after { header 'X-Custom-Header-4', 'foo' }
|
641
|
+
|
631
642
|
options { 'yup' }
|
632
643
|
get
|
633
644
|
end
|
634
645
|
|
635
646
|
options '/example'
|
636
|
-
expect(last_response.status).to
|
647
|
+
expect(last_response.status).to be 200
|
637
648
|
expect(last_response.body).to eql 'yup'
|
638
649
|
expect(last_response.headers['Allow']).to be_nil
|
639
650
|
expect(last_response.headers['X-Custom-Header-1']).to eql 'foo'
|
@@ -650,7 +661,7 @@ describe Grape::API do
|
|
650
661
|
end
|
651
662
|
|
652
663
|
put '/example'
|
653
|
-
expect(last_response.status).to
|
664
|
+
expect(last_response.status).to be 405
|
654
665
|
expect(last_response.body).to eq <<~XML
|
655
666
|
<?xml version="1.0" encoding="UTF-8"?>
|
656
667
|
<error>
|
@@ -670,7 +681,7 @@ describe Grape::API do
|
|
670
681
|
'example'
|
671
682
|
end
|
672
683
|
put '/example'
|
673
|
-
expect(last_response.status).to
|
684
|
+
expect(last_response.status).to be 405
|
674
685
|
expect(last_response.body).to eql '405 Not Allowed'
|
675
686
|
end
|
676
687
|
end
|
@@ -714,7 +725,7 @@ describe Grape::API do
|
|
714
725
|
end
|
715
726
|
|
716
727
|
it 'returns a 204' do
|
717
|
-
expect(last_response.status).to
|
728
|
+
expect(last_response.status).to be 204
|
718
729
|
end
|
719
730
|
|
720
731
|
it 'has an empty body' do
|
@@ -778,7 +789,7 @@ describe Grape::API do
|
|
778
789
|
|
779
790
|
describe 'it adds an OPTIONS route for namespaced endpoints that' do
|
780
791
|
it 'returns a 204' do
|
781
|
-
expect(last_response.status).to
|
792
|
+
expect(last_response.status).to be 204
|
782
793
|
end
|
783
794
|
|
784
795
|
it 'has an empty body' do
|
@@ -796,6 +807,7 @@ describe Grape::API do
|
|
796
807
|
subject.before { header 'X-Custom-Header', 'foo' }
|
797
808
|
subject.namespace :example do
|
798
809
|
before { header 'X-Custom-Header-2', 'foo' }
|
810
|
+
|
799
811
|
get :inner do
|
800
812
|
'example/inner'
|
801
813
|
end
|
@@ -804,7 +816,7 @@ describe Grape::API do
|
|
804
816
|
end
|
805
817
|
|
806
818
|
it 'returns a 204' do
|
807
|
-
expect(last_response.status).to
|
819
|
+
expect(last_response.status).to be 204
|
808
820
|
end
|
809
821
|
|
810
822
|
it 'has an empty body' do
|
@@ -842,7 +854,7 @@ describe Grape::API do
|
|
842
854
|
end
|
843
855
|
|
844
856
|
it 'returns a 405' do
|
845
|
-
expect(last_response.status).to
|
857
|
+
expect(last_response.status).to be 405
|
846
858
|
end
|
847
859
|
|
848
860
|
it 'contains error message in body' do
|
@@ -858,7 +870,7 @@ describe Grape::API do
|
|
858
870
|
end
|
859
871
|
end
|
860
872
|
|
861
|
-
describe 'when hook behaviour is controlled by attributes on the route
|
873
|
+
describe 'when hook behaviour is controlled by attributes on the route' do
|
862
874
|
before do
|
863
875
|
subject.before do
|
864
876
|
error!('Access Denied', 401) unless route.options[:secret] == params[:secret]
|
@@ -881,28 +893,31 @@ describe Grape::API do
|
|
881
893
|
let(:response) { delete('/example') }
|
882
894
|
|
883
895
|
it 'responds with a 405 status' do
|
884
|
-
expect(response.status).to
|
896
|
+
expect(response.status).to be 405
|
885
897
|
end
|
886
898
|
end
|
887
899
|
|
888
900
|
context 'when HTTP method is defined with attribute' do
|
889
901
|
let(:response) { post('/example?secret=incorrect_password') }
|
902
|
+
|
890
903
|
it 'responds with the defined error in the before hook' do
|
891
|
-
expect(response.status).to
|
904
|
+
expect(response.status).to be 401
|
892
905
|
end
|
893
906
|
end
|
894
907
|
|
895
908
|
context 'when HTTP method is defined and the underlying before hook expectation is not met' do
|
896
909
|
let(:response) { post('/example?secret=password&namespace_secret=wrong_namespace_password') }
|
910
|
+
|
897
911
|
it 'ends up in the endpoint' do
|
898
|
-
expect(response.status).to
|
912
|
+
expect(response.status).to be 401
|
899
913
|
end
|
900
914
|
end
|
901
915
|
|
902
916
|
context 'when HTTP method is defined and everything is like the before hooks expect' do
|
903
917
|
let(:response) { post('/example?secret=password&namespace_secret=namespace_password') }
|
918
|
+
|
904
919
|
it 'ends up in the endpoint' do
|
905
|
-
expect(response.status).to
|
920
|
+
expect(response.status).to be 201
|
906
921
|
end
|
907
922
|
end
|
908
923
|
|
@@ -910,7 +925,7 @@ describe Grape::API do
|
|
910
925
|
let(:response) { head('/example?id=504') }
|
911
926
|
|
912
927
|
it 'responds with 401 because before expectations in before hooks are not met' do
|
913
|
-
expect(response.status).to
|
928
|
+
expect(response.status).to be 401
|
914
929
|
end
|
915
930
|
end
|
916
931
|
|
@@ -918,7 +933,7 @@ describe Grape::API do
|
|
918
933
|
let(:response) { head('/example?id=504&secret=password') }
|
919
934
|
|
920
935
|
it 'responds with 200 because before hooks are not called' do
|
921
|
-
expect(response.status).to
|
936
|
+
expect(response.status).to be 200
|
922
937
|
end
|
923
938
|
end
|
924
939
|
end
|
@@ -935,7 +950,7 @@ describe Grape::API do
|
|
935
950
|
end
|
936
951
|
|
937
952
|
it 'returns a 200' do
|
938
|
-
expect(last_response.status).to
|
953
|
+
expect(last_response.status).to be 200
|
939
954
|
end
|
940
955
|
|
941
956
|
it 'has an empty body' do
|
@@ -951,31 +966,33 @@ describe Grape::API do
|
|
951
966
|
'example'
|
952
967
|
end
|
953
968
|
head '/example'
|
954
|
-
expect(last_response.status).to
|
969
|
+
expect(last_response.status).to be 400
|
955
970
|
end
|
956
971
|
end
|
957
972
|
|
958
973
|
context 'do_not_route_head!' do
|
959
|
-
before
|
974
|
+
before do
|
960
975
|
subject.do_not_route_head!
|
961
976
|
subject.get 'example' do
|
962
977
|
'example'
|
963
978
|
end
|
964
979
|
end
|
980
|
+
|
965
981
|
it 'options does not contain HEAD' do
|
966
982
|
options '/example'
|
967
|
-
expect(last_response.status).to
|
983
|
+
expect(last_response.status).to be 204
|
968
984
|
expect(last_response.body).to eql ''
|
969
985
|
expect(last_response.headers['Allow']).to eql 'OPTIONS, GET'
|
970
986
|
end
|
987
|
+
|
971
988
|
it 'does not allow HEAD on a GET request' do
|
972
989
|
head '/example'
|
973
|
-
expect(last_response.status).to
|
990
|
+
expect(last_response.status).to be 405
|
974
991
|
end
|
975
992
|
end
|
976
993
|
|
977
994
|
context 'do_not_route_options!' do
|
978
|
-
before
|
995
|
+
before do
|
979
996
|
subject.do_not_route_options!
|
980
997
|
subject.get 'example' do
|
981
998
|
'example'
|
@@ -984,19 +1001,19 @@ describe Grape::API do
|
|
984
1001
|
|
985
1002
|
it 'does not create an OPTIONS route' do
|
986
1003
|
options '/example'
|
987
|
-
expect(last_response.status).to
|
1004
|
+
expect(last_response.status).to be 405
|
988
1005
|
end
|
989
1006
|
|
990
1007
|
it 'does not include OPTIONS in Allow header' do
|
991
1008
|
options '/example'
|
992
|
-
expect(last_response.status).to
|
1009
|
+
expect(last_response.status).to be 405
|
993
1010
|
expect(last_response.headers['Allow']).to eql 'GET, HEAD'
|
994
1011
|
end
|
995
1012
|
end
|
996
1013
|
|
997
1014
|
describe '.compile!' do
|
998
1015
|
it 'requires the grape/eager_load file' do
|
999
|
-
expect(app).to receive(:require).with('grape/eager_load')
|
1016
|
+
expect(app).to receive(:require).with('grape/eager_load').and_return(nil)
|
1000
1017
|
app.compile!
|
1001
1018
|
end
|
1002
1019
|
|
@@ -1018,7 +1035,7 @@ describe Grape::API do
|
|
1018
1035
|
context 'when the app was mounted' do
|
1019
1036
|
it 'returns the first mounted instance' do
|
1020
1037
|
mounted_app = app
|
1021
|
-
Class.new(
|
1038
|
+
Class.new(described_class) do
|
1022
1039
|
namespace 'new_namespace' do
|
1023
1040
|
mount mounted_app
|
1024
1041
|
end
|
@@ -1046,6 +1063,7 @@ describe Grape::API do
|
|
1046
1063
|
end
|
1047
1064
|
subject.namespace :blah do
|
1048
1065
|
before { @foo = 'foo' }
|
1066
|
+
|
1049
1067
|
get '/' do
|
1050
1068
|
"blah - #{@foo}"
|
1051
1069
|
end
|
@@ -1087,7 +1105,7 @@ describe Grape::API do
|
|
1087
1105
|
@var ||= 'default'
|
1088
1106
|
end
|
1089
1107
|
|
1090
|
-
expect(m).to receive(:do_something!).
|
1108
|
+
expect(m).to receive(:do_something!).twice
|
1091
1109
|
get '/'
|
1092
1110
|
expect(last_response.body).to eql 'default'
|
1093
1111
|
end
|
@@ -1103,21 +1121,23 @@ describe Grape::API do
|
|
1103
1121
|
end
|
1104
1122
|
subject.resource ':id' do
|
1105
1123
|
before { a.do_something! }
|
1124
|
+
|
1106
1125
|
before_validation { b.do_something! }
|
1107
1126
|
after_validation { c.do_something! }
|
1108
1127
|
after { d.do_something! }
|
1128
|
+
|
1109
1129
|
get do
|
1110
1130
|
'got it'
|
1111
1131
|
end
|
1112
1132
|
end
|
1113
1133
|
|
1114
|
-
expect(a).to receive(:do_something!).
|
1115
|
-
expect(b).to receive(:do_something!).
|
1116
|
-
expect(c).to receive(:do_something!).
|
1117
|
-
expect(d).to receive(:do_something!).
|
1134
|
+
expect(a).to receive(:do_something!).once
|
1135
|
+
expect(b).to receive(:do_something!).once
|
1136
|
+
expect(c).to receive(:do_something!).once
|
1137
|
+
expect(d).to receive(:do_something!).once
|
1118
1138
|
|
1119
1139
|
get '/123'
|
1120
|
-
expect(last_response.status).to
|
1140
|
+
expect(last_response.status).to be 200
|
1121
1141
|
expect(last_response.body).to eql 'got it'
|
1122
1142
|
end
|
1123
1143
|
|
@@ -1132,21 +1152,23 @@ describe Grape::API do
|
|
1132
1152
|
end
|
1133
1153
|
subject.resource ':id' do
|
1134
1154
|
before { a.do_something! }
|
1155
|
+
|
1135
1156
|
before_validation { b.do_something! }
|
1136
1157
|
after_validation { c.do_something! }
|
1137
1158
|
after { d.do_something! }
|
1159
|
+
|
1138
1160
|
get do
|
1139
1161
|
'got it'
|
1140
1162
|
end
|
1141
1163
|
end
|
1142
1164
|
|
1143
|
-
expect(a).to receive(:do_something!).
|
1144
|
-
expect(b).to receive(:do_something!).
|
1165
|
+
expect(a).to receive(:do_something!).once
|
1166
|
+
expect(b).to receive(:do_something!).once
|
1145
1167
|
expect(c).to receive(:do_something!).exactly(0).times
|
1146
1168
|
expect(d).to receive(:do_something!).exactly(0).times
|
1147
1169
|
|
1148
1170
|
get '/abc'
|
1149
|
-
expect(last_response.status).to
|
1171
|
+
expect(last_response.status).to be 400
|
1150
1172
|
expect(last_response.body).to eql 'id is invalid'
|
1151
1173
|
end
|
1152
1174
|
|
@@ -1162,21 +1184,23 @@ describe Grape::API do
|
|
1162
1184
|
end
|
1163
1185
|
subject.resource ':id' do
|
1164
1186
|
before { a.here(i += 1) }
|
1187
|
+
|
1165
1188
|
before_validation { b.here(i += 1) }
|
1166
1189
|
after_validation { c.here(i += 1) }
|
1167
1190
|
after { d.here(i += 1) }
|
1191
|
+
|
1168
1192
|
get do
|
1169
1193
|
'got it'
|
1170
1194
|
end
|
1171
1195
|
end
|
1172
1196
|
|
1173
|
-
expect(a).to receive(:here).with(1).
|
1174
|
-
expect(b).to receive(:here).with(2).
|
1175
|
-
expect(c).to receive(:here).with(3).
|
1176
|
-
expect(d).to receive(:here).with(4).
|
1197
|
+
expect(a).to receive(:here).with(1).once
|
1198
|
+
expect(b).to receive(:here).with(2).once
|
1199
|
+
expect(c).to receive(:here).with(3).once
|
1200
|
+
expect(d).to receive(:here).with(4).once
|
1177
1201
|
|
1178
1202
|
get '/123'
|
1179
|
-
expect(last_response.status).to
|
1203
|
+
expect(last_response.status).to be 200
|
1180
1204
|
expect(last_response.body).to eql 'got it'
|
1181
1205
|
end
|
1182
1206
|
end
|
@@ -1267,7 +1291,7 @@ describe Grape::API do
|
|
1267
1291
|
subject.format :json
|
1268
1292
|
subject.get('/error') { error!('error in json', 500) }
|
1269
1293
|
get '/error.json'
|
1270
|
-
expect(last_response.status).to
|
1294
|
+
expect(last_response.status).to be 500
|
1271
1295
|
expect(last_response.headers['Content-Type']).to eql 'application/json'
|
1272
1296
|
end
|
1273
1297
|
|
@@ -1275,7 +1299,7 @@ describe Grape::API do
|
|
1275
1299
|
subject.format :xml
|
1276
1300
|
subject.get('/error') { error!('error in xml', 500) }
|
1277
1301
|
get '/error'
|
1278
|
-
expect(last_response.status).to
|
1302
|
+
expect(last_response.status).to be 500
|
1279
1303
|
expect(last_response.headers['Content-Type']).to eql 'application/xml'
|
1280
1304
|
end
|
1281
1305
|
|
@@ -1534,9 +1558,9 @@ describe Grape::API do
|
|
1534
1558
|
end
|
1535
1559
|
subject.get(:hello) { 'Hello, world.' }
|
1536
1560
|
get '/hello'
|
1537
|
-
expect(last_response.status).to
|
1561
|
+
expect(last_response.status).to be 401
|
1538
1562
|
get '/hello', {}, 'HTTP_AUTHORIZATION' => encode_basic_auth('allow', 'whatever')
|
1539
|
-
expect(last_response.status).to
|
1563
|
+
expect(last_response.status).to be 200
|
1540
1564
|
end
|
1541
1565
|
|
1542
1566
|
it 'is scopable' do
|
@@ -1550,9 +1574,9 @@ describe Grape::API do
|
|
1550
1574
|
end
|
1551
1575
|
|
1552
1576
|
get '/hello'
|
1553
|
-
expect(last_response.status).to
|
1577
|
+
expect(last_response.status).to be 200
|
1554
1578
|
get '/admin/hello'
|
1555
|
-
expect(last_response.status).to
|
1579
|
+
expect(last_response.status).to be 401
|
1556
1580
|
end
|
1557
1581
|
|
1558
1582
|
it 'is callable via .auth as well' do
|
@@ -1562,9 +1586,9 @@ describe Grape::API do
|
|
1562
1586
|
|
1563
1587
|
subject.get(:hello) { 'Hello, world.' }
|
1564
1588
|
get '/hello'
|
1565
|
-
expect(last_response.status).to
|
1589
|
+
expect(last_response.status).to be 401
|
1566
1590
|
get '/hello', {}, 'HTTP_AUTHORIZATION' => encode_basic_auth('allow', 'whatever')
|
1567
|
-
expect(last_response.status).to
|
1591
|
+
expect(last_response.status).to be 200
|
1568
1592
|
end
|
1569
1593
|
|
1570
1594
|
it 'has access to the current endpoint' do
|
@@ -1594,9 +1618,9 @@ describe Grape::API do
|
|
1594
1618
|
|
1595
1619
|
subject.get(:hello) { 'Hello, world.' }
|
1596
1620
|
get '/hello', {}, 'HTTP_AUTHORIZATION' => encode_basic_auth('allow', 'whatever')
|
1597
|
-
expect(last_response.status).to
|
1621
|
+
expect(last_response.status).to be 200
|
1598
1622
|
get '/hello', {}, 'HTTP_AUTHORIZATION' => encode_basic_auth('disallow', 'whatever')
|
1599
|
-
expect(last_response.status).to
|
1623
|
+
expect(last_response.status).to be 401
|
1600
1624
|
end
|
1601
1625
|
|
1602
1626
|
it 'can set instance variables accessible to routes' do
|
@@ -1608,44 +1632,36 @@ describe Grape::API do
|
|
1608
1632
|
|
1609
1633
|
subject.get(:hello) { @hello }
|
1610
1634
|
get '/hello', {}, 'HTTP_AUTHORIZATION' => encode_basic_auth('allow', 'whatever')
|
1611
|
-
expect(last_response.status).to
|
1635
|
+
expect(last_response.status).to be 200
|
1612
1636
|
expect(last_response.body).to eql 'Hello, world.'
|
1613
1637
|
end
|
1614
1638
|
end
|
1615
1639
|
|
1616
1640
|
describe '.logger' do
|
1617
|
-
subject do
|
1618
|
-
Class.new(Grape::API) do
|
1619
|
-
def self.io
|
1620
|
-
@io ||= StringIO.new
|
1621
|
-
end
|
1622
|
-
logger ::Logger.new(io)
|
1623
|
-
end
|
1624
|
-
end
|
1625
|
-
|
1626
1641
|
it 'returns an instance of Logger class by default' do
|
1627
1642
|
expect(subject.logger.class).to eql Logger
|
1628
1643
|
end
|
1629
1644
|
|
1630
|
-
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1634
|
-
|
1635
|
-
|
1645
|
+
context 'with a custom logger' do
|
1646
|
+
subject do
|
1647
|
+
Class.new(described_class) do
|
1648
|
+
def self.io
|
1649
|
+
@io ||= StringIO.new
|
1650
|
+
end
|
1651
|
+
logger ::Logger.new(io)
|
1652
|
+
end
|
1653
|
+
end
|
1636
1654
|
|
1637
|
-
|
1638
|
-
|
1639
|
-
|
1640
|
-
|
1641
|
-
|
1642
|
-
expect(subject.io).to receive(:write).with(message)
|
1643
|
-
subject.logger.info 'this will be logged'
|
1655
|
+
it 'exposes its interaface' do
|
1656
|
+
message = 'this will be logged'
|
1657
|
+
subject.logger.info message
|
1658
|
+
expect(subject.io.string).to include(message)
|
1659
|
+
end
|
1644
1660
|
end
|
1645
1661
|
|
1646
1662
|
it 'does not unnecessarily retain duplicate setup blocks' do
|
1647
1663
|
subject.logger
|
1648
|
-
expect { subject.logger }.
|
1664
|
+
expect { subject.logger }.not_to change(subject.instance_variable_get(:@setup), :size)
|
1649
1665
|
end
|
1650
1666
|
end
|
1651
1667
|
|
@@ -1771,13 +1787,13 @@ describe Grape::API do
|
|
1771
1787
|
end
|
1772
1788
|
|
1773
1789
|
get '/new/abc'
|
1774
|
-
expect(last_response.status).to
|
1790
|
+
expect(last_response.status).to be 404
|
1775
1791
|
get '/legacy/abc'
|
1776
|
-
expect(last_response.status).to
|
1792
|
+
expect(last_response.status).to be 200
|
1777
1793
|
get '/legacy/def'
|
1778
|
-
expect(last_response.status).to
|
1794
|
+
expect(last_response.status).to be 404
|
1779
1795
|
get '/new/def'
|
1780
|
-
expect(last_response.status).to
|
1796
|
+
expect(last_response.status).to be 200
|
1781
1797
|
end
|
1782
1798
|
end
|
1783
1799
|
|
@@ -1997,8 +2013,8 @@ describe Grape::API do
|
|
1997
2013
|
end
|
1998
2014
|
|
1999
2015
|
context 'with multiple apis' do
|
2000
|
-
let(:a) { Class.new(
|
2001
|
-
let(:b) { Class.new(
|
2016
|
+
let(:a) { Class.new(described_class) }
|
2017
|
+
let(:b) { Class.new(described_class) }
|
2002
2018
|
|
2003
2019
|
before do
|
2004
2020
|
a.helpers do
|
@@ -2032,7 +2048,7 @@ describe Grape::API do
|
|
2032
2048
|
raise 'rain!'
|
2033
2049
|
end
|
2034
2050
|
get '/exception'
|
2035
|
-
expect(last_response.status).to
|
2051
|
+
expect(last_response.status).to be 500
|
2036
2052
|
expect(last_response.body).to eq 'rain!'
|
2037
2053
|
end
|
2038
2054
|
|
@@ -2044,7 +2060,7 @@ describe Grape::API do
|
|
2044
2060
|
raise 'rain!'
|
2045
2061
|
end
|
2046
2062
|
get '/exception'
|
2047
|
-
expect(last_response.status).to
|
2063
|
+
expect(last_response.status).to be 500
|
2048
2064
|
expect(last_response.body).to eq({ error: 'rain!' }.to_json)
|
2049
2065
|
end
|
2050
2066
|
|
@@ -2054,7 +2070,7 @@ describe Grape::API do
|
|
2054
2070
|
subject.get('/unrescued') { raise 'beefcake' }
|
2055
2071
|
|
2056
2072
|
get '/rescued'
|
2057
|
-
expect(last_response.status).to
|
2073
|
+
expect(last_response.status).to be 500
|
2058
2074
|
|
2059
2075
|
expect { get '/unrescued' }.to raise_error(RuntimeError, 'beefcake')
|
2060
2076
|
end
|
@@ -2073,10 +2089,10 @@ describe Grape::API do
|
|
2073
2089
|
subject.get('/standard_error') { raise StandardError }
|
2074
2090
|
|
2075
2091
|
get '/child_of_standard_error'
|
2076
|
-
expect(last_response.status).to
|
2092
|
+
expect(last_response.status).to be 402
|
2077
2093
|
|
2078
2094
|
get '/standard_error'
|
2079
|
-
expect(last_response.status).to
|
2095
|
+
expect(last_response.status).to be 401
|
2080
2096
|
end
|
2081
2097
|
|
2082
2098
|
context 'CustomError subclass of Grape::Exceptions::Base' do
|
@@ -2117,7 +2133,7 @@ describe Grape::API do
|
|
2117
2133
|
subject.get('/formatter_exception') { 'Hello world' }
|
2118
2134
|
|
2119
2135
|
get '/formatter_exception'
|
2120
|
-
expect(last_response.status).to
|
2136
|
+
expect(last_response.status).to be 500
|
2121
2137
|
expect(last_response.body).to eq('Formatter Error')
|
2122
2138
|
end
|
2123
2139
|
|
@@ -2127,7 +2143,7 @@ describe Grape::API do
|
|
2127
2143
|
|
2128
2144
|
expect_any_instance_of(Grape::Middleware::Error).to receive(:default_rescue_handler).and_call_original
|
2129
2145
|
get '/'
|
2130
|
-
expect(last_response.status).to
|
2146
|
+
expect(last_response.status).to be 500
|
2131
2147
|
expect(last_response.body).to eql 'Invalid response'
|
2132
2148
|
end
|
2133
2149
|
end
|
@@ -2141,7 +2157,7 @@ describe Grape::API do
|
|
2141
2157
|
raise 'rain!'
|
2142
2158
|
end
|
2143
2159
|
get '/exception'
|
2144
|
-
expect(last_response.status).to
|
2160
|
+
expect(last_response.status).to be 202
|
2145
2161
|
expect(last_response.body).to eq('rescued from rain!')
|
2146
2162
|
end
|
2147
2163
|
|
@@ -2162,9 +2178,10 @@ describe Grape::API do
|
|
2162
2178
|
raise ConnectionError
|
2163
2179
|
end
|
2164
2180
|
get '/exception'
|
2165
|
-
expect(last_response.status).to
|
2181
|
+
expect(last_response.status).to be 500
|
2166
2182
|
expect(last_response.body).to eq('rescued from ConnectionError')
|
2167
2183
|
end
|
2184
|
+
|
2168
2185
|
it 'rescues a specific error' do
|
2169
2186
|
subject.rescue_from ConnectionError do |e|
|
2170
2187
|
rack_response("rescued from #{e.class.name}", 500)
|
@@ -2173,9 +2190,10 @@ describe Grape::API do
|
|
2173
2190
|
raise ConnectionError
|
2174
2191
|
end
|
2175
2192
|
get '/exception'
|
2176
|
-
expect(last_response.status).to
|
2193
|
+
expect(last_response.status).to be 500
|
2177
2194
|
expect(last_response.body).to eq('rescued from ConnectionError')
|
2178
2195
|
end
|
2196
|
+
|
2179
2197
|
it 'rescues a subclass of an error by default' do
|
2180
2198
|
subject.rescue_from RuntimeError do |e|
|
2181
2199
|
rack_response("rescued from #{e.class.name}", 500)
|
@@ -2184,9 +2202,10 @@ describe Grape::API do
|
|
2184
2202
|
raise ConnectionError
|
2185
2203
|
end
|
2186
2204
|
get '/exception'
|
2187
|
-
expect(last_response.status).to
|
2205
|
+
expect(last_response.status).to be 500
|
2188
2206
|
expect(last_response.body).to eq('rescued from ConnectionError')
|
2189
2207
|
end
|
2208
|
+
|
2190
2209
|
it 'rescues multiple specific errors' do
|
2191
2210
|
subject.rescue_from ConnectionError do |e|
|
2192
2211
|
rack_response("rescued from #{e.class.name}", 500)
|
@@ -2201,12 +2220,13 @@ describe Grape::API do
|
|
2201
2220
|
raise DatabaseError
|
2202
2221
|
end
|
2203
2222
|
get '/connection'
|
2204
|
-
expect(last_response.status).to
|
2223
|
+
expect(last_response.status).to be 500
|
2205
2224
|
expect(last_response.body).to eq('rescued from ConnectionError')
|
2206
2225
|
get '/database'
|
2207
|
-
expect(last_response.status).to
|
2226
|
+
expect(last_response.status).to be 500
|
2208
2227
|
expect(last_response.body).to eq('rescued from DatabaseError')
|
2209
2228
|
end
|
2229
|
+
|
2210
2230
|
it 'does not rescue a different error' do
|
2211
2231
|
subject.rescue_from RuntimeError do |e|
|
2212
2232
|
rack_response("rescued from #{e.class.name}", 500)
|
@@ -2272,7 +2292,7 @@ describe Grape::API do
|
|
2272
2292
|
subject.rescue_from :all, with: :not_exist_method
|
2273
2293
|
subject.get('/rescue_method') { raise StandardError }
|
2274
2294
|
|
2275
|
-
expect { get '/rescue_method' }.to raise_error(NoMethodError,
|
2295
|
+
expect { get '/rescue_method' }.to raise_error(NoMethodError, /^undefined method `not_exist_method'/)
|
2276
2296
|
end
|
2277
2297
|
|
2278
2298
|
it 'correctly chooses exception handler if :all handler is specified' do
|
@@ -2327,9 +2347,9 @@ describe Grape::API do
|
|
2327
2347
|
end
|
2328
2348
|
|
2329
2349
|
get '/caught_child'
|
2330
|
-
expect(last_response.status).to
|
2350
|
+
expect(last_response.status).to be 500
|
2331
2351
|
get '/caught_parent'
|
2332
|
-
expect(last_response.status).to
|
2352
|
+
expect(last_response.status).to be 500
|
2333
2353
|
expect { get '/uncaught_parent' }.to raise_error(StandardError)
|
2334
2354
|
end
|
2335
2355
|
|
@@ -2342,7 +2362,7 @@ describe Grape::API do
|
|
2342
2362
|
end
|
2343
2363
|
|
2344
2364
|
get '/caught_child'
|
2345
|
-
expect(last_response.status).to
|
2365
|
+
expect(last_response.status).to be 500
|
2346
2366
|
end
|
2347
2367
|
|
2348
2368
|
it 'does not rescue child errors if rescue_subclasses is false' do
|
@@ -2437,7 +2457,7 @@ describe Grape::API do
|
|
2437
2457
|
end
|
2438
2458
|
|
2439
2459
|
context 'class' do
|
2440
|
-
before
|
2460
|
+
before do
|
2441
2461
|
module ApiSpec
|
2442
2462
|
class CustomErrorFormatter
|
2443
2463
|
def self.call(message, _backtrace, _options, _env, _original_exception)
|
@@ -2446,6 +2466,7 @@ describe Grape::API do
|
|
2446
2466
|
end
|
2447
2467
|
end
|
2448
2468
|
end
|
2469
|
+
|
2449
2470
|
it 'returns a custom error format' do
|
2450
2471
|
subject.rescue_from :all, backtrace: true
|
2451
2472
|
subject.error_formatter :txt, ApiSpec::CustomErrorFormatter
|
@@ -2459,7 +2480,7 @@ describe Grape::API do
|
|
2459
2480
|
|
2460
2481
|
describe 'with' do
|
2461
2482
|
context 'class' do
|
2462
|
-
before
|
2483
|
+
before do
|
2463
2484
|
module ApiSpec
|
2464
2485
|
class CustomErrorFormatter
|
2465
2486
|
def self.call(message, _backtrace, _option, _env, _original_exception)
|
@@ -2489,6 +2510,7 @@ describe Grape::API do
|
|
2489
2510
|
get '/exception'
|
2490
2511
|
expect(last_response.body).to eql '{"error":"rain!"}'
|
2491
2512
|
end
|
2513
|
+
|
2492
2514
|
it 'rescues all errors and return :json with backtrace' do
|
2493
2515
|
subject.rescue_from :all, backtrace: true
|
2494
2516
|
subject.format :json
|
@@ -2500,6 +2522,7 @@ describe Grape::API do
|
|
2500
2522
|
expect(json['error']).to eql 'rain!'
|
2501
2523
|
expect(json['backtrace'].length).to be > 0
|
2502
2524
|
end
|
2525
|
+
|
2503
2526
|
it 'rescues error! and return txt' do
|
2504
2527
|
subject.format :txt
|
2505
2528
|
subject.get '/error' do
|
@@ -2508,23 +2531,26 @@ describe Grape::API do
|
|
2508
2531
|
get '/error'
|
2509
2532
|
expect(last_response.body).to eql 'Access Denied'
|
2510
2533
|
end
|
2534
|
+
|
2511
2535
|
context 'with json format' do
|
2512
2536
|
before { subject.format :json }
|
2513
2537
|
|
2538
|
+
after do
|
2539
|
+
get '/error'
|
2540
|
+
expect(last_response.body).to eql('{"error":"failure"}')
|
2541
|
+
end
|
2542
|
+
|
2514
2543
|
it 'rescues error! called with a string and returns json' do
|
2515
2544
|
subject.get('/error') { error!(:failure, 401) }
|
2516
2545
|
end
|
2546
|
+
|
2517
2547
|
it 'rescues error! called with a symbol and returns json' do
|
2518
2548
|
subject.get('/error') { error!(:failure, 401) }
|
2519
2549
|
end
|
2550
|
+
|
2520
2551
|
it 'rescues error! called with a hash and returns json' do
|
2521
2552
|
subject.get('/error') { error!({ error: :failure }, 401) }
|
2522
2553
|
end
|
2523
|
-
|
2524
|
-
after do
|
2525
|
-
get '/error'
|
2526
|
-
expect(last_response.body).to eql('{"error":"failure"}')
|
2527
|
-
end
|
2528
2554
|
end
|
2529
2555
|
end
|
2530
2556
|
|
@@ -2537,6 +2563,7 @@ describe Grape::API do
|
|
2537
2563
|
get '/excel.xls'
|
2538
2564
|
expect(last_response.content_type).to eq('application/vnd.ms-excel')
|
2539
2565
|
end
|
2566
|
+
|
2540
2567
|
it 'allows to override content-type' do
|
2541
2568
|
subject.get :content do
|
2542
2569
|
content_type 'text/javascript'
|
@@ -2545,6 +2572,7 @@ describe Grape::API do
|
|
2545
2572
|
get '/content'
|
2546
2573
|
expect(last_response.content_type).to eq('text/javascript')
|
2547
2574
|
end
|
2575
|
+
|
2548
2576
|
it 'removes existing content types' do
|
2549
2577
|
subject.content_type :xls, 'application/vnd.ms-excel'
|
2550
2578
|
subject.get :excel do
|
@@ -2562,24 +2590,27 @@ describe Grape::API do
|
|
2562
2590
|
|
2563
2591
|
describe '.formatter' do
|
2564
2592
|
context 'multiple formatters' do
|
2565
|
-
before
|
2593
|
+
before do
|
2566
2594
|
subject.formatter :json, ->(object, _env) { "{\"custom_formatter\":\"#{object[:some]}\"}" }
|
2567
2595
|
subject.formatter :txt, ->(object, _env) { "custom_formatter: #{object[:some]}" }
|
2568
2596
|
subject.get :simple do
|
2569
2597
|
{ some: 'hash' }
|
2570
2598
|
end
|
2571
2599
|
end
|
2600
|
+
|
2572
2601
|
it 'sets one formatter' do
|
2573
2602
|
get '/simple.json'
|
2574
2603
|
expect(last_response.body).to eql '{"custom_formatter":"hash"}'
|
2575
2604
|
end
|
2605
|
+
|
2576
2606
|
it 'sets another formatter' do
|
2577
2607
|
get '/simple.txt'
|
2578
2608
|
expect(last_response.body).to eql 'custom_formatter: hash'
|
2579
2609
|
end
|
2580
2610
|
end
|
2611
|
+
|
2581
2612
|
context 'custom formatter' do
|
2582
|
-
before
|
2613
|
+
before do
|
2583
2614
|
subject.content_type :json, 'application/json'
|
2584
2615
|
subject.content_type :custom, 'application/custom'
|
2585
2616
|
subject.formatter :custom, ->(object, _env) { "{\"custom_formatter\":\"#{object[:some]}\"}" }
|
@@ -2587,15 +2618,18 @@ describe Grape::API do
|
|
2587
2618
|
{ some: 'hash' }
|
2588
2619
|
end
|
2589
2620
|
end
|
2621
|
+
|
2590
2622
|
it 'uses json' do
|
2591
2623
|
get '/simple.json'
|
2592
2624
|
expect(last_response.body).to eql '{"some":"hash"}'
|
2593
2625
|
end
|
2626
|
+
|
2594
2627
|
it 'uses custom formatter' do
|
2595
2628
|
get '/simple.custom', 'HTTP_ACCEPT' => 'application/custom'
|
2596
2629
|
expect(last_response.body).to eql '{"custom_formatter":"hash"}'
|
2597
2630
|
end
|
2598
2631
|
end
|
2632
|
+
|
2599
2633
|
context 'custom formatter class' do
|
2600
2634
|
module ApiSpec
|
2601
2635
|
module CustomFormatter
|
@@ -2604,7 +2638,7 @@ describe Grape::API do
|
|
2604
2638
|
end
|
2605
2639
|
end
|
2606
2640
|
end
|
2607
|
-
before
|
2641
|
+
before do
|
2608
2642
|
subject.content_type :json, 'application/json'
|
2609
2643
|
subject.content_type :custom, 'application/custom'
|
2610
2644
|
subject.formatter :custom, ApiSpec::CustomFormatter
|
@@ -2612,10 +2646,12 @@ describe Grape::API do
|
|
2612
2646
|
{ some: 'hash' }
|
2613
2647
|
end
|
2614
2648
|
end
|
2649
|
+
|
2615
2650
|
it 'uses json' do
|
2616
2651
|
get '/simple.json'
|
2617
2652
|
expect(last_response.body).to eql '{"some":"hash"}'
|
2618
2653
|
end
|
2654
|
+
|
2619
2655
|
it 'uses custom formatter' do
|
2620
2656
|
get '/simple.custom', 'HTTP_ACCEPT' => 'application/custom'
|
2621
2657
|
expect(last_response.body).to eql '{"custom_formatter":"hash"}'
|
@@ -2633,8 +2669,9 @@ describe Grape::API do
|
|
2633
2669
|
expect(last_response.status).to eq(201)
|
2634
2670
|
expect(last_response.body).to eq('{"x":42}')
|
2635
2671
|
end
|
2672
|
+
|
2636
2673
|
context 'lambda parser' do
|
2637
|
-
before
|
2674
|
+
before do
|
2638
2675
|
subject.content_type :txt, 'text/plain'
|
2639
2676
|
subject.content_type :custom, 'text/custom'
|
2640
2677
|
subject.parser :custom, ->(object, _env) { { object.to_sym => object.to_s.reverse } }
|
@@ -2642,6 +2679,7 @@ describe Grape::API do
|
|
2642
2679
|
params[:simple]
|
2643
2680
|
end
|
2644
2681
|
end
|
2682
|
+
|
2645
2683
|
['text/custom', 'text/custom; charset=UTF-8'].each do |content_type|
|
2646
2684
|
it "uses parser for #{content_type}" do
|
2647
2685
|
put '/simple', 'simple', 'CONTENT_TYPE' => content_type
|
@@ -2650,6 +2688,7 @@ describe Grape::API do
|
|
2650
2688
|
end
|
2651
2689
|
end
|
2652
2690
|
end
|
2691
|
+
|
2653
2692
|
context 'custom parser class' do
|
2654
2693
|
module ApiSpec
|
2655
2694
|
module CustomParser
|
@@ -2658,7 +2697,7 @@ describe Grape::API do
|
|
2658
2697
|
end
|
2659
2698
|
end
|
2660
2699
|
end
|
2661
|
-
before
|
2700
|
+
before do
|
2662
2701
|
subject.content_type :txt, 'text/plain'
|
2663
2702
|
subject.content_type :custom, 'text/custom'
|
2664
2703
|
subject.parser :custom, ApiSpec::CustomParser
|
@@ -2666,12 +2705,14 @@ describe Grape::API do
|
|
2666
2705
|
params[:simple]
|
2667
2706
|
end
|
2668
2707
|
end
|
2708
|
+
|
2669
2709
|
it 'uses custom parser' do
|
2670
2710
|
put '/simple', 'simple', 'CONTENT_TYPE' => 'text/custom'
|
2671
2711
|
expect(last_response.status).to eq(200)
|
2672
2712
|
expect(last_response.body).to eql 'elpmis'
|
2673
2713
|
end
|
2674
2714
|
end
|
2715
|
+
|
2675
2716
|
if Object.const_defined? :MultiXml
|
2676
2717
|
context 'multi_xml' do
|
2677
2718
|
it "doesn't parse yaml" do
|
@@ -2696,12 +2737,13 @@ describe Grape::API do
|
|
2696
2737
|
end
|
2697
2738
|
end
|
2698
2739
|
context 'none parser class' do
|
2699
|
-
before
|
2740
|
+
before do
|
2700
2741
|
subject.parser :json, nil
|
2701
2742
|
subject.put 'data' do
|
2702
2743
|
"body: #{env['api.request.body']}"
|
2703
2744
|
end
|
2704
2745
|
end
|
2746
|
+
|
2705
2747
|
it 'does not parse data' do
|
2706
2748
|
put '/data', 'not valid json', 'CONTENT_TYPE' => 'application/json'
|
2707
2749
|
expect(last_response.status).to eq(200)
|
@@ -2711,10 +2753,11 @@ describe Grape::API do
|
|
2711
2753
|
end
|
2712
2754
|
|
2713
2755
|
describe '.default_format' do
|
2714
|
-
before
|
2756
|
+
before do
|
2715
2757
|
subject.format :json
|
2716
2758
|
subject.default_format :json
|
2717
2759
|
end
|
2760
|
+
|
2718
2761
|
it 'returns data in default format' do
|
2719
2762
|
subject.get '/data' do
|
2720
2763
|
{ x: 42 }
|
@@ -2723,6 +2766,7 @@ describe Grape::API do
|
|
2723
2766
|
expect(last_response.status).to eq(200)
|
2724
2767
|
expect(last_response.body).to eq('{"x":42}')
|
2725
2768
|
end
|
2769
|
+
|
2726
2770
|
it 'parses data in default format' do
|
2727
2771
|
subject.post '/data' do
|
2728
2772
|
{ x: params[:x] }
|
@@ -2741,16 +2785,18 @@ describe Grape::API do
|
|
2741
2785
|
raise 'rain!'
|
2742
2786
|
end
|
2743
2787
|
get '/exception'
|
2744
|
-
expect(last_response.status).to
|
2788
|
+
expect(last_response.status).to be 200
|
2745
2789
|
end
|
2790
|
+
|
2746
2791
|
it 'has a default error status' do
|
2747
2792
|
subject.rescue_from :all
|
2748
2793
|
subject.get '/exception' do
|
2749
2794
|
raise 'rain!'
|
2750
2795
|
end
|
2751
2796
|
get '/exception'
|
2752
|
-
expect(last_response.status).to
|
2797
|
+
expect(last_response.status).to be 500
|
2753
2798
|
end
|
2799
|
+
|
2754
2800
|
it 'uses the default error status in error!' do
|
2755
2801
|
subject.rescue_from :all
|
2756
2802
|
subject.default_error_status 400
|
@@ -2758,7 +2804,7 @@ describe Grape::API do
|
|
2758
2804
|
error! 'rain!'
|
2759
2805
|
end
|
2760
2806
|
get '/exception'
|
2761
|
-
expect(last_response.status).to
|
2807
|
+
expect(last_response.status).to be 400
|
2762
2808
|
end
|
2763
2809
|
end
|
2764
2810
|
|
@@ -2784,7 +2830,7 @@ describe Grape::API do
|
|
2784
2830
|
end
|
2785
2831
|
|
2786
2832
|
get '/exception'
|
2787
|
-
expect(last_response.status).to
|
2833
|
+
expect(last_response.status).to be 408
|
2788
2834
|
expect(last_response.body).to eql({ code: 408, static: 'some static text' }.to_json)
|
2789
2835
|
end
|
2790
2836
|
|
@@ -2795,7 +2841,7 @@ describe Grape::API do
|
|
2795
2841
|
end
|
2796
2842
|
|
2797
2843
|
get '/exception'
|
2798
|
-
expect(last_response.status).to
|
2844
|
+
expect(last_response.status).to be 408
|
2799
2845
|
expect(last_response.body).to eql({ code: 408, static: 'some static text' }.to_json)
|
2800
2846
|
end
|
2801
2847
|
end
|
@@ -2806,12 +2852,14 @@ describe Grape::API do
|
|
2806
2852
|
expect(subject.routes).to eq([])
|
2807
2853
|
end
|
2808
2854
|
end
|
2855
|
+
|
2809
2856
|
describe 'single method api structure' do
|
2810
|
-
before
|
2857
|
+
before do
|
2811
2858
|
subject.get :ping do
|
2812
2859
|
'pong'
|
2813
2860
|
end
|
2814
2861
|
end
|
2862
|
+
|
2815
2863
|
it 'returns one route' do
|
2816
2864
|
expect(subject.routes.size).to eq(1)
|
2817
2865
|
route = subject.routes[0]
|
@@ -2820,8 +2868,9 @@ describe Grape::API do
|
|
2820
2868
|
expect(route.request_method).to eq('GET')
|
2821
2869
|
end
|
2822
2870
|
end
|
2871
|
+
|
2823
2872
|
describe 'api structure with two versions and a namespace' do
|
2824
|
-
before
|
2873
|
+
before do
|
2825
2874
|
subject.version 'v1', using: :path
|
2826
2875
|
subject.get 'version' do
|
2827
2876
|
api.version
|
@@ -2837,30 +2886,37 @@ describe Grape::API do
|
|
2837
2886
|
end
|
2838
2887
|
end
|
2839
2888
|
end
|
2889
|
+
|
2840
2890
|
it 'returns the latest version set' do
|
2841
2891
|
expect(subject.version).to eq('v2')
|
2842
2892
|
end
|
2893
|
+
|
2843
2894
|
it 'returns versions' do
|
2844
2895
|
expect(subject.versions).to eq(%w[v1 v2])
|
2845
2896
|
end
|
2897
|
+
|
2846
2898
|
it 'sets route paths' do
|
2847
2899
|
expect(subject.routes.size).to be >= 2
|
2848
2900
|
expect(subject.routes[0].path).to eq('/:version/version(.:format)')
|
2849
2901
|
expect(subject.routes[1].path).to eq('/p/:version/n1/n2/version(.:format)')
|
2850
2902
|
end
|
2903
|
+
|
2851
2904
|
it 'sets route versions' do
|
2852
2905
|
expect(subject.routes[0].version).to eq('v1')
|
2853
2906
|
expect(subject.routes[1].version).to eq('v2')
|
2854
2907
|
end
|
2908
|
+
|
2855
2909
|
it 'sets a nested namespace' do
|
2856
2910
|
expect(subject.routes[1].namespace).to eq('/n1/n2')
|
2857
2911
|
end
|
2912
|
+
|
2858
2913
|
it 'sets prefix' do
|
2859
2914
|
expect(subject.routes[1].prefix).to eq('p')
|
2860
2915
|
end
|
2861
2916
|
end
|
2917
|
+
|
2862
2918
|
describe 'api structure with additional parameters' do
|
2863
|
-
before
|
2919
|
+
before do
|
2864
2920
|
subject.params do
|
2865
2921
|
requires :token, desc: 'a token'
|
2866
2922
|
optional :limit, desc: 'the limit'
|
@@ -2869,14 +2925,17 @@ describe Grape::API do
|
|
2869
2925
|
params[:string].split(params[:token], (params[:limit] || 0).to_i)
|
2870
2926
|
end
|
2871
2927
|
end
|
2928
|
+
|
2872
2929
|
it 'splits a string' do
|
2873
2930
|
get '/split/a,b,c.json', token: ','
|
2874
2931
|
expect(last_response.body).to eq('["a","b","c"]')
|
2875
2932
|
end
|
2933
|
+
|
2876
2934
|
it 'splits a string with limit' do
|
2877
2935
|
get '/split/a,b,c.json', token: ',', limit: '2'
|
2878
2936
|
expect(last_response.body).to eq('["a","b,c"]')
|
2879
2937
|
end
|
2938
|
+
|
2880
2939
|
it 'sets params' do
|
2881
2940
|
expect(subject.routes.map do |route|
|
2882
2941
|
{ params: route.params }
|
@@ -2891,8 +2950,9 @@ describe Grape::API do
|
|
2891
2950
|
]
|
2892
2951
|
end
|
2893
2952
|
end
|
2953
|
+
|
2894
2954
|
describe 'api structure with multiple apis' do
|
2895
|
-
before
|
2955
|
+
before do
|
2896
2956
|
subject.params do
|
2897
2957
|
requires :one, desc: 'a token'
|
2898
2958
|
optional :two, desc: 'the limit'
|
@@ -2907,6 +2967,7 @@ describe Grape::API do
|
|
2907
2967
|
subject.get 'two' do
|
2908
2968
|
end
|
2909
2969
|
end
|
2970
|
+
|
2910
2971
|
it 'sets params' do
|
2911
2972
|
expect(subject.routes.map do |route|
|
2912
2973
|
{ params: route.params }
|
@@ -2926,8 +2987,9 @@ describe Grape::API do
|
|
2926
2987
|
]
|
2927
2988
|
end
|
2928
2989
|
end
|
2990
|
+
|
2929
2991
|
describe 'api structure with an api without params' do
|
2930
|
-
before
|
2992
|
+
before do
|
2931
2993
|
subject.params do
|
2932
2994
|
requires :one, desc: 'a token'
|
2933
2995
|
optional :two, desc: 'the limit'
|
@@ -2938,6 +3000,7 @@ describe Grape::API do
|
|
2938
3000
|
subject.get 'two' do
|
2939
3001
|
end
|
2940
3002
|
end
|
3003
|
+
|
2941
3004
|
it 'sets params' do
|
2942
3005
|
expect(subject.routes.map do |route|
|
2943
3006
|
{ params: route.params }
|
@@ -2954,17 +3017,20 @@ describe Grape::API do
|
|
2954
3017
|
]
|
2955
3018
|
end
|
2956
3019
|
end
|
3020
|
+
|
2957
3021
|
describe 'api with a custom route setting' do
|
2958
|
-
before
|
3022
|
+
before do
|
2959
3023
|
subject.route_setting :custom, key: 'value'
|
2960
3024
|
subject.get 'one'
|
2961
3025
|
end
|
3026
|
+
|
2962
3027
|
it 'exposed' do
|
2963
3028
|
expect(subject.routes.count).to eq 1
|
2964
3029
|
route = subject.routes.first
|
2965
3030
|
expect(route.settings[:custom]).to eq(key: 'value')
|
2966
3031
|
end
|
2967
3032
|
end
|
3033
|
+
|
2968
3034
|
describe 'status' do
|
2969
3035
|
it 'can be set to arbitrary Integer value' do
|
2970
3036
|
subject.get '/foo' do
|
@@ -2973,6 +3039,7 @@ describe Grape::API do
|
|
2973
3039
|
get '/foo'
|
2974
3040
|
expect(last_response.status).to eq 210
|
2975
3041
|
end
|
3042
|
+
|
2976
3043
|
it 'can be set with a status code symbol' do
|
2977
3044
|
subject.get '/foo' do
|
2978
3045
|
status :see_other
|
@@ -2987,10 +3054,12 @@ describe Grape::API do
|
|
2987
3054
|
it 'empty array of routes' do
|
2988
3055
|
expect(subject.routes).to eq([])
|
2989
3056
|
end
|
3057
|
+
|
2990
3058
|
it 'empty array of routes' do
|
2991
3059
|
subject.desc 'grape api'
|
2992
3060
|
expect(subject.routes).to eq([])
|
2993
3061
|
end
|
3062
|
+
|
2994
3063
|
it 'describes a method' do
|
2995
3064
|
subject.desc 'first method'
|
2996
3065
|
subject.get :first
|
@@ -3001,6 +3070,7 @@ describe Grape::API do
|
|
3001
3070
|
expect(route.params).to eq({})
|
3002
3071
|
expect(route.options).to be_a_kind_of(Hash)
|
3003
3072
|
end
|
3073
|
+
|
3004
3074
|
it 'has params which does not include format and version as named captures' do
|
3005
3075
|
subject.version :v1, using: :path
|
3006
3076
|
subject.get :first
|
@@ -3008,6 +3078,7 @@ describe Grape::API do
|
|
3008
3078
|
expect(param_keys).not_to include('format')
|
3009
3079
|
expect(param_keys).not_to include('version')
|
3010
3080
|
end
|
3081
|
+
|
3011
3082
|
it 'describes methods separately' do
|
3012
3083
|
subject.desc 'first method'
|
3013
3084
|
subject.get :first
|
@@ -3021,6 +3092,7 @@ describe Grape::API do
|
|
3021
3092
|
{ description: 'second method', params: {} }
|
3022
3093
|
]
|
3023
3094
|
end
|
3095
|
+
|
3024
3096
|
it 'resets desc' do
|
3025
3097
|
subject.desc 'first method'
|
3026
3098
|
subject.get :first
|
@@ -3032,6 +3104,7 @@ describe Grape::API do
|
|
3032
3104
|
{ description: nil, params: {} }
|
3033
3105
|
]
|
3034
3106
|
end
|
3107
|
+
|
3035
3108
|
it 'namespaces and describe arbitrary parameters' do
|
3036
3109
|
subject.namespace 'ns' do
|
3037
3110
|
desc 'ns second', foo: 'bar'
|
@@ -3043,6 +3116,7 @@ describe Grape::API do
|
|
3043
3116
|
{ description: 'ns second', foo: 'bar', params: {} }
|
3044
3117
|
]
|
3045
3118
|
end
|
3119
|
+
|
3046
3120
|
it 'includes details' do
|
3047
3121
|
subject.desc 'method', details: 'method details'
|
3048
3122
|
subject.get 'method'
|
@@ -3052,6 +3126,7 @@ describe Grape::API do
|
|
3052
3126
|
{ description: 'method', details: 'method details', params: {} }
|
3053
3127
|
]
|
3054
3128
|
end
|
3129
|
+
|
3055
3130
|
it 'describes a method with parameters' do
|
3056
3131
|
subject.desc 'Reverses a string.', params: { 's' => { desc: 'string to reverse', type: 'string' } }
|
3057
3132
|
subject.get 'reverse' do
|
@@ -3063,6 +3138,7 @@ describe Grape::API do
|
|
3063
3138
|
{ description: 'Reverses a string.', params: { 's' => { desc: 'string to reverse', type: 'string' } } }
|
3064
3139
|
]
|
3065
3140
|
end
|
3141
|
+
|
3066
3142
|
it 'does not inherit param descriptions in consequent namespaces' do
|
3067
3143
|
subject.desc 'global description'
|
3068
3144
|
subject.params do
|
@@ -3093,6 +3169,7 @@ describe Grape::API do
|
|
3093
3169
|
} }
|
3094
3170
|
]
|
3095
3171
|
end
|
3172
|
+
|
3096
3173
|
it 'merges the parameters of the namespace with the parameters of the method' do
|
3097
3174
|
subject.desc 'namespace'
|
3098
3175
|
subject.params do
|
@@ -3117,6 +3194,7 @@ describe Grape::API do
|
|
3117
3194
|
} }
|
3118
3195
|
]
|
3119
3196
|
end
|
3197
|
+
|
3120
3198
|
it 'merges the parameters of nested namespaces' do
|
3121
3199
|
subject.desc 'ns1'
|
3122
3200
|
subject.params do
|
@@ -3149,6 +3227,7 @@ describe Grape::API do
|
|
3149
3227
|
} }
|
3150
3228
|
]
|
3151
3229
|
end
|
3230
|
+
|
3152
3231
|
it 'groups nested params and prevents overwriting of params with same name in different groups' do
|
3153
3232
|
subject.desc 'method'
|
3154
3233
|
subject.params do
|
@@ -3172,6 +3251,7 @@ describe Grape::API do
|
|
3172
3251
|
'group2[param2]' => { required: true, desc: 'group2 param2 desc' }
|
3173
3252
|
}]
|
3174
3253
|
end
|
3254
|
+
|
3175
3255
|
it 'uses full name of parameters in nested groups' do
|
3176
3256
|
subject.desc 'nesting'
|
3177
3257
|
subject.params do
|
@@ -3192,6 +3272,7 @@ describe Grape::API do
|
|
3192
3272
|
} }
|
3193
3273
|
]
|
3194
3274
|
end
|
3275
|
+
|
3195
3276
|
it 'allows to set the type attribute on :group element' do
|
3196
3277
|
subject.params do
|
3197
3278
|
group :foo, type: Array do
|
@@ -3199,6 +3280,7 @@ describe Grape::API do
|
|
3199
3280
|
end
|
3200
3281
|
end
|
3201
3282
|
end
|
3283
|
+
|
3202
3284
|
it 'parses parameters when no description is given' do
|
3203
3285
|
subject.params do
|
3204
3286
|
requires :one_param, desc: 'one param'
|
@@ -3210,6 +3292,7 @@ describe Grape::API do
|
|
3210
3292
|
{ description: nil, params: { 'one_param' => { required: true, desc: 'one param' } } }
|
3211
3293
|
]
|
3212
3294
|
end
|
3295
|
+
|
3213
3296
|
it 'does not symbolize params' do
|
3214
3297
|
subject.desc 'Reverses a string.', params: { 's' => { desc: 'string to reverse', type: 'string' } }
|
3215
3298
|
subject.get 'reverse/:s' do
|
@@ -3268,7 +3351,7 @@ describe Grape::API do
|
|
3268
3351
|
subject.version 'v1', using: :path
|
3269
3352
|
|
3270
3353
|
subject.namespace :cool do
|
3271
|
-
app = Class.new(Grape::API)
|
3354
|
+
app = Class.new(Grape::API) # rubocop:disable RSpec/DescribedClass
|
3272
3355
|
app.get('/awesome') do
|
3273
3356
|
'yo'
|
3274
3357
|
end
|
@@ -3284,12 +3367,12 @@ describe Grape::API do
|
|
3284
3367
|
subject.version 'v1', using: :path
|
3285
3368
|
|
3286
3369
|
subject.namespace :cool do
|
3287
|
-
inner_app = Class.new(Grape::API)
|
3370
|
+
inner_app = Class.new(Grape::API) # rubocop:disable RSpec/DescribedClass
|
3288
3371
|
inner_app.get('/awesome') do
|
3289
3372
|
'yo'
|
3290
3373
|
end
|
3291
3374
|
|
3292
|
-
app = Class.new(Grape::API)
|
3375
|
+
app = Class.new(Grape::API) # rubocop:disable RSpec/DescribedClass
|
3293
3376
|
app.mount inner_app
|
3294
3377
|
mount app
|
3295
3378
|
end
|
@@ -3304,7 +3387,7 @@ describe Grape::API do
|
|
3304
3387
|
rack_response("rescued from #{e.message}", 202)
|
3305
3388
|
end
|
3306
3389
|
|
3307
|
-
app = Class.new(
|
3390
|
+
app = Class.new(described_class)
|
3308
3391
|
|
3309
3392
|
subject.namespace :mounted do
|
3310
3393
|
app.rescue_from ArgumentError
|
@@ -3313,15 +3396,16 @@ describe Grape::API do
|
|
3313
3396
|
end
|
3314
3397
|
|
3315
3398
|
get '/mounted/fail'
|
3316
|
-
expect(last_response.status).to
|
3399
|
+
expect(last_response.status).to be 202
|
3317
3400
|
expect(last_response.body).to eq('rescued from doh!')
|
3318
3401
|
end
|
3402
|
+
|
3319
3403
|
it 'prefers rescues defined by mounted if they rescue similar error class' do
|
3320
3404
|
subject.rescue_from StandardError do
|
3321
3405
|
rack_response('outer rescue')
|
3322
3406
|
end
|
3323
3407
|
|
3324
|
-
app = Class.new(
|
3408
|
+
app = Class.new(described_class)
|
3325
3409
|
|
3326
3410
|
subject.namespace :mounted do
|
3327
3411
|
rescue_from StandardError do
|
@@ -3334,12 +3418,13 @@ describe Grape::API do
|
|
3334
3418
|
get '/mounted/fail'
|
3335
3419
|
expect(last_response.body).to eq('inner rescue')
|
3336
3420
|
end
|
3421
|
+
|
3337
3422
|
it 'prefers rescues defined by mounted even if outer is more specific' do
|
3338
3423
|
subject.rescue_from ArgumentError do
|
3339
3424
|
rack_response('outer rescue')
|
3340
3425
|
end
|
3341
3426
|
|
3342
|
-
app = Class.new(
|
3427
|
+
app = Class.new(described_class)
|
3343
3428
|
|
3344
3429
|
subject.namespace :mounted do
|
3345
3430
|
rescue_from StandardError do
|
@@ -3352,12 +3437,13 @@ describe Grape::API do
|
|
3352
3437
|
get '/mounted/fail'
|
3353
3438
|
expect(last_response.body).to eq('inner rescue')
|
3354
3439
|
end
|
3440
|
+
|
3355
3441
|
it 'prefers more specific rescues defined by mounted' do
|
3356
3442
|
subject.rescue_from StandardError do
|
3357
3443
|
rack_response('outer rescue')
|
3358
3444
|
end
|
3359
3445
|
|
3360
|
-
app = Class.new(
|
3446
|
+
app = Class.new(described_class)
|
3361
3447
|
|
3362
3448
|
subject.namespace :mounted do
|
3363
3449
|
rescue_from ArgumentError do
|
@@ -3374,7 +3460,7 @@ describe Grape::API do
|
|
3374
3460
|
|
3375
3461
|
it 'collects the routes of the mounted api' do
|
3376
3462
|
subject.namespace :cool do
|
3377
|
-
app = Class.new(Grape::API)
|
3463
|
+
app = Class.new(Grape::API) # rubocop:disable RSpec/DescribedClass
|
3378
3464
|
app.get('/awesome') {}
|
3379
3465
|
app.post('/sauce') {}
|
3380
3466
|
mount app
|
@@ -3386,7 +3472,7 @@ describe Grape::API do
|
|
3386
3472
|
|
3387
3473
|
it 'mounts on a path' do
|
3388
3474
|
subject.namespace :cool do
|
3389
|
-
app = Class.new(Grape::API)
|
3475
|
+
app = Class.new(Grape::API) # rubocop:disable RSpec/DescribedClass
|
3390
3476
|
app.get '/awesome' do
|
3391
3477
|
'sauce'
|
3392
3478
|
end
|
@@ -3398,8 +3484,8 @@ describe Grape::API do
|
|
3398
3484
|
end
|
3399
3485
|
|
3400
3486
|
it 'mounts on a nested path' do
|
3401
|
-
APP1 = Class.new(
|
3402
|
-
APP2 = Class.new(
|
3487
|
+
APP1 = Class.new(described_class)
|
3488
|
+
APP2 = Class.new(described_class)
|
3403
3489
|
APP2.get '/nice' do
|
3404
3490
|
'play'
|
3405
3491
|
end
|
@@ -3415,7 +3501,7 @@ describe Grape::API do
|
|
3415
3501
|
end
|
3416
3502
|
|
3417
3503
|
it 'responds to options' do
|
3418
|
-
app = Class.new(
|
3504
|
+
app = Class.new(described_class)
|
3419
3505
|
app.get '/colour' do
|
3420
3506
|
'red'
|
3421
3507
|
end
|
@@ -3429,21 +3515,21 @@ describe Grape::API do
|
|
3429
3515
|
end
|
3430
3516
|
|
3431
3517
|
get '/apples/colour'
|
3432
|
-
expect(last_response.status).to
|
3518
|
+
expect(last_response.status).to be 200
|
3433
3519
|
expect(last_response.body).to eq('red')
|
3434
3520
|
options '/apples/colour'
|
3435
|
-
expect(last_response.status).to
|
3521
|
+
expect(last_response.status).to be 204
|
3436
3522
|
get '/apples/pears/colour'
|
3437
|
-
expect(last_response.status).to
|
3523
|
+
expect(last_response.status).to be 200
|
3438
3524
|
expect(last_response.body).to eq('green')
|
3439
3525
|
options '/apples/pears/colour'
|
3440
|
-
expect(last_response.status).to
|
3526
|
+
expect(last_response.status).to be 204
|
3441
3527
|
end
|
3442
3528
|
|
3443
3529
|
it 'responds to options with path versioning' do
|
3444
3530
|
subject.version 'v1', using: :path
|
3445
3531
|
subject.namespace :apples do
|
3446
|
-
app = Class.new(Grape::API)
|
3532
|
+
app = Class.new(Grape::API) # rubocop:disable RSpec/DescribedClass
|
3447
3533
|
app.get('/colour') do
|
3448
3534
|
'red'
|
3449
3535
|
end
|
@@ -3451,14 +3537,14 @@ describe Grape::API do
|
|
3451
3537
|
end
|
3452
3538
|
|
3453
3539
|
get '/v1/apples/colour'
|
3454
|
-
expect(last_response.status).to
|
3540
|
+
expect(last_response.status).to be 200
|
3455
3541
|
expect(last_response.body).to eq('red')
|
3456
3542
|
options '/v1/apples/colour'
|
3457
|
-
expect(last_response.status).to
|
3543
|
+
expect(last_response.status).to be 204
|
3458
3544
|
end
|
3459
3545
|
|
3460
3546
|
it 'mounts a versioned API with nested resources' do
|
3461
|
-
api = Class.new(
|
3547
|
+
api = Class.new(described_class) do
|
3462
3548
|
version 'v1'
|
3463
3549
|
resources :users do
|
3464
3550
|
get :hello do
|
@@ -3473,7 +3559,7 @@ describe Grape::API do
|
|
3473
3559
|
end
|
3474
3560
|
|
3475
3561
|
it 'mounts a prefixed API with nested resources' do
|
3476
|
-
api = Class.new(
|
3562
|
+
api = Class.new(described_class) do
|
3477
3563
|
prefix 'api'
|
3478
3564
|
resources :users do
|
3479
3565
|
get :hello do
|
@@ -3488,7 +3574,7 @@ describe Grape::API do
|
|
3488
3574
|
end
|
3489
3575
|
|
3490
3576
|
it 'applies format to a mounted API with nested resources' do
|
3491
|
-
api = Class.new(
|
3577
|
+
api = Class.new(described_class) do
|
3492
3578
|
format :json
|
3493
3579
|
resources :users do
|
3494
3580
|
get do
|
@@ -3503,7 +3589,7 @@ describe Grape::API do
|
|
3503
3589
|
end
|
3504
3590
|
|
3505
3591
|
it 'applies auth to a mounted API with nested resources' do
|
3506
|
-
api = Class.new(
|
3592
|
+
api = Class.new(described_class) do
|
3507
3593
|
format :json
|
3508
3594
|
http_basic do |username, password|
|
3509
3595
|
username == 'username' && password == 'password'
|
@@ -3524,7 +3610,7 @@ describe Grape::API do
|
|
3524
3610
|
end
|
3525
3611
|
|
3526
3612
|
it 'mounts multiple versioned APIs with nested resources' do
|
3527
|
-
api1 = Class.new(
|
3613
|
+
api1 = Class.new(described_class) do
|
3528
3614
|
version 'one', using: :header, vendor: 'test'
|
3529
3615
|
resources :users do
|
3530
3616
|
get :hello do
|
@@ -3533,7 +3619,7 @@ describe Grape::API do
|
|
3533
3619
|
end
|
3534
3620
|
end
|
3535
3621
|
|
3536
|
-
api2 = Class.new(
|
3622
|
+
api2 = Class.new(described_class) do
|
3537
3623
|
version 'two', using: :header, vendor: 'test'
|
3538
3624
|
resources :users do
|
3539
3625
|
get :hello do
|
@@ -3552,7 +3638,7 @@ describe Grape::API do
|
|
3552
3638
|
end
|
3553
3639
|
|
3554
3640
|
it 'recognizes potential versions with mounted path' do
|
3555
|
-
a = Class.new(
|
3641
|
+
a = Class.new(described_class) do
|
3556
3642
|
version :v1, using: :path
|
3557
3643
|
|
3558
3644
|
get '/hello' do
|
@@ -3560,7 +3646,7 @@ describe Grape::API do
|
|
3560
3646
|
end
|
3561
3647
|
end
|
3562
3648
|
|
3563
|
-
b = Class.new(
|
3649
|
+
b = Class.new(described_class) do
|
3564
3650
|
version :v1, using: :path
|
3565
3651
|
|
3566
3652
|
get '/world' do
|
@@ -3580,11 +3666,11 @@ describe Grape::API do
|
|
3580
3666
|
|
3581
3667
|
context 'when mounting class extends a subclass of Grape::API' do
|
3582
3668
|
it 'mounts APIs with the same superclass' do
|
3583
|
-
base_api = Class.new(
|
3669
|
+
base_api = Class.new(described_class)
|
3584
3670
|
a = Class.new(base_api)
|
3585
3671
|
b = Class.new(base_api)
|
3586
3672
|
|
3587
|
-
expect { a.mount b }.
|
3673
|
+
expect { a.mount b }.not_to raise_error
|
3588
3674
|
end
|
3589
3675
|
end
|
3590
3676
|
|
@@ -3603,22 +3689,22 @@ describe Grape::API do
|
|
3603
3689
|
end
|
3604
3690
|
end
|
3605
3691
|
|
3606
|
-
it '
|
3692
|
+
it 'correctlies include module in nested mount' do
|
3607
3693
|
module_to_include = included_module
|
3608
|
-
v1 = Class.new(
|
3694
|
+
v1 = Class.new(described_class) do
|
3609
3695
|
version :v1, using: :path
|
3610
3696
|
include module_to_include
|
3611
3697
|
my_method
|
3612
3698
|
end
|
3613
|
-
v2 = Class.new(
|
3699
|
+
v2 = Class.new(described_class) do
|
3614
3700
|
version :v2, using: :path
|
3615
3701
|
end
|
3616
|
-
segment_base = Class.new(
|
3702
|
+
segment_base = Class.new(described_class) do
|
3617
3703
|
mount v1
|
3618
3704
|
mount v2
|
3619
3705
|
end
|
3620
3706
|
|
3621
|
-
Class.new(
|
3707
|
+
Class.new(described_class) do
|
3622
3708
|
mount segment_base
|
3623
3709
|
end
|
3624
3710
|
|
@@ -3653,7 +3739,7 @@ describe Grape::API do
|
|
3653
3739
|
end
|
3654
3740
|
|
3655
3741
|
describe '.endpoint' do
|
3656
|
-
before
|
3742
|
+
before do
|
3657
3743
|
subject.format :json
|
3658
3744
|
subject.get '/endpoint/options' do
|
3659
3745
|
{
|
@@ -3662,6 +3748,7 @@ describe Grape::API do
|
|
3662
3748
|
}
|
3663
3749
|
end
|
3664
3750
|
end
|
3751
|
+
|
3665
3752
|
it 'path' do
|
3666
3753
|
get '/endpoint/options'
|
3667
3754
|
options = ::Grape::Json.load(last_response.body)
|
@@ -3673,7 +3760,7 @@ describe Grape::API do
|
|
3673
3760
|
|
3674
3761
|
describe '.route' do
|
3675
3762
|
context 'plain' do
|
3676
|
-
before
|
3763
|
+
before do
|
3677
3764
|
subject.get '/' do
|
3678
3765
|
route.path
|
3679
3766
|
end
|
@@ -3681,6 +3768,7 @@ describe Grape::API do
|
|
3681
3768
|
route.path
|
3682
3769
|
end
|
3683
3770
|
end
|
3771
|
+
|
3684
3772
|
it 'provides access to route info' do
|
3685
3773
|
get '/'
|
3686
3774
|
expect(last_response.body).to eq('/(.:format)')
|
@@ -3688,8 +3776,9 @@ describe Grape::API do
|
|
3688
3776
|
expect(last_response.body).to eq('/path(.:format)')
|
3689
3777
|
end
|
3690
3778
|
end
|
3779
|
+
|
3691
3780
|
context 'with desc' do
|
3692
|
-
before
|
3781
|
+
before do
|
3693
3782
|
subject.desc 'returns description'
|
3694
3783
|
subject.get '/description' do
|
3695
3784
|
route.description
|
@@ -3699,82 +3788,98 @@ describe Grape::API do
|
|
3699
3788
|
route.params[params[:id]]
|
3700
3789
|
end
|
3701
3790
|
end
|
3791
|
+
|
3702
3792
|
it 'returns route description' do
|
3703
3793
|
get '/description'
|
3704
3794
|
expect(last_response.body).to eq('returns description')
|
3705
3795
|
end
|
3796
|
+
|
3706
3797
|
it 'returns route parameters' do
|
3707
3798
|
get '/params/x'
|
3708
3799
|
expect(last_response.body).to eq('y')
|
3709
3800
|
end
|
3710
3801
|
end
|
3711
3802
|
end
|
3803
|
+
|
3712
3804
|
describe '.format' do
|
3713
3805
|
context ':txt' do
|
3714
|
-
before
|
3806
|
+
before do
|
3715
3807
|
subject.format :txt
|
3716
3808
|
subject.content_type :json, 'application/json'
|
3717
3809
|
subject.get '/meaning_of_life' do
|
3718
3810
|
{ meaning_of_life: 42 }
|
3719
3811
|
end
|
3720
3812
|
end
|
3813
|
+
|
3721
3814
|
it 'forces txt without an extension' do
|
3722
3815
|
get '/meaning_of_life'
|
3723
3816
|
expect(last_response.body).to eq({ meaning_of_life: 42 }.to_s)
|
3724
3817
|
end
|
3818
|
+
|
3725
3819
|
it 'does not force txt with an extension' do
|
3726
3820
|
get '/meaning_of_life.json'
|
3727
3821
|
expect(last_response.body).to eq({ meaning_of_life: 42 }.to_json)
|
3728
3822
|
end
|
3823
|
+
|
3729
3824
|
it 'forces txt from a non-accepting header' do
|
3730
3825
|
get '/meaning_of_life', {}, 'HTTP_ACCEPT' => 'application/json'
|
3731
3826
|
expect(last_response.body).to eq({ meaning_of_life: 42 }.to_s)
|
3732
3827
|
end
|
3733
3828
|
end
|
3829
|
+
|
3734
3830
|
context ':txt only' do
|
3735
|
-
before
|
3831
|
+
before do
|
3736
3832
|
subject.format :txt
|
3737
3833
|
subject.get '/meaning_of_life' do
|
3738
3834
|
{ meaning_of_life: 42 }
|
3739
3835
|
end
|
3740
3836
|
end
|
3837
|
+
|
3741
3838
|
it 'forces txt without an extension' do
|
3742
3839
|
get '/meaning_of_life'
|
3743
3840
|
expect(last_response.body).to eq({ meaning_of_life: 42 }.to_s)
|
3744
3841
|
end
|
3842
|
+
|
3745
3843
|
it 'accepts specified extension' do
|
3746
3844
|
get '/meaning_of_life.txt'
|
3747
3845
|
expect(last_response.body).to eq({ meaning_of_life: 42 }.to_s)
|
3748
3846
|
end
|
3847
|
+
|
3749
3848
|
it 'does not accept extensions other than specified' do
|
3750
3849
|
get '/meaning_of_life.json'
|
3751
3850
|
expect(last_response.status).to eq(404)
|
3752
3851
|
end
|
3852
|
+
|
3753
3853
|
it 'forces txt from a non-accepting header' do
|
3754
3854
|
get '/meaning_of_life', {}, 'HTTP_ACCEPT' => 'application/json'
|
3755
3855
|
expect(last_response.body).to eq({ meaning_of_life: 42 }.to_s)
|
3756
3856
|
end
|
3757
3857
|
end
|
3858
|
+
|
3758
3859
|
context ':json' do
|
3759
|
-
before
|
3860
|
+
before do
|
3760
3861
|
subject.format :json
|
3761
3862
|
subject.content_type :txt, 'text/plain'
|
3762
3863
|
subject.get '/meaning_of_life' do
|
3763
3864
|
{ meaning_of_life: 42 }
|
3764
3865
|
end
|
3765
3866
|
end
|
3867
|
+
|
3766
3868
|
it 'forces json without an extension' do
|
3767
3869
|
get '/meaning_of_life'
|
3768
3870
|
expect(last_response.body).to eq({ meaning_of_life: 42 }.to_json)
|
3769
3871
|
end
|
3872
|
+
|
3770
3873
|
it 'does not force json with an extension' do
|
3771
3874
|
get '/meaning_of_life.txt'
|
3772
3875
|
expect(last_response.body).to eq({ meaning_of_life: 42 }.to_s)
|
3773
3876
|
end
|
3877
|
+
|
3774
3878
|
it 'forces json from a non-accepting header' do
|
3775
3879
|
get '/meaning_of_life', {}, 'HTTP_ACCEPT' => 'text/html'
|
3776
3880
|
expect(last_response.body).to eq({ meaning_of_life: 42 }.to_json)
|
3777
3881
|
end
|
3882
|
+
|
3778
3883
|
it 'can be overwritten with an explicit content type' do
|
3779
3884
|
subject.get '/meaning_of_life_with_content_type' do
|
3780
3885
|
content_type 'text/plain'
|
@@ -3783,6 +3888,7 @@ describe Grape::API do
|
|
3783
3888
|
get '/meaning_of_life_with_content_type'
|
3784
3889
|
expect(last_response.body).to eq({ meaning_of_life: 42 }.to_s)
|
3785
3890
|
end
|
3891
|
+
|
3786
3892
|
it 'raised :error from middleware' do
|
3787
3893
|
middleware = Class.new(Grape::Middleware::Base) do
|
3788
3894
|
def before
|
@@ -3797,6 +3903,7 @@ describe Grape::API do
|
|
3797
3903
|
expect(last_response.body).to eq({ error: 'Unauthorized' }.to_json)
|
3798
3904
|
end
|
3799
3905
|
end
|
3906
|
+
|
3800
3907
|
context ':serializable_hash' do
|
3801
3908
|
class SerializableHashExample
|
3802
3909
|
def serializable_hash
|
@@ -3804,9 +3911,10 @@ describe Grape::API do
|
|
3804
3911
|
end
|
3805
3912
|
end
|
3806
3913
|
|
3807
|
-
before
|
3914
|
+
before do
|
3808
3915
|
subject.format :serializable_hash
|
3809
3916
|
end
|
3917
|
+
|
3810
3918
|
it 'instance' do
|
3811
3919
|
subject.get '/example' do
|
3812
3920
|
SerializableHashExample.new
|
@@ -3814,6 +3922,7 @@ describe Grape::API do
|
|
3814
3922
|
get '/example'
|
3815
3923
|
expect(last_response.body).to eq('{"abc":"def"}')
|
3816
3924
|
end
|
3925
|
+
|
3817
3926
|
it 'root' do
|
3818
3927
|
subject.get '/example' do
|
3819
3928
|
{ 'root' => SerializableHashExample.new }
|
@@ -3821,6 +3930,7 @@ describe Grape::API do
|
|
3821
3930
|
get '/example'
|
3822
3931
|
expect(last_response.body).to eq('{"root":{"abc":"def"}}')
|
3823
3932
|
end
|
3933
|
+
|
3824
3934
|
it 'array' do
|
3825
3935
|
subject.get '/examples' do
|
3826
3936
|
[SerializableHashExample.new, SerializableHashExample.new]
|
@@ -3829,10 +3939,12 @@ describe Grape::API do
|
|
3829
3939
|
expect(last_response.body).to eq('[{"abc":"def"},{"abc":"def"}]')
|
3830
3940
|
end
|
3831
3941
|
end
|
3942
|
+
|
3832
3943
|
context ':xml' do
|
3833
|
-
before
|
3944
|
+
before do
|
3834
3945
|
subject.format :xml
|
3835
3946
|
end
|
3947
|
+
|
3836
3948
|
it 'string' do
|
3837
3949
|
subject.get '/example' do
|
3838
3950
|
'example'
|
@@ -3846,6 +3958,7 @@ describe Grape::API do
|
|
3846
3958
|
</error>
|
3847
3959
|
XML
|
3848
3960
|
end
|
3961
|
+
|
3849
3962
|
it 'hash' do
|
3850
3963
|
subject.get '/example' do
|
3851
3964
|
{
|
@@ -3863,6 +3976,7 @@ describe Grape::API do
|
|
3863
3976
|
</hash>
|
3864
3977
|
XML
|
3865
3978
|
end
|
3979
|
+
|
3866
3980
|
it 'array' do
|
3867
3981
|
subject.get '/example' do
|
3868
3982
|
%w[example1 example2]
|
@@ -3877,6 +3991,7 @@ describe Grape::API do
|
|
3877
3991
|
</strings>
|
3878
3992
|
XML
|
3879
3993
|
end
|
3994
|
+
|
3880
3995
|
it 'raised :error from middleware' do
|
3881
3996
|
middleware = Class.new(Grape::Middleware::Base) do
|
3882
3997
|
def before
|
@@ -3938,12 +4053,12 @@ describe Grape::API do
|
|
3938
4053
|
|
3939
4054
|
context 'catch-all' do
|
3940
4055
|
before do
|
3941
|
-
api1 = Class.new(
|
4056
|
+
api1 = Class.new(described_class)
|
3942
4057
|
api1.version 'v1', using: :path
|
3943
4058
|
api1.get 'hello' do
|
3944
4059
|
'v1'
|
3945
4060
|
end
|
3946
|
-
api2 = Class.new(
|
4061
|
+
api2 = Class.new(described_class)
|
3947
4062
|
api2.version 'v2', using: :path
|
3948
4063
|
api2.get 'hello' do
|
3949
4064
|
'v2'
|
@@ -3951,6 +4066,7 @@ describe Grape::API do
|
|
3951
4066
|
subject.mount api1
|
3952
4067
|
subject.mount api2
|
3953
4068
|
end
|
4069
|
+
|
3954
4070
|
[true, false].each do |anchor|
|
3955
4071
|
it "anchor=#{anchor}" do
|
3956
4072
|
subject.route :any, '*path', anchor: anchor do
|
@@ -3983,6 +4099,7 @@ describe Grape::API do
|
|
3983
4099
|
expect(last_response.status).to eq(404)
|
3984
4100
|
expect(last_response.headers['X-Cascade']).to eq('pass')
|
3985
4101
|
end
|
4102
|
+
|
3986
4103
|
it 'does not cascade' do
|
3987
4104
|
subject.version 'v2', using: :path, cascade: false
|
3988
4105
|
get '/v2/hello'
|
@@ -3990,6 +4107,7 @@ describe Grape::API do
|
|
3990
4107
|
expect(last_response.headers.keys).not_to include 'X-Cascade'
|
3991
4108
|
end
|
3992
4109
|
end
|
4110
|
+
|
3993
4111
|
context 'via endpoint' do
|
3994
4112
|
it 'cascades' do
|
3995
4113
|
subject.cascade true
|
@@ -3997,6 +4115,7 @@ describe Grape::API do
|
|
3997
4115
|
expect(last_response.status).to eq(404)
|
3998
4116
|
expect(last_response.headers['X-Cascade']).to eq('pass')
|
3999
4117
|
end
|
4118
|
+
|
4000
4119
|
it 'does not cascade' do
|
4001
4120
|
subject.cascade false
|
4002
4121
|
get '/hello'
|
@@ -4046,12 +4165,14 @@ describe Grape::API do
|
|
4046
4165
|
body false
|
4047
4166
|
end
|
4048
4167
|
end
|
4168
|
+
|
4049
4169
|
it 'returns blank body' do
|
4050
4170
|
get '/blank'
|
4051
4171
|
expect(last_response.status).to eq(204)
|
4052
4172
|
expect(last_response.body).to be_blank
|
4053
4173
|
end
|
4054
4174
|
end
|
4175
|
+
|
4055
4176
|
context 'plain text' do
|
4056
4177
|
before do
|
4057
4178
|
subject.get '/text' do
|
@@ -4060,6 +4181,7 @@ describe Grape::API do
|
|
4060
4181
|
'ignored'
|
4061
4182
|
end
|
4062
4183
|
end
|
4184
|
+
|
4063
4185
|
it 'returns blank body' do
|
4064
4186
|
get '/text'
|
4065
4187
|
expect(last_response.status).to eq(200)
|
@@ -4069,7 +4191,7 @@ describe Grape::API do
|
|
4069
4191
|
end
|
4070
4192
|
|
4071
4193
|
describe 'normal class methods' do
|
4072
|
-
subject(:grape_api) { Class.new(
|
4194
|
+
subject(:grape_api) { Class.new(described_class) }
|
4073
4195
|
|
4074
4196
|
before do
|
4075
4197
|
stub_const('MyAPI', grape_api)
|
@@ -4089,7 +4211,7 @@ describe Grape::API do
|
|
4089
4211
|
describe '.inherited' do
|
4090
4212
|
context 'overriding within class' do
|
4091
4213
|
let(:root_api) do
|
4092
|
-
Class.new(
|
4214
|
+
Class.new(described_class) do
|
4093
4215
|
@bar = 'Hello, world'
|
4094
4216
|
|
4095
4217
|
def self.inherited(child_api)
|
@@ -4115,7 +4237,7 @@ describe Grape::API do
|
|
4115
4237
|
end
|
4116
4238
|
|
4117
4239
|
let(:root_api) do
|
4118
|
-
Class.new(
|
4240
|
+
Class.new(described_class) do
|
4119
4241
|
@bar = 'Hello, world'
|
4120
4242
|
extend Inherited
|
4121
4243
|
end
|
@@ -4130,9 +4252,10 @@ describe Grape::API do
|
|
4130
4252
|
end
|
4131
4253
|
|
4132
4254
|
describe 'const_missing' do
|
4133
|
-
subject(:grape_api) { Class.new(
|
4255
|
+
subject(:grape_api) { Class.new(described_class) }
|
4256
|
+
|
4134
4257
|
let(:mounted) do
|
4135
|
-
Class.new(
|
4258
|
+
Class.new(described_class) do
|
4136
4259
|
get '/missing' do
|
4137
4260
|
SomeRandomConstant
|
4138
4261
|
end
|
@@ -4147,6 +4270,12 @@ describe Grape::API do
|
|
4147
4270
|
end
|
4148
4271
|
|
4149
4272
|
describe 'custom route helpers on nested APIs' do
|
4273
|
+
subject(:grape_api) do
|
4274
|
+
Class.new(described_class) do
|
4275
|
+
version 'v1', using: :path
|
4276
|
+
end
|
4277
|
+
end
|
4278
|
+
|
4150
4279
|
let(:shared_api_module) do
|
4151
4280
|
Module.new do
|
4152
4281
|
# rubocop:disable Style/ExplicitBlockArgument because this causes
|
@@ -4180,7 +4309,7 @@ describe Grape::API do
|
|
4180
4309
|
let(:orders_root) do
|
4181
4310
|
shared = shared_api_definitions
|
4182
4311
|
find = orders_find_endpoint
|
4183
|
-
Class.new(
|
4312
|
+
Class.new(described_class) do
|
4184
4313
|
include shared
|
4185
4314
|
|
4186
4315
|
namespace(:orders) do
|
@@ -4190,7 +4319,7 @@ describe Grape::API do
|
|
4190
4319
|
end
|
4191
4320
|
let(:orders_find_endpoint) do
|
4192
4321
|
shared = shared_api_definitions
|
4193
|
-
Class.new(
|
4322
|
+
Class.new(described_class) do
|
4194
4323
|
include shared
|
4195
4324
|
|
4196
4325
|
uniqe_id_route do
|
@@ -4201,11 +4330,6 @@ describe Grape::API do
|
|
4201
4330
|
end
|
4202
4331
|
end
|
4203
4332
|
end
|
4204
|
-
subject(:grape_api) do
|
4205
|
-
Class.new(Grape::API) do
|
4206
|
-
version 'v1', using: :path
|
4207
|
-
end
|
4208
|
-
end
|
4209
4333
|
|
4210
4334
|
before do
|
4211
4335
|
Grape::API::Instance.extend(shared_api_module)
|