shopify-money 0.14.8 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 186250af5f49f67f218ce8b30f47cd6c20ff762f9fdb2813ca9ffe1d12a7700d
4
- data.tar.gz: 1e6ce179c120a2781dc0be48ee0377c4179e6dc07c8fd6306689947a0847daf4
3
+ metadata.gz: 56953634d128da5cb62dfb11b5c60868a162c4ff7edb9bb810110d17c02469f9
4
+ data.tar.gz: c8e6f0e99b480cfcf9be4183adfc633baf14f0f9ee0d777bea01b225c01cfc09
5
5
  SHA512:
6
- metadata.gz: 3d2076a57d0b364a782ce10ffe8961e8ca57b535b8c12ba006887a92336902694ecf1a9b34538632bdad51ea3bbbf2e44aa15988344a406d16890168c72823a8
7
- data.tar.gz: 8b539f90a996544a93fbb733dbde048460a4a5069e1efef6e44b63ae8e790dd6f90a407b7e4ae0fbbb2d850864b5015204ec8a4663b2d45673589611e16ce02b
6
+ metadata.gz: 4888a59e2f50348092b73c2b7255b215f994f9b47efbd379ad88d6f4624f4eca403840f584f4d5760a17c02d20f38f0fc49f286c0e19e3557e4976037d1f8049
7
+ data.tar.gz: ce77e720fae3724a0cc8303336ac12aee09a7a61862f0ba01f0dc7dce3c4e86f2fd7073ee7828d5cc313b77d9b285dfce07bd84e1d8e289e597e1cf25a349c7d
@@ -50,6 +50,10 @@ class Money
50
50
  self.class == other.class && iso_code == other.iso_code
51
51
  end
52
52
 
53
+ def hash
54
+ [ self.class, iso_code ].hash
55
+ end
56
+
53
57
  def compatible?(other)
54
58
  other.is_a?(NullCurrency) || eql?(other)
55
59
  end
@@ -26,19 +26,10 @@ class Money
26
26
  end
27
27
  alias_method :from_amount, :new
28
28
 
29
- def zero(currency = NULL_CURRENCY)
30
- new(0, currency)
31
- end
32
- alias_method :empty, :zero
33
-
34
29
  def parse(*args, **kwargs)
35
30
  parser.parse(*args, **kwargs)
36
31
  end
37
32
 
38
- def from_cents(cents, currency = nil)
39
- new(cents.round.to_f / 100, currency)
40
- end
41
-
42
33
  def from_subunits(subunits, currency_iso, format: :iso4217)
43
34
  currency = Helpers.value_to_currency(currency_iso)
44
35
 
@@ -106,11 +97,6 @@ class Money
106
97
  coder['currency'] = @currency.iso_code
107
98
  end
108
99
 
109
- def cents
110
- # Money.deprecate('`money.cents` is deprecated and will be removed in the next major release. Please use `money.subunits` instead. Keep in mind, subunits are currency aware.')
111
- (value * 100).to_i
112
- end
113
-
114
100
  def subunits(format: :iso4217)
115
101
  subunit_to_unit_value = if format == :iso4217
116
102
  @currency.subunit_to_unit
@@ -243,10 +229,6 @@ class Money
243
229
  end
244
230
  end
245
231
 
246
- def to_liquid
247
- cents
248
- end
249
-
250
232
  def to_json(options = {})
251
233
  to_s
252
234
  end
@@ -1,5 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
  class Money
