Passed
Push — master ( 371a88...d5ff9b )
by Carsten
01:52
created

BasketTest::testTotals()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 10
nc 1
nop 0
1
<?php
2
3
namespace Tests;
4
5
/**
6
 * This file is part of Lenius Basket, a PHP package to handle
7
 * your shopping basket.
8
 *
9
 * Copyright (c) 2017 Lenius.
10
 * http://github.com/lenius/basket
11
 *
12
 * For the full copyright and license information, please view the LICENSE
13
 * file that was distributed with this source code.
14
 *
15
 * @author Carsten Jonstrup<[email protected]>
16
 * @copyright 2017 Lenius.
17
 *
18
 * @version dev
19
 *
20
 * @link http://github.com/lenius/basket
21
 */
22
use Lenius\Basket\Basket;
23
use Lenius\Basket\Identifier\Runtime as RuntimeIdentifier;
24
use Lenius\Basket\Storage\Runtime as RuntimeStore;
25
use PHPUnit\Framework\TestCase;
26
27
class BasketTest extends TestCase
28
{
29
30
    private $basket;
31
32
    public function setUp()
33
    {
34
        $this->basket = new Basket(new RuntimeStore(), new RuntimeIdentifier());
35
    }
36
37
    public function tearDown()
38
    {
39
        $this->basket->destroy();
40
    }
41
42
    public function testInsert()
43
    {
44
        $actualId = $this->basket->insert([
45
            'id'       => 'foo',
46
            'name'     => 'bar',
47
            'price'    => 100,
48
            'quantity' => 1,
49
            'weight'   => 200,
50
        ]);
51
52
        $identifier = md5('foo'.serialize([]));
53
54
        $this->assertEquals($identifier, $actualId);
55
    }
56
57
    public function testInsertIncrements()
58
    {
59
        $this->basket->insert([
60
            'id'       => 'foo',
61
            'name'     => 'bar',
62
            'price'    => 150,
63
            'quantity' => 1,
64
            'weight'   => 200,
65
        ]);
66
67
        $this->assertEquals(150, $this->basket->total());
68
69
        $this->basket->insert([
70
            'id'       => 'foo',
71
            'name'     => 'bar',
72
            'price'    => 150,
73
            'quantity' => 1,
74
            'weight'   => 200,
75
        ]);
76
77
        $this->assertEquals(300, $this->basket->total());
78
    }
79
80 View Code Duplication
    public function testUpdate()
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
81
    {
82
        $actualId = $this->basket->insert([
83
            'id'       => 'foo',
84
            'name'     => 'bar',
85
            'price'    => 100,
86
            'quantity' => 1,
87
            'weight'   => 200,
88
        ]);
89
90
        $this->basket->update($actualId, 'name', 'baz');
91
92
        $this->assertEquals('baz', $this->basket->item($actualId)->name);
0 ignored issues
show
Documentation introduced by
The property name does not exist on object<Lenius\Basket\Item>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
93
    }
94
95 View Code Duplication
    public function testMagicUpdate()
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
96
    {
97
        $actualId = $this->basket->insert([
98
            'id'       => 'foo',
99
            'name'     => 'bar',
100
            'price'    => 100,
101
            'quantity' => 1,
102
            'weight'   => 200,
103
        ]);
104
105
        foreach ($this->basket->contents() as $item) {
106
            $item->name = 'bim';
107
        }
108
109
        $this->assertEquals('bim', $this->basket->item($actualId)->name);
0 ignored issues
show
Documentation introduced by
The property name does not exist on object<Lenius\Basket\Item>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
110
    }
111
112
    public function testOptions()
113
    {
114
        $actualId = $this->basket->insert([
115
            'id'       => 'foo',
116
            'name'     => 'bar',
117
            'price'    => 100,
118
            'quantity' => 1,
119
            'weight'   => 200,
120
            'options'  => [
121
                [
122
                    'name'   => 'size',
123
                    'price'  => 50,
124
                    'weight' => 100,
125
                ],
126
            ],
127
        ]);
128
129
        $item = $this->basket->item($actualId);
130
131
        $this->assertTrue($item->hasOptions());
132
        $this->assertNotEmpty($item->options);
0 ignored issues
show
Documentation introduced by
The property options does not exist on object<Lenius\Basket\Item>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
133
134
        $item->options = [];
0 ignored issues
show
Documentation introduced by
The property options does not exist on object<Lenius\Basket\Item>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
135
136
        $this->assertFalse($item->hasOptions());
137
        $this->assertEmpty($item->options);
0 ignored issues
show
Documentation introduced by
The property options does not exist on object<Lenius\Basket\Item>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
138
    }
139
140
    public function testWeight()
141
    {
142
        $weight = rand(200, 300);
143
144
        $this->basket->insert([
145
            'id'       => 'foo',
146
            'name'     => 'bar',
147
            'price'    => 100,
148
            'quantity' => 1,
149
            'weight'   => $weight,
150
            'options'  => [
151
                [
152
                    'name'  => 'size',
153
                    'price' => 50,
154
                ],
155
            ],
156
        ]);
157
158
        // Test that the total weight is being calculated successfully
159
        $this->assertEquals($weight, $this->basket->weight());
160
    }
161
162
    public function testWeightOption()
163
    {
164
        $weight = rand(200, 300);
165
        $weight_option = rand(50, 800);
166
        $quantity = rand(1, 10);
167
168
        $this->basket->insert([
169
            'id'       => 'foo',
170
            'name'     => 'bar',
171
            'price'    => 100,
172
            'quantity' => $quantity,
173
            'weight'   => $weight,
174
            'options'  => [
175
                [
176
                    'name'   => 'size',
177
                    'price'  => 50,
178
                    'weight' => $weight_option,
179
                ],
180
            ],
181
        ]);
182
183
        // Test that the total weight is being calculated successfully
184
        $this->assertEquals(($weight + $weight_option) * $quantity, $this->basket->weight());
185
    }
186
187 View Code Duplication
    public function testPriceOption()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
188
    {
189
        $weight = rand(200, 300);
190
        $weight_option = rand(50, 800);
191
        $quantity = rand(1, 10);
0 ignored issues
show
Unused Code introduced by
$quantity is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
192
193
        $this->basket->insert([
194
            'id'       => 'foo',
195
            'name'     => 'bar',
196
            'price'    => 100,
197
            'tax'      => 25,
198
            'quantity' => 1,
199
            'weight'   => $weight,
200
            'options'  => [
201
                [
202
                    'name'   => 'size',
203
                    'price'  => 50,
204
                    'weight' => $weight_option,
205
                ],
206
                [
207
                    'name'   => 'color',
208
                    'price'  => 50,
209
                    'weight' => $weight_option,
210
                ],
211
            ],
212
        ]);
213
214
        // Test that the total price is being calculated successfully
215
        $this->assertEquals(250, $this->basket->total(true));
216
        $this->assertEquals(200, $this->basket->total(false));
217
    }
218
219 View Code Duplication
    public function testPriceDistractOption()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
220
    {
221
        $weight = rand(200, 300);
222
        $weight_option = rand(50, 800);
223
224
        $this->basket->insert([
225
            'id'       => 'foo',
226
            'name'     => 'bar',
227
            'price'    => 100,
228
            'tax'      => 25,
229
            'quantity' => 1,
230
            'weight'   => $weight,
231
            'options'  => [
232
                [
233
                    'name'   => 'size',
234
                    'price'  => -20,
235
                    'weight' => $weight_option,
236
                ],
237
                [
238
                    'name'   => 'color',
239
                    'price'  => 50,
240
                    'weight' => $weight_option,
241
                ],
242
            ],
243
        ]);
244
245
        // Test that the total price is being calculated successfully
246
        $this->assertEquals(162.50, $this->basket->total(true));
247
        $this->assertEquals(130, $this->basket->total(false));
248
    }
249
250 View Code Duplication
    public function testFind()
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
251
    {
252
        $this->basket->insert([
253
            'id'       => 'foo',
254
            'name'     => 'bar',
255
            'price'    => 100,
256
            'quantity' => 1,
257
            'weight'   => 200,
258
        ]);
259
260
        $this->assertInstanceOf('\Lenius\Basket\Item', $this->basket->find('foo'));
261
    }
262
263
    public function testTotals()
264
    {
265
        // Generate a random price and quantity
266
        $price = rand(20, 99999);
267
        $quantity = rand(1, 10);
268
269
        $this->basket->insert([
270
            'id'       => 'foo',
271
            'name'     => 'bar',
272
            'price'    => $price,
273
            'quantity' => $quantity,
274
            'weight'   => 200,
275
        ]);
276
277
        // Test that the total is being calculated successfully
278
        $this->assertEquals($price * $quantity, $this->basket->total());
279
    }
280
281
    public function testTotalItems()
282
    {
283
        $adding = rand(1, 200);
284
        $actualTotal = 0;
285
286
        for ($i = 1; $i <= $adding; $i++) {
287
            $quantity = rand(1, 20);
288
289
            $this->basket->insert([
290
                'id'       => uniqid(),
291
                'name'     => 'bar',
292
                'price'    => 100,
293
                'quantity' => $quantity,
294
                'weight'   => 200,
295
            ]);
296
297
            $actualTotal += $quantity;
298
        }
299
300
        $this->assertEquals($this->basket->totalItems(), $actualTotal);
301
        $this->assertEquals($this->basket->totalItems(true), $adding);
302
    }
303
304 View Code Duplication
    public function testItemRemoval()
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
305
    {
306
        $this->basket->insert([
307
            'id'       => 'foo',
308
            'name'     => 'bar',
309
            'price'    => 100,
310
            'quantity' => 1,
311
            'weight'   => 200,
312
        ]);
313
314
        $contents = &$this->basket->contents();
315
316
        $this->assertNotEmpty($contents);
317
318
        foreach ($contents as $item) {
319
            $item->remove();
320
        }
321
322
        $this->assertEmpty($contents);
323
    }
324
325 View Code Duplication
    public function testAlternateItemRemoval()
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
326
    {
327
        $this->basket->insert([
328
            'id'       => 'foo',
329
            'name'     => 'bar',
330
            'price'    => 100,
331
            'quantity' => 1,
332
            'weight'   => 200,
333
        ]);
334
335
        $contents = &$this->basket->contents();
336
337
        $this->assertNotEmpty($contents);
338
339
        foreach ($contents as $identifier => $item) {
340
            $this->basket->remove($identifier);
341
        }
342
343
        $this->assertEmpty($contents);
344
    }
345
346 View Code Duplication
    public function testItemToArray()
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
347
    {
348
        $actualId = $this->basket->insert([
349
            'id'       => 'foo',
350
            'name'     => 'bar',
351
            'price'    => 100,
352
            'quantity' => 1,
353
            'weight'   => 200,
354
        ]);
355
356
        $this->assertTrue(is_array($this->basket->item($actualId)->toArray()));
357
    }
358
359 View Code Duplication
    public function testbasketToArray()
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
360
    {
361
        $this->basket->insert([
362
            'id'       => 'foo',
363
            'name'     => 'bar',
364
            'price'    => 100,
365
            'quantity' => 1,
366
            'weight'   => 200,
367
        ]);
368
369
        foreach ($this->basket->contents(true) as $item) {
370
            $this->assertTrue(is_array($item));
371
        }
372
    }
373
374 View Code Duplication
    public function testTax()
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
375
    {
376
        $this->basket->insert([
377
            'id'       => 'foo',
378
            'name'     => 'bar',
379
            'price'    => 100,
380
            'quantity' => 1,
381
            'tax'      => 20,
382
            'weight'   => 200,
383
        ]);
384
385
        // Test that the tax is being calculated successfully
386
        $this->assertEquals(20, $this->basket->tax());
387
    }
388
389
    public function testTaxOptions()
390
    {
391
        $this->basket->insert([
392
            'id'       => 'foo',
393
            'name'     => 'bar',
394
            'price'    => 100,
395
            'quantity' => 1,
396
            'tax'      => 20,
397
            'weight'   => 200,
398
            'options'  => [
399
                [
400
                    'name'   => 'Size',
401
                    'value'  => 'L',
402
                    'weight' => 50,
403
                    'price'  => 100,
404
                   ],
405
                 ],
406
        ]);
407
408
        // Test that the tax is being calculated successfully
409
        $this->assertEquals(40, $this->basket->tax());
410
    }
411
412
    public function testTaxMultiply()
413
    {
414
        $this->basket->insert([
415
            'id'       => 'foo',
416
            'name'     => 'bar',
417
            'price'    => 100,
418
            'quantity' => 2,
419
            'tax'      => 20,
420
            'weight'   => 200,
421
        ]);
422
423
        // Test that the tax is being calculated successfully
424
        $this->assertEquals(240, $this->basket->total());
425
426
        // Test that the total method can also return the pre-tax price if false is passed
427
        $this->assertEquals(200, $this->basket->total(false));
428
    }
429
430
    public function testTaxUpdate()
431
    {
432
        $this->basket->insert([
433
            'id'       => 'foo',
434
            'name'     => 'bar',
435
            'price'    => 100,
436
            'quantity' => 1,
437
            'tax'      => 20,
438
            'weight'   => 200,
439
        ]);
440
441
        $identifier = md5('foo'.serialize([]));
442
443
        $item = $this->basket->item($identifier);
444
445
        // Test that the tax is being calculated successfully
446
        $item->tax = 0;
0 ignored issues
show
Documentation introduced by
The property $tax is declared protected in Lenius\Basket\Item. Since you implemented __set(), maybe consider adding a @property or @property-write annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
447
        $this->assertEquals(100, $item->total());
448
        $this->assertEquals(100, $item->total(false));
449
450
        $item->tax = 20;
0 ignored issues
show
Documentation introduced by
The property $tax is declared protected in Lenius\Basket\Item. Since you implemented __set(), maybe consider adding a @property or @property-write annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
451
        $this->assertEquals(120, $item->total());
452
        $this->assertEquals(100, $item->total(false));
453
454
        $item->update('tax', 0);
455
        $this->assertEquals(100, $item->total());
456
        $this->assertEquals($item->total(false), 100);
457
458
        $item->update('tax', 20);
459
        $this->assertEquals(120, $item->total());
460
        $this->assertEquals(100, $item->total(false));
461
    }
462
}
463