require 'spec_helper'

describe Spree::Calculator, :type => :model do

  let(:order) { create(:order) }
  let!(:line_item) { create(:line_item, :order => order) }
  let(:shipment) { create(:shipment, :order => order, :stock_location => create(:stock_location_with_items)) }

  context "with computable" do
    context "and compute methods stubbed out" do
      context "with a Spree::LineItem" do
        it "calls compute_line_item" do
          expect(subject).to receive(:compute_line_item).with(line_item)
          subject.compute(line_item)
        end
      end

      context "with a Spree::Order" do
        it "calls compute_order" do
          expect(subject).to receive(:compute_order).with(order)
          subject.compute(order)
        end
      end

      context "with a Spree::Shipment" do
        it "calls compute_shipment" do
          expect(subject).to receive(:compute_shipment).with(shipment)
          subject.compute(shipment)
        end
      end

      context "with a arbitray object" do
        it "calls the correct compute" do
          s = "Calculator can all"
          expect(subject).to receive(:compute_string).with(s)
          subject.compute(s)
        end
      end
    end

  context "with no stubbing" do
    context "with a Spree::LineItem" do
        it "raises NotImplementedError" do
          expect{subject.compute(line_item)}.to raise_error NotImplementedError, /Please implement \'compute_line_item\(line_item\)\' in your calculator/
        end
      end

      context "with a Spree::Order" do
        it "raises NotImplementedError" do
          expect{subject.compute(order)}.to raise_error NotImplementedError, /Please implement \'compute_order\(order\)\' in your calculator/
        end
      end

      context "with a Spree::Shipment" do
        it "raises NotImplementedError" do
          expect{subject.compute(shipment)}.to raise_error NotImplementedError, /Please implement \'compute_shipment\(shipment\)\' in your calculator/
        end
      end

      context "with a arbitray object" do
        it "raises NotImplementedError" do
          s = "Calculator can all"
          expect{subject.compute(s)}.to raise_error NotImplementedError, /Please implement \'compute_string\(string\)\' in your calculator/
        end
      end
    end
  end

end

require 'spec_helper'


describe Spree::Calculator, :type => :model do

  class SimpleCalculator < Spree::Calculator
    def compute_simple_computable line_item
      'computed'
    end
  end

  class SimpleComputable
  end


  context "with computable" do

    let(:calculator) { SimpleCalculator.new }
    let(:computable) { SimpleComputable.new }

    subject { SimpleCalculator.new.compute computable }

    it 'calls compute method of class type' do
      expect(subject).to eq ( 'computed' )
    end

    context 'computable does not implement right function name' do
      let(:computable) { Spree::LineItem.new }

      it 'raises an error' do
        expect { subject }.to raise_error NotImplementedError, /Please implement \'compute_line_item\(line_item\)\' in your calculator/
      end
    end

  end
end

Remove all the stubbing in the calculator spec
Remove all the stubbing in the calculator spec

From the previous spec it was very unclear how a calculator should work.
By providing simple classes to do the calc/calculable job it removes the
stubs while being more clear what is happening.

Kills all db access as well.