3
+ # A placeholder currency for instances where no actual currency is available,
4
+ # as defined by ISO4217. You should rarely, if ever, need to use this
5
+ # directly. It's here mostly for backwards compatibility and for that reason
6
+ # behaves like a dollar, which is how this gem worked before the introduction
7
+ # of currency.
8
+ #
9
+ # Here follows a list of preferred alternatives over using Money with
10
+ # NullCurrency:
11
+ #
12
+ # For comparisons where you don't know the currency beforehand, you can use
13
+ # Numeric predicate methods like #positive?/#negative?/#zero?/#nonzero?.
14
+ # Comparison operators with Numeric (==, !=, <=, =>, <, >) work as well.
15
+ #
16
+ # @example
17
+ # Money.new(1, 'CAD').positive? #=> true
18
+ # Money.new(2, 'CAD') >= 0 #=> true
19
+ #
20
+ # Money with NullCurrency has behaviour that may surprise you, such as
21
+ # database validations or GraphQL enum not allowing the string representation
22
+ # of NullCurrency. Prefer using Money.new(0, currency) where possible, as
23
+ # this sidesteps these issues and provides additional currency check
24
+ # safeties.
25
+ #
26
+ # Unlike other currencies, it is allowed to calculate a Money object with
27
+ # NullCurrency with another currency. The resulting Money object will have
28
+ # the other currency.
29
+ #
30
+ # @example
31
+ # Money.new(0, Money::NULL_CURRENCY) + Money.new(5, 'CAD')
32
+ # #=> #<Money value:5.00 currency:CAD>
33
+ #
3
34
  class NullCurrency
4
35
 
5
36
  attr_reader :iso_code, :iso_numeric, :name, :smallest_denomination, :subunit_symbol,
@@ -9,7 +40,7 @@ class Money
9
40
  @symbol = '$'
10
41
  @disambiguate_symbol = nil
11
42
  @subunit_symbol = nil
12
- @iso_code = 'XXX' # Valid ISO4217
43
+ @iso_code = 'XXX'
13
44
  @iso_numeric = '999'
14
45
  @name = 'No Currency'
15
46
  @smallest_denomination = 1
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  class Money
3
- VERSION = "0.14.8"
3
+ VERSION = "0.15.0"
4
4
  end
@@ -1,3 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'rubocop/cop/money/missing_currency'
4
+ require 'rubocop/cop/money/zero_money'
@@ -20,11 +20,11 @@ module RuboCop
20
20
  #
21
21
 
22
22
  def_node_matcher :money_new, <<~PATTERN
23
- (send (const nil? :Money) {:new :from_amount :from_cents} $...)
23
+ (send (const {nil? cbase} :Money) {:new :from_amount :from_cents} $...)
24
24
  PATTERN
25
25
 
26
26
  def_node_matcher :to_money_without_currency?, <<~PATTERN
27
- (send _ :to_money)
27
+ ({send csend} _ :to_money)
28
28
  PATTERN
29
29
 
30
30
  def_node_matcher :to_money_block?, <<~PATTERN
@@ -42,11 +42,9 @@ module RuboCop
42
42
  add_offense(node, message: 'to_money is missing currency argument')
43
43
  end
44
44
  end
45
+ alias on_csend on_send
45
46
 
46
47
  def autocorrect(node)
47
- currency = cop_config['ReplacementCurrency']
48
- return unless currency
49
-
50
48
  receiver, method, _ = *node
51
49
 
52
50
  lambda do |corrector|
@@ -55,20 +53,30 @@ module RuboCop
55
53
 
56
54
  corrector.replace(
57
55
  node.loc.expression,
58
- "#{receiver.source}.#{method}(#{amount&.source || 0}, '#{currency}')"
56
+ "#{receiver.source}.#{method}(#{amount&.source || 0}, #{replacement_currency})"
59
57
  )
60
58
  end
61
59
 
62
60
  if to_money_without_currency?(node)
63
- corrector.insert_after(node.loc.expression, "('#{currency}')")
61
+ corrector.insert_after(node.loc.expression, "(#{replacement_currency})")
64
62
  elsif to_money_block?(node)
65
63
  corrector.replace(
66
64
  node.loc.expression,
67
- "#{receiver.source}.#{method} { |x| x.to_money('#{currency}') }"
65
+ "#{receiver.source}.#{method} { |x| x.to_money(#{replacement_currency}) }"
68
66
  )
