datashift 0.1.0 → 0.2.1

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