openc_bot 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.travis.yml +8 -0
  4. data/CHANGELOG.md +2 -0
  5. data/Gemfile +8 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +253 -0
  8. data/Rakefile +14 -0
  9. data/bin/openc_bot +13 -0
  10. data/create_bot.sh +30 -0
  11. data/create_company_bot.sh +16 -0
  12. data/create_simple_licence_bot.sh +31 -0
  13. data/db/.gitkeep +0 -0
  14. data/examples/basic/.gitignore +3 -0
  15. data/examples/basic/Gemfile +7 -0
  16. data/examples/basic/config.yml +21 -0
  17. data/examples/basic/lib/basic.rb +88 -0
  18. data/examples/basic_with_proxy/Gemfile +7 -0
  19. data/examples/basic_with_proxy/config.yml +21 -0
  20. data/examples/basic_with_proxy/lib/basic_with_proxy.rb +103 -0
  21. data/examples/bot_with_simple_iterator/Gemfile +6 -0
  22. data/examples/bot_with_simple_iterator/config.yml +21 -0
  23. data/examples/bot_with_simple_iterator/lib/bot_with_simple_iterator.rb +112 -0
  24. data/examples/company_fetchers/basic.rb +49 -0
  25. data/lib/monkey_patches/mechanize.rb +53 -0
  26. data/lib/openc_bot.rb +89 -0
  27. data/lib/openc_bot/bot_data_validator.rb +18 -0
  28. data/lib/openc_bot/company_fetcher_bot.rb +40 -0
  29. data/lib/openc_bot/exceptions.rb +17 -0
  30. data/lib/openc_bot/helpers/_csv.rb +10 -0
  31. data/lib/openc_bot/helpers/alpha_search.rb +73 -0
  32. data/lib/openc_bot/helpers/dates.rb +33 -0
  33. data/lib/openc_bot/helpers/html.rb +8 -0
  34. data/lib/openc_bot/helpers/incremental_search.rb +106 -0
  35. data/lib/openc_bot/helpers/register_methods.rb +205 -0
  36. data/lib/openc_bot/helpers/text.rb +18 -0
  37. data/lib/openc_bot/incrementers.rb +2 -0
  38. data/lib/openc_bot/incrementers/base.rb +214 -0
  39. data/lib/openc_bot/incrementers/common.rb +47 -0
  40. data/lib/openc_bot/tasks.rb +385 -0
  41. data/lib/openc_bot/templates/README.md +35 -0
  42. data/lib/openc_bot/templates/bin/export_data +28 -0
  43. data/lib/openc_bot/templates/bin/fetch_data +23 -0
  44. data/lib/openc_bot/templates/bin/verify_data +1 -0
  45. data/lib/openc_bot/templates/config.yml +21 -0
  46. data/lib/openc_bot/templates/lib/bot.rb +43 -0
  47. data/lib/openc_bot/templates/lib/company_fetcher_bot.rb +95 -0
  48. data/lib/openc_bot/templates/lib/simple_bot.rb +67 -0
  49. data/lib/openc_bot/templates/spec/bot_spec.rb +11 -0
  50. data/lib/openc_bot/templates/spec/simple_bot_spec.rb +11 -0
  51. data/lib/openc_bot/templates/spec/spec_helper.rb +13 -0
  52. data/lib/openc_bot/version.rb +3 -0
  53. data/lib/simple_openc_bot.rb +289 -0
  54. data/openc_bot.gemspec +35 -0
  55. data/schemas/company-schema.json +112 -0
  56. data/schemas/includes/address.json +23 -0
  57. data/schemas/includes/base-statement.json +27 -0
  58. data/schemas/includes/company.json +14 -0
  59. data/schemas/includes/filing.json +20 -0
  60. data/schemas/includes/license-data.json +27 -0
  61. data/schemas/includes/officer.json +14 -0
  62. data/schemas/includes/previous_name.json +11 -0
  63. data/schemas/includes/share-parcel-data.json +67 -0
  64. data/schemas/includes/share-parcel.json +60 -0
  65. data/schemas/includes/subsidiary-relationship-data.json +52 -0
  66. data/schemas/includes/total-shares.json +10 -0
  67. data/schemas/licence-schema.json +21 -0
  68. data/schemas/share-parcel-schema.json +21 -0
  69. data/schemas/subsidiary-relationship-schema.json +19 -0
  70. data/spec/dummy_classes/foo_bot.rb +4 -0
  71. data/spec/lib/bot_data_validator_spec.rb +69 -0
  72. data/spec/lib/company_fetcher_bot_spec.rb +93 -0
  73. data/spec/lib/exceptions_spec.rb +25 -0
  74. data/spec/lib/helpers/alpha_search_spec.rb +173 -0
  75. data/spec/lib/helpers/dates_spec.rb +65 -0
  76. data/spec/lib/helpers/incremental_search_spec.rb +471 -0
  77. data/spec/lib/helpers/register_methods_spec.rb +558 -0
  78. data/spec/lib/helpers/text_spec.rb +50 -0
  79. data/spec/lib/openc_bot/db/.gitkeep +0 -0
  80. data/spec/lib/openc_bot/incrementers/common_spec.rb +83 -0
  81. data/spec/lib/openc_bot_spec.rb +116 -0
  82. data/spec/schemas/company-schema_spec.rb +676 -0
  83. data/spec/simple_openc_bot_spec.rb +302 -0
  84. data/spec/spec_helper.rb +19 -0
  85. metadata +300 -0