69
67
  end
70
68
  end
71
69
  end
70
+
71
+ private
72
+
73
+ def replacement_currency
74
+ if cop_config['ReplacementCurrency']
75
+ "'#{cop_config['ReplacementCurrency']}'"
76
+ else
77
+ 'Money::NULL_CURRENCY'
78
+ end
79
+ end
72
80
  end
73
81
  end
74
82
  end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Money
6
+ class ZeroMoney < Cop
7
+ # `Money.zero` and it's alias `empty`, with or without currency
8
+ # argument is removed in favour of the more explicit Money.new
9
+ # syntax. Supplying it with a real currency is preferred for
10
+ # additional currency safety checks.
11
+ #
12
+ # If no currency was supplied, it defaults to
13
+ # Money::NULL_CURRENCY which was the default setting of
14
+ # Money.default_currency and should effectively be the same. The cop
15
+ # can be configured with a ReplacementCurrency in case that is more
16
+ # appropriate for your application.
17
+ #
18
+ # @example
19
+ #
20
+ # # bad
21
+ # Money.zero
22
+ #
23
+ # # good when configured with `ReplacementCurrency: CAD`
24
+ # Money.new(0, 'CAD')
25
+ #
26
+
27
+ MSG = 'Money.zero is removed, use `Money.new(0, %<currency>s)`.'
28
+
29
+ def_node_matcher :money_zero, <<~PATTERN
30
+ (send (const {nil? cbase} :Money) {:zero :empty} $...)
31
+ PATTERN
32
+
33
+ def on_send(node)
34
+ money_zero(node) do |currency_arg|
35
+ add_offense(node, message: format(MSG, currency: replacement_currency(currency_arg)))
36
+ end
37
+ end
38
+
39
+ def autocorrect(node)
40
+ receiver, _ = *node
41
+
42
+ lambda do |corrector|
43
+ money_zero(node) do |currency_arg|
44
+ replacement_currency = replacement_currency(currency_arg)
45
+
46
+ corrector.replace(
47
+ node.loc.expression,
48
+ "#{receiver.source}.new(0, #{replacement_currency})"
49
+ )
50
+ end
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def replacement_currency(currency_arg)
57
+ return currency_arg.first.source unless currency_arg.empty?
58
+ return "'#{cop_config['ReplacementCurrency']}'" if cop_config['ReplacementCurrency']
59
+
60
+ 'Money::NULL_CURRENCY'
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -43,7 +43,7 @@ RSpec.describe "Allocator" do
43
43
 
44
44
  specify "#allocate will convert rationals with high precision" do
45
45
  ratios = [Rational(1, 1), Rational(0)]
46
- expect(new_allocator("858993456.12").allocate(ratios)).to eq([Money.new("858993456.12"), Money.empty])
46
+ expect(new_allocator("858993456.12").allocate(ratios)).to eq([Money.new("858993456.12"), Money.new(0, Money::NULL_CURRENCY)])
47
47
  ratios = [Rational(1, 6), Rational(5, 6)]
48
48
  expect(new_allocator("3.00").allocate(ratios)).to eq([Money.new("0.50"), Money.new("2.50")])
49
49
  end
@@ -131,8 +131,8 @@ RSpec.describe "Allocator" do
131
131
 
132
132
  specify "#allocate_max_amounts supports all-zero maxima" do
133
133
  expect(
134
- new_allocator(3).allocate_max_amounts([Money.empty, Money.empty, Money.empty]),
135
- ).to eq([Money.empty, Money.empty, Money.empty])
134
+ new_allocator(3).allocate_max_amounts([Money.new(0, Money::NULL_CURRENCY), Money.new(0, Money::NULL_CURRENCY), Money.new(0, Money::NULL_CURRENCY)]),
135
+ ).to eq([Money.new(0, Money::NULL_CURRENCY), Money.new(0, Money::NULL_CURRENCY), Money.new(0, Money::NULL_CURRENCY)])
136
136
  end
