grape 1.3.3 → 1.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +111 -2
  3. data/CONTRIBUTING.md +2 -1
  4. data/README.md +135 -23
  5. data/UPGRADING.md +237 -46
  6. data/grape.gemspec +5 -5
  7. data/lib/grape/api/instance.rb +34 -42
  8. data/lib/grape/api.rb +21 -16
  9. data/lib/grape/cookies.rb +2 -0
  10. data/lib/grape/dsl/callbacks.rb +1 -1
  11. data/lib/grape/dsl/desc.rb +3 -5
  12. data/lib/grape/dsl/headers.rb +5 -2
  13. data/lib/grape/dsl/helpers.rb +8 -5
  14. data/lib/grape/dsl/inside_route.rb +72 -53
  15. data/lib/grape/dsl/middleware.rb +4 -4
  16. data/lib/grape/dsl/parameters.rb +11 -7
  17. data/lib/grape/dsl/request_response.rb +9 -6
  18. data/lib/grape/dsl/routing.rb +8 -9
  19. data/lib/grape/dsl/settings.rb +5 -5
  20. data/lib/grape/dsl/validations.rb +18 -1
  21. data/lib/grape/eager_load.rb +1 -1
  22. data/lib/grape/endpoint.rb +29 -42
  23. data/lib/grape/error_formatter/json.rb +2 -6
  24. data/lib/grape/error_formatter/xml.rb +2 -6
  25. data/lib/grape/exceptions/empty_message_body.rb +11 -0
  26. data/lib/grape/exceptions/validation.rb +2 -3
  27. data/lib/grape/exceptions/validation_errors.rb +1 -1
  28. data/lib/grape/formatter/json.rb +1 -0
  29. data/lib/grape/formatter/serializable_hash.rb +2 -1
  30. data/lib/grape/formatter/xml.rb +1 -0
  31. data/lib/grape/locale/en.yml +1 -1
  32. data/lib/grape/middleware/auth/base.rb +3 -3
  33. data/lib/grape/middleware/auth/dsl.rb +7 -1
  34. data/lib/grape/middleware/base.rb +6 -3
  35. data/lib/grape/middleware/error.rb +11 -13
  36. data/lib/grape/middleware/formatter.rb +7 -7
  37. data/lib/grape/middleware/stack.rb +10 -3
  38. data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
  39. data/lib/grape/middleware/versioner/header.rb +6 -4
  40. data/lib/grape/middleware/versioner/param.rb +1 -0
  41. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
  42. data/lib/grape/middleware/versioner/path.rb +2 -0
  43. data/lib/grape/parser/json.rb +1 -1
  44. data/lib/grape/parser/xml.rb +1 -1
  45. data/lib/grape/path.rb +1 -0
  46. data/lib/grape/request.rb +4 -1
  47. data/lib/grape/router/attribute_translator.rb +3 -3
  48. data/lib/grape/router/pattern.rb +1 -1
  49. data/lib/grape/router/route.rb +2 -2
  50. data/lib/grape/router.rb +31 -30
  51. data/lib/grape/{serve_file → serve_stream}/file_body.rb +1 -1
  52. data/lib/grape/{serve_file → serve_stream}/sendfile_response.rb +1 -1
  53. data/lib/grape/{serve_file/file_response.rb → serve_stream/stream_response.rb} +8 -8
  54. data/lib/grape/util/base_inheritable.rb +2 -2
  55. data/lib/grape/util/inheritable_setting.rb +1 -3
  56. data/lib/grape/util/lazy_value.rb +4 -2
  57. data/lib/grape/util/strict_hash_configuration.rb +1 -1
  58. data/lib/grape/validations/attributes_iterator.rb +8 -0
  59. data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
  60. data/lib/grape/validations/params_scope.rb +97 -62
  61. data/lib/grape/validations/single_attribute_iterator.rb +1 -1
  62. data/lib/grape/validations/types/custom_type_coercer.rb +16 -3
  63. data/lib/grape/validations/types/dry_type_coercer.rb +1 -1
  64. data/lib/grape/validations/types/invalid_value.rb +24 -0
  65. data/lib/grape/validations/types/json.rb +2 -1
  66. data/lib/grape/validations/types/primitive_coercer.rb +4 -5
  67. data/lib/grape/validations/types.rb +1 -4
  68. data/lib/grape/validations/validator_factory.rb +1 -1
  69. data/lib/grape/validations/validators/all_or_none.rb +8 -5
  70. data/lib/grape/validations/validators/allow_blank.rb +9 -7
  71. data/lib/grape/validations/validators/as.rb +6 -8
  72. data/lib/grape/validations/validators/at_least_one_of.rb +7 -4
  73. data/lib/grape/validations/validators/base.rb +74 -69
  74. data/lib/grape/validations/validators/coerce.rb +63 -76
  75. data/lib/grape/validations/validators/default.rb +36 -34
  76. data/lib/grape/validations/validators/exactly_one_of.rb +9 -6
  77. data/lib/grape/validations/validators/except_values.rb +13 -11
  78. data/lib/grape/validations/validators/multiple_params_base.rb +24 -19
  79. data/lib/grape/validations/validators/mutual_exclusion.rb +8 -5
  80. data/lib/grape/validations/validators/presence.rb +7 -4
  81. data/lib/grape/validations/validators/regexp.rb +8 -5
  82. data/lib/grape/validations/validators/same_as.rb +18 -15
  83. data/lib/grape/validations/validators/values.rb +61 -56
  84. data/lib/grape/validations.rb +6 -0
  85. data/lib/grape/version.rb +1 -1
  86. data/lib/grape.rb +7 -3
  87. data/spec/grape/api/custom_validations_spec.rb +77 -45
  88. data/spec/grape/api/deeply_included_options_spec.rb +3 -3
  89. data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -1
  90. data/spec/grape/api/invalid_format_spec.rb +2 -0
  91. data/spec/grape/api/recognize_path_spec.rb +1 -1
  92. data/spec/grape/api/routes_with_requirements_spec.rb +8 -8
  93. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -15
  94. data/spec/grape/api_remount_spec.rb +25 -19
  95. data/spec/grape/api_spec.rb +576 -211
  96. data/spec/grape/dsl/callbacks_spec.rb +2 -1
  97. data/spec/grape/dsl/headers_spec.rb +39 -9
  98. data/spec/grape/dsl/helpers_spec.rb +3 -2
  99. data/spec/grape/dsl/inside_route_spec.rb +185 -34
  100. data/spec/grape/dsl/logger_spec.rb +16 -18
  101. data/spec/grape/dsl/middleware_spec.rb +2 -1
  102. data/spec/grape/dsl/parameters_spec.rb +2 -0
  103. data/spec/grape/dsl/request_response_spec.rb +1 -0
  104. data/spec/grape/dsl/routing_spec.rb +10 -7
  105. data/spec/grape/endpoint/declared_spec.rb +848 -0
  106. data/spec/grape/endpoint_spec.rb +77 -589
  107. data/spec/grape/entity_spec.rb +29 -23
  108. data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -0
  109. data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -22
  110. data/spec/grape/exceptions/validation_errors_spec.rb +13 -10
  111. data/spec/grape/exceptions/validation_spec.rb +5 -3
  112. data/spec/grape/extensions/param_builders/hash_spec.rb +7 -7
  113. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -8
  114. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -8
  115. data/spec/grape/integration/rack_sendfile_spec.rb +13 -9
  116. data/spec/grape/loading_spec.rb +8 -8
  117. data/spec/grape/middleware/auth/dsl_spec.rb +15 -6
  118. data/spec/grape/middleware/auth/strategies_spec.rb +61 -21
  119. data/spec/grape/middleware/base_spec.rb +24 -15
  120. data/spec/grape/middleware/error_spec.rb +3 -3
  121. data/spec/grape/middleware/exception_spec.rb +111 -161
  122. data/spec/grape/middleware/formatter_spec.rb +28 -7
  123. data/spec/grape/middleware/globals_spec.rb +7 -4
  124. data/spec/grape/middleware/stack_spec.rb +15 -12
  125. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -1
  126. data/spec/grape/middleware/versioner/header_spec.rb +14 -13
  127. data/spec/grape/middleware/versioner/param_spec.rb +7 -1
  128. data/spec/grape/middleware/versioner/path_spec.rb +5 -1
  129. data/spec/grape/middleware/versioner_spec.rb +1 -1
  130. data/spec/grape/parser_spec.rb +4 -0
  131. data/spec/grape/path_spec.rb +52 -52
  132. data/spec/grape/presenters/presenter_spec.rb +7 -6
  133. data/spec/grape/request_spec.rb +6 -4
  134. data/spec/grape/util/inheritable_setting_spec.rb +7 -7
  135. data/spec/grape/util/inheritable_values_spec.rb +3 -2
  136. data/spec/grape/util/reverse_stackable_values_spec.rb +3 -1
  137. data/spec/grape/util/stackable_values_spec.rb +7 -5
  138. data/spec/grape/validations/instance_behaivour_spec.rb +9 -10
  139. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +14 -3
  140. data/spec/grape/validations/params_scope_spec.rb +72 -10
  141. data/spec/grape/validations/single_attribute_iterator_spec.rb +18 -6
  142. data/spec/grape/validations/types/primitive_coercer_spec.rb +63 -7
  143. data/spec/grape/validations/types_spec.rb +8 -8
  144. data/spec/grape/validations/validators/all_or_none_spec.rb +50 -56
  145. data/spec/grape/validations/validators/allow_blank_spec.rb +136 -140
  146. data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -56
  147. data/spec/grape/validations/validators/coerce_spec.rb +248 -33
  148. data/spec/grape/validations/validators/default_spec.rb +121 -78
  149. data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -77
  150. data/spec/grape/validations/validators/except_values_spec.rb +4 -3
  151. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -77
  152. data/spec/grape/validations/validators/presence_spec.rb +16 -1
  153. data/spec/grape/validations/validators/regexp_spec.rb +25 -31
  154. data/spec/grape/validations/validators/same_as_spec.rb +14 -20
  155. data/spec/grape/validations/validators/values_spec.rb +183 -178
  156. data/spec/grape/validations_spec.rb +342 -29
  157. data/spec/integration/eager_load/eager_load_spec.rb +15 -0
  158. data/spec/integration/multi_json/json_spec.rb +1 -1
  159. data/spec/integration/multi_xml/xml_spec.rb +1 -1
  160. data/spec/shared/versioning_examples.rb +32 -29
  161. data/spec/spec_helper.rb +12 -12
  162. data/spec/support/basic_auth_encode_helpers.rb +1 -1
  163. data/spec/support/chunks.rb +14 -0
  164. data/spec/support/versioned_helpers.rb +4 -6
  165. metadata +110 -102
