Completed
Push — 1.0-phpstan ( 5ae83f )
by Kamil
27:50
created

OrderSpec   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 477
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 36
lcom 1
cbo 5
dl 0
loc 477
rs 8.8
c 0
b 0
f 0

36 Methods

Rating   Name   Duplication   Size   Complexity  
A it_has_items_total_equal_to_0_by_default() 0 4 1
A it_creates_adjustments_collection_by_default() 0 4 1
A it_adds_adjustments_properly() 0 9 1
A it_removes_adjustments_properly() 0 16 1
A it_implements_an_order_interface() 0 4 1
A it_implements_an_adjustable_interface() 0 4 1
A it_implements_a_timestampable_interface() 0 4 1
A it_has_no_id_by_default() 0 4 1
A it_does_not_have_completed_checkout_by_default() 0 4 1
A its_checkout_can_be_completed() 0 5 1
A it_has_checkout_completed_when_completion_date_is_set() 0 6 1
A it_has_no_checkout_completion_date_by_default() 0 4 1
A its_checkout_completion_date_is_mutable() 0 7 1
A it_has_no_number_by_default() 0 4 1
A its_number_is_mutable() 0 5 1
A it_creates_items_collection_by_default() 0 4 1
A it_adds_items_properly() 0 10 1
A it_removes_items_properly() 0 12 1
A it_calculates_correct_items_total() 0 23 1
A it_removes_adjustments_recursively_properly() 0 21 1
B it_removes_adjustments_recursively_by_type_properly() 0 34 1
B it_returns_adjustments_recursively() 0 25 1
A it_has_adjustments_total_equal_to_0_by_default() 0 4 1
A it_calculates_correct_adjustments_total() 0 23 1
A it_returns_adjustments_total_recursively() 0 22 1
A it_has_total_equal_to_0_by_default() 0 4 1
A it_has_total_quantity() 0 16 1
B it_calculates_correct_total() 0 30 1
A it_calculates_correct_total_after_items_and_adjustments_changes() 0 48 1
B it_ignores_neutral_adjustments_when_calculating_total() 0 30 1
A it_calculates_correct_total_when_adjustment_is_bigger_than_cost() 0 20 1
A it_initializes_creation_date_by_default() 0 4 1
A it_has_no_last_update_date_by_default() 0 4 1
A it_is_empty_by_default() 0 5 1
A it_clears_items() 0 11 1
A it_has_notes() 0 5 1
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace spec\Sylius\Component\Order\Model;
15
16
use Doctrine\Common\Collections\ArrayCollection;
17
use Doctrine\Common\Collections\Collection;
18
use PhpSpec\ObjectBehavior;
19
use Prophecy\Argument;
20
use Sylius\Component\Order\Model\AdjustableInterface;
21
use Sylius\Component\Order\Model\AdjustmentInterface;
22
use Sylius\Component\Order\Model\OrderInterface;
23
use Sylius\Component\Order\Model\OrderItemInterface;
24
use Sylius\Component\Resource\Model\TimestampableInterface;
25
26
/**
27
 * @author Paweł Jędrzejewski <[email protected]>
28
 */
