datashift 0.0.1 → 0.0.2

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.
Files changed (85) hide show
  1. data/.document +5 -5
  2. data/Gemfile +28 -25
  3. data/LICENSE.txt +26 -26
  4. data/README.markdown +302 -285
  5. data/README.rdoc +19 -19
  6. data/Rakefile +93 -95
  7. data/VERSION +5 -5
  8. data/datashift.gemspec +162 -178
  9. data/lib/applications/jruby/jexcel_file.rb +396 -396
  10. data/lib/applications/jruby/word.rb +79 -79
  11. data/lib/datashift.rb +152 -113
  12. data/lib/datashift/exceptions.rb +11 -11
  13. data/lib/datashift/file_definitions.rb +353 -353
  14. data/lib/datashift/mapping_file_definitions.rb +87 -87
  15. data/lib/datashift/method_detail.rb +236 -236
  16. data/lib/datashift/method_mapper.rb +256 -256
  17. data/lib/generators/csv_generator.rb +36 -36
  18. data/lib/generators/excel_generator.rb +121 -121
  19. data/lib/generators/generator_base.rb +13 -13
  20. data/lib/helpers/core_ext/to_b.rb +24 -24
  21. data/lib/helpers/spree_helper.rb +131 -131
  22. data/lib/java/poi-3.7/LICENSE +507 -507
  23. data/lib/java/poi-3.7/NOTICE +21 -21
  24. data/lib/java/poi-3.7/RELEASE_NOTES.txt +115 -115
  25. data/lib/loaders/csv_loader.rb +98 -98
  26. data/lib/loaders/excel_loader.rb +154 -149
  27. data/lib/loaders/loader_base.rb +403 -331
  28. data/lib/loaders/spreadsheet_loader.rb +136 -136
  29. data/lib/loaders/spree/image_loader.rb +45 -45
  30. data/lib/loaders/spree/product_loader.rb +224 -224
  31. data/spec/csv_loader_spec.rb +30 -30
  32. data/spec/datashift_spec.rb +26 -26
  33. data/spec/db/migrate/20110803201325_create_test_bed.rb +85 -85
  34. data/spec/excel_generator_spec.rb +78 -78
  35. data/spec/excel_loader_spec.rb +204 -176
  36. data/spec/file_definitions.rb +141 -141
  37. data/spec/fixtures/.~lock.ProjectsSingleCategories.xls# +1 -0
  38. data/spec/fixtures/ProjectsDefaults.yml +29 -0
  39. data/spec/fixtures/config/database.yml +24 -24
  40. data/spec/fixtures/interact_models_db.sqlite +0 -0
  41. data/spec/fixtures/interact_spree_db.sqlite +0 -0
  42. data/spec/fixtures/negative/SpreeProdMiss1Mandatory.csv +4 -4
  43. data/spec/fixtures/negative/SpreeProdMissManyMandatory.csv +4 -4
  44. data/spec/fixtures/spree/SpreeProducts.csv +4 -4
  45. data/spec/fixtures/spree/SpreeProductsMultiColumn.csv +4 -4
  46. data/spec/fixtures/spree/SpreeProductsSimple.csv +4 -4
  47. data/spec/fixtures/spree/SpreeZoneExample.csv +5 -5
  48. data/spec/fixtures/test_model_defs.rb +57 -57
  49. data/spec/loader_spec.rb +120 -120
  50. data/spec/method_mapper_spec.rb +237 -237
  51. data/spec/spec_helper.rb +115 -115
  52. data/spec/spree_generator_spec.rb +64 -64
  53. data/spec/spree_loader_spec.rb +310 -310
  54. data/spec/spree_method_mapping_spec.rb +214 -214
  55. data/tasks/config/seed_fu_product_template.erb +15 -15
  56. data/tasks/config/tidy_config.txt +12 -12
  57. data/tasks/db_tasks.rake +65 -64
  58. data/tasks/excel_generator.rake +78 -78
  59. data/tasks/file_tasks.rake +36 -36
  60. data/tasks/import/csv.rake +49 -49
  61. data/tasks/import/excel.rake +71 -66
  62. data/tasks/spree/image_load.rake +108 -108
  63. data/tasks/spree/product_loader.rake +43 -43
  64. data/tasks/word_to_seedfu.rake +166 -166
  65. data/test/helper.rb +18 -18
  66. data/test/test_interact.rb +7 -7
  67. metadata +7 -38
  68. data/Gemfile.lock +0 -211
  69. data/bin/autospec +0 -16
  70. data/bin/convert_to_should_syntax +0 -16
  71. data/bin/erubis +0 -16
  72. data/bin/htmldiff +0 -16
  73. data/bin/jeweler +0 -16
  74. data/bin/ldiff +0 -16
  75. data/bin/nokogiri +0 -16
  76. data/bin/rackup +0 -16
  77. data/bin/rails +0 -16
  78. data/bin/rake +0 -16
  79. data/bin/rake2thor +0 -16
  80. data/bin/ri +0 -16
  81. data/bin/rspec +0 -16
  82. data/bin/spree +0 -16
  83. data/bin/thor +0 -16
  84. data/bin/tilt +0 -16
  85. data/bin/tt +0 -16
data/spec/spec_helper.rb CHANGED
@@ -1,116 +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.
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
116
  end
@@ -1,65 +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
-
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
65
  end
@@ -1,311 +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
-
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
311
  end