Completed
Push — 1.0-phpstan ( ddfe6c )
by Kamil
23:36
created

ProductSpec   B

Complexity

Total Complexity 42

Size/Duplication

Total Lines 421
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 4

Importance

Changes 0
Metric Value
wmc 42
lcom 0
cbo 4
dl 0
loc 421
c 0
b 0
f 0
rs 8.295

42 Methods

Rating   Name   Duplication   Size   Complexity  
A let() 0 5 1
A it_implements_product_interface() 0 4 1
A it_implements_toggleable_interface() 0 4 1
A it_has_no_id_by_default() 0 4 1
A it_has_no_name_by_default() 0 4 1
A its_name_is_mutable() 0 5 1
A it_has_no_slug_by_default() 0 4 1
A its_slug_is_mutable() 0 5 1
A it_has_no_description_by_default() 0 4 1
A its_description_is_mutable() 0 5 1
A it_initializes_attribute_collection_by_default() 0 4 1
A it_adds_attribute() 0 7 1
A it_removes_attribute() 0 12 1
A it_refuses_to_add_non_product_attribute() 0 5 1
A it_refuses_to_remove_non_product_attribute() 0 4 1
A it_has_no_variants_by_default() 0 4 1
A its_says_it_has_variants_only_if_multiple_variants_are_defined() 0 11 1
A it_initializes_variants_collection_by_default() 0 4 1
A it_does_not_include_unavailable_variants_in_available_variants() 0 6 1
A it_returns_available_variants() 0 10 1
A it_initializes_options_collection_by_default() 0 4 1
A it_has_no_options_by_default() 0 4 1
A its_says_it_has_options_only_if_any_option_defined() 0 5 1
A it_adds_option_properly() 0 5 1
A it_removes_option_properly() 0 8 1
A it_initializes_creation_date_by_default() 0 4 1
A its_creation_date_is_mutable() 0 5 1
A it_has_no_last_update_date_by_default() 0 4 1
A its_last_update_date_is_mutable() 0 5 1
A it_is_enabled_by_default() 0 4 1
A it_is_toggleable() 0 8 1
A it_adds_association() 0 7 1
A it_allows_to_remove_association() 0 10 1
A it_is_simple_if_it_has_one_variant_and_no_options() 0 8 1
A it_is_configurable_if_it_has_at_least_two_variants() 0 12 1
A it_is_configurable_if_it_has_one_variant_and_at_least_one_option() 0 11 1
A it_returns_attributes_by_a_base_locale_when_there_is_no_value_for_a_given_locale_or_a_fallback_locale() 0 19 1
B it_returns_attributes_by_a_base_locale_when_there_is_an_empty_value_for_a_given_locale_or_a_fallback_locale() 0 35 1
B it_returns_attributes_by_a_locale_without_a_base_locale() 0 27 1
B it_returns_attributes_by_a_locale_with_a_base_locale() 0 35 1
A it_returns_attributes_by_a_fallback_locale_when_there_is_no_value_for_a_given_locale() 0 19 1
B it_returns_attributes_by_a_fallback_locale_when_there_is_an_empty_value_for_a_given_locale() 0 27 1

How to fix   Complexity   

Complex Class

