solidus_product_assembly 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +35 -0
  3. data/.gem_release.yml +5 -0
  4. data/.github/dependabot.yml +7 -0
  5. data/.github/stale.yml +17 -0
  6. data/.gitignore +14 -2
  7. data/.rspec +2 -2
  8. data/.rubocop.yml +4 -0
  9. data/.rubocop_todo.yml +192 -0
  10. data/CHANGELOG.md +19 -0
  11. data/Gemfile +21 -9
  12. data/LICENSE +26 -0
  13. data/README.md +52 -18
  14. data/Rakefile +4 -19
  15. data/app/controllers/spree/admin/parts_controller.rb +13 -11
  16. data/app/decorators/controllers/solidus_product_assembly/spree/checkout_controller_decorator.rb +13 -0
  17. data/app/decorators/helpers/solidus_product_assembly/spree/admin/orders_helper_decorator.rb +19 -0
  18. data/app/decorators/models/solidus_product_assembly/spree/inventory_unit_decorator.rb +19 -0
  19. data/app/decorators/models/solidus_product_assembly/spree/line_item_decorator.rb +52 -0
  20. data/app/decorators/models/solidus_product_assembly/spree/product_decorator.rb +70 -0
  21. data/app/decorators/models/solidus_product_assembly/spree/return_item_decorator.rb +15 -0
  22. data/app/decorators/models/solidus_product_assembly/spree/shipment_decorator.rb +55 -0
  23. data/app/decorators/models/solidus_product_assembly/spree/stock/availability_validator_decorator.rb +37 -0
  24. data/app/decorators/models/solidus_product_assembly/spree/stock/inventory_unit_builder_decorator.rb +39 -0
  25. data/app/decorators/models/solidus_product_assembly/spree/stock/inventory_units_finalizer_decorator.rb +33 -0
  26. data/app/decorators/models/solidus_product_assembly/spree/stock/inventory_validator_decorator.rb +22 -0
  27. data/app/decorators/models/solidus_product_assembly/spree/variant_decorator.rb +26 -0
  28. data/app/models/spree/assemblies_part.rb +6 -4
  29. data/app/models/spree/calculator/returns/assemblies_default_refund_amount.rb +17 -0
  30. data/app/models/spree/order_inventory_assembly.rb +11 -2
  31. data/app/overrides/add_admin_product_form_fields.rb +7 -5
  32. data/app/overrides/add_admin_tabs.rb +7 -5
  33. data/app/overrides/add_line_item_description.rb +7 -5
  34. data/app/overrides/spree/admin/orders/_carton_manifest/_assembly_parts_price.html.erb.deface +9 -0
  35. data/app/overrides/spree/admin/orders/_carton_manifest/_assembly_parts_total_price.html.erb.deface +9 -0
  36. data/app/overrides/spree/admin/orders/_shipment/stock_contents.html.erb.deface +7 -1
  37. data/app/overrides/spree/products/show/add_links_to_parts.html.erb.deface +2 -2
  38. data/app/views/spree/admin/orders/_assemblies.html.erb +8 -17
  39. data/app/views/spree/admin/orders/_stock_contents.html.erb +2 -62
  40. data/app/views/spree/admin/orders/_stock_contents_2_3.html.erb +69 -0
  41. data/app/views/spree/admin/orders/_stock_contents_2_4.html.erb +70 -0
  42. data/app/views/spree/admin/orders/_stock_item.html.erb +13 -10
  43. data/app/views/spree/admin/parts/_parts_table.html.erb +17 -11
  44. data/app/views/spree/admin/parts/available.html.erb +10 -8
  45. data/app/views/spree/admin/parts/available.js.erb +9 -7
  46. data/app/views/spree/admin/parts/index.html.erb +1 -1
  47. data/app/views/spree/admin/products/_product_assembly_fields.html.erb +2 -2
  48. data/app/views/spree/admin/shared/_product_assembly_product_tabs.html.erb +1 -1
  49. data/app/views/spree/api/line_items/show.v1.rabl +27 -0
  50. data/app/views/spree/checkout/_line_item_manifest.html.erb +3 -1
  51. data/bin/console +17 -0
  52. data/bin/rails +12 -4
  53. data/bin/setup +8 -0
  54. data/config/routes.rb +2 -2
  55. data/db/migrate/20091028152124_add_many_to_many_relation_to_products.rb +7 -5
  56. data/db/migrate/20091029165620_add_parts_fields_to_products.rb +18 -16
  57. data/db/migrate/20120316141830_namespace_product_assembly_for_spree_one.rb +3 -1
  58. data/db/migrate/20140620223938_add_id_to_spree_assemblies_parts.rb +4 -2
  59. data/lib/generators/solidus_product_assembly/install/install_generator.rb +13 -8
  60. data/lib/solidus_product_assembly/engine.rb +11 -8
  61. data/lib/solidus_product_assembly/testing_support/factories.rb +4 -0
  62. data/lib/solidus_product_assembly/version.rb +3 -1
  63. data/lib/solidus_product_assembly.rb +5 -1
  64. data/lib/tasks/spree2_upgrade.rake +12 -12
  65. data/solidus_product_assembly.gemspec +25 -20
  66. data/spec/features/admin/orders_spec.rb +114 -16
  67. data/spec/features/admin/parts_spec.rb +5 -3
  68. data/spec/features/admin/return_items_spec.rb +151 -0
  69. data/spec/features/checkout_spec.rb +103 -21
  70. data/spec/models/spree/assemblies_part_spec.rb +3 -1
  71. data/spec/models/spree/inventory_unit_spec.rb +15 -6
  72. data/spec/models/spree/line_item_spec.rb +6 -4
  73. data/spec/models/spree/order_contents_spec.rb +6 -5
  74. data/spec/models/spree/order_inventory_assembly_spec.rb +8 -6
  75. data/spec/models/spree/order_inventory_spec.rb +7 -3
  76. data/spec/models/spree/product_spec.rb +15 -14
  77. data/spec/models/spree/shipment_spec.rb +20 -13
  78. data/spec/models/spree/stock/availability_validator_spec.rb +22 -33
  79. data/spec/models/spree/stock/coordinator_spec.rb +11 -3
  80. data/spec/models/spree/stock/inventory_unit_builder_spec.rb +5 -7
  81. data/spec/models/spree/variant_spec.rb +3 -1
  82. data/spec/spec_helper.rb +18 -47
  83. data/spec/support/shared_contexts/order_with_bundle.rb +2 -0
  84. metadata +80 -102
  85. data/.travis.yml +0 -21
  86. data/LICENSE.md +0 -13
  87. data/app/controllers/spree/checkout_controller_decorator.rb +0 -9
  88. data/app/helpers/spree/admin/orders_helper_decorator.rb +0 -9
  89. data/app/models/spree/inventory_unit_decorator.rb +0 -13
  90. data/app/models/spree/line_item_decorator.rb +0 -44
  91. data/app/models/spree/product_decorator.rb +0 -56
  92. data/app/models/spree/shipment_decorator.rb +0 -50
  93. data/app/models/spree/stock/availability_validator.rb +0 -28
  94. data/app/models/spree/stock/inventory_unit_builder_decorator.rb +0 -30
  95. data/app/models/spree/stock/inventory_validator_decorator.rb +0 -12
  96. data/app/models/spree/variant_decorator.rb +0 -13