137
137
 
138
138
  specify "#allocate_max_amounts allocates the right amount without rounding error" do
@@ -17,7 +17,7 @@ RSpec.describe Integer do
17
17
  it_should_behave_like "an object supporting to_money"
18
18
 
19
19
  it "parses 0 to Money.zero" do
20
- expect(0.to_money).to eq(Money.zero)
20
+ expect(0.to_money).to eq(Money.new(0, Money::NULL_CURRENCY))
21
21
  end
22
22
  end
23
23
 
@@ -30,7 +30,7 @@ RSpec.describe Float do
30
30
  it_should_behave_like "an object supporting to_money"
31
31
 
32
32
  it "parses 0.0 to Money.zero" do
33
- expect(0.0.to_money).to eq(Money.zero)
33
+ expect(0.0.to_money).to eq(Money.new(0, Money::NULL_CURRENCY))
34
34
  end
35
35
  end
36
36
 
@@ -43,8 +43,8 @@ RSpec.describe String do
43
43
  it_should_behave_like "an object supporting to_money"
44
44
 
45
45
  it "parses an empty string to Money.zero" do
46
- expect(''.to_money).to eq(Money.zero)
47
- expect(' '.to_money).to eq(Money.zero)
46
+ expect(''.to_money).to eq(Money.new(0, Money::NULL_CURRENCY))
47
+ expect(' '.to_money).to eq(Money.new(0, Money::NULL_CURRENCY))
48
48
  end
49
49
  end
50
50
 
@@ -57,6 +57,6 @@ RSpec.describe BigDecimal do
57
57
  it_should_behave_like "an object supporting to_money"
58
58
 
59
59
  it "parses a zero BigDecimal to Money.zero" do
60
- expect(BigDecimal("-0.000").to_money).to eq(Money.zero)
60
+ expect(BigDecimal("-0.000").to_money).to eq(Money.new(0, Money::NULL_CURRENCY))
61
61
  end
62
62
  end
@@ -77,6 +77,16 @@ RSpec.describe "Currency" do
77
77
  end
78
78
  end
79
79
 
80
+ describe "#hash" do
81
+ specify "equal currencies from different loaders have the same hash" do
82
+ currency_1 = Money::Currency.find('USD')
83
+ currency_2 = YAML.load(Money::Currency.find('USD').to_yaml)
84
+
85
+ expect(currency_1.eql?(currency_2)).to eq(true)
86
+ expect(currency_1.hash).to eq(currency_2.hash)
87
+ end
88
+ end
89
+
80
90
  describe "==" do
81
91
  it "returns true when both objects have the same currency" do
82
92
  expect(currency == Money.new(1, 'USD').currency).to eq(true)
@@ -136,7 +136,7 @@ RSpec.describe 'MoneyColumn' do
136
136
 
137
137
  it 'does not overwrite a currency column with a default currency when saving zero' do
138
138
  expect(record.currency.to_s).to eq('EUR')
139
- record.update(price: Money.zero)
139
+ record.update(price: Money.new(0, Money::NULL_CURRENCY))
140
140
  expect(record.currency.to_s).to eq('EUR')
141
141
  end
142
142
 
@@ -8,12 +8,12 @@ RSpec.describe MoneyParser do
8
8
 
9
9
  describe "parsing of amounts with period decimal separator" do
10
10
  it "parses an empty string to $0" do
11
- expect(@parser.parse("")).to eq(Money.zero)
11
+ expect(@parser.parse("")).to eq(Money.new(0, Money::NULL_CURRENCY))
12
12
  end
13
13
 
14
14
  it "parses an invalid string when not strict" do
15
15
  expect(Money).to receive(:deprecate).twice
16
- expect(@parser.parse("no money")).to eq(Money.zero)
16
+ expect(@parser.parse("no money")).to eq(Money.new(0, Money::NULL_CURRENCY))
17
17
  expect(@parser.parse("1..")).to eq(Money.new(1))