@@ -10,10 +10,10 @@ describe Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuild
10
10
  end
11
11
 
12
12
  describe 'in an endpoint' do
13
- context '#params' do
13
+ describe '#params' do
14
14
  before do
15
15
  subject.params do
16
- build_with Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder
16
+ build_with Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder # rubocop:disable RSpec/DescribedClass
17
17
  end
18
18
 
19
19
  subject.get do
@@ -21,7 +21,7 @@ describe Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuild
21
21
  end
22
22
  end
23
23
 
24
- it 'should be of type Hash' do
24
+ it 'is of type Hash' do
25
25
  get '/'
26
26
  expect(last_response.status).to eq(200)
27
27
  expect(last_response.body).to eq('ActiveSupport::HashWithIndifferentAccess')
@@ -31,10 +31,10 @@ describe Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuild
31
31
 
32
32
  describe 'in an api' do
33
33
  before do
34
- subject.send(:include, Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder)
34
+ subject.send(:include, Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder) # rubocop:disable RSpec/DescribedClass
35
35
  end
36
36
 
37
- context '#params' do
37
+ describe '#params' do
38
38
  before do
39
39
  subject.get do
40
40
  params.class
@@ -49,7 +49,7 @@ describe Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuild
49
49
 
50
50
  it 'parses sub hash params' do
51
51
  subject.params do
