adavidev_batch_api 0.2.1.pre.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 (81) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +30 -0
  4. data/changelog.md +60 -0
  5. data/lib/adavidev_batch_api.rb +28 -0
  6. data/lib/batch_api/batch_error.rb +41 -0
  7. data/lib/batch_api/configuration.rb +36 -0
  8. data/lib/batch_api/error_wrapper.rb +44 -0
  9. data/lib/batch_api/internal_middleware/decode_json_body.rb +24 -0
  10. data/lib/batch_api/internal_middleware/response_filter.rb +27 -0
  11. data/lib/batch_api/internal_middleware.rb +87 -0
  12. data/lib/batch_api/operation/rack.rb +74 -0
  13. data/lib/batch_api/operation/rails.rb +42 -0
  14. data/lib/batch_api/operation.rb +2 -0
  15. data/lib/batch_api/processor/executor.rb +18 -0
  16. data/lib/batch_api/processor/sequential.rb +29 -0
  17. data/lib/batch_api/processor.rb +114 -0
  18. data/lib/batch_api/rack_middleware.rb +37 -0
  19. data/lib/batch_api/response.rb +38 -0
  20. data/lib/batch_api/utils.rb +17 -0
  21. data/lib/batch_api/version.rb +3 -0
  22. data/lib/batch_api.rb +28 -0
  23. data/lib/tasks/batch_api_tasks.rake +4 -0
  24. data/readme.md +243 -0
  25. data/spec/dummy/README.rdoc +261 -0
  26. data/spec/dummy/Rakefile +15 -0
  27. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  28. data/spec/dummy/app/assets/javascripts/endpoints.js +2 -0
  29. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  30. data/spec/dummy/app/assets/stylesheets/endpoints.css +4 -0
  31. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  32. data/spec/dummy/app/controllers/endpoints_controller.rb +36 -0
  33. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  34. data/spec/dummy/app/helpers/endpoints_helper.rb +2 -0
  35. data/spec/dummy/app/views/endpoints/get.html.erb +2 -0
  36. data/spec/dummy/app/views/endpoints/post.html.erb +2 -0
  37. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  38. data/spec/dummy/config/application.rb +63 -0
  39. data/spec/dummy/config/boot.rb +10 -0
  40. data/spec/dummy/config/database.yml +25 -0
  41. data/spec/dummy/config/environment.rb +5 -0
  42. data/spec/dummy/config/environments/development.rb +37 -0
  43. data/spec/dummy/config/environments/production.rb +67 -0
  44. data/spec/dummy/config/environments/test.rb +37 -0
  45. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  46. data/spec/dummy/config/initializers/inflections.rb +15 -0
  47. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  48. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  49. data/spec/dummy/config/initializers/session_store.rb +8 -0
  50. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  51. data/spec/dummy/config/locales/en.yml +5 -0
  52. data/spec/dummy/config/routes.rb +64 -0
  53. data/spec/dummy/config.ru +4 -0
  54. data/spec/dummy/db/test.sqlite3 +0 -0
  55. data/spec/dummy/public/404.html +26 -0
  56. data/spec/dummy/public/422.html +26 -0
  57. data/spec/dummy/public/500.html +25 -0
  58. data/spec/dummy/public/favicon.ico +0 -0
  59. data/spec/dummy/script/rails +6 -0
  60. data/spec/dummy/test/functional/endpoints_controller_test.rb +14 -0
  61. data/spec/dummy/test/unit/helpers/endpoints_helper_test.rb +4 -0
  62. data/spec/integration/rails_spec.rb +10 -0
  63. data/spec/integration/shared_examples.rb +267 -0
  64. data/spec/integration/sinatra_integration_spec.rb +14 -0
  65. data/spec/lib/batch_api_spec.rb +20 -0
  66. data/spec/lib/batch_error_spec.rb +23 -0
  67. data/spec/lib/configuration_spec.rb +30 -0
  68. data/spec/lib/error_wrapper_spec.rb +68 -0
  69. data/spec/lib/internal_middleware/decode_json_body_spec.rb +37 -0
  70. data/spec/lib/internal_middleware/response_filter_spec.rb +61 -0
  71. data/spec/lib/internal_middleware_spec.rb +91 -0
  72. data/spec/lib/operation/rack_spec.rb +240 -0
  73. data/spec/lib/operation/rails_spec.rb +100 -0
  74. data/spec/lib/processor/executor_spec.rb +22 -0
  75. data/spec/lib/processor/sequential_spec.rb +39 -0
  76. data/spec/lib/processor_spec.rb +134 -0
  77. data/spec/lib/rack_middleware_spec.rb +103 -0
  78. data/spec/lib/response_spec.rb +53 -0
  79. data/spec/spec_helper.rb +28 -0
  80. data/spec/support/sinatra_app.rb +54 -0
  81. metadata +264 -0
