Passed
Push — master ( 54e3cc...a9003e )
by Dmitry
14:11
created

ProgressivePriceTest::setUp()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 6
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace hiqdev\php\billing\tests\unit\price;
6
7
use Generator;
8
use hiqdev\php\billing\price\ProgressivePrice;
9
use hiqdev\php\billing\price\ProgressivePriceThresholdList;
10
use hiqdev\php\billing\target\Target;
11
use hiqdev\php\billing\type\Type;
12
use hiqdev\php\units\Quantity;
13
use Money\Currencies\ISOCurrencies;
14
use Money\Currency;
15
use Money\Parser\DecimalMoneyParser;
16
use PHPUnit\Framework\TestCase;
17
18
19
class ProgressivePriceTest extends TestCase
20
{
21
    private Quantity $usage;
22
    private DecimalMoneyParser $moneyParser;
23
24
    protected function setUp(): void
25
    {
26
        parent::setUp();
27
28
        $this->usage = Quantity::mbps(720);
29
        $this->moneyParser = new DecimalMoneyParser(new ISOCurrencies());
30
    }
31
32
    private function createProgressivePrice(string $prepaid, string $startPrice, array $thresholdsArray): ProgressivePrice
33
    {
34
        $type = new Type('2222', 'cdn_traf95_max');
35
        $target = new Target('2222', 'overuse,cdn_traf95_max', 'ProgressivePrice');
36
        $prepaid = Quantity::mbps($prepaid);
37
        $money = $this->moneyParser->parse($startPrice, new Currency('EUR'));
38
        $thresholds = ProgressivePriceThresholdList::fromScalarsArray($thresholdsArray);
39
40
        return new ProgressivePrice('2222', $type, $target, $prepaid, $money, $thresholds);
41
    }
42
43
    /** @dataProvider progressivePriceProvider */
44
    public function testUsageIsConvertedToThresholdUnits(
45
        array $thresholdsArray,
46
        int $expectedAmount,
47
        string $startPrice,
48
        string $prepaid = '0',
49
        array $expectedTrace = [],
50
    ): void {
51
        $this->usage = Quantity::gbps(0.72);
52
        $price = $this->createProgressivePrice(
53
            prepaid: $prepaid,
54
            startPrice: $startPrice,
55
            thresholdsArray: $thresholdsArray
56
        );
57
58
        $amount = $price->calculateSum($this->usage);
59
        $this->assertEquals($expectedAmount, $amount->getAmount());
60
        $trace = array_map(fn($trace) => $trace->__toString(), $price->getCalculationTraces());
61
        $this->assertSame($expectedTrace, $trace);
62
    }
63
64
    /** @dataProvider progressivePriceProvider */
65
    public function testProgressivePriceCalculation(
66
        array $thresholdsArray,
67
        int $expectedAmount,
68
        string $startPrice,
69
        string $prepaid = '0',
70
        array $expectedTrace = [],
71
    ): void {
72
        $price = $this->createProgressivePrice(
73
            prepaid: $prepaid,
74
            startPrice: $startPrice,
75
            thresholdsArray: $thresholdsArray
76
        );
77
78
        $usage = $price->calculateUsage($this->usage);
79
        $this->assertSame($this->usage->getQuantity(), $usage->getQuantity());
80
81
        $amount = $price->calculateSum($this->usage);
82
        $this->assertEquals($expectedAmount, $amount->getAmount());
83
84
        $trace = array_map(fn($trace) => $trace->__toString(), $price->getCalculationTraces());
85
        $this->assertSame($expectedTrace, $trace);
86
    }
87
88
    /**
89
     * @dataProvider progressivePriceProvider
90
     */
91
    public function testProgressivePriceSerialization(
92
        array $inputThresholdsArray,
93
        int $expectedAmount,
0 ignored issues
show
Unused Code introduced by
The parameter $expectedAmount is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

93
        /** @scrutinizer ignore-unused */ int $expectedAmount,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
94
        string $startPrice,
95
        string $prepaid = '0'
96
    ): void {
97
        $price = $this->createProgressivePrice(
98
            prepaid: $prepaid,
99
            startPrice: $startPrice,
100
            thresholdsArray: $inputThresholdsArray
101
        );
102
103
        $unserialized = json_decode(json_encode($price), true);
104
        $this->assertArrayHasKey('id', $unserialized);
105
        $this->assertArrayHasKey('type', $unserialized);
106
        $this->assertArrayHasKey('target', $unserialized);
107
        $this->assertArrayHasKey('thresholds', $unserialized);
108
        $this->assertArrayHasKey('price', $unserialized);
109
        $this->assertArrayHasKey('prepaid', $unserialized);
110
111
        $this->assertSame($price->getId(), $unserialized['id']);
112
113
        $this->assertSame($price->getType()->getId(), $unserialized['type']['id']);
114
        $this->assertSame($price->getType()->getName(), $unserialized['type']['name']);
115
116
        $this->assertSame($price->getTarget()->getId(), $unserialized['target']['id']);
117
        $this->assertSame($price->getTarget()->getType(), $unserialized['target']['type']);
118
        $this->assertSame($price->getTarget()->getName(), $unserialized['target']['name']);
119
120
        $this->assertSame($price->getPrice()->getAmount(), $unserialized['price']['amount']);
121
        $this->assertSame($price->getPrice()->getCurrency()->getCode(), $unserialized['price']['currency']);
122
123
        $this->assertSame($price->getPrepaid()->getQuantity(), $unserialized['prepaid']['quantity']);
124
        $this->assertSame($price->getPrepaid()->getUnit()->getName(), $unserialized['prepaid']['unit']);
125
126
        $thresholdsArray = $price->getThresholds()->get();
127
        $unserializedThresholds = array_reverse($unserialized['thresholds']);
128
        $this->assertCount(count($inputThresholdsArray), $unserializedThresholds);
129
        foreach ($thresholdsArray as $index => $threshold) {
130
            $val = (new \ReflectionObject($threshold))->getProperty('price')->getValue($threshold);
131
            $this->assertSame($val, $unserializedThresholds[$index]['price']);
132
            $this->assertSame($threshold->price()->getCurrency()->getCode(), $unserializedThresholds[$index]['currency']);
133
            $this->assertSame($threshold->quantity()->getQuantity(), $unserializedThresholds[$index]['quantity']);
134
            $this->assertSame($threshold->quantity()->getUnit()->getName(), $unserializedThresholds[$index]['unit']);
135
        }
136
    }
137
138
    private function progressivePriceProvider(): Generator
0 ignored issues
show
Unused Code introduced by
The method progressivePriceProvider() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
139
    {
140
        yield 'Simple case' => [
141
            'thresholds' => [
142
                ['price' => '0.0085', 'currency' => 'EUR', 'quantity' => '0', 'unit' => 'mbps'],
143
                ['price' => '0.0080', 'currency' => 'EUR', 'quantity' => '500', 'unit' => 'mbps'],
144
                ['price' => '0.0075', 'currency' => 'EUR', 'quantity' => '600', 'unit' => 'mbps'],
145
                ['price' => '0.0070', 'currency' => 'EUR', 'quantity' => '700', 'unit' => 'mbps'],
146
                ['price' => '0.0065', 'currency' => 'EUR', 'quantity' => '800', 'unit' => 'mbps'],
147
            ],
148
            'money' => 594,
149
            'price' => '0.0085',
150
            'prepaid' => '0',
151
            'trace' => [
152
                '0mbps * 0.0065 = 0.00',
153
                '20mbps * 0.0070 = 0.14',
154
                '100mbps * 0.0075 = 0.75',
155
                '100mbps * 0.0080 = 0.80',
156
                '500mbps * 0.0085 = 4.25',
157
                '0mbps * 0.01 = 0.00',
158
            ],
159
        ];
160
161
        yield 'Different prices for the same quantity – take higher price' => [
162
            'thresholds' => [
163
                ['price' => '6', 'currency' => 'EUR', 'quantity' => '0', 'unit' => 'mbps'],
164
                ['price' => '4', 'currency' => 'EUR', 'quantity' => '100', 'unit' => 'mbps'], // Here the qty is the same
165
                ['price' => '5000', 'currency' => 'EUR', 'quantity' => '0.1', 'unit' => 'gbps'], // as here, despite units are different
166
                ['price' => '3', 'currency' => 'EUR', 'quantity' => '200', 'unit' => 'mbps'],
167
            ],
168
            'money' => 266000,
169
            'price' => '6',
170
            'prepaid' => '0',
171
            'trace' => [
172
                '520mbps * 3 = 1,560.00',
173
                '0.1gbps * 5000 = 500.00',
174
                '0mbps * 4 = 0.00',
175
                '100mbps * 6 = 600.00',
176
                '0mbps * 6 = 0.00',
177
            ],
178
        ];
179
180
        yield 'Bill without prepaid amount' => [
181
            'thresholds' => [
182
                ['price' => '6', 'currency' => 'EUR', 'quantity' => '100', 'unit' => 'mbps'],
183
                ['price' => '5', 'currency' => 'EUR', 'quantity' => '200', 'unit' => 'mbps'],
184
                ['price' => '4', 'currency' => 'EUR', 'quantity' => '300', 'unit' => 'mbps'],
185
                ['price' => '3', 'currency' => 'EUR', 'quantity' => '400', 'unit' => 'mbps'],
186
            ],
187
            'money' => 306000,
188
            'price' => '6',
189
            'prepaid' => '0',
190
            'trace' => [
191
                '320mbps * 3 = 960.00',
192
                '100mbps * 4 = 400.00',
193
                '100mbps * 5 = 500.00',
194
                '100mbps * 6 = 600.00',
195
                '100mbps * 6 = 600.00',
196
            ],
197
        ];
198
199
        yield 'Bill with prepaid amount' => [
200
            'thresholds' => [
201
                ['price' => '1', 'currency' => 'EUR', 'quantity' => '20', 'unit' => 'mbps'],
202
                ['price' => '0.9', 'currency' => 'EUR', 'quantity' => '30', 'unit' => 'mbps'],
203
                ['price' => '856.00', 'currency' => 'EUR', 'quantity' => '0.1', 'unit' => 'gbps'],
204
                ['price' => '0.5521', 'currency' => 'EUR', 'quantity' => '130.5', 'unit' => 'mbps'],
205
            ],
206
            'result' => 43487,
207
            'price' => '1.03',
208
            'prepaid' => '10',
209
            'trace' => [
210
                '589.5mbps * 0.5521 = 325.46',
211
                '0.0305gbps * 856.00 = 26.11',
212
                '70mbps * 0.9 = 63.00',
213
                '10mbps * 1 = 10.00',
214
                '10mbps * 1.03 = 10.30',
215
            ],
216
        ];
217
    }
218
}
219