@@ -1,27 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  namespace :solidus_product_assembly do
2
4
  desc 'Link legacy inventory units to an order line item'
3
- task :upgrade => :environment do
5
+ task upgrade: :environment do
4
6
  shipments = Spree::Shipment.includes(:inventory_units).where("spree_inventory_units.line_item_id IS NULL")
5
7
 
6
8
  shipments.each do |shipment|
7
9
  shipment.inventory_units.includes(:variant).group_by(&:variant).each do |variant, units|
8
-
9
10
  line_item = shipment.order.line_items.detect { |line_item| line_item.variant_id == variant.id }
10
11
 
11
- unless line_item
12
+ next if line_item
12
13
 
13
- begin
14
- master = shipment.order.products.detect { |p| variant.assemblies.include? p }.master
15
- supposed_line_item = shipment.order.line_items.detect { |line_item| line_item.variant_id == master.id }
14
+ begin
15
+ master = shipment.order.products.detect { |p| variant.assemblies.include? p }.master
16
+ supposed_line_item = shipment.order.line_items.detect { |line_item| line_item.variant_id == master.id }
16
17
 
17
- if supposed_line_item
18
- Spree::InventoryUnit.where(id: units.map(&:id)).update_all "line_item_id = #{supposed_line_item.id}"
19
- else
20
- puts "Couldn't find a matching line item for #{variant.name}"
21
- end
22
- rescue
18
+ if supposed_line_item
19
+ Spree::InventoryUnit.where(id: units.map(&:id)).update_all "line_item_id = #{supposed_line_item.id}"
20
+ else
23
21
  puts "Couldn't find a matching line item for #{variant.name}"
