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

ProgressivePriceTest::progressivePriceProvider()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 77
Code Lines 62

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 62
c 1
b 0
f 0
dl 0
loc 77
rs 8.829
cc 1
nc 1
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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