29
final class OrderSpec extends ObjectBehavior
30
{
31
    function it_implements_an_order_interface(): void
32
    {
33
        $this->shouldImplement(OrderInterface::class);
34
    }
35
36
    function it_implements_an_adjustable_interface(): void
37
    {
38
        $this->shouldImplement(AdjustableInterface::class);
39
    }
40
41
    function it_implements_a_timestampable_interface(): void
42
    {
43
        $this->shouldImplement(TimestampableInterface::class);
44
    }
45
46
    function it_has_no_id_by_default(): void
47
    {
48
        $this->getId()->shouldReturn(null);
49
    }
50
51
    function it_does_not_have_completed_checkout_by_default(): void
52
    {
53
        $this->shouldNotBeCheckoutCompleted();
54
    }
55
56
    function its_checkout_can_be_completed(): void
57
    {
58
        $this->completeCheckout();
59
        $this->shouldBeCheckoutCompleted();
60
    }
61
62
    function it_has_checkout_completed_when_completion_date_is_set(): void
63
    {
64
        $this->shouldNotBeCheckoutCompleted();
65
        $this->setCheckoutCompletedAt(new \DateTime('2 days ago'));
66
        $this->shouldBeCheckoutCompleted();
67
    }
68
69
    function it_has_no_checkout_completion_date_by_default(): void
70
    {
71
        $this->getCheckoutCompletedAt()->shouldReturn(null);
72
    }
73
74
    function its_checkout_completion_date_is_mutable(): void
75
    {
76
        $date = new \DateTime('1 hour ago');
77
78
        $this->setCheckoutCompletedAt($date);
79
        $this->getCheckoutCompletedAt()->shouldReturn($date);
80
    }
81
82
    function it_has_no_number_by_default(): void
83
    {
84
        $this->getNumber()->shouldReturn(null);
85
    }
86
87
    function its_number_is_mutable(): void
88
    {
89
        $this->setNumber('001351');
90
        $this->getNumber()->shouldReturn('001351');
91
    }
92
93
    function it_creates_items_collection_by_default(): void
94
    {
95
        $this->getItems()->shouldHaveType(Collection::class);
96
    }
97
98
    function it_adds_items_properly(OrderItemInterface $item): void
99
    {
100
        $item->getTotal()->willReturn(420);
101
        $item->setOrder($this)->shouldBeCalled();
102
103
        $this->hasItem($item)->shouldReturn(false);
104
105
        $this->addItem($item);
106
        $this->hasItem($item)->shouldReturn(true);
107
    }
108
109
    function it_removes_items_properly(OrderItemInterface $item): void
110
    {
111
        $item->getTotal()->willReturn(420);
112
113
        $item->setOrder($this)->shouldBeCalled();
114
        $this->addItem($item);
115
116
        $item->setOrder(null)->shouldBeCalled();
117
        $this->removeItem($item);
118
119
        $this->hasItem($item)->shouldReturn(false);
120
    }
121
122
    function it_has_items_total_equal_to_0_by_default(): void
123
    {
124
        $this->getItemsTotal()->shouldReturn(0);
125
    }
126
127
    function it_calculates_correct_items_total(
128
        OrderItemInterface $item1,
129
        OrderItemInterface $item2,
130
        OrderItemInterface $item3
131
    ): void {
132
        $item1->getTotal()->willReturn(29999);
133
        $item2->getTotal()->willReturn(45000);
134
        $item3->getTotal()->willReturn(250);
135
136
        $item1->setOrder($this)->shouldBeCalled();
137
        $item2->setOrder($this)->shouldBeCalled();
138
        $item3->setOrder($this)->shouldBeCalled();
139
140
        $item1->equals(Argument::any())->willReturn(false);
141
        $item2->equals(Argument::any())->willReturn(false);
142
        $item3->equals(Argument::any())->willReturn(false);
143
144
        $this->addItem($item1);
145
        $this->addItem($item2);
146
        $this->addItem($item3);
147
148
        $this->getItemsTotal()->shouldReturn(75249);
149
    }
150
151
    function it_creates_adjustments_collection_by_default(): void
152
    {
153
        $this->getAdjustments()->shouldHaveType(Collection::class);
154
    }
155
156
    function it_adds_adjustments_properly(AdjustmentInterface $adjustment): void
157
    {
158
        $adjustment->setAdjustable($this)->shouldBeCalled();
159
        $adjustment->isNeutral()->willReturn(true);
160
161
        $this->hasAdjustment($adjustment)->shouldReturn(false);
162
        $this->addAdjustment($adjustment);
163
        $this->hasAdjustment($adjustment)->shouldReturn(true);
164
    }
165
166
    function it_removes_adjustments_properly(AdjustmentInterface $adjustment): void
167
    {
168
        $this->hasAdjustment($adjustment)->shouldReturn(false);
169
170
        $adjustment->setAdjustable($this)->shouldBeCalled();
171
        $adjustment->isNeutral()->willReturn(true);
172
173
        $this->addAdjustment($adjustment);
174
        $this->hasAdjustment($adjustment)->shouldReturn(true);
175
176
        $adjustment->isLocked()->willReturn(false);
177
        $adjustment->setAdjustable(null)->shouldBeCalled();
178
        $this->removeAdjustment($adjustment);
179
180
        $this->hasAdjustment($adjustment)->shouldReturn(false);
181
    }
182
183
    function it_removes_adjustments_recursively_properly(
184
        AdjustmentInterface $orderAdjustment,
185
        OrderItemInterface $item
186
    ): void {
187
        $orderAdjustment->getAmount()->willReturn(420);
188
        $orderAdjustment->isNeutral()->willReturn(true);
189
        $orderAdjustment->isLocked()->willReturn(false);
190
        $orderAdjustment->setAdjustable(Argument::any())->will(function () {});
191
192
        $item->getTotal()->willReturn(666);
193
        $item->setOrder($this)->will(function () {});
194
195
        $this->addAdjustment($orderAdjustment);
196
        $this->addItem($item);
197
198
        $item->removeAdjustmentsRecursively(null)->shouldBeCalled();
199
200
        $this->removeAdjustmentsRecursively();
201
202
        $this->hasAdjustment($orderAdjustment)->shouldReturn(false);
203
    }
204
205
    function it_removes_adjustments_recursively_by_type_properly(
206
        AdjustmentInterface $orderPromotionAdjustment,
207
        AdjustmentInterface $orderTaxAdjustment,
208
        OrderItemInterface $item
209
    ): void {
210
        $orderPromotionAdjustment->getType()->willReturn('promotion');
211
        $orderPromotionAdjustment->isNeutral()->willReturn(true);
212
        $orderPromotionAdjustment->isLocked()->willReturn(false);
213
        $orderPromotionAdjustment->setAdjustable($this)->shouldBeCalled();
214
        $orderPromotionAdjustment->getAmount()->willReturn(420);
215
        $orderPromotionAdjustment->setAdjustable(Argument::any())->will(function () {});
216
217
        $orderTaxAdjustment->getType()->willReturn('tax');
218
        $orderTaxAdjustment->isNeutral()->willReturn(true);
219
        $orderTaxAdjustment->isLocked()->willReturn(false);
220
        $orderTaxAdjustment->setAdjustable($this)->shouldBeCalled();
221
        $orderTaxAdjustment->getAmount()->willReturn(420);
222
        $orderTaxAdjustment->setAdjustable(Argument::any())->will(function () {});
223
224
        $item->getTotal()->willReturn(666);
225
        $item->setOrder($this)->will(function () {});
226
227
        $this->addAdjustment($orderPromotionAdjustment);
228
        $this->addAdjustment($orderTaxAdjustment);
229
        $this->addItem($item);
230
231
        $item->removeAdjustmentsRecursively('tax')->shouldBeCalled();
232
        $orderTaxAdjustment->setAdjustable(null)->shouldBeCalled();
233
234
        $this->removeAdjustmentsRecursively('tax');
235
236
        $this->hasAdjustment($orderPromotionAdjustment)->shouldReturn(true);
237
        $this->hasAdjustment($orderTaxAdjustment)->shouldReturn(false);
238
    }
239
240
    function it_returns_adjustments_recursively(
241
        AdjustmentInterface $orderAdjustment,
242
        AdjustmentInterface $itemAdjustment1,
243
        AdjustmentInterface $itemAdjustment2,
244
        OrderItemInterface $item1,
245
        OrderItemInterface $item2
246
    ): void {
247
        $item1->setOrder($this)->shouldBeCalled();
248
        $item1->getTotal()->willReturn(100);
249
        $item1->getAdjustmentsRecursively(null)->willReturn(new ArrayCollection([$itemAdjustment1->getWrappedObject()]));
250
251
        $item2->setOrder($this)->shouldBeCalled();
252
        $item2->getTotal()->willReturn(100);
253
        $item2->getAdjustmentsRecursively(null)->willReturn(new ArrayCollection([$itemAdjustment2->getWrappedObject()]));
254
255
        $this->addItem($item1);
256
        $this->addItem($item2);
257
258
        $orderAdjustment->setAdjustable($this)->shouldBeCalled();
259
        $orderAdjustment->isNeutral()->willReturn(true);
260
261
        $this->addAdjustment($orderAdjustment);
262
263
        $this->getAdjustmentsRecursively()->shouldIterateAs([$orderAdjustment, $itemAdjustment1, $itemAdjustment2]);
264
    }
265
266
    function it_has_adjustments_total_equal_to_0_by_default(): void
267
    {
268
        $this->getAdjustmentsTotal()->shouldReturn(0);
269
    }
270
271
    function it_calculates_correct_adjustments_total(
272
        AdjustmentInterface $adjustment1,
273
        AdjustmentInterface $adjustment2,
274
        AdjustmentInterface $adjustment3
275
    ): void {
276
        $adjustment1->getAmount()->willReturn(10000);
277
        $adjustment2->getAmount()->willReturn(-4999);
278
        $adjustment3->getAmount()->willReturn(1929);
279
280
        $adjustment1->isNeutral()->willReturn(false);
281
        $adjustment2->isNeutral()->willReturn(false);
282
        $adjustment3->isNeutral()->willReturn(false);
283
284
        $adjustment1->setAdjustable($this)->shouldBeCalled();
285
        $adjustment2->setAdjustable($this)->shouldBeCalled();
286
        $adjustment3->setAdjustable($this)->shouldBeCalled();
287
288
        $this->addAdjustment($adjustment1);
289
        $this->addAdjustment($adjustment2);
290
        $this->addAdjustment($adjustment3);
291
292
        $this->getAdjustmentsTotal()->shouldReturn(6930);
293
    }
294
295
    function it_returns_adjustments_total_recursively(
296
        AdjustmentInterface $itemAdjustment,
297
        AdjustmentInterface $orderAdjustment,
298
        OrderItemInterface $orderItem
299
    ): void {
300
        $itemAdjustment->getAmount()->willReturn(10000);
301
        $orderAdjustment->getAmount()->willReturn(5000);
302
303
        $itemAdjustment->isNeutral()->willReturn(false);
304
        $orderAdjustment->isNeutral()->willReturn(false);
305
306
        $orderAdjustment->setAdjustable($this)->shouldBeCalled();
307
308
        $orderItem->getAdjustmentsRecursively(null)->willReturn(new ArrayCollection([$itemAdjustment->getWrappedObject()]));
309
        $orderItem->setOrder($this)->shouldBeCalled();
310
        $orderItem->getTotal()->willReturn(15000);
311
312
        $this->addItem($orderItem);
313
        $this->addAdjustment($orderAdjustment);
314
315
        $this->getAdjustmentsTotalRecursively()->shouldReturn(15000);
316
    }
317
318
    function it_has_total_equal_to_0_by_default(): void
319
    {
320
        $this->getTotal()->shouldReturn(0);
321
    }
322
323
    function it_has_total_quantity(OrderItemInterface $orderItem1, OrderItemInterface $orderItem2): void
324
    {
325
        $orderItem1->getQuantity()->willReturn(10);
326
        $orderItem1->setOrder($this)->shouldBeCalled();
327
        $orderItem1->getTotal()->willReturn(500);
328
329
        $orderItem2->getQuantity()->willReturn(30);
330
        $orderItem2->setOrder($this)->shouldBeCalled();
331
        $orderItem2->equals($orderItem1)->willReturn(false);
332
        $orderItem2->getTotal()->willReturn(1000);
333
334
        $this->addItem($orderItem1);
335
        $this->addItem($orderItem2);
336
337
        $this->getTotalQuantity()->shouldReturn(40);
338
    }
339
340
    function it_calculates_correct_total(
341
        OrderItemInterface $item1,
342
        OrderItemInterface $item2,
343
        AdjustmentInterface $adjustment1,
344
        AdjustmentInterface $adjustment2
345
    ): void {
346
        $item1->getTotal()->willReturn(29999);
347
        $item2->getTotal()->willReturn(45000);
348
349
        $item1->equals(Argument::any())->willReturn(false);
350
        $item2->equals(Argument::any())->willReturn(false);
351
352
        $item1->setOrder($this)->shouldBeCalled();
353
        $item2->setOrder($this)->shouldBeCalled();
354
355
        $adjustment1->isNeutral()->willReturn(false);
356
        $adjustment1->getAmount()->willReturn(10000);
357
        $adjustment2->isNeutral()->willReturn(false);
358
        $adjustment2->getAmount()->willReturn(-4999);
359
360
        $adjustment1->setAdjustable($this)->shouldBeCalled();
361
        $adjustment2->setAdjustable($this)->shouldBeCalled();
362
363
        $this->addItem($item1);
364
        $this->addItem($item2);
365
        $this->addAdjustment($adjustment1);
366
        $this->addAdjustment($adjustment2);
367
368
        $this->getTotal()->shouldReturn(80000);
369
    }
370
371
    function it_calculates_correct_total_after_items_and_adjustments_changes(
372
        AdjustmentInterface $adjustment1,
373
        AdjustmentInterface $adjustment2,
374
        OrderItemInterface $item1,
375
        OrderItemInterface $item2,
376
        OrderItemInterface $item3
377
    ): void {
378
        $item1->getTotal()->willReturn(29999);
379
        $item2->getTotal()->willReturn(45000);
380
381
        $item1->equals(Argument::any())->willReturn(false);
382
        $item2->equals(Argument::any())->willReturn(false);
383
384
        $item1->setOrder($this)->shouldBeCalled();
385
        $item2->setOrder($this)->shouldBeCalled();
386
387
        $adjustment1->isNeutral()->willReturn(false);
388
        $adjustment1->getAmount()->willReturn(10000);
389
        $adjustment1->setAdjustable($this)->shouldBeCalled();
390
391
        $this->addItem($item1);
392
        $this->addItem($item2);
393
        $this->addAdjustment($adjustment1);
394
395
        $this->getTotal()->shouldReturn(84999);
396
397
        $item2->setOrder(null)->shouldBeCalled();
398
399
        $this->removeItem($item2);
400
401
        $adjustment1->setAdjustable(null)->shouldBeCalled();
402
        $adjustment1->isLocked()->willReturn(false);
403
404
        $adjustment2->isNeutral()->willReturn(false);
405
        $adjustment2->getAmount()->willReturn(-4999);
406
        $adjustment2->setAdjustable($this)->shouldBeCalled();
407
408
        $this->removeAdjustment($adjustment1);
409
        $this->addAdjustment($adjustment2);
410
411
        $item3->getTotal()->willReturn(55000);
412
        $item3->equals(Argument::any())->willReturn(false);
413
        $item3->setOrder($this)->shouldBeCalled();
414
415
        $this->addItem($item3);
416
417
        $this->getTotal()->shouldReturn(80000);
418
    }
419
420
    function it_ignores_neutral_adjustments_when_calculating_total(
421
        OrderItemInterface $item1,
422
        OrderItemInterface $item2,
423
        AdjustmentInterface $adjustment1,
424
        AdjustmentInterface $adjustment2
425
    ): void {
426
        $item1->getTotal()->willReturn(29999);
427
        $item2->getTotal()->willReturn(45000);
428
429
        $item1->equals(Argument::any())->willReturn(false);
430
        $item2->equals(Argument::any())->willReturn(false);
431
432
        $item1->setOrder($this)->shouldBeCalled();
433
        $item2->setOrder($this)->shouldBeCalled();
434
435
        $adjustment1->isNeutral()->willReturn(true);
436
        $adjustment1->getAmount()->willReturn(10000);
437
        $adjustment2->isNeutral()->willReturn(false);
438
        $adjustment2->getAmount()->willReturn(-4999);
439
440
        $adjustment1->setAdjustable($this)->shouldBeCalled();
441
        $adjustment2->setAdjustable($this)->shouldBeCalled();
442
443
        $this->addItem($item1);
444
        $this->addItem($item2);
445
        $this->addAdjustment($adjustment1);
446
        $this->addAdjustment($adjustment2);
447
448
        $this->getTotal()->shouldReturn(70000);
449
    }
450
451
    function it_calculates_correct_total_when_adjustment_is_bigger_than_cost(
452
        OrderItemInterface $item,
453
        AdjustmentInterface $adjustment
454
    ): void {
455
        $item->getTotal()->willReturn(45000);
456
457
        $item->equals(Argument::any())->willReturn(false);
458
459
        $item->setOrder($this)->shouldBeCalled();
460
461
        $adjustment->isNeutral()->willReturn(false);
462
        $adjustment->getAmount()->willReturn(-100000);
463
464
        $adjustment->setAdjustable($this)->shouldBeCalled();
465
466
        $this->addItem($item);
467
        $this->addAdjustment($adjustment);
468
469
        $this->getTotal()->shouldReturn(0);
470
    }
471
472
    function it_initializes_creation_date_by_default(): void
473
    {
474
        $this->getCreatedAt()->shouldHaveType(\DateTimeInterface::class);
475
    }
476
477
    function it_has_no_last_update_date_by_default(): void
478
    {
479
        $this->getUpdatedAt()->shouldReturn(null);
480
    }
481
482
    function it_is_empty_by_default(): void
483
    {
484
        $this->countItems()->shouldReturn(0);
485
        $this->isEmpty()->shouldReturn(true);
486
    }
487
488
    function it_clears_items(OrderItemInterface $item): void
489
    {
490
        $item->getTotal()->willReturn(420);
491
        $item->setOrder($this)->will(function () {});
492
493
        $this->addItem($item);
494
        $this->clearItems();
495
496
        $this->isEmpty()->shouldReturn(true);
497
        $this->getTotal()->shouldReturn(0);
498
    }
499
500
    function it_has_notes(): void
501
    {
502
        $this->setNotes('something squishy');
503
        $this->getNotes()->shouldReturn('something squishy');
504
    }
505
}
506