octiron 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ # Always start SimpleCov
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ add_filter 'spec'
5
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require_relative '../lib/octiron/support/camel_case'
3
+
4
+ class Tester
5
+ include ::Octiron::Support::CamelCase
6
+ end
7
+
8
+ describe ::Octiron::Support::CamelCase do
9
+ before do
10
+ @tester = Tester.new
11
+ end
12
+
13
+ it "capitalizes a single word" do
14
+ expect(@tester.camel_case('foo')).to eql 'Foo'
15
+ end
16
+
17
+ it "capitalizes letters in underscore separated words" do
18
+ expect(@tester.camel_case('foo_bar')).to eql 'FooBar'
19
+ end
20
+
21
+ it "handles symbols" do
22
+ expect(@tester.camel_case(:foo_bar)).to eql 'FooBar'
23
+ end
24
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+ require_relative '../lib/octiron/support/constantize'
3
+
4
+ class Tester
5
+ include ::Octiron::Support::Constantize
6
+ end
7
+
8
+ class Test
9
+ end
10
+
11
+ module TestModule
12
+ class InnerTest
13
+ end
14
+ end
15
+
16
+ class A
17
+ class A
18
+ end
19
+ end
20
+
21
+ class B < A
22
+ class B
23
+ end
24
+ end
25
+
26
+ describe ::Octiron::Support::Constantize do
27
+ before do
28
+ @tester = Tester.new
29
+ end
30
+
31
+ it "throws with an empty path (i.e. '::')" do
32
+ expect do
33
+ @tester.constantize('::')
34
+ end.to raise_error(NameError)
35
+ end
36
+
37
+ it "resolves a constant in the global namespace" do
38
+ expect(@tester.constantize('Test')).to eql Test
39
+ end
40
+
41
+ it "accepts absolute paths (i.e. starting with '::')" do
42
+ expect(@tester.constantize('::Test')).to eql Test
43
+ end
44
+
45
+ it "accepts nested names" do
46
+ expect(@tester.constantize('TestModule::InnerTest')).to \
47
+ eql TestModule::InnerTest
48
+ end
49
+
50
+ it "performs lookup in ancestors" do
51
+ expect(@tester.constantize('A::A')).to eql A::A
52
+
53
+ expect do
54
+ @tester.constantize('A::does_not_exist')
55
+ end.to raise_error(NameError)
56
+
57
+ expect(@tester.constantize('B::B')).to eql B::B
58
+ expect(@tester.constantize('B::A')).to eql A::A
59
+
60
+ expect do
61
+ @tester.constantize('B::does_not_exist')
62
+ end.to raise_error(NameError)
63
+ end
64
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+ require_relative '../lib/octiron/support/identifiers'
3
+
4
+ class Tester
5
+ include ::Octiron::Support::Identifiers
6
+
7
+ def initialize(*_)
8
+ @default_namespace = 'Octiron::Support'
9
+ end
10
+ end
11
+
12
+ class Test
13
+ end
14
+
15
+ module TestModule
16
+ class InnerTest
17
+ end
18
+ end
19
+
20
+ class A
21
+ class A
22
+ end
23
+ end
24
+
25
+ class B < A
26
+ class B
27
+ end
28
+ end
29
+
30
+ describe ::Octiron::Support::Identifiers do
31
+ before do
32
+ @tester = Tester.new
33
+ end
34
+
35
+ it "throws with an empty path (i.e. '::')" do
36
+ expect do
37
+ @tester.identify('::')
38
+ end.to raise_error(NameError)
39
+
40
+ expect do
41
+ @tester.identify('')
42
+ end.to raise_error(NameError)
43
+
44
+ expect do
45
+ @tester.identify(nil)
46
+ end.to raise_error(NameError)
47
+ end
48
+
49
+ it "returns the name of a Class" do
50
+ expect(@tester.identify(Test)).to eql 'Test'
51
+ expect(@tester.identify(A)).to eql 'A'
52
+ expect(@tester.identify(B)).to eql 'B'
53
+ end
54
+
55
+ it "returns Hashes untouched" do
56
+ test_hash = {}
57
+ expect(@tester.identify(test_hash)).to eql test_hash
58
+ expect(@tester.identify(test_hash).object_id).to eql test_hash.object_id
59
+ end
60
+
61
+ it "resolves strings to constant names" do
62
+ expect(@tester.identify('Octiron::Support::Identifiers')).to eql \
63
+ 'Octiron::Support::Identifiers'
64
+ end
65
+
66
+ it "attempts to resolve anything else as constants in the default namespace" do
67
+ expect(@tester.identify(:identifiers)).to eql \
68
+ 'Octiron::Support::Identifiers'
69
+ end
70
+ end
@@ -0,0 +1,311 @@
1
+ require 'spec_helper'
2
+ require_relative '../lib/octiron/transmogrifiers/registry'
3
+
4
+ class Test1
5
+ end
6
+
7
+ class Test2
8
+ end
9
+
10
+ class Test3
11
+ end
12
+
13
+ class Transmogrifier
14
+ attr_reader :invoked
15
+ def initialize
16
+ @invoked = 0
17
+ end
18
+
19
+ def call(_)
20
+ @invoked += 1
21
+ end
22
+ end
23
+
24
+ class HashTransmogrifier < Transmogrifier
25
+ def initialize(bad = false)
26
+ super()
27
+ @bad = bad
28
+ end
29
+
30
+ def call(from)
31
+ super
32
+
33
+ if @bad
34
+ return {}
35
+ end
36
+
37
+ return {
38
+ a: from[:a],
39
+ b_c: from[:b][:c],
40
+ }
41
+ end
42
+ end
43
+
44
+ class Test1To2Transmogrifier < Transmogrifier
45
+ def call(from)
46
+ super
47
+ return Test2.new
48
+ end
49
+ end
50
+
51
+ class Test2To3Transmogrifier < Transmogrifier
52
+ def call(from)
53
+ super
54
+ return Test3.new
55
+ end
56
+ end
57
+
58
+ class Test1To3Transmogrifier < Transmogrifier
59
+ def call(from)
60
+ super
61
+ return Test3.new
62
+ end
63
+ end
64
+
65
+ describe Octiron::Transmogrifiers::Registry do
66
+ describe "construction" do
67
+ it "can be constructed without a default namespace" do
68
+ reg = nil
69
+ expect do
70
+ reg = ::Octiron::Transmogrifiers::Registry.new
71
+ end.not_to raise_error
72
+
73
+ expect(reg.default_namespace).to eql 'Octiron::Transmogrifiers'
74
+ end
75
+
76
+ it "can be constructed with a namespace" do
77
+ reg = nil
78
+ expect do
79
+ reg = ::Octiron::Transmogrifiers::Registry.new(::Octiron::Transmogrifiers)
80
+ end.not_to raise_error
81
+
82
+ expect(reg.default_namespace).to eql 'Octiron::Transmogrifiers'
83
+ end
84
+ end
85
+
86
+ describe "registration" do
87
+ before :each do
88
+ @reg = ::Octiron::Transmogrifiers::Registry.new
89
+ end
90
+
91
+ it "can register a transmogrifier object" do
92
+ expect do
93
+ @reg.register(Test1, Test2, false, Transmogrifier.new)
94
+ end.not_to raise_error
95
+ end
96
+
97
+ it "throws when registering a transmogrifier for the same pair twice" do
98
+ expect do
99
+ @reg.register(Test1, Test2, false, Transmogrifier.new)
100
+ end.not_to raise_error
101
+
102
+ expect do
103
+ @reg.register(Test1, Test2, false, Transmogrifier.new)
104
+ end.to raise_error(ArgumentError)
105
+ end
106
+
107
+ it "can overwrite transmogrifiers" do
108
+ expect do
109
+ @reg.register(Test1, Test2, false, Transmogrifier.new)
110
+ end.not_to raise_error
111
+
112
+ expect do
113
+ @reg.register(Test1, Test2, true, Transmogrifier.new)
114
+ end.not_to raise_error
115
+ end
116
+
117
+ it "can register transmogrifier procs" do
118
+ expect do
119
+ @reg.register(Test1, Test2) do |_|
120
+ end
121
+ end.not_to raise_error
122
+ end
123
+
124
+ it "raises if no transmogrifier is given" do
125
+ expect do
126
+ @reg.register(Test1, Test2)
127
+ end.to raise_error(ArgumentError)
128
+
129
+ expect do
130
+ @reg.register(Test1, Test2, false)
131
+ end.to raise_error(ArgumentError)
132
+ end
133
+
134
+ it "can deregister a transmogrifier" do
135
+ expect do
136
+ @reg.register(Test1, Test2) do |_|
137
+ end
138
+ end.not_to raise_error
139
+
140
+ # First time, there is a transmogrifier
141
+ expect do
142
+ @reg.deregister(Test1, Test2)
143
+ end.not_to raise_error
144
+
145
+ # Second time, there is none - it still shouldn't fail
146
+ expect do
147
+ @reg.deregister(Test1, Test2)
148
+ end.not_to raise_error
149
+ end
150
+ end
151
+
152
+ describe "register argument validation" do
153
+ before :each do
154
+ @reg = ::Octiron::Transmogrifiers::Registry.new
155
+ end
156
+
157
+ it "accepts string names" do
158
+ expect do
159
+ @reg.register('Test1', 'Test2', false, Transmogrifier.new)
160
+ end.not_to raise_error
161
+ end
162
+
163
+ it "accepts symbol names" do
164
+ expect do
165
+ @reg.register(:test1, :test2, false, Transmogrifier.new)
166
+ end.not_to raise_error
167
+ end
168
+
169
+ it "accepts hash prototypes" do
170
+ proto1 = {
171
+ a: nil,
172
+ b: {
173
+ c: 42,
174
+ },
175
+ }
176
+ proto2 = {
177
+ a: nil,
178
+ b_c: nil,
179
+ }
180
+
181
+ expect do
182
+ @reg.register(proto1, proto2, false, Transmogrifier.new)
183
+ end.not_to raise_error
184
+ end
185
+ end
186
+
187
+ describe "transmogrification" do
188
+ before :each do
189
+ @reg = ::Octiron::Transmogrifiers::Registry.new
190
+ @trans1to2 = Test1To2Transmogrifier.new
191
+ @trans2to3 = Test2To3Transmogrifier.new
192
+ @reg.register(Test1, Test2, false, @trans1to2)
193
+ @reg.register(Test2, Test3, false, @trans2to3)
194
+ end
195
+
196
+ it "can transmogrify with a directly registered transmogrifier" do
197
+ result = nil
198
+
199
+ expect do
200
+ result = @reg.transmogrify(Test1.new, Test2)
201
+ end.not_to raise_error
202
+
203
+ expect(result.class).to eql Test2
204
+
205
+ expect(@trans1to2.invoked).to eql 1
206
+ expect(@trans2to3.invoked).to eql 0
207
+ end
208
+
209
+ it "can transmogrify with indirectly registered transmogrifiers" do
210
+ result = nil
211
+
212
+ expect do
213
+ result = @reg.transmogrify(Test1.new, Test3)
214
+ end.not_to raise_error
215
+
216
+ expect(result.class).to eql Test3
217
+
218
+ expect(@trans1to2.invoked).to eql 1
219
+ expect(@trans2to3.invoked).to eql 1
220
+ end
221
+
222
+ it "chooses the shortest transmogrification path" do
223
+ result = nil
224
+
225
+ direct = Test1To3Transmogrifier.new
226
+ @reg.register(Test1, Test3, false, direct)
227
+
228
+ expect do
229
+ result = @reg.transmogrify(Test1.new, Test3)
230
+ end.not_to raise_error
231
+
232
+ expect(result.class).to eql Test3
233
+
234
+ expect(@trans1to2.invoked).to eql 0
235
+ expect(@trans2to3.invoked).to eql 0
236
+ expect(direct.invoked).to eql 1
237
+ end
238
+
239
+ it "fails if no transmogrifier is found" do
240
+ expect do
241
+ @reg.transmogrify(Test1.new, Hash)
242
+ end.to raise_error(ArgumentError)
243
+ end
244
+
245
+ it "fails if a transmogrifier misbehaves" do
246
+ # Register the wrong 'direct' transmogrifier that will then be chosen
247
+ direct = Test1To2Transmogrifier.new
248
+ @reg.register(Test1, Test3, false, direct)
249
+
250
+ expect do
251
+ @reg.transmogrify(Test1.new, Test3)
252
+ end.to raise_error(RuntimeError)
253
+ end
254
+
255
+ it "transmogrifies hashes" do
256
+ proto1 = {
257
+ a: nil,
258
+ b: {
259
+ c: 42,
260
+ },
261
+ }
262
+ proto2 = {
263
+ a: nil,
264
+ b_c: nil,
265
+ }
266
+
267
+ @reg.register(proto1, proto2, false, HashTransmogrifier.new)
268
+
269
+ from = {
270
+ a: 'foo',
271
+ b: {
272
+ c: 42,
273
+ },
274
+ }
275
+
276
+ result = nil
277
+ expect do
278
+ result = @reg.transmogrify(from, proto2)
279
+ end.not_to raise_error
280
+
281
+ expect(result[:a]).to eql 'foo'
282
+ expect(result[:b_c]).to eql 42
283
+ end
284
+
285
+ it "throws if a hash transmogrifier produces bad results" do
286
+ proto1 = {
287
+ a: nil,
288
+ b: {
289
+ c: 42,
290
+ },
291
+ }
292
+ proto2 = {
293
+ a: nil,
294
+ b_c: nil,
295
+ }
296
+
297
+ @reg.register(proto1, proto2, false, HashTransmogrifier.new(true))
298
+
299
+ from = {
300
+ a: 'foo',
301
+ b: {
302
+ c: 42,
303
+ },
304
+ }
305
+
306
+ expect do
307
+ @reg.transmogrify(from, proto2)
308
+ end.to raise_error(RuntimeError)
309
+ end
310
+ end
311
+ end