Completed
Push — master ( da2f6e...d3b8cb )
by Kamil
20:06
created

ItemFixedDiscountActionSpec   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 198
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 8

Importance

Changes 2
Bugs 1 Features 1
Metric Value
wmc 10
lcom 0
cbo 8
dl 0
loc 198
rs 10
c 2
b 1
f 1

10 Methods

Rating   Name   Duplication   Size   Complexity  
A let() 0 7 1
A it_is_initializable() 0 4 1
A it_is_discount_action() 0 4 1
A it_applies_percentage_discount_on_every_unit_in_order() 0 51 1
A it_does_not_apply_promotions_with_amount_0() 0 14 1
A it_does_not_apply_bigger_promotions_than_unit_total() 0 51 1
A it_throws_exception_if_passed_subject_to_execute_is_not_order() 0 9 1
B it_revert_proper_promotion_adjustment_from_all_units() 0 33 1
A it_throws_exception_if_passed_subject_to_revert_is_not_order() 0 9 1
A it_has_configuration_form_type() 0 4 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
namespace spec\Sylius\Component\Core\Promotion\Action;
13
14
use Doctrine\Common\Collections\Collection;
15
use PhpSpec\ObjectBehavior;
16
use Prophecy\Argument;
17
use Sylius\Component\Core\Model\AdjustmentInterface;
18
use Sylius\Component\Core\Model\OrderInterface;
19
use Sylius\Component\Core\Model\OrderItemInterface;
20
use Sylius\Component\Core\Model\OrderItemUnitInterface;
21
use Sylius\Component\Core\Model\PromotionInterface;
22
use Sylius\Component\Core\Promotion\Action\ItemDiscountAction;
23
use Sylius\Component\Core\Promotion\Filter\TaxonFilterInterface;
24
use Sylius\Component\Originator\Originator\OriginatorInterface;
25
use Sylius\Component\Promotion\Model\PromotionSubjectInterface;
26
use Sylius\Component\Resource\Exception\UnexpectedTypeException;
27
use Sylius\Component\Resource\Factory\FactoryInterface;
28
29
/**
30
 * @author Mateusz Zalewski <[email protected]>
31
 */
