datashift 0.1.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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