# encoding: utf-8 require "spec_helper" describe Money do describe ".new" do let(:initializing_value) { 1 } subject(:money) { Money.new(initializing_value) } its(:bank) { should be Money::Bank::VariableExchange.instance } context 'given the initializing value is an integer' do let(:initializing_value) { Integer(1) } it 'stores the integer as the number of cents' do expect(money.cents).to eq initializing_value end end context 'given the initializing value is a float' do context 'and the value is 1.00' do let(:initializing_value) { 1.00 } it { should eq Money.new(1) } end context 'and the value is 1.01' do let(:initializing_value) { 1.01 } it { should eq Money.new(1) } end context 'and the value is 1.50' do let(:initializing_value) { 1.50 } it { should eq Money.new(2) } end end context 'given the initializing value is a rational' do let(:initializing_value) { Rational(1) } it { should eq Money.new(1) } end context 'given the initializing value is money' do let(:initializing_value) { Money.new(1_00, Money::Currency.new('NZD')) } it { should eq initializing_value } end context 'given a currency is not provided' do subject(:money) { Money.new(initializing_value) } its(:currency) { should eq Money.default_currency } end context 'given a currency is provided' do subject(:money) { Money.new(initializing_value, currency) } context 'and the currency is NZD' do let(:currency) { Money::Currency.new('NZD') } its(:currency) { should eq Money::Currency.new('NZD') } end end context "infinite_precision = true" do before { Money.stub(:infinite_precision => true) } context 'given the initializing value is 1.50' do let(:initializing_value) { 1.50 } its(:cents) { should eq BigDecimal('1.50') } end end end describe ".new_with_dollars" do it "is synonym of #new_with_amount" do MoneyExpectation = Class.new(Money) def MoneyExpectation.new_with_amount *args args end MoneyExpectation.new_with_dollars("expectation").should == ["expectation"] end end describe ".new_with_amount" do it "converts given amount to cents" do Money.new_with_amount(1).should == Money.new(100) Money.new_with_amount(1, "USD").should == Money.new(100, "USD") Money.new_with_amount(1, "EUR").should == Money.new(100, "EUR") end it "respects :subunit_to_unit currency property" do Money.new_with_amount(1, "USD").should == Money.new(1_00, "USD") Money.new_with_amount(1, "TND").should == Money.new(1_000, "TND") Money.new_with_amount(1, "CLP").should == Money.new(1, "CLP") end it "does not loose precision" do Money.new_with_amount(1234).cents.should == 1234_00 Money.new_with_amount(100.37).cents.should == 100_37 Money.new_with_amount(BigDecimal.new('1234')).cents.should == 1234_00 end it "accepts optional currency" do m = Money.new_with_amount(1) m.currency.should == Money.default_currency m = Money.new_with_amount(1, Money::Currency.wrap("EUR")) m.currency.should == Money::Currency.wrap("EUR") m = Money.new_with_amount(1, "EUR") m.currency.should == Money::Currency.wrap("EUR") end it "accepts optional bank" do m = Money.new_with_amount(1) m.bank.should == Money.default_bank m = Money.new_with_amount(1, "EUR", bank = Object.new) m.bank.should == bank end it "is associated to the singleton instance of Bank::VariableExchange by default" do Money.new_with_amount(0).bank.should be(Money::Bank::VariableExchange.instance) end end describe ".empty" do it "creates a new Money object of 0 cents" do Money.empty.should == Money.new(0) end end describe ".ca_dollar" do it "creates a new Money object of the given value in CAD" do Money.ca_dollar(50).should == Money.new(50, "CAD") end end describe ".us_dollar" do it "creates a new Money object of the given value in USD" do Money.us_dollar(50).should == Money.new(50, "USD") end end describe ".euro" do it "creates a new Money object of the given value in EUR" do Money.euro(50).should == Money.new(50, "EUR") end end describe ".add_rate" do before do @default_bank = Money.default_bank Money.default_bank = Money::Bank::VariableExchange.new end after do Money.default_bank = @default_bank end it "saves rate into current bank" do Money.add_rate("EUR", "USD", 10) Money.new(10_00, "EUR").exchange_to("USD").should == Money.new(100_00, "USD") end end describe ".disallow_currency_conversions!" do before do @default_bank = Money.default_bank end after do Money.default_bank = @default_bank end it "disallows conversions when doing money arithmetic" do Money.disallow_currency_conversion! expect { Money.new(100, "USD") + Money.new(100, "EUR") }.to raise_exception(Money::Bank::DifferentCurrencyError) end end describe "#cents" do it "is a synonym of #fractional" do expectation = Money.new(0) def expectation.fractional "expectation" end expectation.cents.should == "expectation" end end describe "#fractional" do it "returns the amount in fractional unit" do Money.new(1_00).fractional.should == 1_00 Money.new_with_amount(1).fractional.should == 1_00 end it "stores fractional as an integer regardless of what is passed into the constructor" do [ Money.new(100), 1.to_money, 1.00.to_money, BigDecimal('1.00').to_money ].each do |m| m.fractional.should == 100 m.fractional.should be_a(Fixnum) end end context "loading a serialized Money via YAML" do let(:serialized) { <