Passed
Push — master ( 62401f...daf94f )
by Alec
07:24
created

MoneyTest   A

Complexity

Total Complexity 37

Size/Duplication

Total Lines 464
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 124
dl 0
loc 464
rs 9.44
c 0
b 0
f 0
wmc 37
1
<?php
2
/**
3
 * User: alec
4
 * Date: 05.11.18
5
 * Time: 23:52
6
 */
7
8
namespace Unit\Money;
9
10
11
use AlecRabbit\Money\Calculator\BcMathCalculator;
12
use AlecRabbit\Money\Currency;
13
use AlecRabbit\Money\Money;
14
use PHPUnit\Framework\TestCase;
15
16
class MoneyTest extends TestCase
17
{
18
    /** @test
19
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::newInstanceDataProvider()
20
     * @param $amount
21
     * @param $currency
22
     * @param $resulted_amount
23
     * @param $resulted_currency
24
     */
25
    public function createsNewInstance($amount, $currency, $resulted_amount, $resulted_currency): void
26
    {
27
        $money = new Money($amount, new Currency($currency));
28
        $this->assertEquals($resulted_amount, $money->getAmount());
29
        $this->assertEquals($resulted_currency, $money->getCurrency());
30
    }
31
32
    /** @test
33
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::newInstanceBadDataProvider()
34
     * @param $amount
35
     * @param $currency
36
     */
37
    public function throwsWhenCreatesNewInstance($amount, $currency): void
38
    {
39
        $this->expectException(\InvalidArgumentException::class);
40
        new Money($amount, new Currency($currency));
41
    }
42
43
    /**
44
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::equalityDataProvider()
45
     * @test
46
     * @param $amount
47
     * @param $currency
48
     * @param $second_amount
49
     * @param $second_currency
50
     * @param $equality
51
     */
52
    public function equalsToAnotherMoneyInstance($amount, $currency, $second_amount, $second_currency, $equality): void
53
    {
54
        $money = new Money($amount, new Currency($currency));
55
56
        $this->assertEquals($equality, $money->equals(new Money($second_amount, new Currency($second_currency))));
57
    }
58
59
    /**
60
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::comparisonDataProvider()
61
     * @test
62
     * @param $expected
63
     * @param $amount
64
     * @param $currency
65
     * @param $second_amount
66
     */
67
    public function comparesTwoAmounts($expected, $amount, $currency, $second_amount): void
68
    {
69
        $money = new Money($amount, new Currency($currency));
70
        $other = new Money($second_amount, new Currency($currency));
71
72
        $this->assertEquals($expected, $money->compare($other));
73
        $this->assertEquals(1 === $expected, $money->greaterThan($other));
74
        $this->assertEquals(0 <= $expected, $money->greaterThanOrEqual($other));
75
        $this->assertEquals(-1 === $expected, $money->lessThan($other));
76
        $this->assertEquals(0 >= $expected, $money->lessThanOrEqual($other));
77
78
        if ($expected === 0) {
79
            $this->assertEquals($money, $other);
80
        } else {
81
            $this->assertNotEquals($money, $other);
82
        }
83
        $other = new Money($second_amount, new Currency($currency . 'o'));
84
        $this->expectException(\InvalidArgumentException::class);
85
        $this->assertEquals($expected, $money->compare($other));
86
87
    }
88
89
90
    /**
91
     * @test
92
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::multiplyDataProvider()
93
     * @param $result
94
     * @param $amount
95
     * @param $multiplier
96
     */
97
    public function multipliesTheAmount($result, $amount, $multiplier): void
98
    {
99
        $money = new Money($amount, new Currency('EUR'));
100
101
        $money = $money->multiply($multiplier);
102
103
        $this->assertInstanceOf(Money::class, $money);
104
        $this->assertEquals((string)$result, $money->getAmount());
105
    }
106
107
    /**
108
     * @test
109
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::divideDataProvider()()
110
     * @param $result
111
     * @param $amount
112
     * @param $divisor
113
     */
114
    public function dividesTheAmount($result, $amount, $divisor): void
115
    {
116
        $money = new Money($amount, new Currency('EUR'));
117
        $money = $money->divide($divisor);
118
119
        $this->assertInstanceOf(Money::class, $money);
120
        $this->assertEquals((string)$result, $money->getAmount());
121
    }
122
123
124
//    /**
125
//     * @test
126
//     */
127
//    public function multipliesTheAmountWithLocaleThatUsesCommaSeparator(): void
128
//    {
129
//        $this->setLocale(LC_ALL, 'es_ES.utf8');
130
//
131
//        $money = new Money(100, new Currency('EUR'));
132
//        $money = $money->multiply(0.1);
133
//
134
//        $this->assertInstanceOf(Money::class, $money);
135
//        var_dump($money->getAmount());
136
//        $this->assertEquals(10, $money->getAmount());
137
//    }
138
139
    /**
140
     * @test
141
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::invalidOperandDataProvider()
142
     * @param $operand
143
     */
144
    public function throwsAnExceptionWhenOperandIsInvalidDuringMultiplication($operand): void
145
    {
146
        $money = new Money(1, new Currency('EUR'));
147
        $this->expectException(\InvalidArgumentException::class);
148
        $money->multiply($operand);
149
    }
150
151
    /**
152
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::invalidOperandDataProvider()
153
     * @test
154
     * @param $operand
155
     */
156
    public function throwsAnExceptionWhenOperandIsInvalidDuringDivision($operand): void
157
    {
158
        $money = new Money(1, new Currency('EUR'));
159
        $this->expectException(\InvalidArgumentException::class);
160
        $money->divide($operand);
161
    }
162
163
    /**
164
     * @test
165
     */
166
    public function throwsAnExceptionWhenOperandIsZero(): void
167
    {
168
        $money = new Money(1, new Currency('EUR'));
169
        $this->expectException(\InvalidArgumentException::class);
170
        $money->divide(0);
171
    }
172
173
    /**
174
     * @test
175
     */
176
    public function throwsAnExceptionWhenRatioIsIsEmptyArray(): void
177
    {
178
        $money = new Money(1, new Currency('EUR'));
179
        $this->expectException(\InvalidArgumentException::class);
180
        $money->allocate([]);
181
    }
182
183
    /**
184
     * @test
185
     */
186
    public function throwsAnExceptionWhenRatioIsZero(): void
187
    {
188
        $money = new Money(1, new Currency('EUR'));
189
        $this->expectException(\InvalidArgumentException::class);
190
        $money->allocate([0]);
191
    }
192
193
    /**
194
     * @test
195
     */
196
    public function throwsAnExceptionWhenNumberIsNegative(): void
197
    {
198
        $money = new Money(1, new Currency('EUR'));
199
        $this->expectException(\InvalidArgumentException::class);
200
        $money->allocateTo(-1);
201
    }
202
203
    /**
204
     * @test
205
     */
206
    public function throwsAnExceptionWhenNumberIsZero(): void
207
    {
208
        $money = new Money(1, new Currency('EUR'));
209
        $this->expectException(\InvalidArgumentException::class);
210
        $money->allocateTo(0);
211
    }
212
213
214
    /**
215
     * @test
216
     */
217
    public function throwsAnExceptionWhenRatioIsNegative(): void
218
    {
219
        $money = new Money(1, new Currency('EUR'));
220
        $this->expectException(\InvalidArgumentException::class);
221
        $money->allocate([2, -1]);
222
    }
223
224
    /**
225
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::allocationDataProvider()
226
     * @test
227
     * @param $amount
228
     * @param $ratios
229
     * @param $results
230
     * @param $precision
231
     */
232
    public function allocatesAmount($amount, $ratios, $results, $precision): void
233
    {
234
        $money = new Money($amount, new Currency('EUR'));
235
        $allocated = $money->allocate($ratios, $precision);
236
        /** @var Money $money */
237
        foreach ($allocated as $key => $money) {
238
            $compareTo = new Money($results[$key], $money->getCurrency());
239
            $this->assertEquals($compareTo, $money);
240
        }
241
    }
242
243
244
    /**
245
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::allocationTargetDataProvider()
246
     * @test
247
     * @param $amount
248
     * @param $target
249
     * @param $results
250
     * @param $precision
251
     */
252
    public function allocatesAmountToNTargets($amount, $target, $results, $precision): void
253
    {
254
        $money = new Money($amount, new Currency('EUR'));
255
256
        $allocated = $money->allocateTo($target, $precision);
257
        foreach ($allocated as $key => $money) {
258
            $compareTo = new Money($results[$key], $money->getCurrency());
259
            $this->assertEquals($compareTo, $money);
260
        }
261
    }
262
263
    /**
264
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::comparatorDataProvider()
265
     * @test
266
     * @param $amount
267
     * @param $isZero
268
     * @param $isPositive
269
     * @param $isNegative
270
     */
271
    public function hasComparators($amount, $isZero, $isPositive, $isNegative): void
272
    {
273
        $money = new Money($amount, new Currency('EUR'));
274
275
        $this->assertEquals($isZero, $money->isZero());
276
        $this->assertEquals($isPositive, $money->isPositive());
277
        $this->assertEquals($isNegative, $money->isNegative());
278
    }
279
280
    /**
281
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::comparatorDataProviderTwo()
282
     * @test
283
     * @param $amount
284
     * @param $isNotZero
285
     * @param $isNotPositive
286
     * @param $isNotNegative
287
     */
288
    public function hasComparatorsTwo($amount, $isNotZero, $isNotPositive, $isNotNegative): void
289
    {
290
        $money = new Money($amount, new Currency('EUR'));
291
292
        $this->assertEquals($isNotZero, $money->isNotZero());
293
        $this->assertEquals($isNotPositive, $money->isNotPositive());
294
        $this->assertEquals($isNotNegative, $money->isNotNegative());
295
    }
296
297
    /**
298
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::absoluteDataProvider()
299
     * @test
300
     * @param $amount
301
     * @param $expected
302
     */
303
    public function calculatesTheAbsoluteAmount($expected, $amount): void
304
    {
305
        $money = new Money($amount, new Currency('EUR'));
306
307
        $this->assertEquals($expected, $money->absolute()->getAmount());
308
    }
309
310
    /**
311
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::negativeDataProvider()
312
     * @test
313
     * @param $amount
314
     * @param $result
315
     */
316
    public function calculatesTheNegativeAmount($amount, $result): void
317
    {
318
        $money = new Money($amount, new Currency('EUR'));
319
320
        $money = $money->negative();
321
322
        $this->assertEquals($result, $money->getAmount());
323
    }
324
325
    /**
326
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::modDataProvider()
327
     * @test
328
     * @param $left
329
     * @param $right
330
     * @param $expected
331
     */
332
    public function calculatesTheModulusOfAnAmount($left, $right, $expected): void
333
    {
334
        $money = new Money($left, new Currency('EUR'));
335
        $rightMoney = new Money($right, new Currency('EUR'));
336
337
        $money = $money->mod($rightMoney);
338
339
        $this->assertInstanceOf(Money::class, $money);
340
        $this->assertEquals($expected, $money->getAmount());
341
    }
342
343
    /**
344
     * @test
345
     */
346
    public function convertsToJson(): void
347
    {
348
        $this->assertEquals(
349
            '{"amount":"350","currency":"EUR"}',
350
            json_encode(Money::EUR(350))
351
        );
352
    }
353
354
    /**
355
     * @test
356
     */
357
    public function supportsMaxInt(): void
358
    {
359
        $one = new Money(1, new Currency('EUR'));
360
        $ten = new Money(10, new Currency('EUR'));
361
362
        $this->assertInstanceOf(Money::class, new Money(PHP_INT_MAX, new Currency('EUR')));
363
        $this->assertEquals(
364
            PHP_INT_MAX,
365
            (new Money(PHP_INT_MAX, new Currency('EUR')))->add($one)->add($one)->subtract($one)->subtract($one)->getAmount()
366
        );
367
        $this->assertEquals(
368
            PHP_INT_MAX,
369
            (new Money(PHP_INT_MAX, new Currency('EUR')))->add($ten)->add($one)->subtract($ten)->subtract($one)->getAmount()
370
        );
371
    }
372
373
    /**
374
     * @test
375
     */
376
    public function returnsRatioOf(): void
377
    {
378
        $currency = new Currency('EUR');
379
        $zero = new Money(0, $currency);
380
        $three = new Money(3, $currency);
381
        $six = new Money(6, $currency);
382
383
        $this->assertEquals(0, $zero->ratioOf($six));
384
        $this->assertEquals(0.5, $three->ratioOf($six));
385
        $this->assertEquals(1, $three->ratioOf($three));
386
        $this->assertEquals(2, $six->ratioOf($three));
387
    }
388
389
    /**
390
     * @test
391
     */
392
    public function throwsWhenCalculatingRatioOfZero(): void
393
    {
394
        $this->expectException(\InvalidArgumentException::class);
395
396
        $currency = new Currency('EUR');
397
        $zero = new Money(0, $currency);
398
        $six = new Money(6, $currency);
399
400
        $six->ratioOf($zero);
401
    }
402
403
    /**
404
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::sumDataProvider()
405
     * @test
406
     * @param $values
407
     * @param $sum
408
     */
409
    public function calculatesSum($values, $sum): void
410
    {
411
        $this->assertEquals($sum, Money::sum(...$values));
412
    }
413
414
    /**
415
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::minDataProvider()
416
     * @test
417
     * @param $values
418
     * @param $min
419
     */
420
    public function calculatesMin($values, $min): void
421
    {
422
        $this->assertEquals($min, Money::min(...$values));
423
    }
424
425
    /**
426
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::maxDataProvider()
427
     * @test
428
     * @param $values
429
     * @param $max
430
     */
431
    public function calculatesMax($values, $max): void
432
    {
433
        $this->assertEquals($max, Money::max(...$values));
434
    }
435
436
    /**
437
     * @dataProvider \Unit\DataProviders\MoneyBasicDataProvider::avgDataProvider()
438
     * @test
439
     * @param $values
440
     * @param $avg
441
     */
442
    public function calculatesAvg($values, $avg): void
443
    {
444
        $this->assertEquals($avg, Money::avg(...$values));
445
    }
446
447
    /**
448
     * @test
449
     */
450
    public function throwsWhenCalculatingMinWithZeroArguments(): void
451
    {
452
        $this->expectException(\Throwable::class);
453
        Money::min(...[]);
454
    }
455
456
    /**
457
     * @test
458
     */
459
    public function throwsWhenCalculatingMaxWithZeroArguments(): void
460
    {
461
        $this->expectException(\Throwable::class);
462
        Money::max(...[]);
463
    }
464
465
    /**
466
     * @test
467
     */
468
    public function throwsWhenCalculatingSumWithZeroArguments(): void
469
    {
470
        $this->expectException(\Throwable::class);
471
        Money::sum(...[]);
472
    }
473
474
    /**
475
     * @test
476
     */
477
    public function throwsWhenCalculatingAvgWithZeroArguments(): void
478
    {
479
        $this->expectException(\Throwable::class);
480
        Money::avg(...[]);
481
    }
482
}