24
22
  end
23
+ rescue StandardError
24
+ puts "Couldn't find a matching line item for #{variant.name}"
25
25
  end
26
26
  end
27
27
  end
@@ -1,8 +1,6 @@
1
- # encoding: UTF-8
2
-
3
- lib = File.expand_path('../lib/', __FILE__)
4
- $:.unshift lib unless $:.include?(lib)
1
+ # frozen_string_literal: true
5
2
 
3
+ $:.push File.expand_path('lib', __dir__)
6
4
  require 'solidus_product_assembly/version'
7
5
 
8
6
  Gem::Specification.new do |s|
@@ -11,25 +9,32 @@ Gem::Specification.new do |s|
11
9
  s.version = SolidusProductAssembly::VERSION
12
10
  s.summary = 'Adds oportunity to make bundle of products to your Spree store'
13
11
  s.description = s.summary
14
- s.required_ruby_version = '>= 1.9.3'
12
+ s.license = 'BSD-3-Clause'
13
+
14
+ s.required_ruby_version = '>= 2.4'
15
15
 
16
16
  s.author = 'Roman Smirnov'
17
17
  s.email = 'roman@railsdog.com'
18
18
  s.homepage = 'https://solidus.io'
19
19
 
20
- s.files = `git ls-files`.split("\n")
21
- s.test_files = `git ls-files -- spec/*`.split("\n")
22
- s.require_path = 'lib'
23
- s.requirements << 'none'
24
-
25
- s.add_runtime_dependency 'solidus_backend', [">= 1.0", "< 3"]
26
-
27
- s.add_development_dependency 'rspec-rails', '~> 3.4'
28
- s.add_development_dependency 'sqlite3'
29
- s.add_development_dependency 'ffaker'
30
- s.add_development_dependency 'factory_girl', '~> 4.4'
31
- s.add_development_dependency 'capybara', '~> 2.7'
32
- s.add_development_dependency 'poltergeist', '~> 1.9'
33
- s.add_development_dependency 'database_cleaner', '~> 1.3'
34
- s.add_development_dependency 'simplecov'
20
+ s.files = Dir.chdir(File.expand_path(__dir__)) do
21
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
22
+ end
23
+ s.test_files = Dir['spec/**/*']
24
+ s.bindir = "exe"
25
+ s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
+ s.require_paths = ["lib"]
27
+
28
+ if s.respond_to?(:metadata)
29
+ s.metadata["homepage_uri"] = s.homepage if s.homepage
30
+ s.metadata["source_code_uri"] = "https://github.com/solidusio-contrib/solidus_product_assembly"
31
+ end
32
+
33
+ s.add_dependency 'deface'
34
+ s.add_dependency 'solidus_core', ['>= 1.0', '< 4']
35
+ s.add_dependency 'solidus_support', '~> 0.8'
36
+
37
+ s.add_development_dependency 'github_changelog_generator'
38
+ s.add_development_dependency 'selenium-webdriver'
39
+ s.add_development_dependency 'solidus_dev_support'
35
40
  end
@@ -1,29 +1,127 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe "Orders", type: :feature, js: true do
4
6
  stub_authorization!
5
7
 
