datashift 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. data/.document +5 -0
  2. data/Gemfile +25 -0
  3. data/Gemfile.lock +211 -0
  4. data/LICENSE.txt +27 -0
  5. data/README.markdown +286 -0
  6. data/README.rdoc +19 -0
  7. data/Rakefile +96 -0
  8. data/VERSION +5 -0
  9. data/bin/autospec +16 -0
  10. data/bin/convert_to_should_syntax +16 -0
  11. data/bin/erubis +16 -0
  12. data/bin/htmldiff +16 -0
  13. data/bin/jeweler +16 -0
  14. data/bin/ldiff +16 -0
  15. data/bin/nokogiri +16 -0
  16. data/bin/rackup +16 -0
  17. data/bin/rails +16 -0
  18. data/bin/rake +16 -0
  19. data/bin/rake2thor +16 -0
  20. data/bin/ri +16 -0
  21. data/bin/rspec +16 -0
  22. data/bin/spree +16 -0
  23. data/bin/thor +16 -0
  24. data/bin/tilt +16 -0
  25. data/bin/tt +16 -0
  26. data/datashift.gemspec +178 -0
  27. data/lib/applications/jruby/jexcel_file.rb +397 -0
  28. data/lib/applications/jruby/word.rb +79 -0
  29. data/lib/datashift.rb +114 -0
  30. data/lib/datashift/exceptions.rb +12 -0
  31. data/lib/datashift/file_definitions.rb +353 -0
  32. data/lib/datashift/mapping_file_definitions.rb +88 -0
  33. data/lib/datashift/method_detail.rb +237 -0
  34. data/lib/datashift/method_mapper.rb +257 -0
  35. data/lib/generators/csv_generator.rb +36 -0
  36. data/lib/generators/excel_generator.rb +122 -0
  37. data/lib/generators/generator_base.rb +14 -0
  38. data/lib/helpers/core_ext/to_b.rb +24 -0
  39. data/lib/helpers/spree_helper.rb +131 -0
  40. data/lib/java/poi-3.7/._poi-3.7-20101029.jar5645100390082102460.tmp +0 -0
  41. data/lib/java/poi-3.7/LICENSE +507 -0
  42. data/lib/java/poi-3.7/NOTICE +21 -0
  43. data/lib/java/poi-3.7/RELEASE_NOTES.txt +115 -0
  44. data/lib/java/poi-3.7/lib/commons-logging-1.1.jar +0 -0
  45. data/lib/java/poi-3.7/lib/junit-3.8.1.jar +0 -0
  46. data/lib/java/poi-3.7/lib/log4j-1.2.13.jar +0 -0
  47. data/lib/java/poi-3.7/ooxml-lib/dom4j-1.6.1.jar +0 -0
  48. data/lib/java/poi-3.7/ooxml-lib/geronimo-stax-api_1.0_spec-1.0.jar +0 -0
  49. data/lib/java/poi-3.7/ooxml-lib/xmlbeans-2.3.0.jar +0 -0
  50. data/lib/java/poi-3.7/poi-3.7-20101029.jar +0 -0
  51. data/lib/java/poi-3.7/poi-examples-3.7-20101029.jar +0 -0
  52. data/lib/java/poi-3.7/poi-ooxml-3.7-20101029.jar +0 -0
  53. data/lib/java/poi-3.7/poi-ooxml-schemas-3.7-20101029.jar +0 -0
  54. data/lib/java/poi-3.7/poi-scratchpad-3.7-20101029.jar +0 -0
  55. data/lib/loaders/csv_loader.rb +99 -0
  56. data/lib/loaders/excel_loader.rb +150 -0
  57. data/lib/loaders/loader_base.rb +332 -0
  58. data/lib/loaders/spreadsheet_loader.rb +137 -0
  59. data/lib/loaders/spree/image_loader.rb +46 -0
  60. data/lib/loaders/spree/product_loader.rb +225 -0
  61. data/spec/csv_loader_spec.rb +31 -0
  62. data/spec/datashift_spec.rb +27 -0
  63. data/spec/db/migrate/20110803201325_create_test_bed.rb +85 -0
  64. data/spec/excel_generator_spec.rb +79 -0
  65. data/spec/excel_loader_spec.rb +177 -0
  66. data/spec/file_definitions.rb +141 -0
  67. data/spec/fixtures/BadAssociationName.xls +0 -0
  68. data/spec/fixtures/DemoNegativeTesting.xls +0 -0
  69. data/spec/fixtures/ProjectsMultiCategories.xls +0 -0
  70. data/spec/fixtures/ProjectsSingleCategories.xls +0 -0
  71. data/spec/fixtures/SimpleProjects.xls +0 -0
  72. data/spec/fixtures/config/database.yml +25 -0
  73. data/spec/fixtures/interact_models_db.sqlite +0 -0
  74. data/spec/fixtures/interact_spree_db.sqlite +0 -0
  75. data/spec/fixtures/negative/SpreeProdMiss1Mandatory.csv +4 -0
  76. data/spec/fixtures/negative/SpreeProdMiss1Mandatory.xls +0 -0
  77. data/spec/fixtures/negative/SpreeProdMissManyMandatory.csv +4 -0
  78. data/spec/fixtures/negative/SpreeProdMissManyMandatory.xls +0 -0
  79. data/spec/fixtures/simple_export_spec.xls +0 -0
  80. data/spec/fixtures/simple_template_spec.xls +0 -0
  81. data/spec/fixtures/spree/SpreeProducts.csv +4 -0
  82. data/spec/fixtures/spree/SpreeProducts.xls +0 -0
  83. data/spec/fixtures/spree/SpreeProductsMultiColumn.csv +4 -0
  84. data/spec/fixtures/spree/SpreeProductsMultiColumn.xls +0 -0
  85. data/spec/fixtures/spree/SpreeProductsSimple.csv +4 -0
  86. data/spec/fixtures/spree/SpreeProductsSimple.xls +0 -0
  87. data/spec/fixtures/spree/SpreeZoneExample.csv +5 -0
  88. data/spec/fixtures/spree/SpreeZoneExample.xls +0 -0
  89. data/spec/fixtures/test_model_defs.rb +57 -0
  90. data/spec/loader_spec.rb +121 -0
  91. data/spec/method_mapper_spec.rb +238 -0
  92. data/spec/spec_helper.rb +116 -0
  93. data/spec/spree_generator_spec.rb +65 -0
  94. data/spec/spree_loader_spec.rb +311 -0
  95. data/spec/spree_method_mapping_spec.rb +215 -0
  96. data/tasks/config/seed_fu_product_template.erb +15 -0
  97. data/tasks/config/tidy_config.txt +13 -0
  98. data/tasks/db_tasks.rake +65 -0
  99. data/tasks/excel_generator.rake +79 -0
  100. data/tasks/file_tasks.rake +37 -0
  101. data/tasks/import/csv.rake +50 -0
  102. data/tasks/import/excel.rake +67 -0
  103. data/tasks/spree/image_load.rake +109 -0
  104. data/tasks/spree/product_loader.rake +44 -0
  105. data/tasks/word_to_seedfu.rake +167 -0
  106. data/test/helper.rb +18 -0
  107. data/test/test_interact.rb +7 -0
  108. metadata +301 -0
