kinetic_cafe_error 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ module KineticCafe
2
+ # If Rails is defined, KineticCafe::ErrorEngine will be loaded automatically,
3
+ # providing access to the KineticCafe::ErrorHandler.
4
+ class ErrorEngine < ::Rails::Engine
5
+ end
6
+ end
@@ -0,0 +1,2 @@
1
+ require 'kinetic_cafe/error'
2
+ require 'Kinetic_cafe/error_engine' if defined?(::Rails)
@@ -0,0 +1,15 @@
1
+ # -*- ruby encoding: utf-8 -*-
2
+
3
+ gem 'minitest'
4
+ require 'minitest/autorun'
5
+ require 'minitest/stub_const'
6
+ require 'minitest/moar'
7
+ require 'rack/test'
8
+ require 'kinetic_cafe_error'
9
+
10
+ unless defined? I18n.translate
11
+ module I18n
12
+ def self.translate(*)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,81 @@
1
+ require 'test_helper'
2
+
3
+ describe KineticCafe::Error do
4
+ describe 'defaults' do
5
+ let(:exception) { @exception = KineticCafe::Error.new }
6
+
7
+ it 'defaults correctly' do
8
+ stub I18n, :translate, 'Untranslatable error' do
9
+ expected = '#<KineticCafe::Error: name=error ' \
10
+ "status=bad_request message=\"Untranslatable error\" " \
11
+ 'i18n_key=kcerrors.error i18n_params={} extra=nil cause=>'
12
+ assert_equal expected, exception.inspect
13
+ end
14
+ end
15
+
16
+ it 'returns key/params if I18n.translate is not defined' do
17
+ Object.stub_remove_const(:I18n) do
18
+ assert_equal [ 'kcerrors.error', {} ], exception.i18n_message
19
+ end
20
+ end
21
+
22
+ it '#api_error only includes set values' do
23
+ assert_equal(
24
+ {
25
+ status: :bad_request,
26
+ name: "error",
27
+ internal: false,
28
+ i18n_key: "kcerrors.error"
29
+ },
30
+ exception.api_error
31
+ )
32
+ end
33
+
34
+ it '#error_result includes #api_error and #message' do
35
+ assert_equal(
36
+ {
37
+ error: {
38
+ status: :bad_request,
39
+ name: "error",
40
+ internal: false,
41
+ i18n_key: "kcerrors.error"
42
+ },
43
+ message: nil
44
+ },
45
+ exception.error_result
46
+ )
47
+ end
48
+
49
+ it '#json_result includes #status, #error_result, and layout: false' do
50
+ assert_equal(
51
+ {
52
+ status: :bad_request,
53
+ json: {
54
+ error: {
55
+ status: :bad_request,
56
+ name: "error",
57
+ internal: false,
58
+ i18n_key: "kcerrors.error"
59
+ },
60
+ message: nil
61
+ },
62
+ layout: false
63
+ },
64
+ exception.json_result
65
+ )
66
+ end
67
+
68
+ it 'encodes the :query parameter specially for I18n parameters' do
69
+ exception = KineticCafe::Error.new(query: { a: 1, b: %w(x y z )})
70
+ Object.stub_remove_const(:I18n) do
71
+ assert_equal(
72
+ [
73
+ 'kcerrors.error',
74
+ { query: "a: 1; b[]: x, b[]: y, b[]: z" }
75
+ ],
76
+ exception.i18n_message
77
+ )
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,218 @@
1
+ require 'test_helper'
2
+ require 'rack/test'
3
+
4
+ describe KineticCafe::ErrorDSL do
5
+ it 'cannot be extended onto a non-exception' do
6
+ ex = assert_raises RuntimeError do
7
+ Class.new.send(:extend, KineticCafe::ErrorDSL)
8
+ end
9
+ assert_match(/cannot extend.*StandardError/, ex.message)
10
+ end
11
+
12
+ it 'cannot be extended onto a non-StandardError' do
13
+ ex = assert_raises RuntimeError do
14
+ Class.new(Exception).send(:extend, KineticCafe::ErrorDSL)
15
+ end
16
+ assert_match(/cannot extend.*StandardError/, ex.message)
17
+ end
18
+
19
+ it 'cannot be included' do
20
+ ex = assert_raises RuntimeError do
21
+ Class.new.send(:include, KineticCafe::ErrorDSL)
22
+ end
23
+ assert_match(/cannot be included/, ex.message)
24
+ end
25
+
26
+ describe 'Descendant of Standard Error' do
27
+ let(:base) {
28
+ Class.new(StandardError) do
29
+ extend KineticCafe::ErrorDSL
30
+ end
31
+ }
32
+ let(:instance) { child.new }
33
+
34
+ it 'responds to #define_error' do
35
+ assert base.respond_to?(:define_error)
36
+ end
37
+
38
+ describe '#define_error' do
39
+ describe 'fails when' do
40
+ it 'given bad options' do
41
+ ex = assert_raises ArgumentError do
42
+ base.define_error 'bad options'
43
+ end
44
+ assert_equal 'invalid options', ex.message
45
+ end
46
+
47
+ it 'given empty options' do
48
+ ex = assert_raises ArgumentError do
49
+ base.define_error({})
50
+ end
51
+ assert_equal 'define what error?', ex.message
52
+ end
53
+
54
+ it 'provided both :key and :class' do
55
+ ex = assert_raises ArgumentError do
56
+ base.define_error key: :bar, class: :bar
57
+ end
58
+ assert_equal ':key conflicts with class:bar', ex.message
59
+ end
60
+
61
+ it 'missing both :key and :class' do
62
+ ex = assert_raises ArgumentError do
63
+ base.define_error status: 300
64
+ end
65
+ assert_equal 'one of :key or :class must be provided', ex.message
66
+ end
67
+
68
+ it 'the exception class already exists' do
69
+ base.define_error class: :bar, status: :missing
70
+ ex = assert_raises ArgumentError do
71
+ base.define_error class: :bar, status: :missing
72
+ end
73
+ assert_equal 'key:bar_missing already exists as BarMissing with class:bar',
74
+ ex.message
75
+ end
76
+ end
77
+
78
+ describe 'key-based definition' do
79
+ let(:child) { base.define_error key: :child }
80
+
81
+ it 'returns "child" for #name' do
82
+ refute base.public_instance_methods.include?(:name)
83
+ assert_equal 'child', instance.name
84
+ end
85
+
86
+ it 'returns "kcerrors.child" for #i18n_key' do
87
+ refute base.public_instance_methods.include?(:i18n_key)
88
+ assert_equal 'kcerrors.child', instance.i18n_key
89
+ end
90
+
91
+ it 'returns :bad_request for #default_status (private)' do
92
+ refute base.private_instance_methods.include?(:default_status)
93
+ assert_equal :bad_request, instance.send(:default_status)
94
+ end
95
+
96
+ it 'returns 400 for #default_status without Rack::Utils (private)' do
97
+ Rack.stub_remove_const(:Utils) do
98
+ refute base.private_instance_methods.include?(:default_status)
99
+ assert_equal 400, instance.send(:default_status)
100
+ end
101
+ end
102
+ end
103
+
104
+ describe 'class-based definition' do
105
+ describe 'without status' do
106
+ before do
107
+ KineticCafe.send(:const_set, :TestError, base)
108
+ end
109
+
110
+ after do
111
+ KineticCafe.send(:remove_const, :TestError)
112
+ end
113
+
114
+ let(:child) { base.define_error class: :child }
115
+
116
+ it 'is called ChildTestError' do
117
+ assert child && base.const_defined?(:ChildTestError)
118
+ end
119
+
120
+ it 'returns "child_test_error" for #name' do
121
+ refute base.public_instance_methods.include?(:name)
122
+ assert_equal 'child_test_error', instance.name
123
+ end
124
+
125
+ it 'returns "kcerrors.child_test_error" for #i18n_key' do
126
+ refute base.public_instance_methods.include?(:i18n_key)
127
+ assert_equal 'kcerrors.child_test_error', instance.i18n_key
128
+ end
129
+
130
+ it 'returns :bad_request for #default_status (private)' do
131
+ refute base.private_instance_methods.include?(:default_status)
132
+ assert_equal :bad_request, instance.send(:default_status)
133
+ end
134
+
135
+ it 'returns 400 for #default_status without Rack::Utils (private)' do
136
+ Rack.stub_remove_const(:Utils) do
137
+ refute base.private_instance_methods.include?(:default_status)
138
+ assert_equal 400, instance.send(:default_status)
139
+ end
140
+ end
141
+ end
142
+
143
+ describe 'with symbol status' do
144
+ let(:child) {
145
+ base.define_error class: :child, status: :not_found
146
+ }
147
+
148
+ it 'is called ChildNotFound' do
149
+ assert child && base.const_defined?(:ChildNotFound)
150
+ end
151
+
152
+ it 'returns "child_not_found" for #name' do
153
+ refute base.public_instance_methods.include?(:name)
154
+ assert_equal 'child_not_found', instance.name
155
+ end
156
+
157
+ it 'returns "kcerrors.child_not_found" for #i18n_key' do
158
+ refute base.public_instance_methods.include?(:i18n_key)
159
+ assert_equal 'kcerrors.child_not_found', instance.i18n_key
160
+ end
161
+
162
+ it 'returns :not_found for #default_status (private)' do
163
+ refute base.private_instance_methods.include?(:default_status)
164
+ assert_equal :not_found, instance.send(:default_status)
165
+ end
166
+ end
167
+
168
+ describe 'with numeric status' do
169
+ before do
170
+ KineticCafe.send(:const_set, :TestError, base)
171
+ end
172
+
173
+ after do
174
+ KineticCafe.send(:remove_const, :TestError)
175
+ end
176
+
177
+ let(:child) { base.define_error class: :child, status: 400 }
178
+
179
+ it 'is called ChildTestError' do
180
+ assert child && base.const_defined?(:ChildTestError)
181
+ end
182
+
183
+ it 'returns "child_test_error" for #name' do
184
+ refute base.public_instance_methods.include?(:name)
185
+ assert_equal 'child_test_error', instance.name
186
+ end
187
+
188
+ it 'returns "kcerrors.child_test_error" for #i18n_key' do
189
+ refute base.public_instance_methods.include?(:i18n_key)
190
+ assert_equal 'kcerrors.child_test_error', instance.i18n_key
191
+ end
192
+
193
+ it 'returns 400 for #default_status (private)' do
194
+ refute base.private_instance_methods.include?(:default_status)
195
+ assert_equal 400, instance.send(:default_status)
196
+ end
197
+ end
198
+ end
199
+
200
+ it 'defines #header_only? if requested' do
201
+ child = base.define_error key: :foo, header_only: true
202
+ assert child.new.header_only?
203
+ end
204
+
205
+ it 'squeezes out extra underscores' do
206
+ base.define_error key: :_foo__bar_
207
+ assert base.const_defined?(:FooBar)
208
+ end
209
+
210
+ it 'defines a new exception descended from the base, in the base namespace' do
211
+ refute base.const_defined?(:BarMissing)
212
+ base.define_error class: :bar, status: :missing
213
+ assert base.const_defined?(:BarMissing)
214
+ assert base::BarMissing < base
215
+ end
216
+ end
217
+ end
218
+ end
metadata ADDED
@@ -0,0 +1,305 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kinetic_cafe_error
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ platform: ruby
6
+ authors:
7
+ - Austin Ziegler
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rdoc
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: hoe-doofus
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: hoe-gemspec2
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.1'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: hoe-git
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.6'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.6'
83
+ - !ruby/object:Gem::Dependency
84
+ name: hoe-rubygems
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: hoe-travis
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.2'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.2'
111
+ - !ruby/object:Gem::Dependency
112
+ name: minitest-autotest
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: minitest-focus
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '1.1'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '1.1'
139
+ - !ruby/object:Gem::Dependency
140
+ name: minitest-moar
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: minitest-stub-const
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '0.4'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '0.4'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rack-test
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '0.6'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '0.6'
181
+ - !ruby/object:Gem::Dependency
182
+ name: rake
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '10.0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '10.0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: simplecov
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: '0.7'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: '0.7'
209
+ - !ruby/object:Gem::Dependency
210
+ name: coveralls
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - "~>"
214
+ - !ruby/object:Gem::Version
215
+ version: '0.8'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - "~>"
221
+ - !ruby/object:Gem::Version
222
+ version: '0.8'
223
+ - !ruby/object:Gem::Dependency
224
+ name: hoe
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - "~>"
228
+ - !ruby/object:Gem::Version
229
+ version: '3.13'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - "~>"
235
+ - !ruby/object:Gem::Version
236
+ version: '3.13'
237
+ description: |-
238
+ kinetic_cafe_error provides an API-smart error base class and a DSL for
239
+ defining errors. Under Rails, it also provides a controller concern
240
+ (KineticCafe::ErrorHandler) that has a useful implementation of +rescue_from+
241
+ for KineticCafe::Error types.
242
+ email:
243
+ - aziegler@kineticcafe.com
244
+ executables: []
245
+ extensions: []
246
+ extra_rdoc_files:
247
+ - Contributing.rdoc
248
+ - History.rdoc
249
+ - Licence.rdoc
250
+ - Manifest.txt
251
+ - README.rdoc
252
+ files:
253
+ - ".autotest"
254
+ - ".gemtest"
255
+ - ".travis.yml"
256
+ - Contributing.rdoc
257
+ - Gemfile
258
+ - History.rdoc
259
+ - Licence.rdoc
260
+ - Manifest.txt
261
+ - README.rdoc
262
+ - Rakefile
263
+ - app/controllers/concerns/kinetic_cafe/error_handler.rb
264
+ - app/views/kinetic_cafe/error/page.html.erb
265
+ - config/locales/kinetic_cafe_error.en.yml
266
+ - config/locales/kinetic_cafe_error.en_ca.yml
267
+ - config/locales/kinetic_cafe_error.en_uk.yml
268
+ - config/locales/kinetic_cafe_error.en_us.yml
269
+ - config/locales/kinetic_cafe_error.fr.yml
270
+ - config/locales/kinetic_cafe_error.fr_ca.yml
271
+ - lib/kinetic_cafe/error.rb
272
+ - lib/kinetic_cafe/error_dsl.rb
273
+ - lib/kinetic_cafe/error_engine.rb
274
+ - lib/kinetic_cafe_error.rb
275
+ - test/test_helper.rb
276
+ - test/test_kinetic_cafe_error.rb
277
+ - test/test_kinetic_cafe_error_dsl.rb
278
+ homepage: https://github.com/KineticCafe/kinetic_cafe_error/
279
+ licenses:
280
+ - MIT
281
+ metadata: {}
282
+ post_install_message:
283
+ rdoc_options:
284
+ - "--main"
285
+ - README.rdoc
286
+ require_paths:
287
+ - lib
288
+ required_ruby_version: !ruby/object:Gem::Requirement
289
+ requirements:
290
+ - - ">="
291
+ - !ruby/object:Gem::Version
292
+ version: 1.9.2
293
+ required_rubygems_version: !ruby/object:Gem::Requirement
294
+ requirements:
295
+ - - ">="
296
+ - !ruby/object:Gem::Version
297
+ version: '0'
298
+ requirements: []
299
+ rubyforge_project:
300
+ rubygems_version: 2.4.5
301
+ signing_key:
302
+ specification_version: 4
303
+ summary: kinetic_cafe_error provides an API-smart error base class and a DSL for defining
304
+ errors
305
+ test_files: []