6
- let(:order) { create(:order_with_line_items) }
7
- let(:line_item) { order.line_items.first }
8
- let(:bundle) { line_item.product }
9
- let(:parts) { (1..3).map { create(:variant) } }
8
+ context 'when the order product is a bundle' do
9
+ let(:order) { create(:order_with_line_items) }
10
+ let(:line_item) { order.line_items.first }
11
+ let(:bundle) { line_item.product }
12
+ let(:parts) { (1..3).map { create(:variant) } }
13
+
14
+ before do
15
+ bundle.parts << [parts]
16
+ line_item.update!(quantity: 3)
17
+ order.reload.create_proposed_shipments
18
+ order.finalize!
19
+ end
20
+
21
+ if Spree.solidus_gem_version < Gem::Version.new('2.5')
22
+ context 'Adding tracking number' do
23
+ let(:tracking_number) { 'AA123' }
24
+
25
+ before { visit spree.edit_admin_order_path(order) }
26
+
27
+ it 'allows admin to edit tracking' do
28
+ expect(page).not_to have_content tracking_number
29
+ within '.show-tracking' do
30
+ find('.fa-edit').click
31
+ end
32
+ within '.edit-tracking' do
33
+ expect(page).to have_selector 'input[name="tracking"]'
34
+ fill_in :tracking, with: tracking_number
35
+ find('.fa-ok').click
36
+ expect(page).not_to have_selector 'input[name="tracking"]'
37
+ end
38
+ expect(page).to have_content tracking_number
39
+ end
40
+ end
41
+
42
+ context 'Changing carrier/shipping costs' do
43
+ before do
44
+ visit spree.edit_admin_order_path(order)
45
+ end
10
46
 
11
- before do
12
- bundle.parts << [parts]
13
- line_item.update_attributes!(quantity: 3)
14
- order.reload.create_proposed_shipments
15
- order.finalize!
47
+ it 'allows admin to edit shipping costs' do
48
+ expect(page).not_to have_content 'UPS Ground $100.00'
49
+ within '.show-method' do
50
+ find('.fa-edit').click
51
+ end
52
+ within '.edit-method' do
53
+ find('.fa-ok').click
54
+ end
55
+ expect(page).to have_content 'UPS Ground $100.00'
56
+ end
57
+ end
58
+ else
59
+ context 'Adding tracking number' do
60
+ let(:tracking_number) { 'AA123' }
61
+
62
+ before { visit spree.edit_admin_order_path(order) }
63
+
64
+ it 'allows admin to edit tracking' do
65
+ within '.edit-tracking' do
66
+ expect(page).not_to have_content tracking_number
67
+ find('.js-edit').click
68
+ expect(page).to have_selector 'input[name="tracking"]'
69
+ fill_in :tracking, with: tracking_number
70
+ find('.js-save').click
71
+ expect(page).not_to have_selector 'input[name="tracking"]'
72
+ expect(page).to have_content tracking_number
73
+ end
74
+ end
75
+ end
76
+
77
+ context 'Changing carrier/shipping costs' do
78
+ let(:carrier_name) { 'Fedex' }
79
+ let(:select_name) { 'selected_shipping_method_id' }
80
+
81
+ before do
82
+ create :shipping_method, name: carrier_name
83
+ visit spree.edit_admin_order_path(order)
84
+ end
85
+
86
+ it 'allows admin to edit shipping costs' do
87
+ within '.edit-shipping-method' do
88
+ expect(page).not_to have_content carrier_name
89
+ find('.js-edit').click
90
+ expect(page).to have_selector "select[name='#{select_name}']"
91
+ select "#{carrier_name} $10.00", from: select_name
92
+ find('.js-save').click
93
+ expect(page).not_to have_selector "select[name='#{select_name}']"
94
+ expect(page).to have_content carrier_name
95
+ end
96
+ end
97
+ end
98
+ end
16
99
  end
17
100
 
18
- it "allows admin to edit product bundle" do
19
- visit spree.edit_admin_order_path(order)
101
+ context 'when the order product is not a bundle' do
102
+ let(:order) { create(:order_ready_to_ship, state: 'complete', line_items_count: 1) }
103
+ let(:product) { order.products.first }
104
+ let(:location_name) { 'Foobar warehouse' }
105
+
106
+ before { create :stock_location, name: location_name }
20
107
 
21
- within("table.product-bundles") do
22
- find(".edit-line-item").click
23
- fill_in "quantity", :with => "2"
24
- find(".save-line-item").click
108
+ context 'Splitting items' do
109
+ before { visit spree.edit_admin_order_path(order) }
25
110
 
