Completed
Push — locale-in-url ( c8ed20...ec55a8 )
by Kamil
46:19 queued 21:47
created

ManagingProductsContext::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 9.0856
c 0
b 0
f 0
cc 1
eloc 21
nc 1
nop 10

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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
        $currentPage = $this->resolveCurrentPage();
437
438
        $currentPage->saveChanges();
439
    }
440
441
    /**
442
     * @When /^I change its price to (?:€|£|\$)([^"]+) for "([^"]+)" channel$/
443
     */
444
    public function iChangeItsPriceTo($price, $channelName)
445
    {
446
        $this->updateSimpleProductPage->specifyPrice($channelName, $price);
447
    }
448
449
    /**
450
     * @Given I add the :optionName option to it
451
     */
452
    public function iAddTheOptionToIt($optionName)
453
    {
454
        $this->createConfigurableProductPage->selectOption($optionName);
455
    }
456
457
    /**
458
     * @When I set its :attribute attribute to :value
459
     * @When I set its :attribute attribute to :value in :language
460
     */
461
    public function iSetItsAttributeTo($attribute, $value, $language = 'en_US')
462
    {
463
        $this->createSimpleProductPage->addAttribute($attribute, $value, $language);
464
    }
465
466
    /**
467
     * @When I remove its :attribute attribute
468
     * @When I remove its :attribute attribute from :language
469
     */
470
    public function iRemoveItsAttribute($attribute, $language = 'en_US')
471
    {
472
        $this->createSimpleProductPage->removeAttribute($attribute, $language);
473
    }
474
475
    /**
476
     * @When I try to add new attributes
477
     */
478
    public function iTryToAddNewAttributes()
479
    {
480
        $this->updateSimpleProductPage->addSelectedAttributes();
481
    }
482
483
    /**
484
     * @Then attribute :attributeName of product :product should be :value
485
     * @Then attribute :attributeName of product :product should be :value in :language
486
     */
487
    public function itsAttributeShouldBe($attributeName, ProductInterface $product, $value, $language = 'en_US')
488
    {
489
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
490
491
        Assert::same($this->updateSimpleProductPage->getAttributeValue($attributeName, $language), $value);
492
    }
493
494
    /**
495
     * @Then /^(product "[^"]+") should not have a "([^"]+)" attribute$/
496
     */
497
    public function productShouldNotHaveAttribute(ProductInterface $product, $attribute)
498
    {
499
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
500
501
        Assert::false($this->updateSimpleProductPage->hasAttribute($attribute));
502
    }
503
504
    /**
505
     * @Then /^product "[^"]+" should not have any attributes$/
506
     * @Then /^product "[^"]+" should have (\d+) attributes?$/
507
     */
508
    public function productShouldNotHaveAnyAttributes($count = 0)
509
    {
510
        Assert::same($this->updateSimpleProductPage->getNumberOfAttributes(), (int) $count);
511
    }
512
513
    /**
514
     * @Given product with :element :value should not be added
515
     */
516
    public function productWithNameShouldNotBeAdded($element, $value)
517
    {
518
        $this->iWantToBrowseProducts();
519
520
        Assert::false($this->indexPage->isSingleResourceOnPage([$element => $value]));
521
    }
522
523
    /**
524
     * @When I remove its name from :language translation
525
     */
526
    public function iRemoveItsNameFromTranslation($language)
527
    {
528
        $currentPage = $this->resolveCurrentPage();
529
530
        $currentPage->nameItIn('', $language);
531
    }
532
533
    /**
534
     * @Then /^this product should have (?:a|an) "([^"]+)" option$/
535
     */
536
    public function thisProductShouldHaveOption($productOption)
537
    {
538
        $this->updateConfigurableProductPage->isProductOptionChosen($productOption);
539
    }
540
541
    /**
542
     * @Then the option field should be disabled
543
     */
544
    public function theOptionFieldShouldBeDisabled()
545
    {
546
        Assert::true($this->updateConfigurableProductPage->isProductOptionsDisabled());
547
    }
548
549
    /**
550
     * @When /^I choose main (taxon "([^"]+)")$/
551
     */
552
    public function iChooseMainTaxon(TaxonInterface $taxon)
