<commit_before>require 'spec_helper'

describe Calculator::Weight do
  it_behaves_like "a model using the LocalizedNumber module", [:preferred_per_kg]

  it "computes shipping cost for an order by total weight" do
    variant1 = build(:variant, unit_value: 10_000)
    variant2 = build(:variant, unit_value: 20_000)
    variant3 = build(:variant, unit_value: nil)

    line_item1 = build(:line_item, variant: variant1, quantity: 1)
    line_item2 = build(:line_item, variant: variant2, quantity: 3)
    line_item3 = build(:line_item, variant: variant3, quantity: 5)

    order = double(:order, line_items: [line_item1, line_item2, line_item3])

    subject.set_preference(:per_kg, 5)
    expect(subject.compute(order)).to eq(350) # (10 * 1 + 20 * 3) * 5
  end

  describe "line item with variant_unit weight and variant unit_value" do
    let(:variant) { build(:variant, unit_value: 10_000) }
    let(:line_item) { build(:line_item, variant: variant, quantity: 2) }

    before { subject.set_preference(:per_kg, 5) }

    it "computes shipping cost for a line item" do
      expect(subject.compute(line_item)).to eq(100) # 10 * 2 * 5
    end

    describe "and with final_weight_volume defined" do
      before { line_item.update_attribute :final_weight_volume, '18000' }

      it "computes fee using final_weight_volume, not the variant weight" do
        expect(subject.compute(line_item)).to eq(90) # 18 * 5
      end

      context "where variant unit is not weight" do
        it "uses both final_weight_volume and weight to calculate fee" do
          line_item.variant.update_attribute :weight, 7
          line_item.variant.product.update_attribute :variant_unit, 'items'
          expect(subject.compute(line_item)).to eq(63) # 7 * (18000/10000) * 5
        end
      end
    end
  end

  it "computes shipping cost for an object with an order" do
    variant1 = build(:variant, unit_value: 10_000)
    variant2 = build(:variant, unit_value: 20_000)

    line_item1 = build(:line_item, variant: variant1, quantity: 1)
    line_item2 = build(:line_item, variant: variant2, quantity: 2)

    order = double(:order, line_items: [line_item1, line_item2])
    object_with_order = double(:object_with_order, order: order)

    subject.set_preference(:per_kg, 5)
    expect(subject.compute(object_with_order)).to eq(250) # (10 * 1 + 20 * 2) * 5
  end

  context "when line item final_weight_volume is set" do
    let!(:product) { create(:product, product_attributes) }
    let!(:variant) { create(:variant, variant_attributes.merge(product: product)) }

    let(:calculator) { described_class.new(preferred_per_kg: 6) }
    let(:line_item) do
      build(:line_item, variant: variant, quantity: 2).tap do |object|
        object.send(:calculate_final_weight_volume)
      end
    end

    context "when the product uses weight unit" do
      context "when the product is in g (3g)" do
        let!(:product_attributes) { { variant_unit: "weight", variant_unit_scale: 1.0 } }
        let!(:variant_attributes) { { unit_value: 300.0, weight: 0.30 } }

        it "is correct" do
          expect(line_item.final_weight_volume).to eq(600) # 600g
          line_item.final_weight_volume = 700 # 700g
          expect(calculator.compute(line_item)).to eq(4.2) # 0.7 * 6
        end
      end

      context "when the product is in kg (3kg)" do
        let!(:product_attributes) { { variant_unit: "weight", variant_unit_scale: 1_000.0 } }
        let!(:variant_attributes) { { unit_value: 3_000.0, weight: 3.0 } }

        it "is correct" do
          expect(line_item.final_weight_volume).to eq(6_000) # 6kg
          line_item.final_weight_volume = 7_000 # 7kg<commit_msg>Use create instead of build so that we test with callbacks<commit_after>require 'spec_helper'

