1 | <?php declare(strict_types=1); |
||
2 | /** |
||
3 | * This file is part of the daikon-cqrs/money-interop project. |
||
4 | * |
||
5 | * For the full copyright and license information, please view the LICENSE |
||
6 | * file that was distributed with this source code. |
||
7 | */ |
||
8 | |||
9 | namespace Daikon\Tests\Money\ValueObject; |
||
10 | |||
11 | use Daikon\Interop\InvalidArgumentException; |
||
12 | use Daikon\Money\ValueObject\Money; |
||
13 | use Daikon\Money\ValueObject\MoneyInterface; |
||
14 | use PHPUnit\Framework\TestCase; |
||
15 | |||
16 | final class MoneyTest extends TestCase |
||
17 | { |
||
18 | 1 | public function testFromNative(): void |
|
19 | { |
||
20 | 1 | $this->assertEquals('100USD', Money::fromNative('100USD')->toNative()); |
|
21 | 1 | $this->assertEquals('-100A', Money::fromNative('-100A')->toNative()); |
|
22 | 1 | $this->assertNull(Money::fromNative(null)->toNative()); |
|
23 | |||
24 | 1 | $this->expectException(InvalidArgumentException::class); |
|
25 | 1 | Money::fromNative('100'); |
|
26 | } |
||
27 | |||
28 | 1 | public function testToString(): void |
|
29 | { |
||
30 | 1 | $this->assertEquals('100USD1', (string)Money::fromNative('100USD1')); |
|
31 | 1 | $this->assertEquals('-100A', (string)Money::fromNative('-100A')); |
|
32 | 1 | $this->assertEquals('', Money::fromNative(null)); |
|
33 | 1 | $this->assertEquals('', Money::makeEmpty()); |
|
34 | 1 | } |
|
35 | |||
36 | 1 | public function testZero(): void |
|
37 | { |
||
38 | 1 | $this->assertEquals('0AB', Money::zero('AB')->toNative()); |
|
39 | |||
40 | 1 | $this->expectException(InvalidArgumentException::class); |
|
41 | 1 | Money::zero(); |
|
42 | } |
||
43 | |||
44 | 1 | public function testEquals(): void |
|
45 | { |
||
46 | 1 | $money = Money::fromNative('0SAT'); |
|
47 | 1 | $this->assertTrue($money->equals(Money::fromNative('0SAT'))); |
|
48 | 1 | $this->assertFalse($money->equals(Money::fromNative('0MSAT'))); |
|
49 | |||
50 | 1 | $this->assertTrue(Money::makeEmpty()->equals(Money::fromNative(null))); |
|
51 | |||
52 | 1 | $this->expectException(InvalidArgumentException::class); |
|
53 | /** @psalm-suppress InvalidArgument */ |
||
54 | 1 | $money->equals('nan'); |
|
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
55 | } |
||
56 | |||
57 | 1 | public function testGetAmount(): void |
|
58 | { |
||
59 | 1 | $money = Money::fromNative('0SAT'); |
|
60 | 1 | $this->assertSame('0', $money->getAmount()); |
|
61 | |||
62 | 1 | $this->expectException(InvalidArgumentException::class); |
|
63 | 1 | Money::makeEmpty()->getAmount(); |
|
64 | } |
||
65 | |||
66 | 1 | public function testGetCurrency(): void |
|
67 | { |
||
68 | 1 | $money = Money::fromNative('0SAT'); |
|
69 | 1 | $this->assertSame('SAT', $money->getCurrency()); |
|
70 | |||
71 | 1 | $this->expectException(InvalidArgumentException::class); |
|
72 | 1 | Money::makeEmpty()->getCurrency(); |
|
73 | } |
||
74 | |||
75 | 1 | public function testPercentage(): void |
|
76 | { |
||
77 | 1 | $money = Money::fromNative('0SAT'); |
|
78 | 1 | $this->assertEquals('0SAT', (string)$money->percentage(0)); |
|
79 | 1 | $this->assertSame('0SAT', (string)$money->percentage(10)); |
|
80 | 1 | $this->assertSame('0', $money->percentage(10.12345, MoneyInterface::ROUND_UP)->getAmount()); |
|
81 | 1 | $this->assertEquals('0SAT', (string)$money->percentage(100, MoneyInterface::ROUND_DOWN)); |
|
82 | |||
83 | 1 | $money = Money::fromNative('100SAT'); |
|
84 | 1 | $this->assertEquals('0SAT', (string)$money->percentage(0)); |
|
85 | 1 | $this->assertSame('10SAT', (string)$money->percentage(10)); |
|
86 | 1 | $this->assertSame('11', $money->percentage(10.12345, MoneyInterface::ROUND_UP)->getAmount()); |
|
87 | 1 | $this->assertSame('10', $money->percentage(10.12345, MoneyInterface::ROUND_DOWN)->getAmount()); |
|
88 | 1 | $this->assertEquals('100SAT', (string)$money->percentage(100, MoneyInterface::ROUND_DOWN)); |
|
89 | 1 | } |
|
90 | |||
91 | 1 | public function testPercentageOnEmpty(): void |
|
92 | { |
||
93 | 1 | $this->expectException(InvalidArgumentException::class); |
|
94 | 1 | Money::makeEmpty()->percentage(10); |
|
95 | } |
||
96 | |||
97 | 1 | public function testValueAsserts(): void |
|
98 | { |
||
99 | 1 | $money = Money::zero('SAT'); |
|
100 | 1 | $this->assertTrue($money->isZero()); |
|
101 | 1 | $this->assertFalse($money->isPositive()); |
|
102 | 1 | $this->assertFalse($money->isNegative()); |
|
103 | |||
104 | 1 | $money = Money::fromNative('1SAT'); |
|
105 | 1 | $this->assertFalse($money->isZero()); |
|
106 | 1 | $this->assertTrue($money->isPositive()); |
|
107 | 1 | $this->assertFalse($money->isNegative()); |
|
108 | |||
109 | 1 | $money = Money::fromNative('-1SAT'); |
|
110 | 1 | $this->assertFalse($money->isZero()); |
|
111 | 1 | $this->assertFalse($money->isPositive()); |
|
112 | 1 | $this->assertTrue($money->isNegative()); |
|
113 | 1 | } |
|
114 | |||
115 | 1 | public function testIsZeroOnEmpty(): void |
|
116 | { |
||
117 | 1 | $this->expectException(InvalidArgumentException::class); |
|
118 | 1 | Money::makeEmpty()->isZero(); |
|
119 | } |
||
120 | |||
121 | 1 | public function testIsPositiveOnEmpty(): void |
|
122 | { |
||
123 | 1 | $this->expectException(InvalidArgumentException::class); |
|
124 | 1 | Money::makeEmpty()->isPositive(); |
|
125 | } |
||
126 | |||
127 | 1 | public function testIsNegativeOnEmpty(): void |
|
128 | { |
||
129 | 1 | $this->expectException(InvalidArgumentException::class); |
|
130 | 1 | Money::makeEmpty()->isNegative(); |
|
131 | } |
||
132 | |||
133 | 1 | public function testIsLessThanOrEqual(): void |
|
134 | { |
||
135 | 1 | $zero = Money::zero('SAT'); |
|
136 | 1 | $pos = Money::fromNative('1SAT'); |
|
137 | 1 | $neg = Money::fromNative('-1SAT'); |
|
138 | 1 | $this->assertTrue($zero->isLessThanOrEqual($pos)); |
|
139 | 1 | $this->assertFalse($zero->isLessThanOrEqual($neg)); |
|
140 | 1 | $this->assertTrue($zero->isLessThanOrEqual($zero)); |
|
141 | 1 | $this->assertTrue($neg->isLessThanOrEqual($zero)); |
|
142 | 1 | $this->assertTrue($neg->isLessThanOrEqual($pos)); |
|
143 | 1 | $this->assertTrue($neg->isLessThanOrEqual($neg)); |
|
144 | 1 | $this->assertFalse($pos->isLessThanOrEqual($zero)); |
|
145 | 1 | $this->assertFalse($pos->isLessThanOrEqual($neg)); |
|
146 | 1 | $this->assertTrue($pos->isLessThanOrEqual($pos)); |
|
147 | 1 | } |
|
148 | |||
149 | 1 | public function testIsLessThanOrEqualOnEmpty(): void |
|
150 | { |
||
151 | 1 | $money = Money::fromNative('1BTC'); |
|
152 | 1 | $this->expectException(InvalidArgumentException::class); |
|
153 | 1 | Money::makeEmpty()->isLessThanOrEqual($money); |
|
154 | } |
||
155 | |||
156 | 1 | public function testIsLessThanOrEqualWithEmpty(): void |
|
157 | { |
||
158 | 1 | $money = Money::fromNative('1BTC'); |
|
159 | 1 | $this->expectException(InvalidArgumentException::class); |
|
160 | 1 | $money->isLessThanOrEqual(Money::makeEmpty()); |
|
161 | } |
||
162 | |||
163 | 1 | public function testIsLessThanOrEqualWithDifferentCurrency(): void |
|
164 | { |
||
165 | 1 | $money = Money::fromNative('1BTC'); |
|
166 | 1 | $this->expectException(InvalidArgumentException::class); |
|
167 | 1 | Money::zero('USD')->isLessThanOrEqual($money); |
|
168 | } |
||
169 | |||
170 | 1 | public function testIsGreaterThanOrEqual(): void |
|
171 | { |
||
172 | 1 | $zero = Money::zero('SAT'); |
|
173 | 1 | $pos = Money::fromNative('1SAT'); |
|
174 | 1 | $neg = Money::fromNative('-1SAT'); |
|
175 | 1 | $this->assertFalse($zero->isGreaterThanOrEqual($pos)); |
|
176 | 1 | $this->assertTrue($zero->isGreaterThanOrEqual($neg)); |
|
177 | 1 | $this->assertTrue($zero->isGreaterThanOrEqual($zero)); |
|
178 | 1 | $this->assertFalse($neg->isGreaterThanOrEqual($zero)); |
|
179 | 1 | $this->assertFalse($neg->isGreaterThanOrEqual($pos)); |
|
180 | 1 | $this->assertTrue($neg->isGreaterThanOrEqual($neg)); |
|
181 | 1 | $this->assertTrue($pos->isGreaterThanOrEqual($zero)); |
|
182 | 1 | $this->assertTrue($pos->isGreaterThanOrEqual($neg)); |
|
183 | 1 | $this->assertTrue($pos->isGreaterThanOrEqual($pos)); |
|
184 | 1 | } |
|
185 | |||
186 | 1 | public function testIsGreaterThanOrEqualOnEmpty(): void |
|
187 | { |
||
188 | 1 | $money = Money::fromNative('1BTC'); |
|
189 | 1 | $this->expectException(InvalidArgumentException::class); |
|
190 | 1 | Money::makeEmpty()->isGreaterThanOrEqual($money); |
|
191 | } |
||
192 | |||
193 | 1 | public function testIsGreaterThanOrEqualWithEmpty(): void |
|
194 | { |
||
195 | 1 | $money = Money::fromNative('1BTC'); |
|
196 | 1 | $this->expectException(InvalidArgumentException::class); |
|
197 | 1 | $money->isGreaterThanOrEqual(Money::makeEmpty()); |
|
198 | } |
||
199 | |||
200 | 1 | public function testIsGreaterThanOrEqualWithDifferentCurrency(): void |
|
201 | { |
||
202 | 1 | $money = Money::fromNative('1BTC'); |
|
203 | 1 | $this->expectException(InvalidArgumentException::class); |
|
204 | 1 | Money::zero('USD')->isGreaterThanOrEqual($money); |
|
205 | } |
||
206 | |||
207 | 1 | public function testMakeEmpty(): void |
|
208 | { |
||
209 | 1 | $money = Money::makeEmpty(); |
|
210 | 1 | $this->assertTrue($money->isEmpty()); |
|
211 | 1 | $this->assertNull($money->toNative()); |
|
212 | 1 | } |
|
213 | |||
214 | 1 | public function testAdd(): void |
|
215 | { |
||
216 | 1 | $zero = Money::zero('USD'); |
|
217 | 1 | $pos = Money::fromNative('1USD'); |
|
218 | 1 | $neg = Money::fromNative('-1USD'); |
|
219 | 1 | $this->assertEquals('1USD', (string)$zero->add($pos)); |
|
220 | 1 | $this->assertEquals('-1USD', (string)$zero->add($neg)); |
|
221 | 1 | $this->assertEquals('1USD', (string)$pos->add($zero)); |
|
222 | 1 | $this->assertEquals('0USD', (string)$pos->add($neg)); |
|
223 | 1 | $this->assertEquals('-1USD', (string)$neg->add($zero)); |
|
224 | 1 | $this->assertEquals('0USD', (string)$neg->add($pos)); |
|
225 | 1 | } |
|
226 | |||
227 | 1 | public function testAddOnEmpty(): void |
|
228 | { |
||
229 | 1 | $this->expectException(InvalidArgumentException::class); |
|
230 | 1 | Money::makeEmpty()->add(Money::fromNative('1GBP')); |
|
231 | } |
||
232 | |||
233 | 1 | public function testAddWithDifferentCurrency(): void |
|
234 | { |
||
235 | 1 | $money = Money::fromNative('1SAT'); |
|
236 | 1 | $this->expectException(InvalidArgumentException::class); |
|
237 | 1 | $money->add(Money::fromNative('1GBP')); |
|
238 | } |
||
239 | |||
240 | 1 | public function testSubtract(): void |
|
241 | { |
||
242 | 1 | $zero = Money::zero('USD'); |
|
243 | 1 | $pos = Money::fromNative('1USD'); |
|
244 | 1 | $neg = Money::fromNative('-1USD'); |
|
245 | 1 | $this->assertEquals('-1USD', (string)$zero->subtract($pos)); |
|
246 | 1 | $this->assertEquals('1USD', (string)$zero->subtract($neg)); |
|
247 | 1 | $this->assertEquals('1USD', (string)$pos->subtract($zero)); |
|
248 | 1 | $this->assertEquals('2USD', (string)$pos->subtract($neg)); |
|
249 | 1 | $this->assertEquals('-1USD', (string)$neg->subtract($zero)); |
|
250 | 1 | $this->assertEquals('-2USD', (string)$neg->subtract($pos)); |
|
251 | 1 | } |
|
252 | |||
253 | 1 | public function testSubtractOnEmpty(): void |
|
254 | { |
||
255 | 1 | $this->expectException(InvalidArgumentException::class); |
|
256 | 1 | Money::makeEmpty()->subtract(Money::fromNative('1GBP')); |
|
257 | } |
||
258 | |||
259 | 1 | public function testSubtractWithDifferentCurrency(): void |
|
260 | { |
||
261 | 1 | $money = Money::fromNative('1SAT'); |
|
262 | 1 | $this->expectException(InvalidArgumentException::class); |
|
263 | 1 | $money->subtract(Money::fromNative('1GBP')); |
|
264 | } |
||
265 | |||
266 | 1 | public function testMultiply(): void |
|
267 | { |
||
268 | 1 | $zero = Money::zero('USD'); |
|
269 | 1 | $pos = Money::fromNative('12USD'); |
|
270 | 1 | $neg = Money::fromNative('-12USD'); |
|
271 | |||
272 | 1 | $this->assertTrue($zero->multiply(0)->isZero()); |
|
273 | 1 | $this->assertTrue($zero->multiply(2)->isZero()); |
|
274 | 1 | $this->assertTrue($zero->multiply(0.5)->isZero()); |
|
275 | 1 | $this->assertTrue($zero->multiply(-0.2)->isZero()); |
|
276 | |||
277 | 1 | $this->assertTrue($pos->multiply(0)->isZero()); |
|
278 | 1 | $this->assertEquals('24USD', (string)$pos->multiply(2)); |
|
279 | 1 | $this->assertEquals('6USD', (string)$pos->multiply(0.5)); |
|
280 | 1 | $this->assertEquals('-3USD', (string)$pos->multiply(-0.25)); |
|
281 | |||
282 | 1 | $this->assertTrue($neg->multiply(0)->isZero()); |
|
283 | 1 | $this->assertEquals('-24USD', (string)$neg->multiply(2)); |
|
284 | 1 | $this->assertEquals('-6USD', (string)$neg->multiply(0.5)); |
|
285 | 1 | $this->assertEquals('3USD', (string)$neg->multiply(-0.25)); |
|
286 | 1 | } |
|
287 | |||
288 | 1 | public function testMultiplyOnEmpty(): void |
|
289 | { |
||
290 | 1 | $this->expectException(InvalidArgumentException::class); |
|
291 | 1 | Money::makeEmpty()->multiply(2); |
|
292 | } |
||
293 | |||
294 | 1 | public function testMultiplyNonNumeric(): void |
|
295 | { |
||
296 | 1 | $this->expectException(InvalidArgumentException::class); |
|
297 | 1 | Money::makeEmpty()->multiply('x'); |
|
298 | } |
||
299 | |||
300 | 1 | public function testDivide(): void |
|
301 | { |
||
302 | 1 | $zero = Money::zero('USD'); |
|
303 | 1 | $pos = Money::fromNative('12USD'); |
|
304 | 1 | $neg = Money::fromNative('-12USD'); |
|
305 | |||
306 | 1 | $this->assertTrue($zero->divide(2)->isZero()); |
|
307 | 1 | $this->assertTrue($zero->divide(0.5)->isZero()); |
|
308 | 1 | $this->assertTrue($zero->divide(-0.2)->isZero()); |
|
309 | |||
310 | 1 | $this->assertEquals('6USD', (string)$pos->divide(2)); |
|
311 | 1 | $this->assertEquals('24USD', (string)$pos->divide(0.5)); |
|
312 | 1 | $this->assertEquals('-48USD', (string)$pos->divide(-0.25)); |
|
313 | |||
314 | 1 | $this->assertEquals('-6USD', (string)$neg->divide(2)); |
|
315 | 1 | $this->assertEquals('-24USD', (string)$neg->divide(0.5)); |
|
316 | 1 | $this->assertEquals('48USD', (string)$neg->divide(-0.25)); |
|
317 | |||
318 | 1 | $this->expectException(InvalidArgumentException::class); |
|
319 | 1 | $pos->divide(0); |
|
320 | } |
||
321 | |||
322 | 1 | public function testDivideOnEmpty(): void |
|
323 | { |
||
324 | 1 | $this->expectException(InvalidArgumentException::class); |
|
325 | 1 | Money::makeEmpty()->divide(2); |
|
326 | } |
||
327 | |||
328 | 1 | public function testDivideNonNumeric(): void |
|
329 | { |
||
330 | 1 | $this->expectException(InvalidArgumentException::class); |
|
331 | 1 | Money::makeEmpty()->divide('x'); |
|
332 | } |
||
333 | } |
||
334 |