Complex classes like ProductSpec often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ProductSpec, and based on these observations, apply Extract Interface, too.

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\Product\Model;
15
16
use Doctrine\Common\Collections\Collection;
17
use PhpSpec\ObjectBehavior;
18
use Sylius\Component\Attribute\Model\AttributeValueInterface;
19
use Sylius\Component\Product\Model\ProductAssociationInterface;
20
use Sylius\Component\Product\Model\ProductAttributeInterface;
21
use Sylius\Component\Product\Model\ProductAttributeValueInterface;
22
use Sylius\Component\Product\Model\ProductInterface;
23
use Sylius\Component\Product\Model\ProductOptionInterface;
24
use Sylius\Component\Product\Model\ProductVariantInterface;
25
use Sylius\Component\Resource\Model\ToggleableInterface;
26
27
final class ProductSpec extends ObjectBehavior
28
{
29
    function let()
30
    {
31
        $this->setCurrentLocale('en_US');
32
        $this->setFallbackLocale('en_US');
33
    }
34
35
    function it_implements_product_interface(): void
36
    {
37
        $this->shouldImplement(ProductInterface::class);
38
    }
39
40
    function it_implements_toggleable_interface(): void
41
    {
42
        $this->shouldImplement(ToggleableInterface::class);
43
    }
44
45
    function it_has_no_id_by_default(): void
46
    {
47
        $this->getId()->shouldReturn(null);
48
    }
49
50
    function it_has_no_name_by_default(): void
51
    {
52
        $this->getName()->shouldReturn(null);
53
    }
54
55
    function its_name_is_mutable(): void
56
    {
57
        $this->setName('Super product');
58
        $this->getName()->shouldReturn('Super product');
59
    }
60
61
    function it_has_no_slug_by_default(): void
62
    {
63
        $this->getSlug()->shouldReturn(null);
64
    }
65
66
    function its_slug_is_mutable(): void
67
    {
68
        $this->setSlug('super-product');
69
        $this->getSlug()->shouldReturn('super-product');
70
    }
71
72
    function it_has_no_description_by_default(): void
73
    {
74
        $this->getDescription()->shouldReturn(null);
75
    }
76
77
    function its_description_is_mutable(): void
78
    {
79
        $this->setDescription('This product is super cool because...');
80
        $this->getDescription()->shouldReturn('This product is super cool because...');
81
    }
82
83
    function it_initializes_attribute_collection_by_default(): void
84
    {
85
        $this->getAttributes()->shouldHaveType(Collection::class);
86
    }
87
88
    function it_adds_attribute(ProductAttributeValueInterface $attribute): void
89
    {
90
        $attribute->setProduct($this)->shouldBeCalled();
91
92
        $this->addAttribute($attribute);
93
        $this->hasAttribute($attribute)->shouldReturn(true);
94
    }
95
96
    function it_removes_attribute(ProductAttributeValueInterface $attribute): void
97
    {
98
        $attribute->setProduct($this)->shouldBeCalled();
99
100
        $this->addAttribute($attribute);
101
        $this->hasAttribute($attribute)->shouldReturn(true);
102
103
        $attribute->setProduct(null)->shouldBeCalled();
104
105
        $this->removeAttribute($attribute);
106
        $this->hasAttribute($attribute)->shouldReturn(false);
107
    }
108
109
    function it_refuses_to_add_non_product_attribute(AttributeValueInterface $attribute): void
110
    {
111
        $this->shouldThrow('\InvalidArgumentException')->duringAddAttribute($attribute);
112
        $this->hasAttribute($attribute)->shouldReturn(false);
113
    }
114
115
    function it_refuses_to_remove_non_product_attribute(AttributeValueInterface $attribute): void
116
    {
117
        $this->shouldThrow('\InvalidArgumentException')->duringRemoveAttribute($attribute);
118
    }
119
120
    function it_returns_attributes_by_a_locale_without_a_base_locale(
121
        ProductAttributeInterface $attribute,
122
        ProductAttributeValueInterface $attributeValueEN,
123
        ProductAttributeValueInterface $attributeValuePL
124
    ): void {
125
        $attribute->getCode()->willReturn('colour');
126
127
        $attributeValueEN->setProduct($this)->shouldBeCalled();
128
        $attributeValueEN->getLocaleCode()->willReturn('en_US');
129
        $attributeValueEN->getAttribute()->willReturn($attribute);
0 ignored issues
show
Bug introduced by
The method willReturn() does not seem to exist on object<Sylius\Component\...del\AttributeInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
130
        $attributeValueEN->getCode()->willReturn('colour');
131
        $attributeValueEN->getValue()->willReturn('Blue');
132
133
        $attributeValuePL->setProduct($this)->shouldBeCalled();
134
        $attributeValuePL->getLocaleCode()->willReturn('pl_PL');
135
        $attributeValuePL->getAttribute()->willReturn($attribute);
0 ignored issues
show
Bug introduced by
The method willReturn() does not seem to exist on object<Sylius\Component\...del\AttributeInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
136
        $attributeValuePL->getCode()->willReturn('colour');
137
        $attributeValuePL->getValue()->willReturn('Niebieski');
138
139
        $this->addAttribute($attributeValueEN);
140
        $this->addAttribute($attributeValuePL);
141
142
        $this
143
            ->getAttributesByLocale('pl_PL', 'en_US')
144
            ->shouldIterateAs([$attributeValuePL->getWrappedObject()])
0 ignored issues
show
Bug introduced by
The method getWrappedObject() does not seem to exist on object<Sylius\Component\...ttributeValueInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
145
        ;
146
    }
147
148
    function it_returns_attributes_by_a_locale_with_a_base_locale(
149
        ProductAttributeInterface $attribute,
150
        ProductAttributeValueInterface $attributeValueEN,
151
        ProductAttributeValueInterface $attributeValuePL,
152
        ProductAttributeValueInterface $attributeValueFR
153
    ): void {
154
        $attribute->getCode()->willReturn('colour');
155
156
        $attributeValueEN->setProduct($this)->shouldBeCalled();
157
        $attributeValueEN->getLocaleCode()->willReturn('en_US');
158
        $attributeValueEN->getAttribute()->willReturn($attribute);
0 ignored issues
show
Bug introduced by
The method willReturn() does not seem to exist on object<Sylius\Component\...del\AttributeInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
159
        $attributeValueEN->getCode()->willReturn('colour');
160
        $attributeValueEN->getValue()->willReturn('Blue');
161
162
        $attributeValuePL->setProduct($this)->shouldBeCalled();
163
        $attributeValuePL->getLocaleCode()->willReturn('pl_PL');
164
        $attributeValuePL->getAttribute()->willReturn($attribute);
0 ignored issues
show
Bug introduced by
The method willReturn() does not seem to exist on object<Sylius\Component\...del\AttributeInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
165
        $attributeValuePL->getCode()->willReturn('colour');
166
        $attributeValuePL->getValue()->willReturn('Niebieski');
167
168
        $attributeValueFR->setProduct($this)->shouldBeCalled();
169
        $attributeValueFR->getLocaleCode()->willReturn('fr_FR');
170
        $attributeValueFR->getAttribute()->willReturn($attribute);
0 ignored issues
show
Bug introduced by
The method willReturn() does not seem to exist on object<Sylius\Component\...del\AttributeInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
171
        $attributeValueFR->getCode()->willReturn('colour');
172
        $attributeValueFR->getValue()->willReturn('Bleu');
173
174
        $this->addAttribute($attributeValueEN);
175
        $this->addAttribute($attributeValuePL);
176
        $this->addAttribute($attributeValueFR);
177
178
        $this
179
            ->getAttributesByLocale('pl_PL', 'en_US', 'fr_FR')
180
            ->shouldIterateAs([$attributeValuePL->getWrappedObject()])
0 ignored issues
show
Bug introduced by
The method getWrappedObject() does not seem to exist on object<Sylius\Component\...ttributeValueInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
181
        ;
182
    }
183
184
    function it_returns_attributes_by_a_fallback_locale_when_there_is_no_value_for_a_given_locale(
185
        ProductAttributeInterface $attribute,
186
        ProductAttributeValueInterface $attributeValueEN
187
    ): void {
188
        $attribute->getCode()->willReturn('colour');
189
190
        $attributeValueEN->setProduct($this)->shouldBeCalled();
191
        $attributeValueEN->getLocaleCode()->willReturn('en_US');
192
        $attributeValueEN->getAttribute()->willReturn($attribute);
0 ignored issues
show
Bug introduced by
The method willReturn() does not seem to exist on object<Sylius\Component\...del\AttributeInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
193
        $attributeValueEN->getCode()->willReturn('colour');
194
        $attributeValueEN->getValue()->willReturn('Blue');
195
196
        $this->addAttribute($attributeValueEN);
197
198
        $this
199
            ->getAttributesByLocale('pl_PL', 'en_US')
200
            ->shouldIterateAs([$attributeValueEN->getWrappedObject()])
0 ignored issues
show
Bug introduced by
The method getWrappedObject() does not seem to exist on object<Sylius\Component\...ttributeValueInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
201
        ;
202
    }
203
204
    function it_returns_attributes_by_a_fallback_locale_when_there_is_an_empty_value_for_a_given_locale(
205
        ProductAttributeInterface $attribute,
206
        ProductAttributeValueInterface $attributeValueEN,
207
        ProductAttributeValueInterface $attributeValuePL
208
    ): void {
209
        $attribute->getCode()->willReturn('colour');
210
211
        $attributeValueEN->setProduct($this)->shouldBeCalled();
212
        $attributeValueEN->getLocaleCode()->willReturn('en_US');
213
        $attributeValueEN->getAttribute()->willReturn($attribute);
0 ignored issues
show
Bug introduced by
The method willReturn() does not seem to exist on object<Sylius\Component\...del\AttributeInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
214
        $attributeValueEN->getCode()->willReturn('colour');
215
        $attributeValueEN->getValue()->willReturn('Blue');
216
217
        $attributeValuePL->setProduct($this)->shouldBeCalled();
218
        $attributeValuePL->getLocaleCode()->willReturn('pl_PL');
219
        $attributeValuePL->getAttribute()->willReturn($attribute);
0 ignored issues
show
Bug introduced by
The method willReturn() does not seem to exist on object<Sylius\Component\...del\AttributeInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
220
        $attributeValuePL->getCode()->willReturn('colour');
221
        $attributeValuePL->getValue()->willReturn('');
222
223
        $this->addAttribute($attributeValueEN);
224
        $this->addAttribute($attributeValuePL);
225
226
        $this
227
            ->getAttributesByLocale('pl_PL', 'en_US')
228
            ->shouldIterateAs([$attributeValueEN->getWrappedObject()])
0 ignored issues
show
Bug introduced by
The method getWrappedObject() does not seem to exist on object<Sylius\Component\...ttributeValueInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
229
        ;
230
    }
231
232
    function it_returns_attributes_by_a_base_locale_when_there_is_no_value_for_a_given_locale_or_a_fallback_locale(
233
        ProductAttributeInterface $attribute,
234
        ProductAttributeValueInterface $attributeValueFR
235
    ): void {
236
        $attribute->getCode()->willReturn('colour');
237
238
        $attributeValueFR->setProduct($this)->shouldBeCalled();
239
        $attributeValueFR->getLocaleCode()->willReturn('fr_FR');
240
        $attributeValueFR->getAttribute()->willReturn($attribute);
0 ignored issues
show
Bug introduced by
The method willReturn() does not seem to exist on object<Sylius\Component\...del\AttributeInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
241
        $attributeValueFR->getCode()->willReturn('colour');
242
        $attributeValueFR->getValue()->willReturn('Bleu');
243
244
        $this->addAttribute($attributeValueFR);
245
246
        $this
247
            ->getAttributesByLocale('pl_PL', 'en_US', 'fr_FR')
248
            ->shouldIterateAs([$attributeValueFR->getWrappedObject()])
0 ignored issues
show
Bug introduced by
The method getWrappedObject() does not seem to exist on object<Sylius\Component\...ttributeValueInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
249
        ;
250
    }
251
252
    function it_returns_attributes_by_a_base_locale_when_there_is_an_empty_value_for_a_given_locale_or_a_fallback_locale(
253
        ProductAttributeInterface $attribute,
254
        ProductAttributeValueInterface $attributeValueEN,
255
        ProductAttributeValueInterface $attributeValuePL,
256
        ProductAttributeValueInterface $attributeValueFR
257
    ): void {
258
        $attribute->getCode()->willReturn('colour');
259
260
        $attributeValueEN->setProduct($this)->shouldBeCalled();
261
        $attributeValueEN->getLocaleCode()->willReturn('en_US');
262
        $attributeValueEN->getAttribute()->willReturn($attribute);
0 ignored issues
show
Bug introduced by
The method willReturn() does not seem to exist on object<Sylius\Component\...del\AttributeInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
263
        $attributeValueEN->getCode()->willReturn('colour');
264
        $attributeValueEN->getValue()->willReturn('');
265
266
        $attributeValuePL->setProduct($this)->shouldBeCalled();
267
        $attributeValuePL->getLocaleCode()->willReturn('pl_PL');
268
        $attributeValuePL->getAttribute()->willReturn($attribute);
0 ignored issues
show
Bug introduced by
The method willReturn() does not seem to exist on object<Sylius\Component\...del\AttributeInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
269
        $attributeValuePL->getCode()->willReturn('colour');
270
        $attributeValuePL->getValue()->willReturn(null);
271
272
        $attributeValueFR->setProduct($this)->shouldBeCalled();
273
        $attributeValueFR->getLocaleCode()->willReturn('fr_FR');
274
        $attributeValueFR->getAttribute()->willReturn($attribute);
0 ignored issues
show
Bug introduced by
The method willReturn() does not seem to exist on object<Sylius\Component\...del\AttributeInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
275
        $attributeValueFR->getCode()->willReturn('colour');
276
        $attributeValueFR->getValue()->willReturn('Bleu');
277
278
        $this->addAttribute($attributeValueEN);
279
        $this->addAttribute($attributeValuePL);
280
        $this->addAttribute($attributeValueFR);
281
282
        $this
283
            ->getAttributesByLocale('pl_PL', 'en_US', 'fr_FR')
284
            ->shouldIterateAs([$attributeValueFR->getWrappedObject()])
0 ignored issues
show
Bug introduced by
The method getWrappedObject() does not seem to exist on object<Sylius\Component\...ttributeValueInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
285
        ;
286
    }
287
288
    function it_has_no_variants_by_default(): void
289
    {
290
        $this->hasVariants()->shouldReturn(false);
291
    }
292
293
    function its_says_it_has_variants_only_if_multiple_variants_are_defined(
294
        ProductVariantInterface $firstVariant,
295
        ProductVariantInterface $secondVariant
296
    ): void {
297
        $firstVariant->setProduct($this)->shouldBeCalled();
298
        $secondVariant->setProduct($this)->shouldBeCalled();
299
300
        $this->addVariant($firstVariant);
301
        $this->addVariant($secondVariant);
302
        $this->hasVariants()->shouldReturn(true);
303
    }
304
305
    function it_initializes_variants_collection_by_default(): void
306
    {
307
        $this->getVariants()->shouldHaveType(Collection::class);
308
    }
309
310
    function it_does_not_include_unavailable_variants_in_available_variants(ProductVariantInterface $variant): void
311
    {
312
        $variant->setProduct($this)->shouldBeCalled();
313
314
        $this->addVariant($variant);
315
    }
316
317
    function it_returns_available_variants(
318
        ProductVariantInterface $unavailableVariant,
319
        ProductVariantInterface $variant
320
    ): void {
321
        $unavailableVariant->setProduct($this)->shouldBeCalled();
322
        $variant->setProduct($this)->shouldBeCalled();
323
324
        $this->addVariant($unavailableVariant);
325
        $this->addVariant($variant);
326
    }
327
328
    function it_initializes_options_collection_by_default(): void
329
    {
330
        $this->getOptions()->shouldHaveType(Collection::class);
331
    }
332
333
    function it_has_no_options_by_default(): void
334
    {
335
        $this->hasOptions()->shouldReturn(false);
336
    }
337
338
    function its_says_it_has_options_only_if_any_option_defined(ProductOptionInterface $option): void
339
    {
340
        $this->addOption($option);
341
        $this->hasOptions()->shouldReturn(true);
342
    }
343
344
    function it_adds_option_properly(ProductOptionInterface $option): void
345
    {
346
        $this->addOption($option);
347
        $this->hasOption($option)->shouldReturn(true);
348
    }
349
350
    function it_removes_option_properly(ProductOptionInterface $option): void
351
    {
352
        $this->addOption($option);
353
        $this->hasOption($option)->shouldReturn(true);
354
355
        $this->removeOption($option);
356
        $this->hasOption($option)->shouldReturn(false);
357
    }
358
359
    function it_initializes_creation_date_by_default(): void
360
    {
361
        $this->getCreatedAt()->shouldHaveType(\DateTimeInterface::class);
362
    }
363
364
    function its_creation_date_is_mutable(\DateTime $creationDate): void
365
    {
366
        $this->setCreatedAt($creationDate);
367
        $this->getCreatedAt()->shouldReturn($creationDate);
368
    }
369
370
    function it_has_no_last_update_date_by_default(): void
371
    {
372
        $this->getUpdatedAt()->shouldReturn(null);
373
    }
374
375
    function its_last_update_date_is_mutable(\DateTime $updateDate): void
376
    {
377
        $this->setUpdatedAt($updateDate);
378
        $this->getUpdatedAt()->shouldReturn($updateDate);
379
    }
380
381
    function it_is_enabled_by_default(): void
382
    {
383
        $this->shouldBeEnabled();
384
    }
385
386
    function it_is_toggleable(): void
387
    {
388
        $this->disable();
389
        $this->shouldNotBeEnabled();
390
391
        $this->enable();
392
        $this->shouldBeEnabled();
393
    }
394
395
    function it_adds_association(ProductAssociationInterface $association): void
396
    {
397
        $association->setOwner($this)->shouldBeCalled();
398
        $this->addAssociation($association);
399
400
        $this->hasAssociation($association)->shouldReturn(true);
401
    }
402
403
    function it_allows_to_remove_association(ProductAssociationInterface $association): void
404
    {
405
        $association->setOwner($this)->shouldBeCalled();
406
        $association->setOwner(null)->shouldBeCalled();
407
408
        $this->addAssociation($association);
409
        $this->removeAssociation($association);
410
411
        $this->hasAssociation($association)->shouldReturn(false);
412
    }
413
414
    function it_is_simple_if_it_has_one_variant_and_no_options(ProductVariantInterface $variant): void
415
    {
416
        $variant->setProduct($this)->shouldBeCalled();
417
        $this->addVariant($variant);
418
419
        $this->isSimple()->shouldReturn(true);
420
        $this->isConfigurable()->shouldReturn(false);
421
    }
422
423
    function it_is_configurable_if_it_has_at_least_two_variants(
424
        ProductVariantInterface $firstVariant,
425
        ProductVariantInterface $secondVariant
426
    ): void {
427
        $firstVariant->setProduct($this)->shouldBeCalled();
428
        $this->addVariant($firstVariant);
429
        $secondVariant->setProduct($this)->shouldBeCalled();
430
        $this->addVariant($secondVariant);
431
432
        $this->isConfigurable()->shouldReturn(true);
433
        $this->isSimple()->shouldReturn(false);
434
    }
435
436
    function it_is_configurable_if_it_has_one_variant_and_at_least_one_option(
437
        ProductOptionInterface $option,
438
        ProductVariantInterface $variant
439
    ): void {
440
        $variant->setProduct($this)->shouldBeCalled();
441
        $this->addVariant($variant);
442
        $this->addOption($option);
443
444
        $this->isConfigurable()->shouldReturn(true);
445
        $this->isSimple()->shouldReturn(false);
446
    }
447
}
448