32
class ItemFixedDiscountActionSpec extends ObjectBehavior
33
{
34
    function let(
35
        FactoryInterface $adjustmentFactory,
36
        OriginatorInterface $originator,
37
        TaxonFilterInterface $taxonFilter
38
    ) {
39
        $this->beConstructedWith($adjustmentFactory, $originator, $taxonFilter);
40
    }
41
42
    function it_is_initializable()
43
    {
44
        $this->shouldHaveType('Sylius\Component\Core\Promotion\Action\ItemFixedDiscountAction');
45
    }
46
47
    function it_is_discount_action()
48
    {
49
        $this->shouldHaveType(ItemDiscountAction::class);
50
    }
51
52
    function it_applies_percentage_discount_on_every_unit_in_order(
53
        $adjustmentFactory,
54
        $originator,
55
        $taxonFilter,
56
        AdjustmentInterface $promotionAdjustment1,
57
        AdjustmentInterface $promotionAdjustment2,
58
        Collection $originalItems,
59
        Collection $filteredItems,
60
        Collection $units,
61
        OrderInterface $order,
62
        OrderItemInterface $orderItem,
63
        OrderItemUnitInterface $unit1,
64
        OrderItemUnitInterface $unit2,
65
        PromotionInterface $promotion
66
    ) {
67
        $order->getItems()->willReturn($originalItems);
68
        $originalItems->toArray()->willReturn([$orderItem]);
69
        $taxonFilter
70
            ->filter([$orderItem], ['amount' => 500, 'filters' => ['taxons' => ['testTaxon']]])
71
            ->willReturn($filteredItems)
72
        ;
73
74
        $filteredItems->getIterator()->willReturn(new \ArrayIterator([$orderItem->getWrappedObject()]));
75
76
        $orderItem->getQuantity()->willReturn(2);
77
        $orderItem->getUnits()->willReturn($units);
78
        $units->getIterator()->willReturn(new \ArrayIterator([$unit1->getWrappedObject(), $unit2->getWrappedObject()]));
79
80
        $promotion->getDescription()->willReturn('Test description');
81
82
        $adjustmentFactory->createNew()->willReturn($promotionAdjustment1, $promotionAdjustment2);
83
84
        $unit1->getTotal()->willReturn(1000);
85
        $promotionAdjustment1->setType(AdjustmentInterface::ORDER_ITEM_PROMOTION_ADJUSTMENT)->shouldBeCalled();
86
        $promotionAdjustment1->setLabel('Test description')->shouldBeCalled();
87
        $promotionAdjustment1->setAmount(-500)->shouldBeCalled();
88
89
        $originator->setOrigin($promotionAdjustment1, $promotion)->shouldBeCalled();
90
91
        $unit2->getTotal()->willReturn(1000);
92
        $promotionAdjustment2->setType(AdjustmentInterface::ORDER_ITEM_PROMOTION_ADJUSTMENT)->shouldBeCalled();
93
        $promotionAdjustment2->setLabel('Test description')->shouldBeCalled();
94
        $promotionAdjustment2->setAmount(-500)->shouldBeCalled();
95
96
        $originator->setOrigin($promotionAdjustment2, $promotion)->shouldBeCalled();
97
98
        $unit1->addAdjustment($promotionAdjustment1)->shouldBeCalled();
99
        $unit2->addAdjustment($promotionAdjustment2)->shouldBeCalled();
100
101
        $this->execute($order, ['amount' => 500, 'filters' => ['taxons' => ['testTaxon']]], $promotion);
102
    }
103
104
    function it_does_not_apply_promotions_with_amount_0(
105
        $adjustmentFactory,
106
        OrderInterface $order,
107
        OrderItemUnitInterface $unit1,
108
        OrderItemUnitInterface $unit2,
109
        PromotionInterface $promotion
110
    ) {
111
        $adjustmentFactory->createNew()->shouldNotBeCalled();
112
113
        $unit1->addAdjustment(Argument::any())->shouldNotBeCalled();
114
        $unit2->addAdjustment(Argument::any())->shouldNotBeCalled();
115
116
        $this->execute($order, ['amount' => 0, 'filters' => ['taxons' => ['testTaxon']]], $promotion);
117
    }
118
119
    function it_does_not_apply_bigger_promotions_than_unit_total(
120
        $adjustmentFactory,
121
        $originator,
122
        $taxonFilter,
123
        AdjustmentInterface $promotionAdjustment1,
124
        AdjustmentInterface $promotionAdjustment2,
125
        Collection $originalItems,
126
        Collection $filteredItems,
127
        Collection $units,
128
        OrderInterface $order,
129
        OrderItemInterface $orderItem,
130
        OrderItemUnitInterface $unit1,
131
        OrderItemUnitInterface $unit2,
132
        PromotionInterface $promotion
133
    ) {
134
        $order->getItems()->willReturn($originalItems);
135
        $originalItems->toArray()->willReturn([$orderItem]);
136
        $taxonFilter
137
            ->filter([$orderItem], ['amount' => 1000, 'filters' => ['taxons' => ['testTaxon']]])
138
            ->willReturn($filteredItems)
139
        ;
140
141
        $filteredItems->getIterator()->willReturn(new \ArrayIterator([$orderItem->getWrappedObject()]));
142
143
        $orderItem->getQuantity()->willReturn(2);
144
        $orderItem->getUnits()->willReturn($units);
145
        $units->getIterator()->willReturn(new \ArrayIterator([$unit1->getWrappedObject(), $unit2->getWrappedObject()]));
146
147
        $promotion->getDescription()->willReturn('Test description');
148
149
        $adjustmentFactory->createNew()->willReturn($promotionAdjustment1, $promotionAdjustment2);
150
151
        $unit1->getTotal()->willReturn(300);
152
        $promotionAdjustment1->setType(AdjustmentInterface::ORDER_ITEM_PROMOTION_ADJUSTMENT)->shouldBeCalled();
153
        $promotionAdjustment1->setLabel('Test description')->shouldBeCalled();
154
        $promotionAdjustment1->setAmount(-300)->shouldBeCalled();
155
156
        $originator->setOrigin($promotionAdjustment1, $promotion)->shouldBeCalled();
157
158
        $unit2->getTotal()->willReturn(200);
159
        $promotionAdjustment2->setType(AdjustmentInterface::ORDER_ITEM_PROMOTION_ADJUSTMENT)->shouldBeCalled();
160
        $promotionAdjustment2->setLabel('Test description')->shouldBeCalled();
161
        $promotionAdjustment2->setAmount(-200)->shouldBeCalled();
162
163
        $originator->setOrigin($promotionAdjustment2, $promotion)->shouldBeCalled();
164
165
        $unit1->addAdjustment($promotionAdjustment1)->shouldBeCalled();
166
        $unit2->addAdjustment($promotionAdjustment2)->shouldBeCalled();
167
168
        $this->execute($order, ['amount' => 1000, 'filters' => ['taxons' => ['testTaxon']]], $promotion);
169
    }
170
171
    function it_throws_exception_if_passed_subject_to_execute_is_not_order(
172
        PromotionSubjectInterface $subject,
173
        PromotionInterface $promotion
174
    ) {
175
        $this
176
            ->shouldThrow(UnexpectedTypeException::class)
177
            ->during('execute', [$subject, ['amount' => 1000], $promotion])
178
        ;
179
    }
180
181
    function it_revert_proper_promotion_adjustment_from_all_units(
182
        $originator,
183
        AdjustmentInterface $promotionAdjustment1,
184
        AdjustmentInterface $promotionAdjustment2,
185
        Collection $items,
186
        Collection $units,
187
        Collection $adjustments,
188
        OrderInterface $order,
189
        OrderItemInterface $orderItem,
190
        OrderItemUnitInterface $unit,
191
        PromotionInterface $promotion,
192
        PromotionInterface $someOtherPromotion
193
    ) {
194
        $order->getItems()->willReturn($items);
195
        $items->getIterator()->willReturn(new \ArrayIterator([$orderItem->getWrappedObject()]));
196
197
        $orderItem->getUnits()->willReturn($units);
198
        $units->getIterator()->willReturn(new \ArrayIterator([$unit->getWrappedObject()]));
199
200
        $unit->getAdjustments(AdjustmentInterface::ORDER_ITEM_PROMOTION_ADJUSTMENT)->willReturn($adjustments);
201
        $adjustments
202
            ->getIterator()
203
            ->willReturn(new \ArrayIterator([$promotionAdjustment1->getWrappedObject(), $promotionAdjustment2->getWrappedObject()]))
204
        ;
205
206
        $originator->getOrigin($promotionAdjustment1)->willReturn($promotion);
207
        $unit->removeAdjustment($promotionAdjustment1)->shouldBeCalled();
208
209
        $originator->getOrigin($promotionAdjustment2)->willReturn($someOtherPromotion);
210
        $unit->removeAdjustment($promotionAdjustment2)->shouldNotBeCalled();
211
212
        $this->revert($order, ['amount' => 1000], $promotion);
213
    }
214
215
    function it_throws_exception_if_passed_subject_to_revert_is_not_order(
216
        PromotionSubjectInterface $subject,
217
        PromotionInterface $promotion
218
    ) {
219
        $this
220
            ->shouldThrow(UnexpectedTypeException::class)
221
            ->during('revert', [$subject, ['amount' => 1000], $promotion])
222
        ;
223
    }
224
225
    function it_has_configuration_form_type()
226
    {
227
        $this->getConfigurationFormType()->shouldReturn('sylius_promotion_action_fixed_discount_configuration');
228
    }
229
}
230