52
- build_with Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder
52
+ build_with Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder # rubocop:disable RSpec/DescribedClass
53
53
 
54
54
  optional :a, type: Hash do
55
55
  optional :b, type: Hash do
@@ -70,7 +70,7 @@ describe Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuild
70
70
 
71
71
  it 'params are indifferent to symbol or string keys' do
72
72
  subject.params do
73
- build_with Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder
73
+ build_with Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder # rubocop:disable RSpec/DescribedClass
74
74
  optional :a, type: Hash do
75
75
  optional :b, type: Hash do
76
76
  optional :c, type: String
@@ -90,7 +90,7 @@ describe Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuild
90
90
 
91
91
  it 'responds to string keys' do
92
92
  subject.params do
93
- build_with Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder
93
+ build_with Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder # rubocop:disable RSpec/DescribedClass
94
94
  requires :a, type: String
95
95
  end
96
96
 
@@ -10,10 +10,10 @@ describe Grape::Extensions::Hashie::Mash::ParamBuilder do
10
10
  end
11
11
 
12
12
  describe 'in an endpoint' do
13
- context '#params' do
13
+ describe '#params' do
14
14
  before do
15
15
  subject.params do
16
- build_with Grape::Extensions::Hashie::Mash::ParamBuilder
16
+ build_with Grape::Extensions::Hashie::Mash::ParamBuilder # rubocop:disable RSpec/DescribedClass
17
17
  end