553
    {
554
        $currentPage = $this->resolveCurrentPage();
555
556
        $currentPage->selectMainTaxon($taxon);
557
    }
558
559
    /**
560
     * @Then /^the slug of the ("[^"]+" product) should(?:| still) be "([^"]+)"$/
561
     * @Then /^the slug of the ("[^"]+" product) should(?:| still) be "([^"]+)" (in the "[^"]+" locale)$/
562
     */
563
    public function productSlugShouldBe(ProductInterface $product, $slug, $locale = 'en_US')
564
    {
565
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
566
567
        Assert::same($this->updateSimpleProductPage->getSlug($locale), $slug);
568
    }
569
570
    /**
571
     * @Then /^(this product) main taxon should be "([^"]+)"$/
572
     */
573
    public function thisProductMainTaxonShouldBe(ProductInterface $product, $taxonName)
574
    {
575
        $currentPage = $this->resolveCurrentPage();
576
        $currentPage->open(['id' => $product->getId()]);
577
578
        Assert::true($currentPage->isMainTaxonChosen($taxonName));
579
    }
580
581
    /**
582
     * @Then /^inventory of (this product) should not be tracked$/
583
     */
584
    public function thisProductShouldNotBeTracked(ProductInterface $product)
585
    {
586
        $this->iWantToModifyAProduct($product);
587
588
        Assert::false($this->updateSimpleProductPage->isTracked());
589
    }
590
591
    /**
592
     * @Then /^inventory of (this product) should be tracked$/
593
     */
594
    public function thisProductShouldBeTracked(ProductInterface $product)
595
    {
596
        $this->iWantToModifyAProduct($product);
597
598
        Assert::true($this->updateSimpleProductPage->isTracked());
599
    }
600
601
    /**
602
     * @When I attach the :path image with :type type
603
     * @When I attach the :path image
604
     */
605
    public function iAttachImageWithType($path, $type = null)
606
    {
607
        $currentPage = $this->resolveCurrentPage();
608
609
        $currentPage->attachImage($path, $type);
610
    }
611
612
    /**
613
     * @When I associate as :productAssociationType the :productName product
614
     * @When I associate as :productAssociationType the :firstProductName and :secondProductName products
615
     */
616
    public function iAssociateProductsAsProductAssociation(
617
        ProductAssociationTypeInterface $productAssociationType,
618
        ...$productsNames
619
    ) {
620
        $currentPage = $this->resolveCurrentPage();
621
622
        $currentPage->associateProducts($productAssociationType, $productsNames);
623
    }
624
625
    /**
626
     * @When I remove an associated product :productName from :productAssociationType
627
     */
628
    public function iRemoveAnAssociatedProductFromProductAssociation(
629
        $productName,
630
        ProductAssociationTypeInterface $productAssociationType
631
    ) {
632
        $currentPage = $this->resolveCurrentPage();
633
634
        $currentPage->removeAssociatedProduct($productName, $productAssociationType);
635
    }
636
637
    /**
638
     * @Then /^(?:this product|the product "[^"]+"|it) should(?:| also) have an image with "([^"]*)" type$/
639
     */
640
    public function thisProductShouldHaveAnImageWithType($type)
641
    {
642
        $currentPage = $this->resolveCurrentPage();
643
644
        Assert::true($currentPage->isImageWithTypeDisplayed($type));
645
    }
646
647
    /**
648
     * @Then /^(?:this product|it)(?:| also) should not have any images with "([^"]*)" type$/
649
     */
650
    public function thisProductShouldNotHaveAnyImagesWithType($code)
651
    {
652
        $currentPage = $this->resolveCurrentPage();
653
654
        Assert::false($currentPage->isImageWithTypeDisplayed($code));
655
    }
656
657
    /**
658
     * @When I change the image with the :type type to :path
659
     */
660
    public function iChangeItsImageToPathForTheType($type, $path)
661
    {
662
        $currentPage = $this->resolveCurrentPage();
663
664
        $currentPage->changeImageWithType($type, $path);
665
    }
666
667
    /**
668
     * @When /^I(?:| also) remove an image with "([^"]*)" type$/
669
     */
670
    public function iRemoveAnImageWithType($code)
671
    {
672
        $currentPage = $this->resolveCurrentPage();
673
674
        $currentPage->removeImageWithType($code);
675
    }