26
- sleep(1) # avoid odd "cannot rollback - no transaction is active: rollback transaction"
111
+ it 'allows admin to split items to another stock location' do
112
+ find('.split-item').click
113
+ within '.stock-item-split' do
114
+ expect(page).to have_content "Move #{product.name} to"
115
+ find('.save-split').click
116
+ alert_text = page.driver.browser.switch_to.alert.text
117
+ expect(alert_text).to include 'Please select the split destination'
118
+ page.driver.browser.switch_to.alert.accept
119
+ find('.select2-container').click
120
+ find(:xpath, '//body').all('.select2-drop li.select2-result', text: "#{location_name} (0 on hand)")[0].click
121
+ find('.save-split').click
122
+ end
123
+ expect(page).to have_content /Pending package from '#{location_name}'/i
124
+ end
27
125
  end
28
126
  end
29
127
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe "Parts", type: :feature, js: true do
4
6
  stub_authorization!
5
7
 
6
- let!(:tshirt) { create(:product, :name => "T-Shirt") }
7
- let!(:mug) { create(:product, :name => "Mug") }
8
+ let!(:tshirt) { create(:product, name: "T-Shirt") }
9
+ let!(:mug) { create(:product, name: "Mug") }
8
10
 
9
11
  before do
10
12
  visit spree.admin_product_path(mug)
@@ -19,7 +21,7 @@ describe "Parts", type: :feature, js: true do
19
21
  click_on "Search"
20
22
 
21
23
  within("#search_hits") { click_on "Select" }
22
- page.should have_content(mug.sku)
24
+ expect(page).to have_content(mug.sku)
23
25
 
24
26
  within("#product_parts") do
25
27
  find(".remove_admin_product_part_link").click
