require 'test_helper' module Workarea module Pricing class Discount class ApplicationGroupTest < TestCase setup :create_models def create_models @order = create_order @shippings = [create_shipping(order_id: @order.id)] @discounts = Discount::Collection.new end def assert_compatible_sets(compatible_sets, results) compatible_sets.each do |compatible_set| match = results.detect do |result| result.discounts.length == compatible_set.length && compatible_set.all? { |d| d.in?(result.discounts) } end assert(match.present?) end end def test_calculate_creates_a_group_for_each_unique_set_of_compatible_discounts discount_1 = create_product_discount discount_2 = create_product_discount(compatible_discount_ids: [discount_1.id]) discount_3 = create_product_discount discount_4 = create_product_discount(compatible_discount_ids: [discount_3.id]) discount_5 = create_product_discount(compatible_discount_ids: [discount_3.id]) discount_6 = create_product_discount results = ApplicationGroup.calculate(@discounts, @order, @shippings) assert_equal(4, results.length) compatible_sets = [ [discount_1, discount_2], [discount_3, discount_5], [discount_3, discount_4], [discount_6] ] assert_compatible_sets(compatible_sets, results) end def test_calculate_does_not_allow_hidden_incompatibilities discount_1 = create_product_discount discount_2 = create_product_discount( compatible_discount_ids: [discount_1.id] ) discount_3 = create_product_discount( compatible_discount_ids: [discount_1.id] ) discount_4 = create_product_discount( compatible_discount_ids: [ discount_1.id, discount_2.id, discount_3.id ] ) results = ApplicationGroup.calculate(@discounts, @order, @shippings) assert_equal(2, results.length) compatible_sets = [ [discount_1, discount_2, discount_4], [discount_1, discount_3, discount_4] ] assert_compatible_sets(compatible_sets, results) end def test_calculate_returns_all_discounts_when_the_graph_is_complete compatible_sets = Array.new(5).map { create_product_discount } ids = compatible_sets.map(&:id).map(&:to_s) compatible_sets.each do |discount| discount.update_attributes(compatible_discount_ids: ids) end results = ApplicationGroup.calculate(@discounts, @order, @shippings) assert_equal(1, results.length) # need to sort discounts to resolve undefined behavior match = results.detect { |r| r.discounts.sort == compatible_sets.sort } assert(match.present?) end def test_calculate_returns_groups_when_the_graph_is_a_set_of_disjoint_complete_graphs @discounts = Array.new(20).map { create_product_discount } @discounts.each_slice(5) do |discount_subset| ids = discount_subset.map(&:id).map(&:to_s) discount_subset .each { |d| d.update_attributes(compatible_discount_ids: ids) } end results = ApplicationGroup.calculate(@discounts, @order, @shippings) assert_equal(4, results.length) @discounts.each_slice(5) do |discount_subset| # need to sort discounts to resolve undefined behavior match = results.detect { |r| r.discounts.sort == discount_subset.sort } assert(match.present?) end end def test_value_calculates_the_total_value_of_the_discounts create_pricing_sku(id: 'SKU', prices: [{ regular: 5.to_m }]) create_order_total_discount( name: 'Discount', amount_type: 'flat', amount: 2 ) @order.add_item(product_id: 'PRODUCT', sku: 'SKU') Calculators::ItemCalculator.test_adjust(@order) group = ApplicationGroup.new(@discounts, @order, @shippings) assert_equal(2.to_m, group.value) end def test_value_always_returns_a_money_value create_shipping_discount create_pricing_sku(id: 'SKU', prices: [{ regular: 5.to_m }]) @order.add_item(product_id: 'PRODUCT', sku: 'SKU') value = ApplicationGroup.new(@discounts, @order, @shippings).value assert_instance_of(Money, value) end def test_value_has_no_side_effects create_pricing_sku(id: 'SKU', prices: [{ regular: 5.to_m }]) create_order_total_discount( name: 'Discount', amount_type: 'flat', amount: 2 ) @order.add_item(product_id: 'PRODUCT', sku: 'SKU') Calculators::ItemCalculator.test_adjust(@order) ApplicationGroup.new(@discounts, @order, @shippings).value assert_equal(1, @order.items.first.price_adjustments.length) end def test_value_calculates_the_total_value_of_the_free_gift_discounts free_product = create_product( name: 'Free Product', variants: [{ sku: 'FREESKU', regular: 5.to_m }] ) create_free_gift_discount( name: 'Free Item Discount', sku: free_product.skus.first ) create_pricing_sku(id: 'SKU', prices: [{ regular: 5.to_m }]) @order.add_item(product_id: 'PRODUCT', sku: 'SKU') Calculators::ItemCalculator.test_adjust(@order) group = ApplicationGroup.new(@discounts, @order, @shippings) assert_equal(5.to_m, group.value) end end end end end