18
18
  end
19
19
 
@@ -9,10 +9,6 @@ RSpec.describe "Money" do
9
9
  let (:non_fractional_money) { Money.new(1, 'JPY') }
10
10
  let (:zero_money) { Money.new(0) }
11
11
 
12
- it "is contructable with empty class method" do
13
- expect(Money.empty).to eq(Money.new)
14
- end
15
-
16
12
  context "default currency not set" do
17
13
  before(:each) do
18
14
  @default_currency = Money.default_currency
@@ -28,15 +24,11 @@ RSpec.describe "Money" do
28
24
  end
29
25
 
30
26
  it ".zero has no currency" do
31
- expect(Money.zero.currency).to be_a(Money::NullCurrency)
27
+ expect(Money.new(0, Money::NULL_CURRENCY).currency).to be_a(Money::NullCurrency)
32
28
  end
33
29
 
34
30
  it ".zero is a 0$ value" do
35
- expect(Money.zero).to eq(Money.new(0))
36
- end
37
-
38
- it ".zero accepts an optional currency" do
39
- expect(Money.zero('USD')).to eq(Money.new(0, 'USD'))
31
+ expect(Money.new(0, Money::NULL_CURRENCY)).to eq(Money.new(0))
40
32
  end
41
33
 
42
34
  it "returns itself with to_money" do
@@ -247,11 +239,6 @@ RSpec.describe "Money" do
247
239
  expect((1.50 * Money.new(1.00))).to eq(Money.new(1.50))
248
240
  end
249
241
 
250
- it "is multipliable by a cents amount" do
251
- expect((Money.new(1.00) * 0.50)).to eq(Money.new(0.50))
252
- expect((0.50 * Money.new(1.00))).to eq(Money.new(0.50))
253
- end
254
-
255
242
  it "is multipliable by a rational" do
256
243
  expect((Money.new(3.3) * Rational(1, 12))).to eq(Money.new(0.28))
257
244
  expect((Rational(1, 12) * Money.new(3.3))).to eq(Money.new(0.28))
@@ -306,10 +293,6 @@ RSpec.describe "Money" do
306
293
  expect { Money.new(55.00) / 55 }.to raise_error(RuntimeError)
307
294
  end
308
295
 
309
- it "returns cents in to_liquid" do
310
- expect(Money.new(1.00).to_liquid).to eq(100)
311
- end
312
-
313
296
  it "returns cents in to_json" do
314
297
  expect(Money.new(1.00).to_json).to eq("1.00")
315
298
  end
@@ -330,19 +313,7 @@ RSpec.describe "Money" do
330
313
  expect(Money.new(1.50).to_f.to_s).to eq("1.5")
331
314
  end
332
315
 
333
- it "is creatable from an integer value in cents" do
334
- expect(Money.from_cents(1950)).to eq(Money.new(19.50))
335
- end
336
-
337
- it "is creatable from an integer value of 0 in cents" do
338
- expect(Money.from_cents(0)).to eq(Money.new)
339
- end
340
-
341
- it "is creatable from a float cents amount" do
342
- expect(Money.from_cents(1950.5)).to eq(Money.new(19.51))
343
- end
344
-
345
- describe '#from_subunits' do
316
+ describe '#from_subunits' do
346
317
  it "creates Money object from an integer value in cents and currency" do
347
318
  expect(Money.from_subunits(1950, 'CAD')).to eq(Money.new(19.50))
348
319
  end
@@ -619,10 +590,6 @@ RSpec.describe "Money" do
619
590
  expect(money.value).to eq(BigDecimal("1.00"))
620
591
  end
621
592
 
622
- it "returns cents as 100 cents" do
623
- expect(money.cents).to eq(100)
624
- end
625
-
626
593
  it "returns cents as 100 cents" do
