simple_wallet 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,193 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ describe SimpleWallet::TransferService do
6
+ let(:from_account) { create(:simple_wallet_account) }
7
+ let(:to_account) { create(:simple_wallet_account) }
8
+
9
+ let(:amount) { 25 }
10
+ let(:note) { "Here is your alms." }
11
+
12
+ let(:transfer) do
13
+ SimpleWallet::TransferService.new(
14
+ from: from_account,
15
+ to: to_account,
16
+ amount: amount,
17
+ note: note
18
+ )
19
+ end
20
+
21
+ before do
22
+ SimpleWallet::AccountCreditingService.new(
23
+ account: from_account,
24
+ amount: +1_000_000,
25
+ note: "AI income"
26
+ ).credit
27
+
28
+ from_account&.reload
29
+ end
30
+
31
+ describe "Validation" do
32
+ describe "when from account is blank" do
33
+ let(:from_account) { nil }
34
+
35
+ it "returns false and adds an error" do
36
+ refute transfer.transfer
37
+ assert_includes transfer.errors[:from], "can't be blank"
38
+ end
39
+ end
40
+
41
+ describe "when to account is blank" do
42
+ let(:to_account) { nil }
43
+
44
+ it "returns false and adds an error" do
45
+ refute transfer.transfer
46
+ assert_includes transfer.errors[:to], "can't be blank"
47
+ end
48
+ end
49
+
50
+ describe "when amount is zero" do
51
+ let(:amount) { 0 }
52
+
53
+ it "returns false and adds an error" do
54
+ refute transfer.transfer
55
+ assert_includes transfer.errors[:amount], "must be greater than 0"
56
+ end
57
+ end
58
+
59
+ describe "when amount is negative" do
60
+ let(:amount) { -35 }
61
+
62
+ it "returns false and adds an error" do
63
+ refute transfer.transfer
64
+ assert_includes transfer.errors[:amount], "must be greater than 0"
65
+ end
66
+ end
67
+
68
+ describe "when amount is greater than :from account balance" do
69
+ let(:amount) { from_account.balance + 5 }
70
+
71
+ it "returns false and adds an error" do
72
+ refute transfer.transfer
73
+ assert_includes transfer.errors[:amount], "exceeds available balance"
74
+ end
75
+ end
76
+
77
+ describe "when note is blank" do
78
+ let(:note) { "" }
79
+
80
+ it "returns false and adds an error" do
81
+ refute transfer.transfer
82
+ assert_includes transfer.errors[:note], "can't be blank"
83
+ end
84
+ end
85
+ end
86
+
87
+ describe "#transfer" do
88
+ describe "when operation is valid" do
89
+ it "creates debiting transfer for :from account and crediting transfer to :to account" do
90
+ assert_difference -> { from_account.transactions.count }, 1 do
91
+ assert_difference -> { to_account.transactions.count }, 1 do
92
+ assert transfer.transfer
93
+ end
94
+ end
95
+
96
+ from_account.transactions.last.tap do |transaction|
97
+ assert_equal "SimpleWallet::Transaction::Debit", transaction.type
98
+ assert_nil transaction.source
99
+ assert_equal -25, transaction.amount
100
+ assert_equal 1000000, transaction.pre_account_balance
101
+ assert_equal "Here is your alms.", transaction.note
102
+ end
103
+
104
+ to_account.transactions.last.tap do |transaction|
105
+ assert_equal "SimpleWallet::Transaction::Credit", transaction.type
106
+ assert_nil transaction.source
107
+ assert_equal 25, transaction.amount
108
+ assert_equal 0, transaction.pre_account_balance
109
+ assert_equal "Here is your alms.", transaction.note
110
+ end
111
+ end
112
+
113
+ it "tells accounts to recalculate their balances" do
114
+ assert_equal 1_000_000, from_account.reload.balance
115
+ assert_equal 0, to_account.reload.balance
116
+
117
+ assert transfer.transfer
118
+
119
+ assert_equal 999975, from_account.reload.balance
120
+ assert_equal 25, to_account.reload.balance
121
+ end
122
+ end
123
+
124
+ describe "when operation is not valid" do
125
+ let(:note) { "" }
126
+
127
+ it "doesn't create new transfer transaction for any account" do
128
+ assert_no_difference(-> { from_account.transactions.count }) do
129
+ assert_no_difference(-> { to_account.transactions.count }) do
130
+ refute transfer.transfer
131
+ end
132
+ end
133
+ end
134
+
135
+ it "doesn't change any account's balance" do
136
+ assert_no_changes(-> { from_account.reload.balance }) do
137
+ assert_no_changes(-> { to_account.reload.balance }) do
138
+ refute transfer.transfer
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ describe "when something goes wrong when we credit :to account" do
145
+ before do
146
+ # Let's break something to simulate this:
147
+ transfer.send(:crediting_service).send(:crediting_transaction).note = ""
148
+ end
149
+
150
+ it "doesn't create new transfer transaction for any account" do
151
+ assert_no_difference(-> { from_account.transactions.count }) do
152
+ assert_no_difference(-> { to_account.transactions.count }) do
153
+ refute transfer.transfer
154
+ end
155
+ end
156
+
157
+ assert_includes transfer.errors[:note], "can't be blank"
158
+ end
159
+
160
+ it "doesn't change any account's balance" do
161
+ assert_no_changes(-> { from_account.reload.balance }) do
162
+ assert_no_changes(-> { to_account.reload.balance }) do
163
+ refute transfer.transfer
164
+ end
165
+ end
166
+
167
+ assert_includes transfer.errors[:note], "can't be blank"
168
+ end
169
+ end
170
+
171
+ describe "when unexpected error happens" do
172
+ it "doesn't create new transactions for any account" do
173
+ transfer.stub(:after_operation, ->(*args) { raise "Oops" }) do
174
+ assert_no_difference(-> { from_account.transactions.count }) do
175
+ assert_no_difference(-> { to_account.transactions.count }) do
176
+ assert_raises(RuntimeError) { transfer.transfer }
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ it "doesn't change any account's balance" do
183
+ transfer.stub(:after_operation, ->(*args) { raise "Oops" }) do
184
+ assert_no_changes(-> { from_account.reload.balance }) do
185
+ assert_no_changes(-> { to_account.reload.balance }) do
186
+ assert_raises(RuntimeError) { transfer.transfer }
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_wallet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcin Urbanski
@@ -41,6 +41,7 @@ files:
41
41
  - app/services/simple_wallet/account_crediting_service.rb
42
42
  - app/services/simple_wallet/account_debiting_service.rb
43
43
  - app/services/simple_wallet/service.rb
44
+ - app/services/simple_wallet/transfer_service.rb
44
45
  - config/locales/simple_wallet.en.yml
45
46
  - db/migrate/20260329170901_create_simple_wallet_account.rb
46
47
  - db/migrate/20260329181402_create_simple_wallet_transactions.rb
@@ -96,6 +97,7 @@ files:
96
97
  - test/models/transaction/debit_test.rb
97
98
  - test/services/account_crediting_service_test.rb
98
99
  - test/services/account_debiting_service_test.rb
100
+ - test/services/transfer_service_test.rb
99
101
  - test/test_helper.rb
100
102
  homepage: https://github.com/murbanski/simple_wallet
101
103
  licenses:
@@ -171,4 +173,5 @@ test_files:
171
173
  - test/models/transaction/debit_test.rb
172
174
  - test/services/account_crediting_service_test.rb
173
175
  - test/services/account_debiting_service_test.rb
176
+ - test/services/transfer_service_test.rb
174
177
  - test/test_helper.rb