Completed
Push — assert-overflow ( bc734e )
by Kamil
19:55
created

ManagingProductsContext   F

Complexity

Total Complexity 89

Size/Duplication

Total Lines 1068
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 17

Importance

Changes 0
Metric Value
wmc 89
lcom 3
cbo 17
dl 0
loc 1068
rs 0.8336
c 0
b 0
f 0

How to fix   Complexity   

Complex Class

Complex classes like ManagingProductsContext 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 ManagingProductsContext, 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
namespace Sylius\Behat\Context\Ui\Admin;
13
14
use Behat\Behat\Context\Context;
15
use Behat\Mink\Exception\ElementNotFoundException;
16
use Sylius\Behat\NotificationType;
17
use Sylius\Behat\Page\Admin\Crud\CreatePageInterface;
18
use Sylius\Behat\Page\Admin\Crud\UpdatePageInterface;
19
use Sylius\Behat\Page\Admin\Product\CreateConfigurableProductPageInterface;
20
use Sylius\Behat\Page\Admin\Product\CreateSimpleProductPageInterface;
21
use Sylius\Behat\Page\Admin\Product\IndexPageInterface;
22
use Sylius\Behat\Page\Admin\Product\IndexPerTaxonPageInterface;
23
use Sylius\Behat\Page\Admin\Product\UpdateConfigurableProductPageInterface;
24
use Sylius\Behat\Page\Admin\Product\UpdateSimpleProductPageInterface;
25
use Sylius\Behat\Page\Admin\ProductReview\IndexPageInterface as ProductReviewIndexPageInterface;
26
use Sylius\Behat\Page\SymfonyPageInterface;
27
use Sylius\Behat\Service\NotificationCheckerInterface;
28
use Sylius\Behat\Service\Resolver\CurrentPageResolverInterface;
29
use Sylius\Behat\Service\SharedStorageInterface;
30
use Sylius\Component\Core\Model\ProductInterface;
31
use Sylius\Component\Product\Model\ProductAssociationTypeInterface;
32
use Sylius\Component\Taxonomy\Model\TaxonInterface;
33
use Webmozart\Assert\Assert;
34
35
/**
36
 * @author Kamil Kokot <[email protected]>
37
 * @author Magdalena Banasiak <[email protected]>
38
 * @author Łukasz Chruściel <[email protected]>
39
 */