676
677
    /**
678
     * @When I remove the first image
679
     */
680
    public function iRemoveTheFirstImage()
681
    {
682
        $currentPage = $this->resolveCurrentPage();
683
684
        $currentPage->removeFirstImage();
685
    }
686
687
    /**
688
     * @When I change the first image type to :type
689
     */
690
    public function iChangeTheFirstImageTypeTo($type)
691
    {
692
        $currentPage = $this->resolveCurrentPage();
693
694
        $currentPage->modifyFirstImageType($type);
695
    }
696
697
    /**
698
     * @Then /^(this product) should not have any images$/
699
     */
700
    public function thisProductShouldNotHaveImages(ProductInterface $product)
701
    {
702
        $this->iWantToModifyAProduct($product);
703
704
        $currentPage = $this->resolveCurrentPage();
705
706
        Assert::same($currentPage->countImages(), 0);
707
    }
708
709
    /**
710
     * @Then /^(this product) should(?:| still) have (?:only one|(\d+)) images?$/
711
     */
712
    public function thereShouldStillBeOnlyOneImageInThisProduct(ProductInterface $product, $count = 1)
713
    {
714
        $this->iWantToModifyAProduct($product);
715
716
        $currentPage = $this->resolveCurrentPage();
717
718
        Assert::same($currentPage->countImages(), (int) $count);
719
    }
720
721
    /**
722
     * @Then /^there should be no reviews of (this product)$/
723
     */
724
    public function thereAreNoProductReviews(ProductInterface $product)
725
    {
726
        $this->productReviewIndexPage->open();
727
728
        Assert::false($this->productReviewIndexPage->isSingleResourceOnPage(['reviewSubject' => $product->getName()]));
729
    }
730
731
    /**
732
     * @Then this product should( also) have an association :productAssociationType with product :productName
733
     * @Then this product should( also) have an association :productAssociationType with products :firstProductName and :secondProductName
734
     */
735
    public function theProductShouldHaveAnAssociationWithProducts(
736
        ProductAssociationTypeInterface $productAssociationType,
737
        ...$productsNames
738
    ) {
739
        foreach ($productsNames as $productName) {
740
            Assert::true(
741
                $this->updateSimpleProductPage->hasAssociatedProduct($productName, $productAssociationType),
742
                sprintf(
743
                    'This product should have an association %s with product %s.',
744
                    $productAssociationType->getName(),
745
                    $productName
746
                )
747
            );
748
        }
749
    }
750
751
    /**
752
     * @Then this product should not have an association :productAssociationType with product :productName
753
     */
754
    public function theProductShouldNotHaveAnAssociationWithProduct(
755
        ProductAssociationTypeInterface $productAssociationType,
756
        $productName
757
    ) {
758
        Assert::false($this->updateSimpleProductPage->hasAssociatedProduct($productName, $productAssociationType));
759
    }
760
761
    /**
762
     * @Then I should be notified that simple product code has to be unique
763
     */
764
    public function iShouldBeNotifiedThatSimpleProductCodeHasToBeUnique()
765
    {
766
        $this->assertValidationMessage('code', 'Simple product code must be unique among all products and product variants.');
767
    }
768
769
    /**
770
     * @Then I should be notified that slug has to be unique
771
     */
772
    public function iShouldBeNotifiedThatSlugHasToBeUnique()
773
    {
774
        $this->assertValidationMessage('slug', 'Product slug must be unique.');
775
    }
776
777
    /**
778
     * @Then I should be notified that code has to be unique
779
     */
780
    public function iShouldBeNotifiedThatCodeHasToBeUnique()
781
    {
782
        $this->assertValidationMessage('code', 'Product code must be unique.');
783
    }
784
785
    /**
786
     * @Then I should be notified that price must be defined for every channel
787
     */
788
    public function iShouldBeNotifiedThatPriceMustBeDefinedForEveryChannel()
789
    {
790
        $this->assertValidationMessage('channel_pricings', 'You must define price for every channel.');
791
    }
792
793
    /**
794
     * @Then they should have order like :firstProductName, :secondProductName and :thirdProductName
795
     */
796
    public function theyShouldHaveOrderLikeAnd(...$productNames)