18
18
 
19
19
  subject.get do
@@ -21,7 +21,7 @@ describe Grape::Extensions::Hashie::Mash::ParamBuilder do
21
21
  end
22
22
  end
23
23
 
24
- it 'should be of type Hashie::Mash' do
24
+ it 'is of type Hashie::Mash' do
25
25
  get '/'
26
26
  expect(last_response.status).to eq(200)
27
27
  expect(last_response.body).to eq('Hashie::Mash')
@@ -31,17 +31,17 @@ describe Grape::Extensions::Hashie::Mash::ParamBuilder do
31
31
 
32
32
  describe 'in an api' do
33
33
  before do
34
- subject.send(:include, Grape::Extensions::Hashie::Mash::ParamBuilder)
34
+ subject.send(:include, Grape::Extensions::Hashie::Mash::ParamBuilder) # rubocop:disable RSpec/DescribedClass
35
35
  end
36
36
 
37
- context '#params' do
37
+ describe '#params' do
38
38
  before do
39
39
  subject.get do
40
40
  params.class
41
41
  end
42
42
  end
43
43
 
44
- it 'should be Hashie::Mash' do
44
+ it 'is Hashie::Mash' do
45
45
  get '/'
46
46
  expect(last_response.status).to eq(200)
47
47
  expect(last_response.body).to eq('Hashie::Mash')
@@ -57,7 +57,7 @@ describe Grape::Extensions::Hashie::Mash::ParamBuilder do
57
57
  end
58
58
  end
59
59
 
60
- it 'should be Hashie::Mash' do
60
+ it 'is Hashie::Mash' do
61
61
  get '/foo'
62
62
  expect(last_response.status).to eq(200)
63
63
  expect(last_response.body).to eq('Hashie::Mash')
@@ -66,7 +66,7 @@ describe Grape::Extensions::Hashie::Mash::ParamBuilder do
66
66
 
67
67
  it 'is indifferent to key or symbol access' do
68
68
  subject.params do
69
- build_with Grape::Extensions::Hashie::Mash::ParamBuilder
69
+ build_with Grape::Extensions::Hashie::Mash::ParamBuilder # rubocop:disable RSpec/DescribedClass
70
70
  requires :a, type: String
71
71
  end
72
72
  subject.get '/foo' do
@@ -4,12 +4,16 @@ require 'spec_helper'
4
4
 
5
5
  describe Rack::Sendfile do
6
6
  subject do
7
- send_file = file_streamer
7
+ content_object = file_object
8
8
  app = Class.new(Grape::API) do
9
9
  use Rack::Sendfile
10
10
  format :json
11
11
  get do
12
- file send_file
12
+ if content_object.is_a?(String)
13
+ sendfile content_object
14
+ else
15
+ stream content_object
16
+ end
13
17
  end
14
18
  end
15
19
 
@@ -22,9 +26,9 @@ describe Rack::Sendfile do
22
26
  app.call(env)
23
27
  end
24
28
 
25
- context do
26
- let(:file_streamer) do
27
- double(:file_streamer, to_path: '/accel/mapping/some/path')
29
+ context 'when calling sendfile' do
30
+ let(:file_object) do
31
+ '/accel/mapping/some/path'
28
32
  end
29
33
 
30
34
  it 'contains Sendfile headers' do
@@ -33,14 +37,14 @@ describe Rack::Sendfile do
33
37
  end
34
38
  end
35
39
 