@@ -0,0 +1,151 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe "Return Items", type: :feature, js: true do
6
+ stub_authorization!
7
+
8
+ let(:line_item) { order.line_items.first }
9
+
10
+ before do
11
+ allow_any_instance_of(Spree::Admin::ReimbursementsController).to receive(:try_spree_current_user) { Spree.user_class.new }
12
+ end
13
+
14
+ context 'when the order product is a bundle' do
15
+ let(:bundle) { line_item.product }
16
+ let(:parts) { (1..3).map { create(:variant) } }
17
+
18
+ before do
19
+ create :refund_reason, name: Spree::RefundReason::RETURN_PROCESSING_REASON, mutable: false
20
+ bundle.parts << [parts]
21
+ bundle.set_part_count(parts.first, 2)
22
+ parts.each { |p| p.stock_items.first.set_count_on_hand 4 }
23
+ 3.times { order.next }
24
+ create :payment, order: order, amount: order.amount
25
+ order.next
26
+ order.complete
27
+ order.payments.each(&:capture!)
28
+ order.shipments.each { |s| s.update state: :ready }
29
+ order.shipments.each(&:ship!)
30
+ end
31
+
32
+ context 'with a single item cart' do
33
+ let(:order) { create(:order_with_line_items) }
34
+
35
+ it 'successfully generates a RMA, a reimbursement and a refund' do
36
+ visit spree.edit_admin_order_path(order)
37
+
38
+ expect(page).to have_selector '.line-item-total', text: '$10.00'
39
+
40
+ click_link 'RMA'
41
+ click_link 'New RMA'
42
+
43
+ expect(page).to have_selector '.return-item-charged', text: '$2.50', count: 4
44
+
45
+ find('#select-all').click
46
+ select Spree::StockLocation.first.name, from: 'Stock Location'
47
+ click_button 'Create'
48
+
49
+ expect(page).to have_content 'Return Authorization has been successfully created!'
50
+
51
+ click_link 'Customer Returns'
52
+ click_link 'New Customer Return'
53
+ find('#select-all').click
54
+ page.execute_script %{$('option[value="receive"]').attr('selected', 'selected')}
55
+ select Spree::StockLocation.first.name, from: 'Stock Location'
56
+ click_button 'Create'
57
+
58
+ expect(page).to have_content 'Customer Return has been successfully created!'
59
+
60
+ click_button 'Create reimbursement'
61
+ click_button 'Reimburse'
62
+
63
+ within 'table.reimbursement-refunds' do
64
+ expect(page).to have_content '$10.00'
65
+ end
66
+ end
67
+ end
68
+
69
+ context 'with a multiple items cart' do
70
+ let(:order) { create(:order_with_line_items, line_items_attributes: [{ quantity: 2 }]) }
71
+
72
+ it 'successfully generates a RMA, a reimbursement and a refund' do
73
+ visit spree.edit_admin_order_path(order)
74
+
75
+ expect(page).to have_selector '.line-item-total', text: '$20.00'
76
+
77
+ click_link 'RMA'
78
+ click_link 'New RMA'
79
+
80
+ expect(page).to have_selector '.return-item-charged', text: '$2.50', count: 8
81
+
82
+ find('#select-all').click
83
+ select Spree::StockLocation.first.name, from: 'Stock Location'
84
+ click_button 'Create'
85
+
86
+ expect(page).to have_content 'Return Authorization has been successfully created!'
87
+
88
+ click_link 'Customer Returns'
89
+ click_link 'New Customer Return'
90
+ find('#select-all').click
91
+ page.execute_script %{$('option[value="receive"]').attr('selected', 'selected')}
92
+ select Spree::StockLocation.first.name, from: 'Stock Location'
93
+ click_button 'Create'
94
+
95
+ expect(page).to have_content 'Customer Return has been successfully created!'
96
+
97
+ click_button 'Create reimbursement'
98
+ click_button 'Reimburse'
99
+
100
+ within 'table.reimbursement-refunds' do
101
+ expect(page).to have_content '$20.00'
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ context 'when the product is not a bundle' do
108
+ before do
109
+ order.reload.create_proposed_shipments
110
+ order.finalize!
111
+ order.update state: :complete
112
+ order.shipments.update_all state: :shipped
113
+ end
114
+
115
+ context 'with a single item cart' do
116
+ let(:order) { create(:order_with_line_items) }
117
+
118
+ it 'builds one return item for each product' do
119
+ visit spree.edit_admin_order_path(order)
120
+
121
+ expect(page).to have_selector '.item-total', text: '$10.00'
122
+
123
+ click_link 'RMA'
124
+ click_link 'New RMA'
125
+
126
+ within '.return-items-table tbody' do
127
+ expect(page).to have_selector 'tr', count: 1
128
+ expect(page).to have_selector '.return-item-pre-tax-refund-amount', text: '$10.00', count: 1
129
+ end
130
+ end
131
+ end
132
+
133
+ context 'with a multiple items cart' do
134
+ let(:order) { create(:order_with_line_items, line_items_attributes: [{ quantity: 2 }]) }
135
+
136
+ it 'builds one return item for each product' do
137
+ visit spree.edit_admin_order_path(order)
138
+
139
+ expect(page).to have_selector '.item-total', text: '$20.00'
140
+
141
+ click_link 'RMA'
142
+ click_link 'New RMA'
143
+
144
+ within '.return-items-table tbody' do
145
+ expect(page).to have_selector 'tr', count: 2
146
+ expect(page).to have_selector '.return-item-pre-tax-refund-amount', text: '$10.00', count: 2
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
@@ -1,48 +1,51 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe "Checkout", type: :feature do
4
6
  let!(:store) { create :store, default: true }
5
- let!(:country) { create(:country, :name => "United States", :states_required => true) }
6
- let!(:state) { create(:state, :name => "Ohio", :country => country) }
7
+ let!(:country) { create(:country, name: "United States", states_required: true) }
8
+ let!(:state) { create(:state, name: "Ohio", country: country) }
7
9
  let!(:shipping_method) { create(:shipping_method) }
8
10
  let!(:stock_location) { create(:stock_location) }
9
11
  let!(:payment_method) { create(:check_payment_method) }
10
12
  let!(:zone) { create(:zone) }
11
13
 
12
- let(:product) { create(:product, :name => "RoR Mug") }
14
+ let(:product) { create(:product, name: "RoR Mug") }
13
15
  let(:variant) { create(:variant) }
16
+ let(:other_variant) { create(:variant) }
14
17
 
15
18
  stub_authorization!
16
19
 
17
- before { product.parts << variant << create(:variant) }
20
+ before { product.parts << variant << other_variant }
18
21
 
19
22
  shared_context "purchases product with part included" do
20
23
  before do
24
+ visit spree.root_path
21
25
  add_product_to_cart
22
26
  click_button "Checkout"
23
27
 
