require "spec_helper" describe "Adding items to the cart", type: :feature do context "when adding a bundle to the cart" do context "when none of the bundle items are packs or have options" do specify "the cart lists the contents of the bundle" do bundle = create(:product_in_stock, name: "Bundle", sku: "BUNDLE") keychain = create(:product_in_stock, name: "Keychain", sku: "KEYCHAIN", can_be_part: true) shirt = create(:product_in_stock, name: "Shirt", sku: "SHIRT", can_be_part: true) add_part_to_bundle(bundle, keychain.master) add_part_to_bundle(bundle, shirt.master) visit spree.product_path(bundle) click_button "add-to-cart-button" within("#cart-detail") do within("tbody tr:first-child") do expect(page).to have_content(bundle.name) expect(page).to have_css("input[value='1']") expect(page).to have_content("(1) Keychain (KEYCHAIN)") expect(page).to have_content("(1) Shirt (SHIRT)") end end end end context "when one of the variants is a pack" do specify "the cart displays the same quantity for part line items" do bundle = create(:product_in_stock, name: "Bundle", sku: "BUNDLE") keychain = create(:product_in_stock, name: "Keychain", sku: "KEYCHAIN", can_be_part: true) _shirt, shirts_by_size = create_bundle_product_with_options( name: "Shirt", sku: "SHIRT", option_type: "Size", option_values: ["Small"] ) add_part_to_bundle(bundle, keychain.master, count: 2) add_part_to_bundle(bundle, shirts_by_size["small"]) visit spree.product_path(bundle) click_button "add-to-cart-button" within("#cart-detail tbody tr:first-child") do expect(page).to have_content(bundle.name) expect(page).to have_css("input[value='1']") expect(page).to have_content("(2) Keychain (KEYCHAIN)") expect(page).to have_content("(1) Shirt (Size: Small) (SHIRT-SMALL)") end end context "when ordering more than one of the bundle" do specify "the part quantity is multiplied by the bundle quantity" do bundle = create(:product_in_stock, name: "Bundle", sku: "BUNDLE") keychain = create(:product_in_stock, name: "Keychain", sku: "KEYCHAIN", can_be_part: true) shirt = create(:product_in_stock, name: "Shirt", sku: "SHIRT", can_be_part: true) add_part_to_bundle(bundle, keychain.master, count: 2) add_part_to_bundle(bundle, shirt.master) visit spree.product_path(bundle) fill_in "quantity", with: 2 click_button "add-to-cart-button" within("#cart-detail tbody tr:first-child") do expect(page).to have_content(bundle.name) expect(page).to have_css("input[value='2']") expect(page).to have_content("(4) Keychain (KEYCHAIN)") expect(page).to have_content("(2) Shirt (SHIRT)") end end end end context "when a bundle items has a variant (that is not user-selectable)" do specify "the cart includes the variant when listing items bundle items" do bundle = create(:product_in_stock, name: "Bundle", sku: "BUNDLE") keychain = create(:product_in_stock, name: "Keychain", sku: "KEYCHAIN", can_be_part: true) _shirt, shirts_by_size = create_bundle_product_with_options( name: "Shirt", sku: "SHIRT", option_type: "Size", option_values: ["Small"] ) add_part_to_bundle(bundle, keychain.master) add_part_to_bundle(bundle, shirts_by_size["small"]) visit spree.product_path(bundle) click_button "add-to-cart-button" within("#cart-detail tbody tr:first-child") do expect(page).to have_content(bundle.name) expect(page).to have_css("input[value='1']") expect(page).to have_content("(1) Keychain (KEYCHAIN)") expect(page).to have_content("(1) Shirt (Size: Small) (SHIRT-SMALL)") end end end context "when one of the bundle items has a user-selectable variant" do specify "the cart includes the variant when listing bundle items" do bundle = create(:product_in_stock, name: "Bundle", sku: "BUNDLE") keychain = create(:product_in_stock, name: "Keychain", sku: "KEYCHAIN", can_be_part: true) shirt, _shirts_by_size = create_bundle_product_with_options( name: "Shirt", sku: "SHIRT", option_type: "Size", option_values: ["Small", "Medium"] ) add_part_to_bundle(bundle, keychain.master, count: 1) add_part_to_bundle( bundle, shirt.master, variant_selection_deferred: true ) visit spree.product_path(bundle) select "Size: Medium", from: "Variant" click_button "add-to-cart-button" within("#cart-detail tbody tr:first-child") do expect(page).to have_content(bundle.name) expect(page).to have_css("input[value='1']") expect(page).to have_content("(1) Keychain (KEYCHAIN)") expect(page).to( have_content("(1) Shirt (Size: Medium) (SHIRT-MEDIUM)") ) end end end end def create_bundle_product_with_options(args) option_type_presentation = args.fetch(:option_type) option_value_presentations = args.fetch(:option_values) option_values = option_value_presentations.map do |presentation| create(:option_value, presentation: presentation) end option_type = create(:option_type, presentation: option_type_presentation, name: option_type_presentation.downcase, option_values: option_values) product_attributes = args.slice(:name, :sku).merge( option_types: [option_type], can_be_part: true ) product = create(:product, product_attributes) variants = variants_by_option(product, option_values) [product, variants] end def variants_by_option(product, option_values) option_values.each_with_object({}) do |value, hash| hash[value.presentation.downcase] = create( :variant_in_stock, product: product, sku: "#{product.sku}-#{value.presentation.upcase}", option_values: [value] ) end end def add_part_to_bundle(bundle, variant, options = {}) attributes = options.reverse_merge( assembly_id: bundle.id, part_id: variant.id, ) create(:assemblies_part, attributes).tap do |_part| bundle.reload end end end