627
594
  expect(money.subunits).to eq(100)
628
595
  end
@@ -783,20 +750,6 @@ RSpec.describe "Money" do
783
750
  end
784
751
 
785
752
  describe "from_amount quacks like RubyMoney" do
786
- it "accepts numeric values" do
787
- expect(Money.from_amount(1)).to eq Money.from_cents(1_00)
788
- expect(Money.from_amount(1.0)).to eq Money.from_cents(1_00)
789
- expect(Money.from_amount(BigDecimal("1"))).to eq Money.from_cents(1_00)
790
- end
791
-
792
- it "accepts string values" do
793
- expect(Money.from_amount("1")).to eq Money.from_cents(1_00)
794
- end
795
-
796
- it "accepts nil values" do
797
- expect(Money.from_amount(nil)).to eq Money.from_cents(0)
798
- end
799
-
800
753
  it "accepts an optional currency parameter" do
801
754
  expect { Money.from_amount(1, "CAD") }.to_not raise_error
802
755
  end
@@ -816,10 +769,14 @@ RSpec.describe "Money" do
816
769
  money = YAML.dump(Money.new(750, 'usd'))
817
770
  expect(money).to eq("--- !ruby/object:Money\nvalue: '750.0'\ncurrency: USD\n")
818
771
  end
772
+
773
+ it "does not change BigDecimal value to Integer while rounding for currencies without subunits" do
774
+ money = Money.new(100, 'JPY').to_yaml
775
+ expect(money).to eq("--- !ruby/object:Money\nvalue: '100.0'\ncurrency: JPY\n")
776
+ end
819
777
  end
820
778
 
821
779
  describe "YAML deserialization" do
822
-
823
780
  it "accepts values with currencies" do
824
781
  money = YAML.load("--- !ruby/object:Money\nvalue: '750.0'\ncurrency: USD\n")
825
782
  expect(money).to eq(Money.new(750, 'usd'))
@@ -963,10 +920,4 @@ RSpec.describe "Money" do
963
920
  expect(money.currency.iso_code).to eq('EUR')
964
921
  end
965
922
  end
966
-
967
- describe '#to_yaml' do
968
- it 'returns a yaml representation' do
969
- expect(Money.new(100, 'JPY').to_yaml).to eq("--- !ruby/object:Money\nvalue: '100.0'\ncurrency: JPY\n")
970
- end
971
- end
972
923
  end
@@ -8,12 +8,16 @@ RSpec.describe RuboCop::Cop::Money::MissingCurrency do
8
8
 
9
9
  let(:config) { RuboCop::Config.new }
10
10
 
11
- describe '#on_send' do
12
- it 'registers an offense for Money.new without a currency argument' do
11
+ context 'with default configuration' do
12
+ it 'registers an offense and corrects for Money.new without a currency argument' do
13
13
  expect_offense(<<~RUBY)
14
14
  Money.new(1)
15
15
  ^^^^^^^^^^^^ Money is missing currency argument
16
16
  RUBY
17
+
18
+ expect_correction(<<~RUBY)
19
+ Money.new(1, Money::NULL_CURRENCY)
20
+ RUBY
17
21
  end
18
22
 
19
23
  it 'does not register an offense for Money.new with currency argument' do
@@ -22,18 +26,26 @@ RSpec.describe RuboCop::Cop::Money::MissingCurrency do
22
26
  RUBY
23
27
  end
24
28
 
25
- it 'registers an offense for Money.new without a currency argument' do
29
+ it 'registers an offense and corrects for Money.new without a currency argument' do
26
30
  expect_offense(<<~RUBY)
27
31
  Money.new
28
32
  ^^^^^^^^^ Money is missing currency argument
29
33
  RUBY
34
+
35
+ expect_correction(<<~RUBY)
36
+ Money.new(0, Money::NULL_CURRENCY)
37
+ RUBY
30
38
  end
31
39
 
