grape 1.6.0 → 1.6.1
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 +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)
|