36
- context do
37
- let(:file_streamer) do
38
- double(:file_streamer)
40
+ context 'when streaming non file content' do
41
+ let(:file_object) do
42
+ double(:file_object, each: nil)
39
43
  end
40
44
 
41
45
  it 'not contains Sendfile headers' do
42
46
  headers = subject[1]
43
- expect(headers).to_not include('X-Accel-Redirect')
47
+ expect(headers).not_to include('X-Accel-Redirect')
44
48
  end
45
49
  end
46
50
  end
@@ -3,6 +3,14 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Grape::API do
6
+ subject do
7
+ CombinedApi = combined_api
8
+ Class.new(Grape::API) do
9
+ format :json
10
+ mount CombinedApi => '/'
11
+ end
12
+ end
13
+
6
14
  let(:jobs_api) do
7
15
  Class.new(Grape::API) do
8
16
  namespace :one do
@@ -26,14 +34,6 @@ describe Grape::API do
26
34
  end
27
35
  end
28
36
 
29
- subject do
30
- CombinedApi = combined_api
31
- Class.new(Grape::API) do
32
- format :json
33
- mount CombinedApi => '/'
34
- end
35
- end
36
-
37
37
  def app
38
38
  subject
39
39
  end
@@ -5,7 +5,7 @@ require 'spec_helper'
5
5
  describe Grape::Middleware::Auth::DSL do
6
6
  subject { Class.new(Grape::API) }
7
7
 
8
- let(:block) { ->() {} }
8
+ let(:block) { -> {} }
9
9
  let(:settings) do