32
- it 'registers an offense for Money.from_amount without a currency argument' do
40
+ it 'registers an offense and corrects for Money.from_amount without a currency argument' do
33
41
  expect_offense(<<~RUBY)
34
42
  Money.from_amount(1)
35
43
  ^^^^^^^^^^^^^^^^^^^^ Money is missing currency argument
36
44
  RUBY
45
+
46
+ expect_correction(<<~RUBY)
47
+ Money.from_amount(1, Money::NULL_CURRENCY)
48
+ RUBY
37
49
  end
38
50
 
39
51
  it 'does not register an offense for Money.from_amount with currency argument' do
@@ -42,11 +54,15 @@ RSpec.describe RuboCop::Cop::Money::MissingCurrency do
42
54
  RUBY
43
55
  end
44
56
 
45
- it 'registers an offense for Money.from_cents without a currency argument' do
57
+ it 'registers an offense and corrects for Money.from_cents without a currency argument' do
46
58
  expect_offense(<<~RUBY)
47
59
  Money.from_cents(1)
48
60
  ^^^^^^^^^^^^^^^^^^^ Money is missing currency argument
49
61
  RUBY
62
+
63
+ expect_correction(<<~RUBY)
64
+ Money.from_cents(1, Money::NULL_CURRENCY)
65
+ RUBY
50
66
  end
51
67
 
52
68
  it 'does not register an offense for Money.from_cents with currency argument' do
@@ -55,11 +71,26 @@ RSpec.describe RuboCop::Cop::Money::MissingCurrency do
55
71
  RUBY
56
72
  end
57
73
 
58
- it 'registers an offense for to_money without a currency argument' do
74
+ it 'registers an offense and corrects for to_money without a currency argument' do
59
75
  expect_offense(<<~RUBY)
60
76
  '1'.to_money
61
77
  ^^^^^^^^^^^^ to_money is missing currency argument
62
78
  RUBY
79
+
80
+ expect_correction(<<~RUBY)
81
+ '1'.to_money(Money::NULL_CURRENCY)
82
+ RUBY
83
+ end
84
+
85
+ it 'registers an offense and corrects for safe navigation to_money without a currency argument' do
86
+ expect_offense(<<~RUBY)
87
+ item&.to_money
88
+ ^^^^^^^^^^^^^^ to_money is missing currency argument
89
+ RUBY
90
+
91
+ expect_correction(<<~RUBY)
92
+ item&.to_money(Money::NULL_CURRENCY)
93
+ RUBY
63
94
  end
64
95
 
65
96
  it 'does not register an offense for to_money with currency argument' do
@@ -68,15 +99,19 @@ RSpec.describe RuboCop::Cop::Money::MissingCurrency do
68
99
  RUBY
69
100
  end
70
101
 
71
- it 'registers an offense for to_money block pass form' do
102
+ it 'registers an offense and corrects for to_money block pass form' do
72
103
  expect_offense(<<~RUBY)
73
104
  ['1'].map(&:to_money)
74
105
  ^^^^^^^^^^^^^^^^^^^^^ to_money is missing currency argument
75
106
  RUBY
107
+
108
+ expect_correction(<<~RUBY)
109
+ ['1'].map { |x| x.to_money(Money::NULL_CURRENCY) }
110
+ RUBY
76
111
  end
77
112
  end
78
113
 
79
- describe '#autocorrect' do
114
+ context 'with ReplacementCurrency configuration' do
80
115
  let(:config) do
