hash_engine 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,144 @@
1
+ require 'hash_engine'
2
+
3
+ describe HashEngine do
4
+ describe 'extract' do
5
+ describe 'should return errors' do
6
+ it 'when instructions is empty' do
7
+ HashEngine.extract(nil, {}).should ==
8
+ {:error => ['Missing instructions']}
9
+ end
10
+
11
+ it 'when instructions are nil' do
12
+ HashEngine.extract(nil, nil).should ==
13
+ {:error => ['Missing instructions']}
14
+ end
15
+
16
+ it 'when object is mil' do
17
+ HashEngine.extract(nil, {'person' => 'person'}).should ==
18
+ {:error => ['Missing object(s)']}
19
+ end
20
+
21
+ it 'when number of objects dont match instructions' do
22
+ objects = mock 'Person'
23
+ instructions = {'person' => 'person', 'company' => 'company'}
24
+ HashEngine.extract(objects, instructions).should ==
25
+ {:error => ['Instructions given for company, person but only 1 object given']}
26
+ end
27
+
28
+ it 'when instructions wants a missing object' do
29
+ objects = {'person' => 'person', 'address' => 'address'}
30
+ instructions = {'person' => 'person', 'company' => 'company'}
31
+ HashEngine.extract(objects, instructions).should ==
32
+ {:error => ['Missing object(s): company']}
33
+ end
34
+ end
35
+
36
+ describe 'return values' do
37
+ before :each do
38
+ @instructions = {'person' => {'first_name' => nil,
39
+ 'name' => nil,
40
+ 'military' => nil,
41
+ 'dob' => {'method' => 'date_of_birth'}
42
+ }
43
+ }
44
+ @person = mock 'Person', :first_name => 'Mark',
45
+ # :name => 'Mark',
46
+ :military? => false,
47
+ :date_of_birth => Time.at(0)
48
+ @output = HashEngine.extract(@person,@instructions)
49
+ end
50
+
51
+ it 'should get "Mark" for first_name' do
52
+ @output['first_name'].should == 'Mark'
53
+ end
54
+
55
+ it 'should get "false" for military' do
56
+ @output['military'].should == false
57
+ end
58
+
59
+ it 'should get "" for dob' do
60
+ @output['dob'].should == Time.at(0)
61
+ end
62
+
63
+ it 'should not have name' do
64
+ @output['name'].should == nil
65
+ @output.has_key?('name').should == false
66
+ end
67
+
68
+ it 'should have error for missing name' do
69
+ @output[:error].should == ["person does not respond to any of: name, name?"]
70
+ end
71
+ end
72
+ end
73
+
74
+
75
+ it 'fetch_objects'
76
+
77
+ describe 'fetch_attributes' do
78
+ it 'should check each field'
79
+ it 'should not fetch_value for reserved keys'
80
+ end
81
+
82
+ describe 'fetch_value' do
83
+ it 'should call a method on the object'
84
+ it 'should add an error if the object doesnt respond to the method'
85
+ end
86
+
87
+ describe 'set_result_or_recurse' do
88
+ it 'should set result'
89
+ it 'should append error'
90
+ it 'should recurse'
91
+ end
92
+
93
+ describe 'fetch_method_array' do
94
+ it 'should return 3 elements' do
95
+ HashEngine.fetch_method_array('field', {'method' => 'other_field'}).should == ['other_field', 'field', 'field?']
96
+ end
97
+
98
+ it 'should return 2 elements' do
99
+ HashEngine.fetch_method_array('field', nil).should == ['field', 'field?']
100
+ end
101
+ end
102
+
103
+ describe 'fetch_method' do
104
+ it 'should return method' do
105
+ object = mock 'Object', :other_field => :foo
106
+ HashEngine.fetch_method(object, 'field', {'method' => 'other_field'}).should == 'other_field'
107
+ end
108
+
109
+ it 'should return field' do
110
+ object = mock 'Object', :field => :foo
111
+ HashEngine.fetch_method(object, 'field', nil).should == 'field'
112
+ end
113
+
114
+ it 'should return field?' do
115
+ object = mock 'Object', :field? => :foo
116
+ HashEngine.fetch_method(object, 'field', nil).should == 'field?'
117
+ end
118
+
119
+ it 'should return nil' do
120
+ object = mock 'Object', :other_field => :foo
121
+ HashEngine.fetch_method(object, 'field', nil).should == nil
122
+ end
123
+ end
124
+
125
+ describe 'fetch_method_args' do
126
+ it 'should return [] when no field_instructions' do
127
+ HashEngine.fetch_method_args(nil, nil).should == []
128
+ end
129
+
130
+ it 'should return [] when no args' do
131
+ HashEngine.fetch_method_args(nil, {'method' => 'foo'}).should == []
132
+ end
133
+
134
+ it 'should return args unmodified if already an array' do
135
+ HashEngine.fetch_method_args(nil, {'method_args' => ['foo']}).should == ['foo']
136
+ end
137
+
138
+ it 'should convert to an array' do
139
+ HashEngine.fetch_method_args(nil, {'method_args' => 'foo'}).should == ['foo']
140
+ end
141
+ end
142
+
143
+ it 'append_error_for_required_fields'
144
+ end
@@ -0,0 +1,30 @@
1
+ require 'hash_engine'
2
+
3
+ describe HashEngine do
4
+ describe 'valid_fetcher?' do
5
+ it 'returns true when key exists' do
6
+ HashEngine.valid_fetcher?('input').should be_true
7
+ end
8
+
9
+ it 'returns false when key does not exist' do
10
+ HashEngine.valid_fetcher?('foo').should be_false
11
+ end
12
+ end
13
+
14
+ describe 'fetcher' do
15
+ it 'returns the input field from customer_data' do
16
+ HashEngine.fetcher('input', 'foo', {'foo' => 'bar'}).should == 'bar'
17
+ end
18
+
19
+ it 'returns the literal' do
20
+ HashEngine.fetcher('literal', 'foo', {'foo' => 'bar'}).should == 'foo'
21
+ end
22
+
23
+ it 'returns multiple data fields' do
24
+ customer_data = {:field1 => :value1, :field2 => :value2}
25
+ field_data = [:field1, :field2]
26
+ expected = [:value1, :value2]
27
+ HashEngine.fetcher('data', field_data, customer_data).should == expected
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+ require 'hash_engine'
3
+
4
+ describe HashEngine do
5
+ describe 'format' do
6
+ # data, format_type, output
7
+ [['sample', 'string', 'sample'],
8
+ [' sample', 'string', 'sample'],
9
+ ['sample ', 'string', 'sample'],
10
+ [' sample ', 'string', 'sample'],
11
+ [55, 'string', '55'],
12
+ [:sample, 'string', 'sample'],
13
+ ['sample', 'first', 's'],
14
+ ['ÑAlaman', 'first', 'Ñ'],
15
+ [55, 'first', '5'],
16
+ ['sample', 'alphanumeric', 'sample'],
17
+ ['s_a+m=p%l-e', 'alphanumeric', 'sample'],
18
+ [55, 'alphanumeric', '55'],
19
+ ['sample', 'no_whitespace', 'sample'],
20
+ ['sam-ple', 'no_whitespace', 'sam-ple'],
21
+ ['s_a+m=p%le', 'no_whitespace', 'sample'],
22
+ [55, 'no_whitespace', '55'],
23
+ ['123sample', 'alpha', 'sample'],
24
+ ['s_a45m=p%l-e', 'alpha', 'sample'],
25
+ ['123sample', 'numeric', '123'],
26
+ ['682-59-7267', 'numeric', '682597267'],
27
+ ['ext 99', 'numeric', '99'],
28
+ ['2000.99', 'float', 2000.99],
29
+ ['sample', 'integer', 0],
30
+ ['123sample', 'integer', 123],
31
+ [55, 'integer', 55],
32
+ [true, 'integer', 1],
33
+ [false, 'integer', 0],
34
+ [nil, 'integer', 0],
35
+ [Date.parse('2009-07-14'), {'strftime'=>"%Y-%m-%d"}, '2009-07-14'],
36
+ ['2009-07-14', 'date', Date.parse('2009-07-14')],
37
+ ['true', 'boolean', true],
38
+ ['TrUe', 'boolean', true],
39
+ ['t', 'boolean', true],
40
+ ['T', 'boolean', true],
41
+ [1, 'boolean', true],
42
+ ['yes', 'boolean', true],
43
+ ['Y', 'boolean', true],
44
+ [2, 'boolean', false],
45
+ ['false', 'boolean', false],
46
+ ['no', 'boolean', false],
47
+ ['sample', 'gibberish', 'sample'],
48
+ ['sample', nil, 'sample']
49
+ ].each {|data, format_type, output|
50
+ it "#{data.class} #{data.inspect} should be cast as #{format_type} #{output.inspect}" do
51
+ HashEngine.action('format', format_type, data).should == output
52
+ end
53
+ }
54
+ end
55
+ end
@@ -0,0 +1,365 @@
1
+ require 'hash_engine'
2
+ require 'yaml'
3
+
4
+ describe HashEngine do
5
+ describe 'nil_check' do
6
+ it { HashEngine.nil_check({'allow_nil' => false}, nil).should be_true }
7
+ it { HashEngine.nil_check({'allow_nil' => true}, nil).should be_false }
8
+ it { HashEngine.nil_check({'allow_nil' => false}, :ll).should be_false }
9
+ end
10
+
11
+ describe 'blank_check' do
12
+ it { HashEngine.blank_check({'allow_blank' => false}, '').should be_true }
13
+ it { HashEngine.blank_check({'allow_blank' => false}, ' ').should be_true }
14
+ it { HashEngine.blank_check({'allow_blank' => true}, '').should be_false }
15
+ it { HashEngine.blank_check({'allow_blank' => false}, 'string').should be_false }
16
+ end
17
+
18
+ describe 'required_check' do
19
+ it { HashEngine.required_check({'optional' => true}).should be_false }
20
+ it { HashEngine.required_check({}).should be_true }
21
+ it { HashEngine.required_check({'optional' => false}).should be_true }
22
+ end
23
+
24
+ describe 'suppress_nil' do
25
+ it { HashEngine.suppress_nil({'suppress_nil' => true}, nil).should be_true }
26
+ it { HashEngine.suppress_nil({'suppress_nil' => false}, nil).should be_false }
27
+ it { HashEngine.suppress_nil({'suppress_nil' => true}, :ll).should be_false }
28
+ end
29
+
30
+ describe 'suppress_blank' do
31
+ it { HashEngine.suppress_blank({'suppress_blank' => true}, '').should be_true }
32
+ it { HashEngine.suppress_blank({'suppress_blank' => true}, ' ').should be_true }
33
+ it { HashEngine.suppress_blank({'suppress_blank' => false}, '').should be_false }
34
+ it { HashEngine.suppress_blank({'suppress_blank' => true}, 'string').should be_false }
35
+ end
36
+
37
+ it 'default_or_supress'
38
+
39
+ it 'transform'
40
+
41
+ it 'simple_instructions'
42
+
43
+ describe 'concat' do
44
+ it 'returns arg2 if arg1 is nil' do
45
+ HashEngine.concat(nil, :arg).should == :arg
46
+ end
47
+
48
+ it 'combines arg1 + arg2 when both are arrays' do
49
+ arg1 = [:arg1_1, :arg1_2]
50
+ arg2 = [:arg2_1, :arg2_2]
51
+ HashEngine.concat(arg1, arg2).should == [:arg1_1, :arg1_2, :arg2_1, :arg2_2]
52
+ end
53
+
54
+ it 'adds arg2 to the end when arg1 is an array' do
55
+ arg1 = [:arg1_1, :arg1_2]
56
+ HashEngine.concat(arg1, :arg2).should == [:arg1_1, :arg1_2, :arg2]
57
+ end
58
+
59
+ it 'puts arg1 at the front when arg2 is an array' do
60
+ arg2 = [:arg2_1, :arg2_2]
61
+ HashEngine.concat(:arg1, arg2).should == [:arg1, :arg2_1, :arg2_2]
62
+ end
63
+
64
+ it 'creates an array when niether arg1 or arg2 is' do
65
+ HashEngine.concat(:arg1, :arg2).should == [:arg1, :arg2]
66
+ end
67
+ end
68
+
69
+ it 'process_instructions'
70
+
71
+ it 'get_value'
72
+
73
+ # output_2:
74
+ # conditional_input:
75
+ # left_operand
76
+ # input: data_key_1
77
+ # operator: eq
78
+ # right_operand:
79
+ # input: data_key_4
80
+ # true_instructions:
81
+ # data:
82
+ # - data_key_2
83
+ # - data_key_3
84
+ # join: '#'
85
+ # false_instructions:
86
+ # data:
87
+ # - data_key_1
88
+ # - data_key_4
89
+ # join: '#'
90
+ # When data_value_1 is the same as data_value_4 the result would be => data_value_2#data_value_3
91
+ # When data_value_1 is not the same as data_value_4 the result would be => data_value_1#data_value_4
92
+ describe 'conditional_eval' do
93
+ let(:data) do
94
+ {'data_key_1' => 'data_value_1',
95
+ 'data_key_2' => 'data_value_2',
96
+ 'data_key_3' => 'data_value_3',
97
+ 'data_key_4' => 'data_value_4',
98
+ 'data_key_5' => 'data_value_5'}
99
+ end
100
+
101
+ context 'specified in an array' do
102
+ it 'handles trivial case' do
103
+ yaml =<<EOYAML
104
+ fields:
105
+ status:
106
+ - conditional_eval:
107
+ left_operand:
108
+ input: data_key_1
109
+ operator: eq
110
+ right_operand:
111
+ input: data_key_4
112
+ true_instructions:
113
+ input: data_key_2
114
+ false_instructions:
115
+ input: data_key_3
116
+ EOYAML
117
+ instructions = YAML.load yaml
118
+ results = HashEngine.transform(data, instructions)
119
+ results[:error].should == []
120
+ results['status'].should == 'data_value_3'
121
+ end
122
+
123
+ it 'handles complex operand' do
124
+ yaml =<<EOYAML
125
+ fields:
126
+ status:
127
+ - conditional_eval:
128
+ left_operand:
129
+ data:
130
+ - data_key_2
131
+ - data_key_3
132
+ join: '#'
133
+ operator: eq
134
+ right_operand:
135
+ input: data_key_4
136
+ true_instructions:
137
+ input: data_key_2
138
+ false_instructions:
139
+ input: data_key_3
140
+ EOYAML
141
+ instructions = YAML.load yaml
142
+ results = HashEngine.transform(data, instructions)
143
+ results[:error].should == []
144
+ results['status'].should == 'data_value_3'
145
+ end
146
+
147
+ it 'handles complex result instructions' do
148
+ yaml =<<EOYAML
149
+ fields:
150
+ status:
151
+ - conditional_eval:
152
+ left_operand:
153
+ input: data_key_1
154
+ operator: eq
155
+ right_operand:
156
+ input: data_key_4
157
+ true_instructions:
158
+ data:
159
+ - data_key_2
160
+ - data_key_3
161
+ join: '#'
162
+ false_instructions:
163
+ data:
164
+ - data_key_1
165
+ - data_key_4
166
+ join: '#'
167
+ EOYAML
168
+ instructions = YAML.load yaml
169
+ results = HashEngine.transform(data, instructions)
170
+ results[:error].should == []
171
+ results['status'].should == 'data_value_1#data_value_4'
172
+ end
173
+ end
174
+
175
+ context 'specified in a hash' do
176
+ it 'handles trivial case' do
177
+ yaml =<<EOYAML
178
+ fields:
179
+ status:
180
+ conditional_eval:
181
+ left_operand:
182
+ input: data_key_1
183
+ operator: eq
184
+ right_operand:
185
+ input: data_key_4
186
+ true_instructions:
187
+ input: data_key_2
188
+ false_instructions:
189
+ input: data_key_3
190
+ EOYAML
191
+ instructions = YAML.load yaml
192
+ results = HashEngine.transform(data, instructions)
193
+ results[:error].should == []
194
+ results['status'].should == 'data_value_3'
195
+ end
196
+
197
+ it 'handles complex operand' do
198
+ yaml =<<EOYAML
199
+ fields:
200
+ status:
201
+ conditional_eval:
202
+ left_operand:
203
+ data:
204
+ - data_key_2
205
+ - data_key_3
206
+ join: '#'
207
+ operator: eq
208
+ right_operand:
209
+ input: data_key_4
210
+ true_instructions:
211
+ input: data_key_2
212
+ false_instructions:
213
+ input: data_key_3
214
+ EOYAML
215
+ instructions = YAML.load yaml
216
+ results = HashEngine.transform(data, instructions)
217
+ results[:error].should == []
218
+ results['status'].should == 'data_value_3'
219
+ end
220
+
221
+ it 'handles complex result instructions' do
222
+ yaml =<<EOYAML
223
+ fields:
224
+ status:
225
+ conditional_eval:
226
+ left_operand:
227
+ input: data_key_1
228
+ operator: eq
229
+ right_operand:
230
+ input: data_key_4
231
+ true_instructions:
232
+ data:
233
+ - data_key_2
234
+ - data_key_3
235
+ join: '#'
236
+ false_instructions:
237
+ data:
238
+ - data_key_1
239
+ - data_key_4
240
+ join: '#'
241
+ EOYAML
242
+ instructions = YAML.load yaml
243
+ results = HashEngine.transform(data, instructions)
244
+ results[:error].should == []
245
+ results['status'].should == 'data_value_1#data_value_4'
246
+ end
247
+ end
248
+ end
249
+
250
+ describe 'transformation' do
251
+ let(:data) do
252
+ {'vendor_status' => 'ok',
253
+ 'vendor_payload' => 'http://www.domain.com',
254
+ 'vendor_uuid' => '1234ABCD'}
255
+ end
256
+
257
+ it 'trivial case' do
258
+ yaml =<<EOYAML
259
+ fields:
260
+ payload: vendor_payload
261
+ EOYAML
262
+ instructions = YAML.load yaml
263
+ results = HashEngine.transform(data, instructions)
264
+ results[:error].should be_empty
265
+ results['payload'].should == 'http://www.domain.com'
266
+ end
267
+
268
+ it 'simple case' do
269
+ yaml =<<EOYAML
270
+ fields:
271
+ payload:
272
+ input: vendor_payload
273
+ EOYAML
274
+ instructions = YAML.load yaml
275
+ results = HashEngine.transform(data, instructions)
276
+ results[:error].should be_empty
277
+ results['payload'].should == 'http://www.domain.com'
278
+ end
279
+
280
+ it 'simple formatting' do
281
+ yaml =<<EOYAML
282
+ fields:
283
+ uuid:
284
+ input: vendor_uuid
285
+ format: numeric
286
+ EOYAML
287
+ instructions = YAML.load yaml
288
+ results = HashEngine.transform(data, instructions)
289
+ results[:error].should be_empty
290
+ results['uuid'].should == '1234'
291
+ end
292
+
293
+ it 'lookup map case' do
294
+ yaml =<<EOYAML
295
+ fields:
296
+ status:
297
+ input: vendor_status
298
+ lookup_map:
299
+ ok: accepted
300
+ decline: reject
301
+ default: error
302
+ EOYAML
303
+ instructions = YAML.load yaml
304
+ results = HashEngine.transform(data, instructions)
305
+ results[:error].should be_empty
306
+ results['status'].should == 'accepted'
307
+ end
308
+
309
+ it 'copied source case' do
310
+ yaml =<<EOYAML
311
+ copy_source: true
312
+ fields:
313
+ status:
314
+ input: vendor_status
315
+ lookup_map:
316
+ ok: accepted
317
+ decline: reject
318
+ default: error
319
+ EOYAML
320
+ instructions = YAML.load yaml
321
+ results = HashEngine.transform(data, instructions)
322
+ expected = {'vendor_status' => 'ok',
323
+ 'vendor_payload' => 'http://www.domain.com',
324
+ 'vendor_uuid' => '1234ABCD',
325
+ :error => [],
326
+ 'status' => 'accepted'}
327
+ results.should == expected
328
+ end
329
+
330
+ it 'multiple data case' do
331
+ yaml =<<EOYAML
332
+ fields:
333
+ status:
334
+ - input: vendor_status
335
+ - data:
336
+ - vendor_status
337
+ - vendor_status
338
+ - join: ', '
339
+ EOYAML
340
+ instructions = YAML.load yaml
341
+ results = HashEngine.transform(data, instructions)
342
+ results[:error].should be_empty
343
+ results['status'].should == 'ok, ok, ok'
344
+ end
345
+
346
+ it 'multiple data case with an action in the middle' do
347
+ yaml =<<EOYAML
348
+ fields:
349
+ status:
350
+ - input: vendor_status
351
+ - subgroup:
352
+ input: vendor_status
353
+ lookup_map:
354
+ ok: accepted
355
+ decline: reject
356
+ default: error
357
+ - join: ', '
358
+ EOYAML
359
+ instructions = YAML.load yaml
360
+ results = HashEngine.transform(data, instructions)
361
+ results[:error].should be_empty
362
+ results['status'].should == 'ok, accepted'
363
+ end
364
+ end
365
+ end