24
- fill_in "order_email", :with => "ryan@spreecommerce.com"
28
+ fill_in "order_email", with: "ryan@spreecommerce.com"
25
29
  click_button "Continue"
26
30
  fill_in_address
27
31
 
28
32
  click_button "Save and Continue"
29
33
  expect(current_path).to eql(spree.checkout_state_path("delivery"))
30
- page.should have_content(variant.product.name)
34
+ expect(page).to have_content(variant.product.name)
31
35
 
32
36
  click_button "Save and Continue"
33
37
  expect(current_path).to eql(spree.checkout_state_path("payment"))
34
38
 
35
39
  click_button "Save and Continue"
36
- expect(current_path).to eq spree.checkout_state_path('confirm')
37
- page.should have_content(variant.product.name)
40
+ expect(page).to have_current_path spree.checkout_state_path('confirm'), ignore_query: true
41
+ expect(page).to have_content(variant.product.name)
38
42
 
39
43
  click_button "Place Order"
40
- page.should have_content('Your order has been processed successfully')
44
+ expect(page).to have_content('Your order has been processed successfully')
41
45
  end
42
46
  end
43
47
 
44
- context "backend order shipments UI", js: true do
45
-
48
+ shared_examples 'purchasable assembly' do
46
49
  context "ordering only the product assembly" do
47
50
  include_context "purchases product with part included"
48
51
 
@@ -50,7 +53,7 @@ describe "Checkout", type: :feature do
50
53
  visit spree.admin_orders_path
51
54
  click_on Spree::Order.last.number
52
55
 
53
- page.should have_content(variant.product.name)
56
+ expect(page).to have_content(variant.product.name)
54
57
  end
55
58
  end
56
59
 
@@ -60,28 +63,107 @@ describe "Checkout", type: :feature do
60
63
  click_link variant.product.name
61
64
  click_button "add-to-cart-button"
62
65
  end
66
+
63
67
  include_context "purchases product with part included"
64
68
 
65
69
  it "views parts bundled and not" do
66
70
  visit spree.admin_orders_path
67
71
  click_on Spree::Order.last.number
68
72
 
69
- page.should have_content(variant.product.name)
73
+ expect(page).to have_content(variant.product.name)
70
74
  end
71
75
  end
72
-
73
76
  end
74
77
 
78
+ context "backend order shipments UI", js: true do
79
+ context 'when the product and parts are backorderable' do
80
+ it_behaves_like 'purchasable assembly'
81
+ end
82
+
83
+ context 'when the product and parts are not backorderable' do
84
+ context 'when there is enough quantity available' do
85
+ before do
86
+ Spree::StockItem.update_all backorderable: false
87
+ variant.stock_items.each { |stock_item| stock_item.set_count_on_hand 2 }
88
+ other_variant.stock_items.each { |stock_item| stock_item.set_count_on_hand 1 }
89
+ product.stock_items.each { |stock_item| stock_item.set_count_on_hand 1 }
90
+ end
91
+
92
+ it_behaves_like 'purchasable assembly'
93
+
94
+ context 'when the order can be processed' do
95
+ include_context "purchases product with part included"
96
+
97
+ before do
98
+ visit spree.admin_orders_path
99
+ click_on Spree::Order.last.number
100
+ end
101
+
102
+ it 'marks the order as paid and shipped showing proper parts information' do
103
+ within '#order_tab_summary' do
104
+ expect(page).to have_selector '#shipment_status', text: 'Pending'
105
+ expect(page).to have_selector '#payment_status', text: 'Balance due'
106
+ end
107
+
108
+ click_link 'Payments'
109
+ find('.fa-capture').click
110
+
111
+ within '#order_tab_summary' do
112
+ expect(page).to have_selector '#shipment_status', text: 'Ready'
113
+ expect(page).to have_selector '#payment_status', text: 'Paid'
114
+ end
115
+
116
+ click_link 'Shipments'
117
+
118
+ within '.stock-contents' do
119
+ expect(page).to have_selector '.item-price', text: '---'
120
+ expect(page).to have_selector '.item-total', text: '---'
121
+ expect(page).to have_selector '.item-qty-show', count: 2, text: '1 x on hand'
122
+ end
123
+
124
+ expect(page).not_to have_selector '.stock-contents.carton'
125
+
126
+ click_button 'Ship'
127
+
128
+ within '.stock-contents' do
129
+ expect(page).to have_selector '.item-qty-show', count: 2, text: '1 x Shipped'
130
+ end
131
+
132
+ within '.stock-contents.carton' do
133
+ expect(page).to have_selector '.item-qty-show', count: 2, text: '1 x Shipped'
134
+ expect(page).to have_selector '.item-price', text: '---'
135
+ expect(page).to have_selector '.item-total', text: '---'
136
+ end
137
+
138
+ within '#order_tab_summary' do
139
+ expect(page).to have_selector '#shipment_status', text: 'Shipped'
140
+ expect(page).to have_selector '#payment_status', text: 'Paid'
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
75
147
 