10
10
  {
11
11
  opaque: 'secret',
@@ -16,7 +16,7 @@ describe Grape::Middleware::Auth::DSL do
16
16
  end
17
17
 
18
18
  describe '.auth' do
19
- it 'stets auth parameters' do
19
+ it 'sets auth parameters' do
20
20
  expect(subject.base_instance).to receive(:use).with(Grape::Middleware::Auth::Base, settings)
21
21
 
22
22
  subject.auth :http_digest, realm: settings[:realm], opaque: settings[:opaque], &settings[:proc]
@@ -38,16 +38,25 @@ describe Grape::Middleware::Auth::DSL do
38
38
  end
39
39
 
40
40
  describe '.http_basic' do
41
- it 'stets auth parameters' do
41
+ it 'sets auth parameters' do
42
42
  subject.http_basic realm: 'my_realm', &settings[:proc]
43
43
  expect(subject.auth).to eq(realm: 'my_realm', type: :http_basic, proc: block)
44
44
  end
45
45
  end
46
46
 
47
47
  describe '.http_digest' do
48
- it 'stets auth parameters' do
49
- subject.http_digest realm: 'my_realm', opaque: 'my_opaque', &settings[:proc]
50
- expect(subject.auth).to eq(realm: 'my_realm', type: :http_digest, proc: block, opaque: 'my_opaque')
48
+ context 'when realm is a hash' do
49
+ it 'sets auth parameters' do
50
+ subject.http_digest realm: { realm: 'my_realm', opaque: 'my_opaque' }, &settings[:proc]
51
+ expect(subject.auth).to eq(realm: { realm: 'my_realm', opaque: 'my_opaque' }, type: :http_digest, proc: block)
52
+ end
53
+ end
54
+
55
+ context 'when realm is not hash' do
56
+ it 'sets auth parameters' do
57
+ subject.http_digest realm: 'my_realm', opaque: 'my_opaque', &settings[:proc]
58
+ expect(subject.auth).to eq(realm: 'my_realm', type: :http_digest, proc: block, opaque: 'my_opaque')
59
+ end
51
60
  end
52
61
  end
53
62
  end
@@ -36,13 +36,23 @@ describe Grape::Middleware::Auth::Strategies do
36
36
  RSpec::Matchers.define :be_challenge do
37
37
  match do |actual_response|
38
38
  actual_response.status == 401 &&
39
- actual_response['WWW-Authenticate'] =~ /^Digest / &&
39
+ actual_response['WWW-Authenticate'].start_with?('Digest ') &&
40
40
  actual_response.body.empty?
41
41
  end
42
42
  end
43
43
 
44
44
  module StrategiesSpec
45
- class Test < Grape::API
45
+ class PasswordHashed < Grape::API
46
+ http_digest(realm: { realm: 'Test Api', opaque: 'secret', passwords_hashed: true }) do |username|
47
+ { 'foo' => Digest::MD5.hexdigest(['foo', 'Test Api', 'bar'].join(':')) }[username]
48
+ end
49
+
50
+ get '/test' do
51
+ [{ hey: 'you' }, { there: 'bar' }, { foo: 'baz' }]
52
+ end
53
+ end
54
+
55
+ class PasswordIsNotHashed < Grape::API
46
56
  http_digest(realm: 'Test Api', opaque: 'secret') do |username|
47
57
  { 'foo' => 'bar' }[username]
48
58
  end
@@ -53,30 +63,60 @@ describe Grape::Middleware::Auth::Strategies do
53
63
  end
54
64
  end
55
65
 
56
- def app
57
- StrategiesSpec::Test
58
- end
66
+ context 'when password is hashed' do
67
+ def app
68
+ StrategiesSpec::PasswordHashed
69
+ end
59
70
 
60
- it 'is a digest authentication challenge' do
61
- get '/test'
62
- expect(last_response).to be_challenge
63
- end
71
+ it 'is a digest authentication challenge' do
72
+ get '/test'
73
+ expect(last_response).to be_challenge
74
+ end
64
75
 
65
- it 'throws a 401 if no auth is given' do
66
- get '/test'
67
- expect(last_response.status).to eq(401)
68
- end
76
+ it 'throws a 401 if no auth is given' do
77
+ get '/test'
78
+ expect(last_response.status).to eq(401)
79
+ end
69
80
 
70
- it 'authenticates if given valid creds' do
71
- digest_authorize 'foo', 'bar'
72
- get '/test'
73
- expect(last_response.status).to eq(200)
81
+ it 'authenticates if given valid creds' do
82
+ digest_authorize 'foo', 'bar'
83
+ get '/test'
84
+ expect(last_response.status).to eq(200)
85
+ end
86
+
87
+ it 'throws a 401 if given invalid creds' do
88
+ digest_authorize 'bar', 'foo'
89
+ get '/test'
90
+ expect(last_response.status).to eq(401)
91
+ end
74
92
  end
75
93
 
76
- it 'throws a 401 if given invalid creds' do
77
- digest_authorize 'bar', 'foo'
78
- get '/test'
79
- expect(last_response.status).to eq(401)
94
+ context 'when password is not hashed' do
95
+ def app
96
+ StrategiesSpec::PasswordIsNotHashed
97
+ end
98
+
99
+ it 'is a digest authentication challenge' do
100
+ get '/test'
101
+ expect(last_response).to be_challenge
102
+ end
103
+
104
+ it 'throws a 401 if no auth is given' do
105
+ get '/test'
106
+ expect(last_response.status).to eq(401)
107
+ end
108
+
109
+ it 'authenticates if given valid creds' do
110
+ digest_authorize 'foo', 'bar'
111
+ get '/test'
112
+ expect(last_response.status).to eq(200)
113
+ end
114
+
115
+ it 'throws a 401 if given invalid creds' do
116
+ digest_authorize 'bar', 'foo'
117
+ get '/test'
118
+ expect(last_response.status).to eq(401)
119
+ end
80
120
  end
81
121
  end
82
122
  end
@@ -3,7 +3,8 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Grape::Middleware::Base do
6
- subject { Grape::Middleware::Base.new(blank_app) }
6
+ subject { described_class.new(blank_app) }
7
+
7
8
  let(:blank_app) { ->(_) { [200, {}, 'Hi there.'] } }
8
9
 
9
10
  before do
@@ -20,6 +21,8 @@ describe Grape::Middleware::Base do
20
21
  end
21
22
 
22
23
  context 'callbacks' do
24
+ after { subject.call!({}) }
25
+
23
26
  it 'calls #before' do
24
27
  expect(subject).to receive(:before)
25
28
  end
@@ -27,8 +30,6 @@ describe Grape::Middleware::Base do
27
30
  it 'calls #after' do
28
31
  expect(subject).to receive(:after)
29
32
  end
30
-
31
- after { subject.call!({}) }
32
33
  end
33
34
 
34
35
  context 'callbacks on error' do
@@ -58,7 +59,7 @@ describe Grape::Middleware::Base do
58
59
  context 'with patched warnings' do
59
60
  before do
60
61
  @warnings = warnings = []
61
- allow_any_instance_of(Grape::Middleware::Base).to receive(:warn) { |m| warnings << m }
62
+ allow_any_instance_of(described_class).to receive(:warn) { |m| warnings << m }
62
63
  allow(subject).to receive(:after).and_raise(StandardError)
63
64
  end
64
65
 
@@ -75,49 +76,57 @@ describe Grape::Middleware::Base do
75
76
  end
76
77
 
77
78
  describe '#response' do
78
- subject { Grape::Middleware::Base.new(response) }
79
+ subject do
80
+ puts described_class
81
+ described_class.new(response)
82
+ end
79
83
 
80
- context Array do
84
+ before { subject.call({}) }
85
+
86
+ context 'when Array' do
81
87
  let(:response) { ->(_) { [204, { abc: 1 }, 'test'] } }
82
88
 
83
89
  it 'status' do
84
- subject.call({})
85
90
  expect(subject.response.status).to eq(204)
86
91
  end
87
92
 
88
93
  it 'body' do
89
- subject.call({})
90
94
  expect(subject.response.body).to eq(['test'])
91
95
  end
92
96
 
93
97
  it 'header' do
94
- subject.call({})
95
98
  expect(subject.response.header).to have_key(:abc)
96
99
  end
100
+
101
+ it 'returns the memoized Rack::Response instance' do
102
+ expect(subject.response).to be(subject.response)
103
+ end
97
104
  end
98
105
 
99
- context Rack::Response do
106
+ context 'when Rack::Response' do
100
107
  let(:response) { ->(_) { Rack::Response.new('test', 204, abc: 1) } }
101
108
 
102
109
  it 'status' do
103
- subject.call({})
104
110
  expect(subject.response.status).to eq(204)
105
111
  end
106
112
 
107
113
  it 'body' do
108
- subject.call({})
109
114
  expect(subject.response.body).to eq(['test'])
110
115
  end
111
116
 
112
117
  it 'header' do
113
- subject.call({})
114
118
  expect(subject.response.header).to have_key(:abc)
115
119
  end
120
+
121
+ it 'returns the memoized Rack::Response instance' do
122
+ expect(subject.response).to be(subject.response)
123
+ end
116
124
  end
117
125
  end
118
126
 
119
127
  describe '#context' do
120
- subject { Grape::Middleware::Base.new(blank_app) }
128
+ subject { described_class.new(blank_app) }
129
+
121
130
  it 'allows access to response context' do
122
131
  subject.call(Grape::Env::API_ENDPOINT => { header: 'some header' })
123
132
  expect(subject.context).to eq(header: 'some header')
@@ -126,7 +135,7 @@ describe Grape::Middleware::Base do
126
135
 
127
136
  context 'options' do
128
137
  it 'persists options passed at initialization' do
129
- expect(Grape::Middleware::Base.new(blank_app, abc: true).options[:abc]).to be true
138
+ expect(described_class.new(blank_app, abc: true).options[:abc]).to be true
130
139
  end
131
140
 
132
141
  context 'defaults' do
@@ -16,8 +16,7 @@ describe Grape::Middleware::Error do
16
16
 
17
17
  class ErrApp
18
18
  class << self
19
- attr_accessor :error
20
- attr_accessor :format
19
+ attr_accessor :error, :format
21
20
 
22
21
  def call(_env)
23
22
  throw :error, error
@@ -30,7 +29,7 @@ describe Grape::Middleware::Error do
30
29
  opts = options
31
30
  Rack::Builder.app do
32
31
  use Spec::Support::EndpointFaker
33
- use Grape::Middleware::Error, opts
32
+ use Grape::Middleware::Error, **opts
34
33
  run ErrorSpec::ErrApp
35
34
  end
36
35
  end
@@ -63,6 +62,7 @@ describe Grape::Middleware::Error do
63
62
 
64
63
  context 'with http code' do
65
64
  let(:options) { { default_message: 'Aww, hamburgers.' } }
65
+
66
66
  it 'adds the status code if wanted' do
67
67
  ErrorSpec::ErrApp.error = { message: { code: 200 } }
68
68
  get '/'