81
116
  RuboCop::Config.new(
82
117
  'Money/MissingCurrency' => {
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../rubocop_helper'
4
+ require 'rubocop/cop/money/zero_money'
5
+
6
+ RSpec.describe RuboCop::Cop::Money::ZeroMoney do
7
+ subject(:cop) { described_class.new(config) }
8
+
9
+ let(:config) { RuboCop::Config.new }
10
+
11
+ context 'with default configuration' do
12
+ it 'registers an offense and corrects Money.zero without currency' do
13
+ expect_offense(<<~RUBY)
14
+ Money.zero
15
+ ^^^^^^^^^^ Money.zero is removed, use `Money.new(0, Money::NULL_CURRENCY)`.
16
+ RUBY
17
+
18
+ expect_correction(<<~RUBY)
19
+ Money.new(0, Money::NULL_CURRENCY)
20
+ RUBY
21
+ end
22
+
23
+ it 'registers an offense and corrects Money.zero with currency' do
24
+ expect_offense(<<~RUBY)
25
+ Money.zero('CAD')
26
+ ^^^^^^^^^^^^^^^^^ Money.zero is removed, use `Money.new(0, 'CAD')`.
27
+ RUBY
28
+
29
+ expect_correction(<<~RUBY)
30
+ Money.new(0, 'CAD')
31
+ RUBY
32
+ end
33
+
34
+ it 'does not register an offense when using Money.new with a currency' do
35
+ expect_no_offenses(<<~RUBY)
36
+ Money.new(0, 'CAD')
37
+ RUBY
38
+ end
39
+ end
40
+
41
+ context 'with ReplacementCurrency configuration' do
42
+ let(:config) do
43
+ RuboCop::Config.new(
44
+ 'Money/ZeroMoney' => {
45
+ 'ReplacementCurrency' => 'CAD'
46
+ }
47
+ )
48
+ end
49
+
50
+ it 'registers an offense and corrects Money.zero without currency' do
51
+ expect_offense(<<~RUBY)
52
+ Money.zero
53
+ ^^^^^^^^^^ Money.zero is removed, use `Money.new(0, 'CAD')`.
54
+ RUBY
55
+
56
+ expect_correction(<<~RUBY)
57
+ Money.new(0, 'CAD')
58
+ RUBY
59
+ end
60
+
61
+ it 'registers an offense and corrects Money.zero with currency' do
62
+ expect_offense(<<~RUBY)
63
+ Money.zero('EUR')
64
+ ^^^^^^^^^^^^^^^^^ Money.zero is removed, use `Money.new(0, 'EUR')`.
65
+ RUBY
66
+
67
+ expect_correction(<<~RUBY)
68
+ Money.new(0, 'EUR')
69
+ RUBY
70
+ end
71
+
72
+ it 'does not register an offense when using Money.new with a currency' do
73
+ expect_no_offenses(<<~RUBY)
74
+ Money.new(0, 'EUR')
75
+ RUBY
76
+ end
77
+ end
78
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify-money
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.8
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify Inc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-06 00:00:00.000000000 Z
11
+ date: 2021-01-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -135,6 +135,7 @@ files:
135
135
  - lib/money_column/railtie.rb
136
136
  - lib/rubocop/cop/money.rb
137
137
  - lib/rubocop/cop/money/missing_currency.rb
138
+ - lib/rubocop/cop/money/zero_money.rb
138
139
  - lib/shopify-money.rb
139
140
  - money.gemspec
140
141
  - spec/accounting_money_parser_spec.rb
@@ -149,6 +150,7 @@ files:
149
150
  - spec/money_spec.rb
150
151
  - spec/null_currency_spec.rb
151
152
  - spec/rubocop/cop/money/missing_currency_spec.rb
153
+ - spec/rubocop/cop/money/zero_money_spec.rb
152
154
  - spec/rubocop_helper.rb
153
155
  - spec/schema.rb
154
156
  - spec/spec_helper.rb
@@ -189,6 +191,7 @@ test_files:
189
191
  - spec/money_spec.rb
190
192
  - spec/null_currency_spec.rb
191
193
  - spec/rubocop/cop/money/missing_currency_spec.rb
194
+ - spec/rubocop/cop/money/zero_money_spec.rb
192
195
  - spec/rubocop_helper.rb
193
196
  - spec/schema.rb
194
197
  - spec/spec_helper.rb