797
    {
798
        Assert::true($this->indexPerTaxonPage->hasProductsInOrder($productNames));
799
    }
800
801
    /**
802
     * @When I save my new configuration
803
     */
804
    public function iSaveMyNewConfiguration()
805
    {
806
        $this->indexPerTaxonPage->savePositions();
807
    }
808
809
    /**
810
     * @When I set the position of :productName to :position
811
     */
812
    public function iSetThePositionOfTo($productName, $position)
813
    {
814
        $this->indexPerTaxonPage->setPositionOfProduct($productName, (int) $position);
815
    }
816
817
    /**
818
     * @Then this product should( still) have slug :value in :language
819
     */
820
    public function thisProductElementShouldHaveSlugIn($slug, $language)
821
    {
822
        Assert::same($this->updateSimpleProductPage->getSlug($language), $slug);
823
    }
824
825
    /**
826
     * @When I set its shipping category as :shippingCategoryName
827
     */
828
    public function iSetItsShippingCategoryAs($shippingCategoryName)
829
    {
830
        $this->createSimpleProductPage->selectShippingCategory($shippingCategoryName);
831
    }
832
833
    /**
834
     * @Then /^(it|this product) should be priced at (?:€|£|\$)([^"]+) for channel "([^"]+)"$/
835
     * @Then /^(product "[^"]+") should be priced at (?:€|£|\$)([^"]+) for channel "([^"]+)"$/
836
     */
837
    public function itShouldBePricedAtForChannel(ProductInterface $product, $price, $channelName)
838
    {
839
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
840
841
        Assert::same($this->updateSimpleProductPage->getPriceForChannel($channelName), $price);
842
    }
843
844
    /**
845
     * @Then /^(this product) should no longer have price for channel "([^"]+)"$/
846
     */
847
    public function thisProductShouldNoLongerHavePriceForChannel(ProductInterface $product, $channelName)
848
    {
849
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
850
851
        try {
852
            $this->updateSimpleProductPage->getPriceForChannel($channelName);
853
        } catch (ElementNotFoundException $exception) {
854
            return;
855
        }
856
857
        throw new \Exception(
858
            sprintf('Product "%s" should not have price defined for channel "%s".', $product->getName(), $channelName)
859
        );
860
    }
861
862
    /**
863
     * @Then I should be notified that I have to define product variants' prices for newly assigned channels first
864
     */
865
    public function iShouldBeNotifiedThatIHaveToDefineProductVariantsPricesForNewlyAssignedChannelsFirst()
866
    {
867
        Assert::same(
868
            $this->updateConfigurableProductPage->getValidationMessage('channels'),
869
            'You have to define product variants\' prices for newly assigned channels first.'
870
        );
871
    }
872
873
    /**
874
     * @param string $element
875
     * @param string $value
876
     */
877
    private function assertElementValue($element, $value)
878
    {
879
        /** @var UpdatePageInterface $currentPage */
880
        $currentPage = $this->resolveCurrentPage();
881
882
        Assert::isInstanceOf($currentPage, UpdatePageInterface::class);
883
884
        Assert::true(
885
            $currentPage->hasResourceValues([$element => $value]),
886
            sprintf('Product should have %s with %s value.', $element, $value)
887
        );
888
    }
889
890
    /**
891
     * @param string $element
892
     * @param string $message
893
     */
894
    private function assertValidationMessage($element, $message)
895
    {
896
        /** @var CreatePageInterface|UpdatePageInterface $currentPage */
897
        $currentPage = $this->resolveCurrentPage();
898
899
        Assert::same($currentPage->getValidationMessage($element), $message);
900
    }
901
902
    /**
903
     * @return SymfonyPageInterface|IndexPageInterface|IndexPerTaxonPageInterface|CreateSimpleProductPageInterface|CreateConfigurableProductPageInterface|UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface
904
     */
905
    private function resolveCurrentPage()
906
    {
907
        return $this->currentPageResolver->getCurrentPageWithForm([
908
            $this->indexPage,
909
            $this->indexPerTaxonPage,
910
            $this->createSimpleProductPage,
911
            $this->createConfigurableProductPage,
912
            $this->updateSimpleProductPage,
913
            $this->updateConfigurableProductPage,
914
        ]);
915
    }
916
}
917