# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Spree::Money do
before do
stub_spree_preferences(currency: "USD")
end
describe '#initialize' do
subject do
Spree::Deprecation.silence do
described_class.new(amount, currency: currency, with_currency: true).to_s
end
end
context 'with no currency' do
let(:currency) { nil }
let(:amount){ 10 }
it { should == "$10.00 USD" }
end
context 'with currency' do
let(:currency){ 'USD' }
context "CAD" do
let(:amount){ '10.00' }
let(:currency){ 'CAD' }
it { should == "$10.00 CAD" }
end
context "with string amount" do
let(:amount){ '10.00' }
it { should == "$10.00 USD" }
end
context "with no decimal point" do
let(:amount){ '10' }
it { should == "$10.00 USD" }
end
context "with symbol" do
let(:amount){ '$10.00' }
it { should == "$10.00 USD" }
end
context "with extra currency" do
let(:amount){ '$10.00 USD' }
it { should == "$10.00 USD" }
end
context "with different currency" do
let(:currency){ 'USD' }
let(:amount){ '$10.00 CAD' }
it { should == "$10.00 CAD" }
end
context "with commas" do
let(:amount){ '1,000.00' }
it { should == "$1,000.00 USD" }
end
context "with comma for decimal point" do
let(:amount){ '10,00' }
it { should == "$10.00 USD" }
end
context 'with fixnum' do
let(:amount){ 10 }
it { should == "$10.00 USD" }
end
context 'with float' do
let(:amount){ 10.00 }
it { should == "$10.00 USD" }
end
context 'with BigDecimal' do
let(:amount){ BigDecimal('10.00') }
it { should == "$10.00 USD" }
end
end
end
it "formats correctly" do
money = Spree::Money.new(10)
expect(money.to_s).to eq("$10.00")
end
it "can get cents" do
money = Spree::Money.new(10)
expect(money.cents).to eq(1000)
end
context "with currency" do
it "passed in option" do
money = Spree::Money.new(10, with_currency: true, html_wrap: false)
expect(money.to_s).to eq("$10.00 USD")
end
end
context "hide cents" do
it "hides cents suffix" do
money = Spree::Money.new(10, no_cents: true)
expect(money.to_s).to eq("$10")
end
it "shows cents suffix" do
money = Spree::Money.new(10)
expect(money.to_s).to eq("$10.00")
end
end
context "currency parameter" do
context "when currency is specified in Canadian Dollars" do
it "uses the currency param over the global configuration" do
money = Spree::Money.new(10, currency: 'CAD', with_currency: true, html_wrap: false)
expect(money.to_s).to eq("$10.00 CAD")
end
end
context "when currency is specified in Japanese Yen" do
it "uses the currency param over the global configuration" do
money = Spree::Money.new(100, currency: 'JPY', html_wrap: false)
expect(money.to_s).to eq("¥100")
end
end
end
context "symbol positioning" do
it "passed in option" do
money = Spree::Money.new(10, format: '%n %u', html_wrap: false)
expect(money.to_s).to eq("10.00 $")
end
it "config option" do
money = Spree::Money.new(10, format: '%n %u', html_wrap: false)
expect(money.to_s).to eq("10.00 $")
end
end
context "sign before symbol" do
it "defaults to -$10.00" do
money = Spree::Money.new(-10)
expect(money.to_s).to eq("-$10.00")
end
it "passed in option" do
money = Spree::Money.new(-10, sign_before_symbol: false)
expect(money.to_s).to eq("$-10.00")
end
end
context "JPY" do
before do
stub_spree_preferences(currency: "JPY")
end
it "formats correctly" do
money = Spree::Money.new(1000, html_wrap: false)
expect(money.to_s).to eq("¥1,000")
end
end
context "EUR" do
before do
stub_spree_preferences(currency: "EUR")
end
# Regression test for https://github.com/spree/spree/issues/2634
it "formats as plain by default" do
money = Spree::Money.new(10, format: '%n %u')
expect(money.to_s).to eq("10.00 €")
end
it "formats as HTML if asked (nicely) to" do
money = Spree::Money.new(10, format: '%n %u')
# The HTML'ified version of "10.00 €"
expect(money.to_html).to eq("10.00 €")
end
it "formats as HTML with currency" do
money = Spree::Money.new(10, format: '%n %u', with_currency: true)
# The HTML'ified version of "10.00 €"
expect(money.to_html).to eq("10.00 € EUR")
end
end
describe "#as_json" do
let(:options) { double('options') }
it "returns the expected string" do
money = Spree::Money.new(10)
expect(money.as_json(options)).to eq("$10.00")
end
end
describe 'subtraction' do
context "for money objects with same currency" do
let(:money_1) { Spree::Money.new(32.00, currency: "USD") }
let(:money_2) { Spree::Money.new(15.00, currency: "USD") }
it "subtracts correctly" do
expect(money_1 - money_2).to eq(Spree::Money.new(17.00, currency: "USD"))
end
end
context "when trying to subtract money objects in different currencies" do
let(:money_1) { Spree::Money.new(32.00, currency: "EUR") }
let(:money_2) { Spree::Money.new(15.00, currency: "USD") }
it "will not work" do
expect { money_1 - money_2 }.to raise_error(Money::Bank::UnknownRate)
end
end
context "if other does not respond to .money" do
let(:money_1) { Spree::Money.new(32.00, currency: "EUR") }
let(:money_2) { ::Money.new(1500) }
it 'raises a TypeError' do
expect { money_1 - money_2 }.to raise_error(TypeError)
end
end
end
describe 'addition' do
context "for money objects with same currency" do
let(:money_1) { Spree::Money.new(37.00, currency: "USD") }
let(:money_2) { Spree::Money.new(15.00, currency: "USD") }
it "subtracts correctly" do
expect(money_1 + money_2).to eq(Spree::Money.new(52.00, currency: "USD"))
end
end
context "when trying to subtract money objects in different currencies" do
let(:money_1) { Spree::Money.new(32.00, currency: "EUR") }
let(:money_2) { Spree::Money.new(15.00, currency: "USD") }
it "will not work" do
expect { money_1 + money_2 }.to raise_error(Money::Bank::UnknownRate)
end
end
context "if other does not respond to .money" do
let(:money_1) { Spree::Money.new(32.00, currency: "EUR") }
let(:money_2) { ::Money.new(1500) }
it 'raises a TypeError' do
expect { money_1 + money_2 }.to raise_error(TypeError)
end
end
end
describe 'equality checks' do
context "if other does not respond to .money" do
let(:money_1) { Spree::Money.new(32.00, currency: "EUR") }
let(:money_2) { ::Money.new(1500) }
it 'raises a TypeError' do
expect { money_1 == money_2 }.to raise_error(TypeError)
end
end
end
it "includes Comparable" do
expect(described_class).to include(Comparable)
end
describe "<=>" do
let(:usd_10) { Spree::Money.new(10, currency: "USD") }
let(:usd_20) { Spree::Money.new(20, currency: "USD") }
let(:usd_30) { Spree::Money.new(30, currency: "USD") }
it "compares the two amounts" do
expect(usd_20 <=> usd_20).to eq 0
expect(usd_20 <=> usd_10).to be > 0
expect(usd_20 <=> usd_30).to be < 0
end
context "with a non Spree::Money object" do
it "raises an error" do
expect { usd_10 <=> 20 }.to raise_error(TypeError)
end
end
context "with differing currencies" do
let(:cad) { Spree::Money.new(10, currency: "CAD") }
it "raises an error" do
expect { usd_10 <=> cad }.to raise_error(
Spree::Money::DifferentCurrencyError
)
end
end
end
end