kinetic_cafe_error 1.0

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.
@@ -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: []