76
148
  def fill_in_address
77
149
  address = "order_bill_address_attributes"
78
- fill_in "#{address}_firstname", :with => "Ryan"
79
- fill_in "#{address}_lastname", :with => "Bigg"
80
- fill_in "#{address}_address1", :with => "143 Swan Street"
81
- fill_in "#{address}_city", :with => "Richmond"
82
- select "Ohio", :from => "#{address}_state_id"
83
- fill_in "#{address}_zipcode", :with => "12345"
84
- fill_in "#{address}_phone", :with => "(555) 555-5555"
150
+
151
+ if use_address_full_name?
152
+ fill_in "#{address}_name", with: "Ryan Bigg"
153
+ else
154
+ fill_in "#{address}_firstname", with: "Ryan"
155
+ fill_in "#{address}_lastname", with: "Bigg"
156
+ end
157
+
158
+ fill_in "#{address}_address1", with: "143 Swan Street"
159
+ fill_in "#{address}_city", with: "Richmond"
160
+ select "Ohio", from: "#{address}_state_id"
161
+ fill_in "#{address}_zipcode", with: "12345"
162
+ fill_in "#{address}_phone", with: "(555) 555-5555"
163
+ end
164
+
165
+ def use_address_full_name?
166
+ SolidusSupport.combined_first_and_last_name_in_address?
85
167
  end
86
168
 
87
169
  def add_product_to_cart
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  module Spree
@@ -11,7 +13,7 @@ module Spree
11
13
 
12
14
  context "get" do
13
15
  it "brings part by product and variant id" do
14
- subject.class.get(product.id, variant.id).part.should == variant
16
+ expect(subject.class.get(product.id, variant.id).part).to eq variant
15
17
  end
16
18
  end
17
19
  end
@@ -1,16 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  module Spree
4
6
  describe InventoryUnit do
7
+ subject { described_class.create!(attributes) }
8
+
5
9
  let!(:order) { create(:order_with_line_items) }
6
10
  let(:line_item) { order.line_items.first }
7
11
  let(:product) { line_item.product }
12
+ let(:shipment) { create(:shipment, order: order) }
8
13
 
9
- subject { InventoryUnit.create(line_item: line_item, variant: line_item.variant, order: order) }
14
+ if Spree.solidus_gem_version < Gem::Version.new('2.5.x')
15
+ let(:attributes) { { shipment: shipment, line_item: line_item, variant: line_item.variant, order: order } }
16
+ else
17
+ let(:attributes) { { shipment: shipment, line_item: line_item, variant: line_item.variant } }
18
+ end
10
19
 
11
- context 'if the unit is not part of an assembly' do
12
- it 'it will return the percentage of a line item' do
13
- expect(subject.percentage_of_line_item).to eql(BigDecimal.new(1))
20
+ context 'if the unit is not part of an assembly' do
21
+ it 'will return the percentage of a line item' do
22
+ expect(subject.percentage_of_line_item).to eql(BigDecimal(1))
14
23
  end
15
24
  end
16
25
 
@@ -23,9 +32,9 @@ module Spree
23
32
  order.finalize!
24
33
  end
25
34
 
26
- it 'it will return the percentage of a line item' do
35
+ it 'will return the percentage of a line item' do
27
36
  subject.line_item = line_item
28
- expect(subject.percentage_of_line_item).to eql(BigDecimal.new(0.5, 2))
37
+ expect(subject.percentage_of_line_item).to eql(BigDecimal(0.5, 2))
29
38
  end
30
39
  end
31
40
  end