describe Calculator::Weight do
  it_behaves_like "a model using the LocalizedNumber module", [:preferred_per_kg]

  it "computes shipping cost for an order by total weight" do
    variant1 = build(:variant, unit_value: 10_000)
    variant2 = build(:variant, unit_value: 20_000)
    variant3 = build(:variant, unit_value: nil)

    line_item1 = build(:line_item, variant: variant1, quantity: 1)
    line_item2 = build(:line_item, variant: variant2, quantity: 3)
    line_item3 = build(:line_item, variant: variant3, quantity: 5)

    order = double(:order, line_items: [line_item1, line_item2, line_item3])

    subject.set_preference(:per_kg, 5)
    expect(subject.compute(order)).to eq(350) # (10 * 1 + 20 * 3) * 5
  end

  describe "line item with variant_unit weight and variant unit_value" do
    let(:variant) { create(:variant, unit_value: 10_000) }
    let(:line_item) { create(:line_item, variant: variant, quantity: 2) }

    before { subject.set_preference(:per_kg, 5) }

    it "computes shipping cost for a line item" do
      expect(subject.compute(line_item)).to eq(100) # 10 * 2 * 5
    end

    describe "and with final_weight_volume defined" do
      before { line_item.update_attribute :final_weight_volume, '18000' }

      it "computes fee using final_weight_volume, not the variant weight" do
        expect(subject.compute(line_item)).to eq(90) # 18 * 5
      end

      context "where variant unit is not weight" do
        it "uses both final_weight_volume and weight to calculate fee" do
          line_item.variant.update_attribute :weight, 7
          line_item.variant.product.update_attribute :variant_unit, 'items'
          expect(subject.compute(line_item)).to eq(63) # 7 * (18000/10000) * 5
        end
      end
    end
  end

  it "computes shipping cost for an object with an order" do
    variant1 = create(:variant, unit_value: 10_000)
    variant2 = create(:variant, unit_value: 20_000)

    line_item1 = create(:line_item, variant: variant1, quantity: 1)
    line_item2 = create(:line_item, variant: variant2, quantity: 2)

    order = double(:order, line_items: [line_item1, line_item2])
    object_with_order = double(:object_with_order, order: order)

    subject.set_preference(:per_kg, 5)
    expect(subject.compute(object_with_order)).to eq(250) # (10 * 1 + 20 * 2) * 5
  end

  context "when line item final_weight_volume is set" do
    let!(:product) { create(:product, product_attributes) }
    let!(:variant) { create(:variant, variant_attributes.merge(product: product)) }

    let(:calculator) { described_class.new(preferred_per_kg: 6) }
    let(:line_item) do
      create(:line_item, variant: variant, quantity: 2).tap do |object|
        object.send(:calculate_final_weight_volume)
      end
    end

    context "when the product uses weight unit" do
      context "when the product is in g (3g)" do
        let!(:product_attributes) { { variant_unit: "weight", variant_unit_scale: 1.0 } }
        let!(:variant_attributes) { { unit_value: 300.0, weight: 0.30 } }

        it "is correct" do
          expect(line_item.final_weight_volume).to eq(600) # 600g
          line_item.final_weight_volume = 700 # 700g
          expect(calculator.compute(line_item)).to eq(4.2) # 0.7 * 6
        end
      end

      context "when the product is in kg (3kg)" do
        let!(:product_attributes) { { variant_unit: "weight", variant_unit_scale: 1_000.0 } }
        let!(:variant_attributes) { { unit_value: 3_000.0, weight: 3.0 } }

        it "is correct" do
          expect(line_item.final_weight_volume).to eq(6_000) # 6kg
          line_item.final_weight_volume = 7_000 # 7kg
{'fraction_non_alphanumeric': 0.10792534487422234, 'fraction_numerical': 0.042737354611847446, 'mean_word_length': 3.4954407294832825, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '233886', 'n_tokens_mistral': 2594, 'n_tokens_neox': 2333, 'n_words': 645}