@@ -0,0 +1,558 @@
1
+ # encoding: UTF-8
2
+ require_relative '../../spec_helper'
3
+ require 'openc_bot'
4
+ require 'openc_bot/helpers/register_methods'
5
+
6
+ module ModuleThatIncludesRegisterMethods
7
+ extend OpencBot
8
+ extend OpencBot::Helpers::RegisterMethods
9
+ PRIMARY_KEY_NAME = :custom_uid
10
+ SCHEMA_NAME = 'company-schema'
11
+ end
12
+
13
+ module ModuleWithNoCustomPrimaryKey
14
+ extend OpencBot
15
+ extend OpencBot::Helpers::RegisterMethods
16
+ end
17
+
18
+ describe 'a module that includes RegisterMethods' do
19
+
20
+ before do
21
+ ModuleThatIncludesRegisterMethods.stub(:sqlite_magic_connection).
22
+ and_return(test_database_connection)
23
+ end
24
+
25
+ after do
26
+ remove_test_database
27
+ end
28
+
29
+ describe "#datum_exists?" do
30
+ before do
31
+ ModuleThatIncludesRegisterMethods.stub(:select).and_return([])
32
+
33
+ end
34
+
35
+ it "should select_data from database" do
36
+ expected_sql_query = "ocdata.custom_uid FROM ocdata WHERE custom_uid = ? LIMIT 1"
37
+ ModuleThatIncludesRegisterMethods.should_receive(:select).with(expected_sql_query, '4567').and_return([])
38
+ ModuleThatIncludesRegisterMethods.datum_exists?('4567')
39
+ end
40
+
41
+ it "should return true if result returned" do
42
+ ModuleThatIncludesRegisterMethods.stub(:select).and_return([{'custom_uid' => '4567'}])
43
+
44
+ ModuleThatIncludesRegisterMethods.datum_exists?('4567').should be_true
45
+ end
46
+
47
+ it "should return false if result returned" do
48
+ ModuleThatIncludesRegisterMethods.datum_exists?('4567').should be_false
49
+ end
50
+ end
51
+
52
+ describe "#export_data" do
53
+ before do
54
+ ModuleThatIncludesRegisterMethods.stub(:select).and_return([])
55
+
56
+ end
57
+
58
+ it "should select_data from database" do
59
+ expected_sql_query = "ocdata.* from ocdata"
60
+ ModuleThatIncludesRegisterMethods.should_receive(:select).with(expected_sql_query).and_return([])
61
+ ModuleThatIncludesRegisterMethods.export_data
62
+ end
63
+
64
+ it "should yield rows that have been passed to post_process" do
65
+ datum = {'food' => 'tofu'}
66
+ ModuleThatIncludesRegisterMethods.stub(:select).and_return([datum])
67
+ ModuleThatIncludesRegisterMethods.should_receive(:post_process).with(datum, true).and_return(datum)
68
+ ModuleThatIncludesRegisterMethods.export_data{|x|}
69
+ end
70
+ end
71
+
72
+
73
+ describe '#primary_key_name' do
74
+ it 'should return :uid if PRIMARY_KEY_NAME not set' do
75
+ ModuleWithNoCustomPrimaryKey.send(:primary_key_name).should == :uid
76
+ end
77
+
78
+ it 'should return value if PRIMARY_KEY_NAME set' do
79
+ ModuleThatIncludesRegisterMethods.send(:primary_key_name).should == :custom_uid
80
+ end
81
+ end
82
+
83
+ describe "#use_alpha_search" do
84
+ context 'and no USE_ALPHA_SEARCH constant' do
85
+ it "should not return true" do
86
+ ModuleThatIncludesRegisterMethods.use_alpha_search.should_not be_true
87
+ end
88
+ end
89
+
90
+ context 'and USE_ALPHA_SEARCH constant set' do
91
+ it "should return USE_ALPHA_SEARCH" do
92
+ stub_const("ModuleThatIncludesRegisterMethods::USE_ALPHA_SEARCH", true)
93
+ ModuleThatIncludesRegisterMethods.use_alpha_search.should be_true
94
+ end
95
+ end
96
+ end
97
+
98
+ describe "#schema_name" do
99
+ context 'and no SCHEMA_NAME constant' do
100
+ it "should return nil" do
101
+ ModuleWithNoCustomPrimaryKey.schema_name.should be_nil
102
+ end
103
+ end
104
+
105
+ context 'and SCHEMA_NAME constant set' do
106
+ it "should return SCHEMA_NAME" do
107
+ ModuleThatIncludesRegisterMethods.schema_name.should == 'company-schema'
108
+ end
109
+ end
110
+ end
111
+
112
+ describe "#update_data" do
113
+ before do
114
+ ModuleThatIncludesRegisterMethods.stub(:fetch_data_via_incremental_search)
115
+ ModuleThatIncludesRegisterMethods.stub(:update_stale)
116
+ end
117
+
118
+ it "should get new records via incremental search" do
119
+ ModuleThatIncludesRegisterMethods.should_not_receive(:fetch_data_via_alpha_search)
120
+ ModuleThatIncludesRegisterMethods.should_receive(:fetch_data_via_incremental_search)
121
+ ModuleThatIncludesRegisterMethods.update_data
122
+ end
123
+
124
+ it "should get new records via alpha search if use_alpha_search" do
125
+ ModuleThatIncludesRegisterMethods.should_receive(:use_alpha_search).and_return(true)
126
+ ModuleThatIncludesRegisterMethods.should_not_receive(:fetch_data_via_incremental_search)
127
+ ModuleThatIncludesRegisterMethods.should_receive(:fetch_data_via_alpha_search)
128
+ ModuleThatIncludesRegisterMethods.update_data
129
+ end
130
+
131
+ it "should update stale records" do
132
+ ModuleThatIncludesRegisterMethods.should_receive(:update_stale)
133
+ ModuleThatIncludesRegisterMethods.update_data
134
+ end
135
+
136
+ it "should save run report" do
137
+ ModuleThatIncludesRegisterMethods.should_receive(:save_run_report).with(:status => 'success')
138
+ ModuleThatIncludesRegisterMethods.update_data
139
+ end
140
+
141
+ it "should not raise error if passed options" do
142
+ lambda { ModuleThatIncludesRegisterMethods.update_data }.should_not raise_error
143
+ end
144
+ end
145
+
146
+ describe "#update_stale" do
147
+ it "should get uids of stale entries" do
148
+ ModuleThatIncludesRegisterMethods.should_receive(:stale_entry_uids)
149
+ ModuleThatIncludesRegisterMethods.update_stale
150
+ end
151
+
152
+ it "should update_datum for each entry yielded by stale_entries" do
153
+ ModuleThatIncludesRegisterMethods.stub(:stale_entry_uids).and_yield('234').and_yield('666').and_yield('876')
154
+ ModuleThatIncludesRegisterMethods.should_receive(:update_datum).with('234')
155
+ ModuleThatIncludesRegisterMethods.should_receive(:update_datum).with('666')
156
+ ModuleThatIncludesRegisterMethods.should_receive(:update_datum).with('876')
157
+ ModuleThatIncludesRegisterMethods.update_stale
158
+ end
159
+
160
+ context "and limit passed in" do
161
+ it "should pass on limit to #stale_entries" do
162
+ ModuleThatIncludesRegisterMethods.should_receive(:stale_entry_uids).with(42)
163
+ ModuleThatIncludesRegisterMethods.update_stale(42)
164
+ end
165
+ end
166
+ end
167
+
168
+ describe "#stale_entry_uids" do
169
+ before do
170
+ ModuleThatIncludesRegisterMethods.save_data([:custom_uid], :custom_uid => '99999')
171
+ ModuleThatIncludesRegisterMethods.save_data([:custom_uid], :custom_uid => 'A094567')
172
+ end
173
+
174
+ it "should get entries which have not been retrieved or are more than 1 month old" do
175
+ ModuleThatIncludesRegisterMethods.save_data([:custom_uid], :custom_uid => '5234888', :retrieved_at => (Date.today-40).to_time)
176
+ ModuleThatIncludesRegisterMethods.save_data([:custom_uid], :custom_uid => '9234567', :retrieved_at => (Date.today-2).to_time)
177
+
178
+ expect {|b| ModuleThatIncludesRegisterMethods.stale_entry_uids(&b)}.to yield_successive_args('99999', 'A094567', '5234888')
179
+ end
180
+
181
+ context "and no retrieved_at column" do
182
+ it "should not raise error" do
183
+ lambda { ModuleThatIncludesRegisterMethods.stale_entry_uids {} }.should_not raise_error
184
+ end
185
+
186
+ it "should create retrieved_at column" do
187
+ ModuleThatIncludesRegisterMethods.stale_entry_uids {}
188
+ ModuleThatIncludesRegisterMethods.select('* from ocdata').first.keys.should include('retrieved_at')
189
+ end
190
+
191
+ it "should retry" do
192
+ expect {|b| ModuleThatIncludesRegisterMethods.stale_entry_uids(&b)}.to yield_successive_args('99999','A094567')
193
+ end
194
+ end
195
+ end
196
+
197
+ describe '#prepare_and_save_data' do
198
+ before do
199
+ @params = {:name => 'Foo Inc', :custom_uid => '12345', :foo => ['bar','baz'], :foo2 => {:bar => 'baz'}}
200
+ end
201
+
202
+ it "should insert_or_update data using primary_key" do
203
+ ModuleThatIncludesRegisterMethods.should_receive(:insert_or_update).with([:custom_uid], anything)
204
+ ModuleThatIncludesRegisterMethods.prepare_and_save_data(@params)
205
+ end
206
+
207
+ it "should save basic data" do
208
+ ModuleThatIncludesRegisterMethods.should_receive(:insert_or_update).with(anything, hash_including(:name => 'Foo Inc', :custom_uid => '12345'))
209
+ ModuleThatIncludesRegisterMethods.prepare_and_save_data(@params)
210
+ end
211
+
212
+ it "should convert arrays and hashes to json" do
213
+ ModuleThatIncludesRegisterMethods.should_receive(:insert_or_update).with(anything, hash_including(:foo => ['bar','baz'].to_json, :foo2 => {:bar => 'baz'}.to_json))
214
+ ModuleThatIncludesRegisterMethods.prepare_and_save_data(@params)
215
+ end
216
+
217
+ it "should convert time and datetimes to iso601 version" do
218
+ some_date = Date.parse('2012-04-23')
219
+ some_time = Time.now
220
+ ModuleThatIncludesRegisterMethods.should_receive(:insert_or_update).with(anything, hash_including(:some_date => some_date.iso8601, :some_time => some_time.iso8601))
221
+ ModuleThatIncludesRegisterMethods.prepare_and_save_data(@params.merge(:some_date => some_date, :some_time => some_time))
222
+ end
223
+
224
+ it "should not change original params" do
225
+ dup_params = Marshal.load( Marshal.dump(@params) )
226
+ ModuleThatIncludesRegisterMethods.prepare_and_save_data(@params)
227
+ @params.should == dup_params
228
+ end
229
+
230
+ it "should return true" do
231
+ ModuleThatIncludesRegisterMethods.prepare_and_save_data(@params).should be_true
232
+ end
233
+ end
234
+
235
+
236
+ describe "#update_datum for uid" do
237
+ before do
238
+ @dummy_time = Time.now
239
+ @uid = '23456'
240
+ Time.stub(:now).and_return(@dummy_time)
241
+ @fetch_datum_response = 'some really useful data'
242
+ # @processed_data = ModuleThatIncludesRegisterMethods.process_datum(@fetch_datum_response)
243
+ @processed_data = {:foo => 'bar'}
244
+ ModuleThatIncludesRegisterMethods.stub(:fetch_datum).and_return(@fetch_datum_response)
245
+ ModuleThatIncludesRegisterMethods.stub(:process_datum).and_return(@processed_data)
246
+ @processed_data_with_retrieved_at_and_uid = @processed_data.merge(:custom_uid => @uid, :retrieved_at => @dummy_time)
247
+ ModuleThatIncludesRegisterMethods.stub(:save_data)
248
+ ModuleThatIncludesRegisterMethods.stub(:validate_datum).and_return([])
249
+ end
250
+
251
+ it "should fetch_datum for company number" do
252
+ ModuleThatIncludesRegisterMethods.should_receive(:fetch_datum).with(@uid).and_return(@fetch_datum_response)
253
+ ModuleThatIncludesRegisterMethods.update_datum(@uid)
254
+ end
255
+
256
+ context "and nothing returned from fetch_datum" do
257
+ before do
258
+ ModuleThatIncludesRegisterMethods.stub(:fetch_datum) # => nil
259
+ end
260
+
261
+ it "should not process_datum" do
262
+ ModuleThatIncludesRegisterMethods.should_not_receive(:process_datum)
263
+ ModuleThatIncludesRegisterMethods.update_datum(@uid)
264
+ end
265
+
266
+ it "should not save data" do
267
+ ModuleThatIncludesRegisterMethods.should_not_receive(:save_data)
268
+ ModuleThatIncludesRegisterMethods.update_datum(@uid)
269
+ end
270
+
271
+ it "should return nil" do
272
+ ModuleThatIncludesRegisterMethods.update_datum(@uid).should be_nil
273
+ end
274
+
275
+ end
276
+
277
+ context 'and data returned from fetch_datum' do
278
+ it "should process_datum returned from fetching" do
279
+ ModuleThatIncludesRegisterMethods.should_receive(:process_datum).with(@fetch_datum_response)
280
+ ModuleThatIncludesRegisterMethods.update_datum(@uid)
281
+ end
282
+
283
+ it "should validate processed data" do
284
+ ModuleThatIncludesRegisterMethods.should_receive(:validate_datum).with(hash_including(@processed_data_with_retrieved_at_and_uid)).and_call_original
285
+ ModuleThatIncludesRegisterMethods.update_datum(@uid)
286
+ end
287
+
288
+ it "should prepare processed data for saving including timestamp" do
289
+ ModuleThatIncludesRegisterMethods.should_receive(:prepare_for_saving).with(hash_including(@processed_data_with_retrieved_at_and_uid)).and_call_original
290
+ ModuleThatIncludesRegisterMethods.update_datum(@uid)
291
+ end
292
+
293
+ it "should include data in data to be prepared for saving" do
294
+ ModuleThatIncludesRegisterMethods.should_receive(:prepare_for_saving).with(hash_including(:data => @fetch_datum_response)).and_call_original
295
+ ModuleThatIncludesRegisterMethods.update_datum(@uid)
296
+ end
297
+
298
+ it "should use supplied retrieved_at in preference to default" do
299
+ different_time = (Date.today-3).iso8601
300
+ ModuleThatIncludesRegisterMethods.stub(:process_datum).
301
+ and_return(@processed_data.merge(:retrieved_at => different_time))
302
+ ModuleThatIncludesRegisterMethods.should_receive(:prepare_for_saving).
303
+ with(hash_including(:retrieved_at => different_time)).and_call_original
304
+ ModuleThatIncludesRegisterMethods.update_datum(@uid)
305
+ end
306
+
307
+ it "should save prepared_data" do
308
+ ModuleThatIncludesRegisterMethods.stub(:prepare_for_saving).and_return({:foo => 'some prepared data'})
309
+
310
+ ModuleThatIncludesRegisterMethods.should_receive(:insert_or_update).with([:custom_uid], hash_including(:foo => 'some prepared data'))
311
+ ModuleThatIncludesRegisterMethods.update_datum(@uid)
312
+ end
313
+
314
+ it "should return data including uid" do
315
+ ModuleThatIncludesRegisterMethods.update_datum(@uid).should == @processed_data_with_retrieved_at_and_uid
316
+ end
317
+
318
+ it "should not output jsonified processed data by default" do
319
+ ModuleThatIncludesRegisterMethods.should_not_receive(:puts).with(@processed_data_with_retrieved_at_and_uid.to_json)
320
+ ModuleThatIncludesRegisterMethods.update_datum(@uid)
321
+ end
322
+
323
+ it "should output jsonified processed data to STDOUT if passed true as second argument" do
324
+ expected_output = @processed_data_with_retrieved_at_and_uid.
325
+ merge(:retrieved_at => @processed_data_with_retrieved_at_and_uid[:retrieved_at].iso8601)
326
+ # json output is in different, unknown order, so we test output like this
327
+ ModuleThatIncludesRegisterMethods.should_receive(:puts) { |output| json_hash = JSON.parse(output); json_hash == expected_output }
328
+ ModuleThatIncludesRegisterMethods.update_datum(@uid, true)
329
+ end
330
+
331
+
332
+ context "and exception raised" do
333
+ before do
334
+ ModuleThatIncludesRegisterMethods.stub(:process_datum).and_raise('something went wrong')
335
+ end
336
+
337
+ it "should output error message if true passes as second argument" do
338
+ ModuleThatIncludesRegisterMethods.should_receive(:puts).with(/error.+went wrong/m)
339
+ ModuleThatIncludesRegisterMethods.update_datum(@uid, true)
340
+ end
341
+
342
+ it "should return nil if true not passed as second argument" do
343
+ ModuleThatIncludesRegisterMethods.update_datum(@uid).should be_nil
344
+ end
345
+
346
+ it "should output error message if true not passed as second argument" do
347
+ ModuleThatIncludesRegisterMethods.should_not_receive(:puts).with(/error/)
348
+ ModuleThatIncludesRegisterMethods.update_datum(@uid).should be_nil
349
+ end
350
+ end
351
+ end
352
+ end
353
+
354
+ describe '#registry_url for uid' do
355
+ it 'should get computed_registry_url' do
356
+ ModuleThatIncludesRegisterMethods.should_receive(:computed_registry_url).with('338811').and_return('http://some.url')
357
+ ModuleThatIncludesRegisterMethods.registry_url('338811').should == 'http://some.url'
358
+ end
359
+
360
+ context "and computed_registry_url returns nil" do
361
+ it 'should get registry_url_from_db' do
362
+ ModuleThatIncludesRegisterMethods.stub(:computed_registry_url)
363
+ ModuleThatIncludesRegisterMethods.should_receive(:registry_url_from_db).with('338811').and_return('http://another.url')
364
+ ModuleThatIncludesRegisterMethods.registry_url('338811').should == 'http://another.url'
365
+ end
366
+ end
367
+ end
368
+
369
+ describe "#fetch_registry_page for company_number" do
370
+ before do
371
+ @dummy_client = double('http_client', :get_content => nil)
372
+ ModuleThatIncludesRegisterMethods.stub(:_client).and_return(@dummy_client)
373
+ ModuleThatIncludesRegisterMethods.stub(:registry_url).and_return('http://some.registry.url')
374
+ end
375
+
376
+ it "should GET registry_page for registry_url for company_number" do
377
+ ModuleThatIncludesRegisterMethods.should_receive(:registry_url).
378
+ with('76543').and_return('http://some.registry.url')
379
+ @dummy_client.should_receive(:get_content).with('http://some.registry.url')
380
+ ModuleThatIncludesRegisterMethods.fetch_registry_page('76543')
381
+ end
382
+
383
+ it "should return result of GETing registry_page" do
384
+ @dummy_client.stub(:get_content).and_return(:registry_page_html)
385
+ ModuleThatIncludesRegisterMethods.fetch_registry_page('76543').should == :registry_page_html
386
+ end
387
+ end
388
+
389
+ describe "#validate_datum" do
390
+ before do
391
+ @valid_params = {:name => 'Foo Inc', :company_number => '12345', :jurisdiction_code => 'ie'}
392
+ end
393
+
394
+ it "should check json version of datum against given schema" do
395
+ JSON::Validator.should_receive(:fully_validate).with(File.expand_path("../../../../schemas/company-schema.json", __FILE__), @valid_params.to_json, anything)
396
+ ModuleThatIncludesRegisterMethods.validate_datum(@valid_params)
397
+ end
398
+
399
+ context "and datum is valid" do
400
+ it "should return empty array" do
401
+ ModuleThatIncludesRegisterMethods.validate_datum(@valid_params).should == []
402
+ end
403
+ end
404
+
405
+ context "and datum is not valid" do
406
+ it "should return errors" do
407
+ result = ModuleThatIncludesRegisterMethods.validate_datum({:name => 'Foo Inc', :jurisdiction_code => 'ie'})
408
+ result.should be_kind_of Array
409
+ result.size.should == 1
410
+ result.first[:failed_attribute].should == "Required"
411
+ result.first[:message].should match 'company_number'
412
+ end
413
+ end
414
+ end
415
+
416
+ describe "save_entity" do
417
+ before do
418
+ @params = {:name => 'Foo Inc', :custom_uid => '12345', :data => {:foo => 'bar'}}
419
+ end
420
+
421
+ it "should validate entity data" do
422
+ ModuleThatIncludesRegisterMethods.should_receive(:validate_datum).with(@params.except(:data)).and_return([])
423
+ ModuleThatIncludesRegisterMethods.save_entity(@params)
424
+ end
425
+
426
+ context "and entity_data is valid (excluding :data)" do
427
+ before do
428
+ ModuleThatIncludesRegisterMethods.stub(:validate_datum).and_return([])
429
+ end
430
+
431
+ it "should prepare and save data" do
432
+ ModuleThatIncludesRegisterMethods.should_receive(:prepare_and_save_data).with(@params)
433
+ ModuleThatIncludesRegisterMethods.save_entity(@params)
434
+ end
435
+
436
+ it "should return true" do
437
+ ModuleThatIncludesRegisterMethods.save_entity(@params).should be_true
438
+ end
439
+ end
440
+
441
+ context "and entity_data is not valid" do
442
+ before do
443
+ ModuleThatIncludesRegisterMethods.stub(:validate_datum).and_return([{:message=>'Not valid'}])
444
+ end
445
+
446
+ it "should not prepare and save data" do
447
+ ModuleThatIncludesRegisterMethods.should_not_receive(:prepare_and_save_data)
448
+ ModuleThatIncludesRegisterMethods.save_entity(@params)
449
+ end
450
+
451
+ it "should not return true" do
452
+ ModuleThatIncludesRegisterMethods.save_entity(@params).should_not be_true
453
+ end
454
+ end
455
+ end
456
+
457
+ describe "save_entity!" do
458
+ before do
459
+ @params = {:name => 'Foo Inc', :custom_uid => '12345', :data => {:foo => 'bar'}}
460
+ end
461
+
462
+ it "should validate entity data (excluding :data)" do
463
+ ModuleThatIncludesRegisterMethods.should_receive(:validate_datum).with(@params.except(:data)).and_return([])
464
+ ModuleThatIncludesRegisterMethods.save_entity!(@params)
465
+ end
466
+
467
+ context "and entity_data is valid" do
468
+ before do
469
+ ModuleThatIncludesRegisterMethods.stub(:validate_datum).and_return([])
470
+ end
471
+
472
+ it "should prepare and save data" do
473
+ ModuleThatIncludesRegisterMethods.should_receive(:prepare_and_save_data).with(@params)
474
+ ModuleThatIncludesRegisterMethods.save_entity!(@params)
475
+ end
476
+
477
+ it "should return true" do
478
+ ModuleThatIncludesRegisterMethods.save_entity!(@params).should be_true
479
+ end
480
+ end
481
+
482
+ context "and entity_data is not valid" do
483
+ before do
484
+ ModuleThatIncludesRegisterMethods.stub(:validate_datum).and_return([{:message=>'Not valid'}])
485
+ end
486
+
487
+ it "should not prepare and save data" do
488
+ ModuleThatIncludesRegisterMethods.should_not_receive(:prepare_and_save_data)
489
+ lambda {ModuleThatIncludesRegisterMethods.save_entity!(@params)}
490
+ end
491
+
492
+ it "should raise exception" do
493
+ lambda {ModuleThatIncludesRegisterMethods.save_entity!(@params)}.should raise_error(OpencBot::RecordInvalid)
494
+ end
495
+ end
496
+ end
497
+
498
+ describe '#post_process' do
499
+ before do
500
+ @unprocessed_data = { :name => 'Foo Corp',
501
+ :company_number => '12345',
502
+ :serialised_field_1 => "[\"foo\",\"bar\"]",
503
+ :serialised_field_2 => "[{\"position\":\"gestor\",\"name\":\"JOSE MANUEL REYES R.\",\"other_attributes\":{\"foo\":\"bar\"}}]",
504
+ :serialised_field_3 => "{\"foo\":\"bar\"}",
505
+ :serialised_field_4 => "[]",
506
+ :serialised_field_5 => "{}",
507
+ :serialised_field_6 => nil,
508
+ }
509
+ end
510
+
511
+ context 'in general' do
512
+ before do
513
+ @processed_data = ModuleThatIncludesRegisterMethods.post_process(@unprocessed_data)
514
+ end
515
+
516
+ it 'should include non-serialised fields' do
517
+ @processed_data[:name].should == @unprocessed_data[:name]
518
+ @processed_data[:company_number].should == @unprocessed_data[:company_number]
519
+ end
520
+
521
+ it 'should deserialize fields' do
522
+ @processed_data[:serialised_field_1].should == ['foo','bar']
523
+ @processed_data[:serialised_field_3].should == {'foo' => 'bar'}
524
+ @processed_data[:serialised_field_4].should == []
525
+ @processed_data[:serialised_field_5].should == {}
526
+ end
527
+
528
+ it 'should deserialize nested fields correctly' do
529
+ @processed_data[:serialised_field_2].first[:position].should == "gestor"
530
+ @processed_data[:serialised_field_2].first[:other_attributes][:foo].should == "bar"
531
+ end
532
+
533
+ it 'should not do anything with null value' do
534
+ @processed_data[:serialised_field_6].should be_nil
535
+ @processed_data.has_key?(:serialised_field_6).should be_true
536
+ end
537
+ end
538
+
539
+ context 'with `skip_nulls` argument as true' do
540
+ before do
541
+ @processed_data = ModuleThatIncludesRegisterMethods.post_process(@unprocessed_data, true)
542
+ end
543
+
544
+ it 'should remove value from result' do
545
+ @processed_data.has_key?(:serialised_field_6).should be_false
546
+ end
547
+ end
548
+
549
+
550
+ context "and there is generic :data field" do
551
+ it "should not include it" do
552
+ ModuleThatIncludesRegisterMethods.post_process(@unprocessed_data.merge(:data => 'something else'))[:data].should be_nil
553
+ ModuleThatIncludesRegisterMethods.post_process(@unprocessed_data.merge(:data => "{\"bar\":\"baz\"}"))[:data].should be_nil
554
+ end
555
+ end
556
+ end
557
+
558
+ end