@@ -0,0 +1,7 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Your secret key for verifying the integrity of signed cookies.
4
+ # If you change this key, all old signed cookies will become invalid!
5
+ # Make sure the secret is at least 30 characters and all random,
6
+ # no regular words or you'll be exposed to dictionary attacks.
7
+ Dummy::Application.config.secret_token = '62dfab0df1ef66ae95f30772dda6387acdb66116bfdae29d824033e2a5b7d713a9fe4fb7735d5e9931207e73774af200ec9008d12ab1d3df41e8c7744194a6c0'
@@ -0,0 +1,8 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ Dummy::Application.config.session_store :cookie_store, key: '_dummy_session'
4
+
5
+ # Use the database for sessions instead of the cookie-based default,
6
+ # which shouldn't be used to store highly confidential information
7
+ # (create the session table with "rails generate session_migration")
8
+ # Dummy::Application.config.session_store :active_record_store
@@ -0,0 +1,14 @@
1
+ # Be sure to restart your server when you modify this file.
2
+ #
3
+ # This file contains settings for ActionController::ParamsWrapper which
4
+ # is enabled by default.
5
+
6
+ # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7
+ ActiveSupport.on_load(:action_controller) do
8
+ wrap_parameters format: [:json]
9
+ end
10
+
11
+ # Disable root element in JSON by default.
12
+ ActiveSupport.on_load(:active_record) do
13
+ self.include_root_in_json = false
14
+ end
@@ -0,0 +1,5 @@
1
+ # Sample localization file for English. Add more files in this directory for other locales.
2
+ # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3
+
4
+ en:
5
+ hello: "Hello world"
@@ -0,0 +1,64 @@
1
+ Dummy::Application.routes.draw do
2
+
3
+ post "/endpoint" => "endpoints#post"
4
+ get "/endpoint" => "endpoints#get"
5
+ get "/endpoint/error" => "endpoints#error"
6
+ get "/endpoint/capture/:captured" => "endpoints#capture"
7
+
8
+ # The priority is based upon order of creation:
9
+ # first created -> highest priority.
10
+
11
+ # Sample of regular route:
12
+ # match 'products/:id' => 'catalog#view'
13
+ # Keep in mind you can assign values other than :controller and :action
14
+
15
+ # Sample of named route:
16
+ # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
17
+ # This route can be invoked with purchase_url(:id => product.id)
18
+
19
+ # Sample resource route (maps HTTP verbs to controller actions automatically):
20
+ # resources :products
21
+
22
+ # Sample resource route with options:
23
+ # resources :products do
24
+ # member do
25
+ # get 'short'
26
+ # post 'toggle'
27
+ # end
28
+ #
29
+ # collection do
30
+ # get 'sold'
31
+ # end
32
+ # end
33
+
34
+ # Sample resource route with sub-resources:
35
+ # resources :products do
36
+ # resources :comments, :sales
37
+ # resource :seller
38
+ # end
39
+
40
+ # Sample resource route with more complex sub-resources
41
+ # resources :products do
42
+ # resources :comments
43
+ # resources :sales do
44
+ # get 'recent', :on => :collection
45
+ # end
46
+ # end
47
+
48
+ # Sample resource route within a namespace:
49
+ # namespace :admin do
50
+ # # Directs /admin/products/* to Admin::ProductsController
51
+ # # (app/controllers/admin/products_controller.rb)
52
+ # resources :products
53
+ # end
54
+
55
+ # You can have the root of your site routed with "root"
56
+ # just remember to delete public/index.html.
57
+ # root :to => 'welcome#index'
58
+
59
+ # See how all your routes lay out with "rake routes"
60
+
61
+ # This is a legacy wild controller route that's not recommended for RESTful applications.
62
+ # Note: This route will make all actions in every controller accessible via GET requests.
63
+ # match ':controller(/:action(/:id))(.:format)'
64
+ end
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
+ run Dummy::Application
File without changes
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/404.html -->
21
+ <div class="dialog">
22
+ <h1>The page you were looking for doesn't exist.</h1>
23
+ <p>You may have mistyped the address or the page may have moved.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/422.html -->
21
+ <div class="dialog">
22
+ <h1>The change you wanted was rejected.</h1>
23
+ <p>Maybe you tried to change something you didn't have access to.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/500.html -->
21
+ <div class="dialog">
22
+ <h1>We're sorry, but something went wrong.</h1>
23
+ </div>
24
+ </body>
25
+ </html>
File without changes
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,14 @@
1
+ require 'test_helper'
2
+
3
+ class EndpointsControllerTest < ActionController::TestCase
4
+ test "should get get" do
5
+ get :get
6
+ assert_response :success
7
+ end
8
+
9
+ test "should get post" do
10
+ get :post
11
+ assert_response :success
12
+ end
13
+
14
+ end
@@ -0,0 +1,4 @@
1
+ require 'test_helper'
2
+
3
+ class EndpointsHelperTest < ActionView::TestCase
4
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ require_relative './shared_examples'
3
+
4
+ describe "Rails integration specs" do
5
+ before :each do
6
+ BatchApi.stub(:rails?).and_return(true)
7
+ end
8
+
9
+ it_should_behave_like "integrating with a server"
10
+ end
@@ -0,0 +1,267 @@
1
+ shared_examples_for "a get request" do
2
+ it "returns the body as objects" do
3
+ @result = JSON.parse(response.body)["results"][0]
4
+ @result["body"].should == get_result[:body]
5
+ end
6
+
7
+ it "returns the expected status" do
8
+ @result["status"].should == get_result[:status]
9
+ end
10
+
11
+ it "returns the expected headers" do
12
+ @result["headers"].should include(get_result[:headers])
13
+ end
14
+
15
+ it "verifies that the right headers were received" do
16
+ @result["headers"]["REQUEST_HEADERS"].should include(
17
+ headerize(get_headers)
18
+ )
19
+ end
20
+ end
21
+
22
+ shared_examples_for "integrating with a server" do
23
+ def headerize(hash)
24
+ Hash[hash.map do |k, v|
25
+ ["HTTP_#{k.to_s.upcase}", v.to_s]
26
+ end]
27
+ end
28
+
29
+ before :all do
30
+ BatchApi.config.endpoint = "/batch"
31
+ BatchApi.config.verb = :post
32
+ end
33
+
34
+ before :each do
35
+ BatchApi::ErrorWrapper.stub(:expose_backtrace?).and_return(false)
36
+ end
37
+
38
+ # these are defined in the dummy app's endpoints controller
39
+ let(:get_headers) { {"foo" => "bar"} }
40
+ let(:get_params) { {"other" => "value" } }
41
+
42
+ let(:get_request) { {
43
+ url: "/endpoint",
44
+ method: "get",
45
+ headers: get_headers,
46
+ params: get_params
47
+ } }
48
+
49
+ let(:get_by_default_request) { {
50
+ url: "/endpoint",
51
+ headers: get_headers,
52
+ params: get_params
53
+ } }
54
+
55
+ let(:get_result) { {
56
+ status: 422,
57
+ body: {
58
+ "result" => "GET OK",
59
+ "params" => get_params.merge(
60
+ BatchApi.rails? ? {
61
+ "controller" => "endpoints",
62
+ "action" => "get"
63
+ } : {}
64
+ )
65
+ },
66
+ headers: { "GET" => "hello" }
67
+ } }
68
+
69
+ # these are defined in the dummy app's endpoints controller
70
+ let(:post_headers) { {"foo" => "bar"} }
71
+ let(:post_params) { {"other" => "value"} }
72
+
73
+ let(:post_request) { {
74
+ url: "/endpoint",
75
+ method: "post",
76
+ headers: post_headers,
77
+ params: post_params
78
+ } }
79
+
80
+ let(:post_result) { {
81
+ status: 203,
82
+ body: {
83
+ "result" => "POST OK",
84
+ "params" => post_params.merge(
85
+ BatchApi.rails? ? {
86
+ "controller" => "endpoints",
87
+ "action" => "post"
88
+ } : {}
89
+ )
90
+ },
91
+ headers: { "POST" => "guten tag" }
92
+ } }
93
+
94
+ let(:error_request) { {
95
+ url: "/endpoint/error",
96
+ method: "get"
97
+ } }
98
+
99
+ let(:error_response) { {
100
+ status: 500,
101
+ body: { "error" => { "message" => "StandardError" } }
102
+ } }
103
+
104
+ let(:missing_request) { {
105
+ url: "/dont/work",
106
+ method: "delete"
107
+ } }
108
+
109
+ let(:missing_response) { {
110
+ status: 404,
111
+ body: {}
112
+ } }
113
+
114
+ let(:parameter) {
115
+ (rand * 10000).to_i
116
+ }
117
+
118
+ let(:parameter_request) { {
119
+ url: "/endpoint/capture/#{parameter}",
120
+ method: "get"
121
+ } }
122
+
123
+ let(:parameter_result) { {
124
+ body: {
125
+ "result" => parameter.to_s
126
+ }
127
+ } }
128
+
129
+ let(:silent_request) { {
130
+ url: "/endpoint",
131
+ method: "post",
132
+ silent: true
133
+ } }
134
+
135
+ let(:failed_silent_request) {
136
+ error_request.merge(silent: true)
137
+ }
138
+
139
+ let(:failed_silent_result) {
140
+ error_response
141
+ }
142
+
143
+ before :each do
144
+ @t = Time.now
145
+ xhr :post, "/batch", {
146
+ ops: [
147
+ get_request,
148
+ post_request,
149
+ error_request,
150
+ missing_request,
151
+ parameter_request,
152
+ silent_request,
153
+ failed_silent_request,
154
+ get_by_default_request
155
+ ],
156
+ sequential: true
157
+ }.to_json, "CONTENT_TYPE" => "application/json"
158
+ end
159
+
160
+ it "returns a 200" do
161
+ response.status.should == 200
162
+ end
163
+
164
+ it "includes results" do
165
+ JSON.parse(response.body)["results"].should be_a(Array)
166
+ end
167
+
168
+ context "for a get request" do
169
+ describe "with an explicit get" do
170
+ before :each do
171
+ @result = JSON.parse(response.body)["results"][0]
172
+ end
173
+
174
+ it_should_behave_like "a get request"
175
+ end
176
+
177
+ describe "with no method" do
178
+ before :each do
179
+ @result = JSON.parse(response.body)["results"][7]
180
+ end
181
+
182
+ it_should_behave_like "a get request"
183
+ end
184
+ end
185
+
186
+ context "for a request with parameters" do
187
+ describe "the response" do
188
+ before :each do
189
+ @result = JSON.parse(response.body)["results"][4]
190
+ end
191
+
192
+ it "properly parses the URL segment as a paramer" do
193
+ @result["body"].should == parameter_result[:body]
194
+ end
195
+ end
196
+ end
197
+
198
+ context "for a post request" do
199
+ describe "the response" do
200
+ before :each do
201
+ @result = JSON.parse(response.body)["results"][1]
202
+ end
203
+
204
+ it "returns the body as objects (since DecodeJsonBody is default)" do
205
+ @result["body"].should == post_result[:body]
206
+ end
207
+
208
+ it "returns the expected status" do
209
+ @result["status"].should == post_result[:status]
210
+ end
211
+
212
+ it "returns the expected headers" do
213
+ @result["headers"].should include(post_result[:headers])
214
+ end
215
+
216
+ it "verifies that the right headers were received" do
217
+ @result["headers"]["REQUEST_HEADERS"].should include(headerize(post_headers))
218
+ end
219
+ end
220
+ end
221
+
222
+ context "for a request that returns an error" do
223
+ before :each do
224
+ @result = JSON.parse(response.body)["results"][2]
225
+ end
226
+
227
+ it "returns the right status" do
228
+ @result["status"].should == error_response[:status]
229
+ end
230
+
231
+ it "returns the right error information" do
232
+ # we don't care about the backtrace,
233
+ # the main thing is that the messsage arrives
234
+ @result["body"]["error"].should include(error_response[:body]["error"])
235
+ end
236
+ end
237
+
238
+ context "for a request that returns error" do
239
+ before :each do
240
+ @result = JSON.parse(response.body)["results"][3]
241
+ end
242
+
243
+ it "returns the right status" do
244
+ @result["status"].should == 404
245
+ end
246
+ end
247
+
248
+ context "for a silent request" do
249
+ before :each do
250
+ @result = JSON.parse(response.body)["results"][5]
251
+ end
252
+
253
+ it "returns nothing" do
254
+ @result.should == {}
255
+ end
256
+ end
257
+
258
+ context "for a silent request that causes an error" do
259
+ before :each do
260
+ @result = JSON.parse(response.body)["results"][6]
261
+ end
262
+
263
+ it "returns a regular result" do
264
+ @result.keys.should_not be_empty
265
+ end
266
+ end
267
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+ require 'support/sinatra_app'
3
+ require 'rack/test'
4
+ require_relative './shared_examples'
5
+
6
+ describe "Sinatra integration" do
7
+ include Rack::Test::Methods
8
+
9
+ def app
10
+ SinatraApp
11
+ end
12
+
13
+ it_should_behave_like "integrating with a server"
14
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ require 'batch_api'
3
+
4
+ describe BatchApi do
5
+ describe ".config" do
6
+ it "has a reader for config" do
7
+ BatchApi.config.should_not be_nil
8
+ end
9
+
10
+ it "provides a default config" do
11
+ BatchApi.config.should be_a(BatchApi::Configuration)
12
+ end
13
+ end
14
+
15
+ describe ".rails?" do
16
+ it "returns a value we can't test based on whether Rails is defined" do
17
+ BatchApi.rails?.should_not be_nil
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe BatchApi::Errors::BatchError do
4
+
5
+ [
6
+ BatchApi::Errors::OperationLimitExceeded,
7
+ BatchApi::Errors::BadOptionError,
8
+ BatchApi::Errors::NoOperationsError,
9
+ BatchApi::Errors::MalformedOperationError
10
+ ].each do |klass|
11
+ it "provides a #{klass} error based on ArgumentError" do
12
+ klass.superclass.should == ArgumentError
13
+ end
14
+
15
+ it "is is also a BatchError" do
16
+ klass.new.should be_a(BatchApi::Errors::BatchError)
17
+ end
18
+
19
+ it "has a status code of 422" do
20
+ klass.new.status_code.should == 422
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ module BatchApi
4
+ describe Configuration do
5
+ let(:config) { Configuration.new }
6
+
7
+ describe "options" do
8
+ {
9
+ verb: :post,
10
+ endpoint: "/batch",
11
+ limit: 50,
12
+ batch_middleware: InternalMiddleware::DEFAULT_BATCH_MIDDLEWARE,
13
+ operation_middleware: InternalMiddleware::DEFAULT_OPERATION_MIDDLEWARE
14
+ }.each_pair do |option, default|
15
+ opt, defa = option, default
16
+ describe "##{opt}" do
17
+ it "has an accessor for #{opt}" do
18
+ stubby = stub
19
+ config.send("#{opt}=", stubby)
20
+ config.send(opt).should == stubby
21
+ end
22
+
23
+ it "defaults #{opt} to #{defa.inspect}" do
24
+ config.send(opt).should == defa
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+ require 'batch_api/error_wrapper'
3
+
4
+ describe BatchApi::ErrorWrapper do
5
+ let(:exception) {
6
+ StandardError.new(Faker::Lorem.words(3)).tap do |e|
7
+ e.set_backtrace(Kernel.caller)
8
+ end
9
+ }
10
+
11
+ let(:error) { BatchApi::ErrorWrapper.new(exception) }
12
+
13
+ describe "#body" do
14
+ it "includes the message in the body" do
15
+ error.body[:error][:message].should == exception.message
16
+ end
17
+
18
+ it "includes the backtrace if it should be there" do
19
+ error.stub(:expose_backtrace?).and_return(true)
20
+ error.body[:error][:backtrace].should == exception.backtrace
21
+ end
22
+
23
+ it "includes the backtrace if it should be there" do
24
+ error.stub(:expose_backtrace?).and_return(false)
25
+ error.body[:backtrace].should be_nil
26
+ end
27
+ end
28
+
29
+ describe "#render" do
30
+ it "returns the appropriate status" do
31
+ status = stub
32
+ error.stub(:status_code).and_return(status)
33
+ error.render[0].should == status
34
+ end
35
+
36
+ it "returns appropriate content type" do
37
+ ctype = stub
38
+ BatchApi::RackMiddleware.stub(:content_type).and_return(ctype)
39
+ error.render[1].should == ctype
40
+ end
41
+
42
+ it "returns the JSONified body as the 2nd" do
43
+ error.render[2].should == [MultiJson.dump(error.body)]
44
+ end
45
+ end
46
+
47
+ describe "#status_code" do
48
+ it "returns 500 by default" do
49
+ error.status_code.should == 500
50
+ end
51
+
52
+ it "returns another status code if the error supports that" do
53
+ err = StandardError.new
54
+ code = stub
55
+ err.stub(:status_code).and_return(code)
56
+ BatchApi::ErrorWrapper.new(err).status_code.should == code
57
+ end
58
+ end
59
+
60
+ describe ".expose_backtrace?" do
61
+ it "returns false if Rails.env.production?" do
62
+ Rails.env.stub(:production?).and_return(true)
63
+ BatchApi::ErrorWrapper.expose_backtrace?.should be_false
64
+ Rails.env.stub(:production?).and_return(false)
65
+ BatchApi::ErrorWrapper.expose_backtrace?.should be_true
66
+ end
67
+ end
68
+ end