40
final class ManagingProductsContext implements Context
41
{
42
    /**
43
     * @var SharedStorageInterface
44
     */
45
    private $sharedStorage;
46
47
    /**x
48
     * @var CreateSimpleProductPageInterface
49
     */
50
    private $createSimpleProductPage;
51
52
    /**
53
     * @var CreateConfigurableProductPageInterface
54
     */
55
    private $createConfigurableProductPage;
56
57
    /**
58
     * @var IndexPageInterface
59
     */
60
    private $indexPage;
61
62
    /**
63
     * @var UpdateSimpleProductPageInterface
64
     */
65
    private $updateSimpleProductPage;
66
67
    /**
68
     * @var UpdateConfigurableProductPageInterface
69
     */
70
    private $updateConfigurableProductPage;
71
72
    /**
73
     * @var ProductReviewIndexPageInterface
74
     */
75
    private $productReviewIndexPage;
76
77
    /**
78
     * @var IndexPerTaxonPageInterface
79
     */
80
    private $indexPerTaxonPage;
81
82
    /**
83
     * @var CurrentPageResolverInterface
84
     */
85
    private $currentPageResolver;
86
87
    /**
88
     * @var NotificationCheckerInterface
89
     */
90
    private $notificationChecker;
91
92
    /**
93
     * @param SharedStorageInterface $sharedStorage
94
     * @param CreateSimpleProductPageInterface $createSimpleProductPage
95
     * @param CreateConfigurableProductPageInterface $createConfigurableProductPage
96
     * @param IndexPageInterface $indexPage
97
     * @param UpdateSimpleProductPageInterface $updateSimpleProductPage
98
     * @param UpdateConfigurableProductPageInterface $updateConfigurableProductPage
99
     * @param ProductReviewIndexPageInterface $productReviewIndexPage
100
     * @param IndexPerTaxonPageInterface $indexPerTaxonPage
101
     * @param CurrentPageResolverInterface $currentPageResolver
102
     * @param NotificationCheckerInterface $notificationChecker
103
     */
104
    public function __construct(
105
        SharedStorageInterface $sharedStorage,
106
        CreateSimpleProductPageInterface $createSimpleProductPage,
107
        CreateConfigurableProductPageInterface $createConfigurableProductPage,
108
        IndexPageInterface $indexPage,
109
        UpdateSimpleProductPageInterface $updateSimpleProductPage,
110
        UpdateConfigurableProductPageInterface $updateConfigurableProductPage,
111
        ProductReviewIndexPageInterface $productReviewIndexPage,
112
        IndexPerTaxonPageInterface $indexPerTaxonPage,
113
        CurrentPageResolverInterface $currentPageResolver,
114
        NotificationCheckerInterface $notificationChecker
115
    ) {
116
        $this->sharedStorage = $sharedStorage;
117
        $this->createSimpleProductPage = $createSimpleProductPage;
118
        $this->createConfigurableProductPage = $createConfigurableProductPage;
119
        $this->indexPage = $indexPage;
120
        $this->updateSimpleProductPage = $updateSimpleProductPage;
121
        $this->updateConfigurableProductPage = $updateConfigurableProductPage;
122
        $this->productReviewIndexPage = $productReviewIndexPage;
123
        $this->indexPerTaxonPage = $indexPerTaxonPage;
124
        $this->currentPageResolver = $currentPageResolver;
125
        $this->notificationChecker = $notificationChecker;
126
    }
127
128
    /**
129
     * @Given I want to create a new simple product
130
     */
131
    public function iWantToCreateANewSimpleProduct()
132
    {
133
        $this->createSimpleProductPage->open();
134
    }
135
136
    /**
137
     * @Given I want to create a new configurable product
138
     */
139
    public function iWantToCreateANewConfigurableProduct()
140
    {
141
        $this->createConfigurableProductPage->open();
142
    }
143
144
    /**
145
     * @When I specify its code as :code
146
     * @When I do not specify its code
147
     */
148
    public function iSpecifyItsCodeAs($code = null)
149
    {
150
        $currentPage = $this->resolveCurrentPage();
151
152
        $currentPage->specifyCode($code);
153
    }
154
155
    /**
156
     * @When I name it :name in :language
157
     * @When I rename it to :name in :language
158
     */
159
    public function iRenameItToIn($name, $language)
160
    {
161
        $currentPage = $this->resolveCurrentPage();
162
163
        $currentPage->nameItIn($name, $language);
164
    }
165
166
    /**
167
     * @When I add it
168
     * @When I try to add it
169
     */
170
    public function iAddIt()
171
    {
172
        /** @var CreatePageInterface $currentPage */
173
        $currentPage = $this->resolveCurrentPage();
174
175
        $currentPage->create();
176
    }
177
178
    /**
179
     * @When I disable its inventory tracking
180
     */
181
    public function iDisableItsTracking()
182
    {
183
        $this->updateSimpleProductPage->disableTracking();
184
    }
185
186
    /**
187
     * @When I enable its inventory tracking
188
     */
189
    public function iEnableItsTracking()
190
    {
191
        $this->updateSimpleProductPage->enableTracking();
192
    }
193
194
    /**
195
     * @When /^I set its(?:| default) price to "(?:€|£|\$)([^"]+)" for "([^"]+)" channel$/
196
     */
197
    public function iSetItsPriceTo($price, $channelName)
198
    {
199
        $this->createSimpleProductPage->specifyPrice($channelName, $price);
200
    }
201
202
    /**
203
     * @When I make it available in channel :channel
204
     */
205
    public function iMakeItAvailableInChannel($channel)
206
    {
207
        $this->createSimpleProductPage->checkChannel($channel);
208
    }
209
210
    /**
211
     * @When I assign it to channel :channel
212
     */
213
    public function iAssignItToChannel($channel)
214
    {
215
        // Temporary solution until we will make current page resolver work with product pages
216
        $this->updateConfigurableProductPage->checkChannel($channel);
217
    }
218
219
    /**
220
     * @When I choose :calculatorName calculator
221
     */
222
    public function iChooseCalculator($calculatorName)
223
    {
224
        $this->createSimpleProductPage->choosePricingCalculator($calculatorName);
225
    }
226
227
    /**
228
     * @When I set its slug to :slug
229
     * @When I set its slug to :slug in :language
230
     * @When I remove its slug
231
     */
232
    public function iSetItsSlugToIn($slug = null, $language = 'en_US')
233
    {
234
        $this->createSimpleProductPage->specifySlugIn($slug, $language);
235
    }
236
237
    /**
238
     * @When I enable slug modification
239
     * @When I enable slug modification in :localeCode
240
     */
241
    public function iEnableSlugModification($localeCode = 'en_US')
242
    {
243
        $this->updateSimpleProductPage->activateLanguageTab($localeCode);
244
        $this->updateSimpleProductPage->enableSlugModification($localeCode);
245
    }
246
247
    /**
248
     * @Then the product :productName should appear in the store
249
     * @Then the product :productName should be in the shop
250
     * @Then this product should still be named :productName
251
     */
252
    public function theProductShouldAppearInTheShop($productName)
253
    {
254
        $this->iWantToBrowseProducts();
255
256
        Assert::true($this->indexPage->isSingleResourceOnPage(['name' => $productName]));
257
    }
258
259
    /**
260
     * @Given I am browsing products
261
     * @When I want to browse products
262
     */
263
    public function iWantToBrowseProducts()
264
    {
265
        $this->indexPage->open();
266
    }
267
268
    /**
269
     * @When /^I am browsing products from ("([^"]+)" taxon)$/
270
     */
271
    public function iAmBrowsingProductsFromTaxon(TaxonInterface $taxon)
272
    {
273
        $this->indexPerTaxonPage->open(['taxonId' => $taxon->getId()]);
274
    }
275
276
    /**
277
     * @When I filter them by :taxonName taxon
278
     */
279
    public function iFilterThemByTaxon($taxonName)
280
    {
281
        $this->indexPage->filterByTaxon($taxonName);
282
    }
283
284
    /**
285
     * @Then I should( still) see a product with :field :value
286
     */
287
    public function iShouldSeeProductWith($field, $value)
288
    {
289
        Assert::true($this->indexPage->isSingleResourceOnPage([$field => $value]));
290
    }
291
292
    /**
293
     * @Then I should not see any product with :field :value
294
     */
295
    public function iShouldNotSeeAnyProductWith($field, $value)
296
    {
297
        Assert::false($this->indexPage->isSingleResourceOnPage([$field => $value]));
298
    }
299
300
    /**
301
     * @Then the first product on the list should have :field :value
302
     */
303
    public function theFirstProductOnTheListShouldHave($field, $value)
304
    {
305
        $currentPage = $this->resolveCurrentPage();
306
307
        Assert::same($currentPage->getColumnFields($field)[0], $value);
308
    }
309
310
    /**
311
     * @Then the last product on the list should have :field :value
312
     */
313
    public function theLastProductOnTheListShouldHave($field, $value)
314
    {
315
        $values = $this->indexPerTaxonPage->getColumnFields($field);
316
317
        Assert::same(end($values), $value);
318
    }
319
320
    /**
321
     * @When I switch the way products are sorted by :field
322
     * @When I start sorting products by :field
323
     * @Given the products are already sorted by :field
324
     */
325
    public function iSortProductsBy($field)
326
    {
327
        $this->indexPage->sortBy($field);
328
    }
329
330
    /**
331
     * @Then I should see :numberOfProducts products in the list
332
     */
333
    public function iShouldSeeProductsInTheList($numberOfProducts)
334
    {
335
        Assert::same($this->indexPage->countItems(), (int) $numberOfProducts);
336
    }
337
338
    /**
339
     * @When I delete the :product product
340
     * @When I try to delete the :product product
341
     */
342
    public function iDeleteProduct(ProductInterface $product)
343
    {
344
        $this->sharedStorage->set('product', $product);
345
346
        $this->iWantToBrowseProducts();
347
        $this->indexPage->deleteResourceOnPage(['name' => $product->getName()]);
348
    }
349
350
    /**
351
     * @Then /^(this product) should not exist in the product catalog$/
352
     */
353
    public function productShouldNotExist(ProductInterface $product)
354
    {
355
        $this->iWantToBrowseProducts();
356
357
        Assert::false($this->indexPage->isSingleResourceOnPage(['code' => $product->getCode()]));
358
    }
359
360
    /**
361
     * @Then I should be notified that this product is in use and cannot be deleted
362
     */
363
    public function iShouldBeNotifiedOfFailure()
364
    {
365
        $this->notificationChecker->checkNotification(
366
            'Cannot delete, the product is in use.',
367
            NotificationType::failure()
368
        );
369
    }
370
371
    /**
372
     * @Then /^(this product) should still exist in the product catalog$/
373
     */
374
    public function productShouldExistInTheProductCatalog(ProductInterface $product)
375
    {
376
        $this->theProductShouldAppearInTheShop($product->getName());
377
    }
378
379
    /**
380
     * @When I want to modify the :product product
381
     * @When /^I want to modify (this product)$/
382
     */
383
    public function iWantToModifyAProduct(ProductInterface $product)
384
    {
385
        $this->sharedStorage->set('product', $product);
386
387
        if ($product->isSimple()) {
388
            $this->updateSimpleProductPage->open(['id' => $product->getId()]);
389
            return;
390
        }
391
392
        $this->updateConfigurableProductPage->open(['id' => $product->getId()]);
393
    }
394
395
    /**
396
     * @Then the code field should be disabled
397
     */
398
    public function theCodeFieldShouldBeDisabled()
399
    {
400
        $currentPage = $this->resolveCurrentPage();
401
402
        Assert::true($currentPage->isCodeDisabled());
403
    }
404
405
    /**
406
     * @Then the slug field should not be editable
407
     * @Then the slug field in :localeCode (also )should not be editable
408
     */
409
    public function theSlugFieldShouldNotBeEditable($localeCode = 'en_US')
410
    {
411
        Assert::true($this->updateSimpleProductPage->isSlugReadOnlyIn($localeCode));
412
    }
413
414
    /**
415
     * @Then this product name should be :name
416
     */
417
    public function thisProductElementShouldBe($name)
418
    {
419
        $this->assertElementValue('name', $name);
420
    }
421
422
    /**
423
     * @Then /^I should be notified that (code|name|slug) is required$/
424
     */
425
    public function iShouldBeNotifiedThatIsRequired($element)
426
    {
427
        $this->assertValidationMessage($element, sprintf('Please enter product %s.', $element));
428
    }
429
430
    /**
431
     * @When I save my changes
432
     * @When I try to save my changes
433
     */
434
    public function iSaveMyChanges()
435
    {
436
        /** @var UpdatePageInterface $currentPage */
437
        $currentPage = $this->resolveCurrentPage();
438
439
        $currentPage->saveChanges();
440
    }
441
442
    /**
443
     * @When /^I change its price to (?:€|£|\$)([^"]+) for "([^"]+)" channel$/
444
     */
445
    public function iChangeItsPriceTo($price, $channelName)
446
    {
447
        $this->updateSimpleProductPage->specifyPrice($channelName, $price);
448
    }
449
450
    /**
451
     * @Given I add the :optionName option to it
452
     */
453
    public function iAddTheOptionToIt($optionName)
454
    {
455
        $this->createConfigurableProductPage->selectOption($optionName);
456
    }
457
458
    /**
459
     * @When I set its :attribute attribute to :value
460
     * @When I set its :attribute attribute to :value in :language
461
     */
462
    public function iSetItsAttributeTo($attribute, $value, $language = 'en_US')
463
    {
464
        $this->createSimpleProductPage->addAttribute($attribute, $value, $language);
465
    }
466
467
    /**
468
     * @When I remove its :attribute attribute
469
     * @When I remove its :attribute attribute from :language
470
     */
471
    public function iRemoveItsAttribute($attribute, $language = 'en_US')
472
    {
473
        $this->createSimpleProductPage->removeAttribute($attribute, $language);
474
    }
475
476
    /**
477
     * @When I try to add new attributes
478
     */
479
    public function iTryToAddNewAttributes()
480
    {
481
        $this->updateSimpleProductPage->addSelectedAttributes();
482
    }
483
484
    /**
485
     * @Then attribute :attributeName of product :product should be :value
486
     * @Then attribute :attributeName of product :product should be :value in :language
487
     */
488
    public function itsAttributeShouldBe($attributeName, ProductInterface $product, $value, $language = 'en_US')
489
    {
490
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
491
492
        Assert::same($this->updateSimpleProductPage->getAttributeValue($attributeName, $language), $value);
493
    }
494
495
    /**
496
     * @Then /^(product "[^"]+") should not have a "([^"]+)" attribute$/
497
     */
498
    public function productShouldNotHaveAttribute(ProductInterface $product, $attribute)
499
    {
500
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
501
502
        Assert::false($this->updateSimpleProductPage->hasAttribute($attribute));
503
    }
504
505
    /**
506
     * @Then product :product should not have any attributes
507
     * @Then product :product should have :count attribute
508
     */
509
    public function productShouldNotHaveAnyAttributes(ProductInterface $product, $count = 0)
510
    {
511
        Assert::same($this->updateSimpleProductPage->getNumberOfAttributes(), (int) $count);
512
    }
513
514
    /**
515
     * @Given product with :element :value should not be added
516
     */
517
    public function productWithNameShouldNotBeAdded($element, $value)
518
    {
519
        $this->iWantToBrowseProducts();
520
521
        Assert::false($this->indexPage->isSingleResourceOnPage([$element => $value]));
522
    }
523
524
    /**
525
     * @When I remove its name from :language translation
526
     */
527
    public function iRemoveItsNameFromTranslation($language)
528
    {
529
        $currentPage = $this->resolveCurrentPage();
530
531
        $currentPage->nameItIn('', $language);
532
    }
533
534
    /**
535
     * @Then /^this product should have (?:a|an) "([^"]+)" option$/
536
     */
537
    public function thisProductShouldHaveOption($productOption)
538
    {
539
        $this->updateConfigurableProductPage->isProductOptionChosen($productOption);
540
    }
541
542
    /**
543
     * @Then the option field should be disabled
544
     */
545
    public function theOptionFieldShouldBeDisabled()
546
    {
547
        Assert::true($this->updateConfigurableProductPage->isProductOptionsDisabled());
548
    }
549
550
    /**
551
     * @When /^I choose main (taxon "([^"]+)")$/
552
     */
553
    public function iChooseMainTaxon(TaxonInterface $taxon)
554
    {
555
        $currentPage = $this->resolveCurrentPage();
556
557
        $currentPage->selectMainTaxon($taxon);
558
    }
559
560
    /**
561
     * @Then /^the slug of the ("[^"]+" product) should(?:| still) be "([^"]+)"$/
562
     * @Then /^the slug of the ("[^"]+" product) should(?:| still) be "([^"]+)" (in the "[^"]+" locale)$/
563
     */
564
    public function productSlugShouldBe(ProductInterface $product, $slug, $locale = 'en_US')
565
    {
566
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
567
568
        Assert::same($this->updateSimpleProductPage->getSlug($locale), $slug);
569
    }
570
571
    /**
572
     * @Then /^(this product) main taxon should be "([^"]+)"$/
573
     */
574
    public function thisProductMainTaxonShouldBe(ProductInterface $product, $taxonName)
575
    {
576
        $currentPage = $this->resolveCurrentPage();
577
        $currentPage->open(['id' => $product->getId()]);
578
579
        Assert::true($currentPage->isMainTaxonChosen($taxonName));
580
    }
581
582
    /**
583
     * @Then /^inventory of (this product) should not be tracked$/
584
     */
585
    public function thisProductShouldNotBeTracked(ProductInterface $product)
586
    {
587
        $this->iWantToModifyAProduct($product);
588
589
        Assert::false($this->updateSimpleProductPage->isTracked());
590
    }
591
592
    /**
593
     * @Then /^inventory of (this product) should be tracked$/
594
     */
595
    public function thisProductShouldBeTracked(ProductInterface $product)
596
    {
597
        $this->iWantToModifyAProduct($product);
598
599
        Assert::true($this->updateSimpleProductPage->isTracked());
600
    }
601
602
    /**
603
     * @When I attach the :path image with a code :code
604
     */
605
    public function iAttachImageWithACode($path, $code)
606
    {
607
        /** @var CreatePageInterface|UpdatePageInterface $currentPage */
608
        $currentPage = $this->resolveCurrentPage();
609
610
        $currentPage->attachImage($path, $code);
611
    }
612
613
    /**
614
     * @When I attach the :path image without a code
615
     */
616
    public function iAttachImageWithoutACode($path)
617
    {
618
        /** @var UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface $currentPage */
619
        $currentPage = $this->resolveCurrentPage();
620
621
        $currentPage->attachImage($path);
622
    }
623
624
    /**
625
     * @When I associate as :productAssociationType the :productName product
626
     * @When I associate as :productAssociationType the :firstProductName and :secondProductName products
627
     */
628
    public function iAssociateProductsAsProductAssociation(
629
        ProductAssociationTypeInterface $productAssociationType,
630
        ...$productsNames
631
    ) {
632
        /** @var UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface $currentPage */
633
        $currentPage = $this->resolveCurrentPage();
634
635
        $currentPage->associateProducts($productAssociationType, $productsNames);
636
    }
637
638
    /**
639
     * @When I remove an associated product :productName from :productAssociationType
640
     */
641
    public function iRemoveAnAssociatedProductFromProductAssociation(
642
        $productName,
643
        ProductAssociationTypeInterface $productAssociationType
644
    ) {
645
        /** @var UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface $currentPage */
646
        $currentPage = $this->resolveCurrentPage();
647
648
        $currentPage->removeAssociatedProduct($productName, $productAssociationType);
649
    }
650
651
    /**
652
     * @Then /^(this product) should have(?:| also) an image with a code "([^"]*)"$/
653
     * @Then /^the (product "[^"]+") should have(?:| also) an image with a code "([^"]*)"$/
654
     */
655
    public function thisProductShouldHaveAnImageWithCode(ProductInterface $product, $code)
656
    {
657
        $this->sharedStorage->set('product', $product);
658
659
        /** @var UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface $currentPage */
660
        $currentPage = $this->resolveCurrentPage();
661
662
        Assert::true($currentPage->isImageWithCodeDisplayed($code));
663
    }
664
665
    /**
666
     * @Then /^this product should not have(?:| also) an image with a code "([^"]*)"$/
667
     */
668
    public function thisProductShouldNotHaveAnImageWithCode($code)
669
    {
670
        /** @var UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface $currentPage */
671
        $currentPage = $this->resolveCurrentPage();
672
673
        Assert::false($currentPage->isImageWithCodeDisplayed($code));
674
    }
675
676
    /**
677
     * @When I change the image with the :code code to :path
678
     */
679
    public function iChangeItsImageToPathForTheCode($path, $code)
680
    {
681
        /** @var UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface $currentPage */
682
        $currentPage = $this->resolveCurrentPage();
683
684
        $currentPage->changeImageWithCode($code, $path);
685
    }
686
687
    /**
688
     * @When /^I remove(?:| also) an image with a code "([^"]*)"$/
689
     */
690
    public function iRemoveAnImageWithACode($code)
691
    {
692
        /** @var UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface $currentPage */
693
        $currentPage = $this->resolveCurrentPage();
694
695
        $currentPage->removeImageWithCode($code);
696
    }
697
698
    /**
699
     * @When I remove the first image
700
     */
701
    public function iRemoveTheFirstImage()
702
    {
703
        /** @var UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface $currentPage */
704
        $currentPage = $this->resolveCurrentPage();
705
706
        $currentPage->removeFirstImage();
707
    }
708
709
    /**
710
     * @Then /^(this product) should not have any images$/
711
     */
712
    public function thisProductShouldNotHaveImages(ProductInterface $product)
713
    {
714
        $this->iWantToModifyAProduct($product);
715
716
        $currentPage = $this->resolveCurrentPage();
717
718
        Assert::same($currentPage->countImages(), 0);
719
    }
720
721
    /**
722
     * @Then the image code field should be disabled
723
     */
724
    public function theImageCodeFieldShouldBeDisabled()
725
    {
726
        /** @var UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface $currentPage */
727
        $currentPage = $this->resolveCurrentPage();
728
729
        Assert::true($currentPage->isImageCodeDisabled());
730
    }
731
732
    /**
733
     * @Then I should be notified that the image with this code already exists
734
     */
735
    public function iShouldBeNotifiedThatTheImageWithThisCodeAlreadyExists()
736
    {
737
        Assert::same($this->updateSimpleProductPage->getValidationMessageForImage(), 'Image code must be unique within this product.');
738
    }
739
740
    /**
741
     * @Then I should be notified that an image code is required
742
     */
743
    public function iShouldBeNotifiedThatAnImageCodeIsRequired()
744
    {
745
        /** @var UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface $currentPage */
746
        $currentPage = $this->resolveCurrentPage();
747
748
        Assert::same($currentPage->getValidationMessageForImage(), 'Please enter an image code.');
749
    }
750
751
    /**
752
     * @Then there should still be only one image in the :product product
753
     */
754
    public function thereShouldStillBeOnlyOneImageInThisTaxon(ProductInterface $product)
755
    {
756
        $this->iWantToModifyAProduct($product);
757
758
        $currentPage = $this->resolveCurrentPage();
759
760
        Assert::same($currentPage->countImages(), 1);
761
    }
762
763
    /**
764
     * @Then /^there should be no reviews of (this product)$/
765
     */
766
    public function thereAreNoProductReviews(ProductInterface $product)
767
    {
768
        $this->productReviewIndexPage->open();
769
770
        Assert::false($this->productReviewIndexPage->isSingleResourceOnPage(['reviewSubject' => $product->getName()]));
771
    }
772
773
    /**
774
     * @Then this product should( also) have an association :productAssociationType with product :productName
775
     * @Then this product should( also) have an association :productAssociationType with products :firstProductName and :secondProductName
776
     */
777
    public function theProductShouldHaveAnAssociationWithProducts(
778
        ProductAssociationTypeInterface $productAssociationType,
779
        ...$productsNames
780
    ) {
781
        foreach ($productsNames as $productName) {
782
            Assert::true(
783
                $this->updateSimpleProductPage->hasAssociatedProduct($productName, $productAssociationType),
784
                sprintf(
785
                    'This product should have an association %s with product %s.',
786
                    $productAssociationType->getName(),
787
                    $productName
788
                )
789
            );
790
        }
791
    }
792
793
    /**
794
     * @Then this product should not have an association :productAssociationType with product :productName
795
     */
796
    public function theProductShouldNotHaveAnAssociationWithProducts(
797
        ProductAssociationTypeInterface $productAssociationType,
798
        $productName
799
    ) {
800
        Assert::false($this->updateSimpleProductPage->hasAssociatedProduct($productName);
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected ';', expecting ',' or ')'
Loading history...
801
    }
802
803
    /**
804
     * @Then I should be notified that simple product code has to be unique
805
     */
806
    public function iShouldBeNotifiedThatSimpleProductCodeHasToBeUnique()
807
    {
808
        $this->assertValidationMessage('code', 'Simple product code must be unique among all products and product variants.');
809
    }
810
811
    /**
812
     * @Then I should not be notified that simple product code has to be unique
813
     */
814
    public function iShouldNotBeNotifiedThatSimpleProductCodeHasToBeUnique()
815
    {
816
        /** @var CreatePageInterface|UpdatePageInterface $currentPage */
817
        $currentPage = $this->resolveCurrentPage();
818
819
        try {
820
            $validationMessge = $currentPage->getValidationMessage('code');
821
822
            Assert::notSame($validationMessge, 'Simple product code must be unique among all products and product variants.');
823
        } catch (ElementNotFoundException $e) {
824
            // intentionally left blank, as it could not have any validation at all
825
        }
826
    }
827
828
    /**
829
     * @Then I should be notified that slug has to be unique
830
     */
831
    public function iShouldBeNotifiedThatSlugHasToBeUnique()
832
    {
833
        $this->assertValidationMessage('slug', 'Product slug must be unique.');
834
    }
835
836
    /**
837
     * @Then I should be notified that code has to be unique
838
     */
839
    public function iShouldBeNotifiedThatCodeHasToBeUnique()
840
    {
841
        $this->assertValidationMessage('code', 'Product code must be unique.');
842
    }
843
844
    /**
845
     * @Then I should be notified that price must be defined for every channel
846
     */
847
    public function iShouldBeNotifiedThatPriceMustBeDefinedForEveryChannel()
848
    {
849
        $this->assertValidationMessage('channel_pricings', 'You must define price for every channel.');
850
    }
851
852
    /**
853
     * @Then they should have order like :firstProductName, :secondProductName and :thirdProductName
854
     */
855
    public function theyShouldHaveOrderLikeAnd(...$productNames)
856
    {
857
        Assert::true($this->indexPerTaxonPage->hasProductsInOrder($productNames));
858
    }
859
860
    /**
861
     * @When I save my new configuration
862
     */
863
    public function iSaveMyNewConfiguration()
864
    {
865
        $this->indexPerTaxonPage->savePositions();
866
    }
867
868
    /**
869
     * @When I set the position of :productName to :position
870
     */
871
    public function iSetThePositionOfTo($productName, $position)
872
    {
873
        $this->indexPerTaxonPage->setPositionOfProduct($productName, (int) $position);
874
    }
875
876
    /**
877
     * @Then this product should( still) have slug :value in :language
878
     */
879
    public function thisProductElementShouldHaveSlugIn($slug, $language)
880
    {
881
        Assert::same($this->updateSimpleProductPage->getSlug($language), $slug);
882
    }
883
884
    /**
885
     * @When I set its shipping category as :shippingCategoryName
886
     */
887
    public function iSetItsShippingCategoryAs($shippingCategoryName)
888
    {
889
        $this->createSimpleProductPage->selectShippingCategory($shippingCategoryName);
890
    }
891
892
    /**
893
     * @Then /^(it|this product) should be priced at (?:€|£|\$)([^"]+) for channel "([^"]+)"$/
894
     * @Then /^(product "[^"]+") should be priced at (?:€|£|\$)([^"]+) for channel "([^"]+)"$/
895
     */
896
    public function itShouldBePricedAtForChannel(ProductInterface $product, $price, $channelName)
897
    {
898
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
899
900
        Assert::same($this->updateSimpleProductPage->getPriceForChannel($channelName), $price);
901
    }
902
903
    /**
904
     * @Then /^(this product) should no longer have price for channel "([^"]+)"$/
905
     */
906
    public function thisProductShouldNoLongerHavePriceForChannel(ProductInterface $product, $channelName)
907
    {
908
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
909
910
        try {
911
            $this->updateSimpleProductPage->getPriceForChannel($channelName);
912
        } catch (ElementNotFoundException $exception) {
913
            return;
914
        }
915
916
        throw new \Exception(
917
            sprintf('Product "%s" should not have price defined for channel "%s".', $product->getName(), $channelName)
918
        );
919
    }
920
921
    /**
922
     * @Then I should be notified that the :imageNumber image should have an unique code
923
     */
924
    public function iShouldBeNotifiedThatTheFirstImageShouldHaveAnUniqueCode($imageNumber)
925
    {
926
        Assert::same(
927
            $this->updateSimpleProductPage->getValidationMessageForImageAtPosition((int) $imageNumber - 1),
928
            'Image code must be unique within this product.'
929
        );
930
    }
931
932
    /**
933
     * @Then I should be notified that I have to define product variants' prices for newly assigned channels first
934
     */
935
    public function iShouldBeNotifiedThatIHaveToDefineProductVariantsPricesForNewlyAssignedChannelsFirst()
936
    {
937
        Assert::same(
938
            $this->updateConfigurableProductPage->getValidationMessage('channels'),
939
            'You have to define product variants\' prices for newly assigned channels first.'
940
        );
941
    }
942
943
    /**
944
     * @param string $element
945
     * @param string $value
946
     */
947
    private function assertElementValue($element, $value)
948
    {
949
        /** @var UpdatePageInterface $currentPage */
950
        $currentPage = $this->resolveCurrentPage();
951
952
        Assert::isInstanceOf($currentPage, UpdatePageInterface::class);
953
954
        Assert::true(
955
            $currentPage->hasResourceValues([$element => $value]),
956
            sprintf('Product should have %s with %s value.', $element, $value)
957
        );
958
    }
959
960
    /**
961
     * @param string $element
962
     * @param string $message
963
     */
964
    private function assertValidationMessage($element, $message)
965
    {
966
        /** @var CreatePageInterface|UpdatePageInterface $currentPage */
967
        $currentPage = $this->resolveCurrentPage();
968
969
        Assert::same($currentPage->getValidationMessage($element), $message);
970
    }
971
972
    /**
973
     * @return IndexPageInterface|IndexPerTaxonPageInterface|CreateSimpleProductPageInterface|CreateConfigurableProductPageInterface|UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface
974
     */
975
    private function resolveCurrentPage()
976
    {
977
        return $this->currentPageResolver->getCurrentPageWithForm([
978
            $this->indexPage,
979
            $this->indexPerTaxonPage,
980
            $this->createSimpleProductPage,
981
            $this->createConfigurableProductPage,
982
            $this->updateSimpleProductPage,
983
            $this->updateConfigurableProductPage,
984
        ]);
985
    }
986
}
987