hash_engine 0.3.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,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