@@ -0,0 +1,116 @@
1
+ require 'erb'
2
+ require 'yaml'
3
+
4
+ require File.dirname(__FILE__) + '/../lib/datashift'
5
+
6
+ include DataShift
7
+
8
+ #.# Copyright:: (c) Autotelik Media Ltd 2011
9
+ # Author :: Tom Statter
10
+ # Date :: Aug 2011
11
+ # License:: MIT
12
+ #
13
+ # Details:: Spec Helper for Active Record Loader
14
+ #
15
+ #
16
+ # We are not setup as a Rails project so need to mimic an active record database setup so
17
+ # we have some AR models top test against. Create an in memory database from scratch.
18
+ #
19
+ $DataShiftFixturePath = File.join(File.dirname(__FILE__), 'fixtures')
20
+ $DataShiftDatabaseYml = File.join($DataShiftFixturePath, 'config/database.yml')
21
+
22
+ module DataShift
23
+
24
+ def db_connect( env = 'test_file', version = nil)
25
+
26
+ version ? gem('activerecord', version) : gem('activerecord')
27
+
28
+ require 'active_record'
29
+
30
+ # Some active record stuff seems to rely on the RAILS_ENV being set ?
31
+
32
+ ENV['RAILS_ENV'] = env
33
+
34
+ configuration = {}
35
+
36
+ configuration[:database_configuration] = YAML::load( ERB.new(IO.read($DataShiftDatabaseYml)).result )
37
+ db = configuration[:database_configuration][ env ]
38
+
39
+ puts "Setting DB Config - #{db.inspect}"
40
+ ActiveRecord::Base.configurations = db
41
+
42
+ #ActiveRecord::Base.logger = Logger.new(STDOUT)
43
+
44
+ require 'logger'
45
+ logdir = File.dirname(__FILE__) + '/logs'
46
+ FileUtils.mkdir_p(logdir) unless File.exists?(logdir)
47
+ ActiveRecord::Base.logger = Logger.new(logdir + '/test.log')
48
+
49
+ @ilog = ActiveRecord::Base.logger
50
+
51
+ puts "Connecting to DB"
52
+ ActiveRecord::Base.establish_connection( db )
53
+
54
+
55
+ # See errors #<NameError: uninitialized constant RAILS_CACHE> when doing save (AR without Rails)
56
+ # so copied this from ... Rails::Initializer.initialize_cache
57
+ Object.const_set "RAILS_CACHE", ActiveSupport::Cache.lookup_store( :memory_store )
58
+
59
+ @ilog.info "Connected to DB - #{ActiveRecord::Base.connection.inspect}"
60
+ end
61
+
62
+ def db_clear
63
+ [Project, Milestone, Category, Version, LoaderRelease].each {|x| x.delete_all}
64
+ end
65
+
66
+ def load_in_memory
67
+ load "#{Rails.root}/db/schema.rb"
68
+ end
69
+
70
+ def migrate_up
71
+ ActiveRecord::Migrator.up( File.dirname(__FILE__) + '/db/migrate')
72
+ end
73
+
74
+ def results_path
75
+ File.join($DataShiftFixturePath, 'results')
76
+ end
77
+
78
+ def results_clear
79
+ begin FileUtils.rm_rf(results_path); rescue; end
80
+
81
+ FileUtils.mkdir(results_path) unless File.exists?(results_path);
82
+ end
83
+
84
+ # Return location of an expected results file and ensure tree clean before test
85
+ def result_file( name )
86
+ expect = File.join(results_path, name)
87
+
88
+ begin FileUtils.rm(expect); rescue; end
89
+
90
+ expect
91
+ end
92
+
93
+ def ifixture_file( name )
94
+ File.join($DataShiftFixturePath, name)
95
+ end
96
+
97
+ end
98
+
99
+
100
+ RSpec.configure do |config|
101
+ # config.use_transactional_fixtures = true
102
+ # config.use_instantiated_fixtures = false
103
+ # config.fixture_path = RAILS_ROOT + '/spec/fixtures'
104
+
105
+ # You can declare fixtures for each behaviour like this:
106
+ # describe "...." do
107
+ # fixtures :table_a, :table_b
108
+ #
109
+ # Alternatively, if you prefer to declare them only once, you can
110
+ # do so here, like so ...
111
+ #
112
+ # config.global_fixtures = :table_a, :table_b
113
+ #
114
+ # If you declare global fixtures, be aware that they will be declared
115
+ # for all of your examples, even those that don't use them.
116
+ end
@@ -0,0 +1,65 @@
1
+ # Copyright:: (c) Autotelik Media Ltd 2011
2
+ # Author :: Tom Statter
3
+ # Date :: Summer 2011
4
+ #
5
+ # License:: MIT - Free, OpenSource
6
+ #
7
+ # Details:: Specification for Spree generator aspect of datashift gem.
8
+ #
9
+ # Provides Loaders and rake tasks specifically tailored for uploading or exporting
10
+ # Spree Products, associations and Images
11
+ #
12
+ require File.dirname(__FILE__) + '/spec_helper'
13
+
14
+ require 'spree_helper'
15
+ require 'excel_generator'
16
+
17
+ include DataShift
18
+
19
+ describe 'SpreeLoader' do
20
+
21
+ before(:all) do
22
+
23
+ # we are not a Spree project, nor is it practical to externally generate
24
+ # a complete Spree application for testing so we implement a mini migrate/boot of our own
25
+ Spree.load() # require Spree gems
26
+
27
+ # key to YAML db e.g test_memory, test_mysql
28
+ db_connect( 'test_spree_standalone' )
29
+
30
+ Spree.boot # create a sort-of Spree app
31
+
32
+ Spree.migrate_up # create an sqlite Spree database on the fly
33
+ end
34
+
35
+ before do
36
+ end
37
+
38
+ it "should export any Spree model to .xls spreedsheet" do
39
+
40
+ expect = result_file('optionstypes_export_spec.xls')
41
+
42
+ gen = ExcelGenerator.new(expect)
43
+
44
+ items = OptionType.all
45
+
46
+ gen.export(items)
47
+
48
+ File.exists?(expect).should be_true
49
+ end
50
+
51
+ it "should export a Spree model and associations to .xls spreedsheet" do
52
+
53
+ expect = result_file('shiprates_export_spec.xls')
54
+
55
+ gen = ExcelGenerator.new(expect)
56
+
57
+ items = OptionType.all
58
+
59
+ gen.export_with_associations(OptionType, items)
60
+
61
+ File.exists?(expect).should be_true
62
+
63
+ end
64
+
65
+ end
@@ -0,0 +1,311 @@
1
+ # Copyright:: (c) Autotelik Media Ltd 2011
2
+ # Author :: Tom Statter
3
+ # Date :: Summer 2011
4
+ #
5
+ # License:: MIT - Free, OpenSource
6
+ #
7
+ # Details:: Specification for Spree aspect of datashift gem.
8
+ #
9
+ # Provides Loaders and rake tasks specifically tailored for uploading or exporting
10
+ # Spree Products, associations and Images
11
+ #
12
+ require File.dirname(__FILE__) + '/spec_helper'
13
+
14
+ require 'spree_helper'
15
+ require 'product_loader'
16
+
17
+ include DataShift
18
+
19
+ describe 'SpreeLoader' do
20
+
21
+ before(:all) do
22
+
23
+ # key to YAML db e.g test_memory, test_mysql
24
+ db_connect( 'test_spree_standalone' )
25
+
26
+ # See errors #<NameError: uninitialized constant RAILS_CACHE> when doing save (AR without Rails)
27
+ # so copied this from ... Rails::Initializer.initialize_cache
28
+ Object.const_set "RAILS_CACHE", ActiveSupport::Cache.lookup_store( :memory_store )
29
+
30
+ RAILS_CACHE = ActiveSupport::Cache.lookup_store( :memory_store )
31
+
32
+ # we are not a Spree project, nor is it practical to externally generate
33
+ # a complete Spree application for testing so we implement a mini migrate/boot of our own
34
+ Spree.load() # require Spree gems
35
+ Spree.boot # create a sort-of Spree app
36
+
37
+ Spree.migrate_up # create an sqlite Spree database on the fly
38
+
39
+ @klazz = Product
40
+
41
+ $SpreeFixturePath = File.join($DataShiftFixturePath, 'spree')
42
+
43
+ $SpreeNegativeFixturePath = File.join($DataShiftFixturePath, 'negative')
44
+
45
+ end
46
+
47
+ def spree_fix( source)
48
+ File.join($SpreeFixturePath, source)
49
+ end
50
+
51
+ before(:each) do
52
+
53
+ MethodMapper.clear
54
+ MethodMapper.find_operators( @klazz )
55
+
56
+ # Reset main tables - TODO should really purge properly, or roll back a transaction
57
+ [OptionType, OptionValue, Product, Property, Variant, Taxonomy, Taxon, Zone].each { |x| x.delete_all }
58
+
59
+ Product.count.should == 0
60
+
61
+ Taxon.count.should == 0
62
+
63
+ # want to test both lookup and dynamic creation - this Taxonomy should be found, rest created
64
+ root = Taxonomy.create( :name => 'Paintings' )
65
+ Taxon.create( :name => 'Landscape', :taxonomy => root )
66
+
67
+ Taxon.count.should == 2
68
+
69
+
70
+ @product_loader = DataShift::Spree::ProductLoader.new
71
+ end
72
+
73
+
74
+ it "should process a simple .xls spreadsheet" do
75
+
76
+ Zone.delete_all
77
+
78
+ loader = ExcelLoader.new(Zone)
79
+
80
+ loader.perform_load( spree_fix('SpreeZoneExample.xls') )
81
+
82
+ loader.loaded_count.should == Zone.count
83
+ end
84
+
85
+ it "should process a simple csv file" do
86
+
87
+ Zone.delete_all
88
+
89
+ loader = CsvLoader.new(Zone)
90
+
91
+ loader.perform_load( spree_fix('SpreeZoneExample.csv') )
92
+
93
+ loader.loaded_count.should == Zone.count
94
+ end
95
+
96
+
97
+ # Loader should perform identically regardless of source, whether csv, .xls etc
98
+
99
+ it "should load basic Products .xls via Spree loader", :focus => true do
100
+ test_basic_product('SpreeProductsSimple.xls')
101
+ end
102
+
103
+ it "should load basic Products from .csv via Spree loader" do
104
+ test_basic_product('SpreeProductsSimple.csv')
105
+ end
106
+
107
+ it "should raise an error for unsupported file types" do
108
+ lambda { test_basic_product('SpreeProductsSimple.xml') }.should raise_error UnsupportedFileType
109
+ end
110
+
111
+ def test_basic_product( source )
112
+
113
+ @product_loader.perform_load( spree_fix(source), :mandatory => ['sku', 'name', 'price'] )
114
+
115
+ Product.count.should == 3
116
+
117
+ @product_loader.failed_objects.size.should == 0
118
+ @product_loader.loaded_objects.size.should == 3
119
+
120
+ @product_loader.loaded_count.should == Product.count
121
+
122
+ p = Product.first
123
+
124
+ p.sku.should == "SIMPLE_001"
125
+ p.price.should == 345.78
126
+ p.name.should == "Simple Product for AR Loader"
127
+ p.description.should == "blah blah"
128
+ p.cost_price.should == 320.00
129
+ p.option_types.should have_exactly(1).items
130
+ p.count_on_hand.should == 12
131
+
132
+ Product.last.option_types.should have_exactly(2).items
133
+ Product.last.count_on_hand.should == 23
134
+ end
135
+
136
+
137
+ # Operation and results should be identical when loading multiple associations
138
+ # if using either single column embedded syntax, or one column per entry.
139
+
140
+ it "should load Products and create Variants from single column" do
141
+ test_variants_creation('SpreeProducts.xls')
142
+ end
143
+
144
+
145
+ it "should load Products and create Variants from multiple column" do
146
+ test_variants_creation('SpreeProductsMultiColumn.xls')
147
+ end
148
+
149
+ def test_variants_creation( source )
150
+ @product_loader.perform_load( spree_fix(source), :mandatory => ['sku', 'name', 'price'] )
151
+
152
+ expected_multi_column_variants
153
+ end
154
+
155
+
156
+ def expected_multi_column_variants
157
+
158
+ # 3 MASTER products, 11 VARIANTS
159
+ Product.count.should == 3
160
+ Variant.count.should == 14
161
+
162
+ p = Product.first
163
+
164
+ p.sku.should == "DEMO_001"
165
+
166
+ p.sku.should == "DEMO_001"
167
+ p.price.should == 399.99
168
+ p.description.should == "blah blah"
169
+ p.cost_price.should == 320.00
170
+
171
+ Product.all.select {|m| m.is_master.should == true }
172
+
173
+ p.variants.should have_exactly(3).items
174
+
175
+ Variant.all[1].sku.should == "DEMO_001_0"
176
+ Variant.all[1].price.should == 399.99
177
+
178
+ v = p.variants[0]
179
+
180
+ v.sku.should == "DEMO_001_0"
181
+ v.price.should == 399.99
182
+ v.count_on_hand.should == 12
183
+
184
+ p.variants[1].count_on_hand.should == 6
185
+ p.variants[2].count_on_hand.should == 7
186
+
187
+ Variant.last.price.should == 50.34
188
+ Variant.last.count_on_hand.should == 18
189
+
190
+ @product_loader.failed_objects.size.should == 0
191
+ end
192
+
193
+
194
+ # Operation and results should be identical when loading multiple associations
195
+ # if using either single column embedded syntax, or one column per entry.
196
+
197
+ it "should load Products and multiple Properties from single column" do
198
+ test_properties_creation( 'SpreeProducts.xls' )
199
+ end
200
+
201
+ it "should load Products and multiple Properties from multiple column" do
202
+ test_properties_creation( 'SpreeProductsMultiColumn.xls' )
203
+ end
204
+
205
+ def test_properties_creation( source )
206
+
207
+ # want to test both lookup and dynamic creation - this Prop should be found, rest created
208
+ Property.create( :name => 'test_pp_001', :presentation => 'Test PP 001' )
209
+
210
+ Property.count.should == 1
211
+
212
+ @product_loader.perform_load( spree_fix(source), :mandatory => ['sku', 'name', 'price'] )
213
+
214
+ expected_multi_column_properties
215
+
216
+ end
217
+
218
+ def expected_multi_column_properties
219
+ Property.count.should == 4
220
+
221
+ Product.first.properties.should have_exactly(1).items
222
+
223
+ p3 = Product.all.last
224
+
225
+ p3.properties.should have_exactly(3).items
226
+
227
+ p3.properties.should include Property.find_by_name('test_pp_002')
228
+
229
+ # Test the optional text value got set on assigned product property
230
+ p3.product_properties.select {|p| p.value == 'Example free value' }.should have_exactly(1).items
231
+
232
+ end
233
+
234
+ # Operation and results should be identical when loading multiple associations
235
+ # if using either single column embedded syntax, or one column per entry.
236
+
237
+ it "should load Products and multiple Taxons from single column" do
238
+ test_taxon_creation( 'SpreeProducts.xls' )
239
+ end
240
+
241
+ it "should load Products and multiple Taxons from multiple columns" do
242
+ test_taxon_creation( 'SpreeProductsMultiColumn.xls' )
243
+ end
244
+
245
+ def test_taxon_creation( source )
246
+
247
+ @product_loader.perform_load( spree_fix(source), :mandatory => ['sku', 'name', 'price'] )
248
+
249
+ expected_multi_column_taxons
250
+ end
251
+
252
+ def expected_multi_column_taxons
253
+
254
+ Taxonomy.count.should == 4
255
+ Taxon.count.should == 5
256
+
257
+ Product.first.taxons.should have_exactly(2).items
258
+ Product.last.taxons.should have_exactly(1).items
259
+
260
+ p2 = Product.all[1]
261
+
262
+ p2.taxons.should have_exactly(3).items
263
+
264
+ t = Taxon.find_by_name('Oils')
265
+
266
+ t.should_not be_nil
267
+
268
+ p2.taxons.collect( &:id ).should include(t.id)
269
+
270
+ end
271
+
272
+
273
+ # REPEAT THE WHOLE TEST SUITE VIA CSV
274
+
275
+ it "should load Products from single column csv as per .xls" do
276
+ test_variants_creation('SpreeProducts.csv')
277
+
278
+ expected_multi_column_properties
279
+
280
+ expected_multi_column_taxons
281
+ end
282
+
283
+
284
+ it "should load Products from multiple column csv as per .xls" do
285
+ test_variants_creation('SpreeProductsMultiColumn.csv')
286
+
287
+ expected_multi_column_properties
288
+
289
+ expected_multi_column_taxons
290
+ end
291
+
292
+
293
+ it "should raise exception when mandatory columns missing from .xls", :ex => true do
294
+ expect {@product_loader.perform_load($SpreeNegativeFixturePath + '/SpreeProdMissManyMandatory.xls', :mandatory => ['sku', 'name', 'price'] )}.to raise_error(DataShift::MissingMandatoryError)
295
+ end
296
+
297
+
298
+ it "should raise exception when single mandatory column missing from .xls", :ex => true do
299
+ expect {@product_loader.perform_load($SpreeNegativeFixturePath + '/SpreeProdMiss1Mandatory.xls', :mandatory => 'sku' )}.to raise_error(DataShift::MissingMandatoryError)
300
+ end
301
+
302
+ it "should raise exception when mandatory columns missing from .csv", :ex => true do
303
+ expect {@product_loader.perform_load($SpreeNegativeFixturePath + '/SpreeProdMissManyMandatory.csv', :mandatory => ['sku', 'name', 'price'] )}.to raise_error(DataShift::MissingMandatoryError)
304
+ end
305
+
306
+
307
+ it "should raise exception when single mandatory column missing from .csv", :ex => true do
308
+ expect {@product_loader.perform_load($SpreeNegativeFixturePath + '/SpreeProdMiss1Mandatory.csv', :mandatory => 'sku' )}.to raise_error(DataShift::MissingMandatoryError)
309
+ end
310
+
311
+ end