Completed
Push — 1.7 ( 0983e5...497e44 )
by Kamil
05:26
created

theProductWithCodeShouldNotHaveShippingRequired()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Sylius\Behat\Context\Ui\Admin;
15
16
use Behat\Behat\Context\Context;
17
use Behat\Mink\Exception\ElementNotFoundException;
18
use Sylius\Behat\NotificationType;
19
use Sylius\Behat\Page\Admin\Crud\CreatePageInterface;
20
use Sylius\Behat\Page\Admin\Crud\UpdatePageInterface;
21
use Sylius\Behat\Page\Admin\Product\CreateConfigurableProductPageInterface;
22
use Sylius\Behat\Page\Admin\Product\CreateSimpleProductPageInterface;
23
use Sylius\Behat\Page\Admin\Product\IndexPageInterface;
24
use Sylius\Behat\Page\Admin\Product\IndexPerTaxonPageInterface;
25
use Sylius\Behat\Page\Admin\Product\UpdateConfigurableProductPageInterface;
26
use Sylius\Behat\Page\Admin\Product\UpdateSimpleProductPageInterface;
27
use Sylius\Behat\Page\Admin\ProductReview\IndexPageInterface as ProductReviewIndexPageInterface;
28
use Sylius\Behat\Page\Admin\ProductVariant\CreatePageInterface as VariantCreatePageInterface;
29
use Sylius\Behat\Page\Admin\ProductVariant\GeneratePageInterface;
30
use Sylius\Behat\Service\NotificationCheckerInterface;
31
use Sylius\Behat\Service\Resolver\CurrentPageResolverInterface;
32
use Sylius\Behat\Service\SharedStorageInterface;
33
use Sylius\Component\Core\Model\ChannelInterface;
34
use Sylius\Component\Core\Model\ProductInterface;
35
use Sylius\Component\Core\Model\TaxonInterface;
36
use Sylius\Component\Product\Model\ProductAssociationTypeInterface;
37
use Webmozart\Assert\Assert;
38
39
final class ManagingProductsContext implements Context
40
{
41
    /** @var SharedStorageInterface */
42
    private $sharedStorage;
43
44
    /** @var CreateSimpleProductPageInterface */
45
    private $createSimpleProductPage;
46
47
    /** @var CreateConfigurableProductPageInterface */
48
    private $createConfigurableProductPage;
49
50
    /** @var IndexPageInterface */
51
    private $indexPage;
52
53
    /** @var UpdateSimpleProductPageInterface */
54
    private $updateSimpleProductPage;
55
56
    /** @var UpdateConfigurableProductPageInterface */
57
    private $updateConfigurableProductPage;
58
59
    /** @var ProductReviewIndexPageInterface */
60
    private $productReviewIndexPage;
61
62
    /** @var IndexPerTaxonPageInterface */
63
    private $indexPerTaxonPage;
64
65
    /** @var VariantCreatePageInterface */
66
    private $variantCreatePage;
67
68
    /** @var GeneratePageInterface */
69
    private $variantGeneratePage;
70
71
    /** @var CurrentPageResolverInterface */
72
    private $currentPageResolver;
73
74
    /** @var NotificationCheckerInterface */
75
    private $notificationChecker;
76
77
    public function __construct(
78
        SharedStorageInterface $sharedStorage,
79
        CreateSimpleProductPageInterface $createSimpleProductPage,
80
        CreateConfigurableProductPageInterface $createConfigurableProductPage,
81
        IndexPageInterface $indexPage,
82
        UpdateSimpleProductPageInterface $updateSimpleProductPage,
83
        UpdateConfigurableProductPageInterface $updateConfigurableProductPage,
84
        ProductReviewIndexPageInterface $productReviewIndexPage,
85
        IndexPerTaxonPageInterface $indexPerTaxonPage,
86
        VariantCreatePageInterface $variantCreatePage,
87
        GeneratePageInterface $variantGeneratePage,
88
        CurrentPageResolverInterface $currentPageResolver,
89
        NotificationCheckerInterface $notificationChecker
90
    ) {
91
        $this->sharedStorage = $sharedStorage;
92
        $this->createSimpleProductPage = $createSimpleProductPage;
93
        $this->createConfigurableProductPage = $createConfigurableProductPage;
94
        $this->indexPage = $indexPage;
95
        $this->updateSimpleProductPage = $updateSimpleProductPage;
96
        $this->updateConfigurableProductPage = $updateConfigurableProductPage;
97
        $this->productReviewIndexPage = $productReviewIndexPage;
98
        $this->indexPerTaxonPage = $indexPerTaxonPage;
99
        $this->variantCreatePage = $variantCreatePage;
100
        $this->variantGeneratePage = $variantGeneratePage;
101
        $this->currentPageResolver = $currentPageResolver;
102
        $this->notificationChecker = $notificationChecker;
103
    }
104
105
    /**
106
     * @Given I want to create a new simple product
107
     */
108
    public function iWantToCreateANewSimpleProduct()
109
    {
110
        $this->createSimpleProductPage->open();
111
    }
112
113
    /**
114
     * @Given I want to create a new configurable product
115
     */
116
    public function iWantToCreateANewConfigurableProduct()
117
    {
118
        $this->createConfigurableProductPage->open();
119
    }
120
121
    /**
122
     * @When I specify its code as :code
123
     * @When I do not specify its code
124
     */
125
    public function iSpecifyItsCodeAs($code = null)
126
    {
127
        $currentPage = $this->resolveCurrentPage();
128
129
        $currentPage->specifyCode($code ?? '');
0 ignored issues
show
Bug introduced by
The method specifyCode does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...pleProductPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
130
    }
131
132
    /**
133
     * @When I name it :name in :language
134
     * @When I rename it to :name in :language
135
     */
136
    public function iRenameItToIn($name, $language)
137
    {
138
        $currentPage = $this->resolveCurrentPage();
139
140
        $currentPage->nameItIn($name, $language);
0 ignored issues
show
Bug introduced by
The method nameItIn does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
141
    }
142
143
    /**
144
     * @When I add it
145
     * @When I try to add it
146
     */
147
    public function iAddIt()
148
    {
149
        /** @var CreatePageInterface $currentPage */
150
        $currentPage = $this->resolveCurrentPage();
151
152
        $currentPage->create();
153
    }
154
155
    /**
156
     * @When I disable its inventory tracking
157
     */
158
    public function iDisableItsTracking()
159
    {
160
        $this->updateSimpleProductPage->disableTracking();
161
    }
162
163
    /**
164
     * @When I enable its inventory tracking
165
     */
166
    public function iEnableItsTracking()
167
    {
168
        $this->updateSimpleProductPage->enableTracking();
169
    }
170
171
    /**
172
     * @When /^I set its(?:| default) price to "(?:€|£|\$)([^"]+)" for "([^"]+)" channel$/
173
     */
174
    public function iSetItsPriceTo(string $price, string $channelName)
175
    {
176
        $this->createSimpleProductPage->specifyPrice($channelName, $price);
177
    }
178
179
    /**
180
     * @When /^I set its original price to "(?:€|£|\$)([^"]+)" for "([^"]+)" channel$/
181
     */
182
    public function iSetItsOriginalPriceTo(int $originalPrice, $channelName)
183
    {
184
        $this->createSimpleProductPage->specifyOriginalPrice($channelName, $originalPrice);
185
    }
186
187
    /**
188
     * @When I make it available in channel :channel
189
     */
190
    public function iMakeItAvailableInChannel(ChannelInterface $channel)
191
    {
192
        $this->createSimpleProductPage->checkChannel($channel->getName());
193
    }
194
195
    /**
196
     * @When I assign it to channel :channel
197
     */
198
    public function iAssignItToChannel(ChannelInterface $channel)
199
    {
200
        // Temporary solution until we will make current page resolver work with product pages
201
        $this->updateConfigurableProductPage->checkChannel($channel->getName());
202
    }
203
204
    /**
205
     * @When I choose :calculatorName calculator
206
     */
207
    public function iChooseCalculator($calculatorName)
208
    {
209
        $this->createSimpleProductPage->choosePricingCalculator($calculatorName);
210
    }
211
212
    /**
213
     * @When I set its slug to :slug
214
     * @When I set its slug to :slug in :language
215
     * @When I remove its slug
216
     */
217
    public function iSetItsSlugToIn(?string $slug = null, $language = 'en_US')
218
    {
219
        $this->createSimpleProductPage->specifySlugIn($slug, $language);
220
    }
221
222
    /**
223
     * @When I choose to show this product in the :channel channel
224
     */
225
    public function iChooseToShowThisProductInTheChannel(string $channel): void
226
    {
227
        $this->updateSimpleProductPage->showProductInChannel($channel);
228
    }
229
230
    /**
231
     * @When I choose to show this product in this channel
232
     */
233
    public function iChooseToShowThisProductInThisChannel(): void
234
    {
235
        $this->updateSimpleProductPage->showProductInSingleChannel();
236
    }
237
238
    /**
239
     * @When I enable slug modification
240
     * @When I enable slug modification in :localeCode
241
     */
242
    public function iEnableSlugModification($localeCode = 'en_US')
243
    {
244
        $this->updateSimpleProductPage->activateLanguageTab($localeCode);
245
        $this->updateSimpleProductPage->enableSlugModification($localeCode);
246
    }
247
248
    /**
249
     * @Then I should see the product :productName in the list
250
     * @Then the product :productName should appear in the store
251
     * @Then the product :productName should be in the shop
252
     * @Then this product should still be named :productName
253
     */
254
    public function theProductShouldAppearInTheShop(string $productName): void
255
    {
256
        $this->iWantToBrowseProducts();
257
258
        Assert::true($this->indexPage->isSingleResourceOnPage(['name' => $productName]));
259
    }
260
261
    /**
262
     * @Given I am browsing products
263
     * @When I browse products
264
     * @When I want to browse products
265
     */
266
    public function iWantToBrowseProducts()
267
    {
268
        $this->indexPage->open();
269
    }
270
271
    /**
272
     * @When /^I am browsing products from ("([^"]+)" taxon)$/
273
     */
274
    public function iAmBrowsingProductsFromTaxon(TaxonInterface $taxon)
275
    {
276
        $this->indexPerTaxonPage->open(['taxonId' => $taxon->getId()]);
277
    }
278
279
    /**
280
     * @When I filter them by :taxonName taxon
281
     */
282
    public function iFilterThemByTaxon($taxonName)
283
    {
284
        $this->indexPage->filterByTaxon($taxonName);
285
    }
286
287
    /**
288
     * @When I check (also) the :productName product
289
     */
290
    public function iCheckTheProduct(string $productName): void
291
    {
292
        $this->indexPage->checkResourceOnPage(['name' => $productName]);
293
    }
294
295
    /**
296
     * @When I delete them
297
     */
298
    public function iDeleteThem(): void
299
    {
300
        $this->indexPage->bulkDelete();
301
    }
302
303
    /**
304
     * @Then I should( still) see a product with :field :value
305
     */
306
    public function iShouldSeeProductWith($field, $value)
307
    {
308
        Assert::true($this->indexPage->isSingleResourceOnPage([$field => $value]));
309
    }
310
311
    /**
312
     * @Then I should not see any product with :field :value
313
     */
314
    public function iShouldNotSeeAnyProductWith($field, $value)
315
    {
316
        Assert::false($this->indexPage->isSingleResourceOnPage([$field => $value]));
317
    }
318
319
    /**
320
     * @Then the first product on the list should have :field :value
321
     */
322
    public function theFirstProductOnTheListShouldHave($field, $value)
323
    {
324
        $currentPage = $this->resolveCurrentPage();
325
326
        Assert::same($currentPage->getColumnFields($field)[0], $value);
0 ignored issues
show
Bug introduced by
The method getColumnFields does only exist in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface, but not in Sylius\Behat\Page\Admin\...pleProductPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
327
    }
328
329
    /**
330
     * @Then the last product on the list should have :field :value
331
     */
332
    public function theLastProductOnTheListShouldHave($field, $value)
333
    {
334
        $values = $this->indexPerTaxonPage->getColumnFields($field);
335
336
        Assert::same(end($values), $value);
337
    }
338
339
    /**
340
     * @When I switch the way products are sorted by :field
341
     * @When I start sorting products by :field
342
     * @Given the products are already sorted by :field
343
     */
344
    public function iSortProductsBy($field)
345
    {
346
        $this->indexPage->sortBy($field);
347
    }
348
349
    /**
350
     * @Then I should see a single product in the list
351
     * @Then I should see :numberOfProducts products in the list
352
     */
353
    public function iShouldSeeProductsInTheList(int $numberOfProducts = 1): void
354
    {
355
        Assert::same($this->indexPage->countItems(), (int) $numberOfProducts);
356
    }
357
358
    /**
359
     * @When I delete the :product product
360
     * @When I try to delete the :product product
361
     */
362
    public function iDeleteProduct(ProductInterface $product)
363
    {
364
        $this->sharedStorage->set('product', $product);
365
366
        $this->iWantToBrowseProducts();
367
        $this->indexPage->deleteResourceOnPage(['name' => $product->getName()]);
368
    }
369
370
    /**
371
     * @Then /^(this product) should not exist in the product catalog$/
372
     */
373
    public function productShouldNotExist(ProductInterface $product)
374
    {
375
        $this->iWantToBrowseProducts();
376
377
        Assert::false($this->indexPage->isSingleResourceOnPage(['code' => $product->getCode()]));
378
    }
379
380
    /**
381
     * @Then I should be notified that this product is in use and cannot be deleted
382
     */
383
    public function iShouldBeNotifiedOfFailure()
384
    {
385
        $this->notificationChecker->checkNotification(
386
            'Cannot delete, the product is in use.',
387
            NotificationType::failure()
388
        );
389
    }
390
391
    /**
392
     * @Then /^(this product) should still exist in the product catalog$/
393
     */
394
    public function productShouldExistInTheProductCatalog(ProductInterface $product)
395
    {
396
        $this->theProductShouldAppearInTheShop($product->getName());
397
    }
398
399
    /**
400
     * @When I want to modify the :product product
401
     * @When /^I want to modify (this product)$/
402
     * @When I modify the :product product
403
     */
404
    public function iWantToModifyAProduct(ProductInterface $product): void
405
    {
406
        $this->sharedStorage->set('product', $product);
407
408
        if ($product->isSimple()) {
409
            $this->updateSimpleProductPage->open(['id' => $product->getId()]);
410
411
            return;
412
        }
413
414
        $this->updateConfigurableProductPage->open(['id' => $product->getId()]);
415
    }
416
417
    /**
418
     * @Then the code field should be disabled
419
     */
420
    public function theCodeFieldShouldBeDisabled()
421
    {
422
        $currentPage = $this->resolveCurrentPage();
423
424
        Assert::true($currentPage->isCodeDisabled());
0 ignored issues
show
Bug introduced by
The method isCodeDisabled does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
425
    }
426
427
    /**
428
     * @Then the slug field should not be editable
429
     * @Then the slug field in :localeCode (also )should not be editable
430
     */
431
    public function theSlugFieldShouldNotBeEditable($localeCode = 'en_US')
432
    {
433
        Assert::true($this->updateSimpleProductPage->isSlugReadonlyIn($localeCode));
434
    }
435
436
    /**
437
     * @Then this product name should be :name
438
     */
439
    public function thisProductElementShouldBe($name)
440
    {
441
        $this->assertElementValue('name', $name);
442
    }
443
444
    /**
445
     * @Then /^I should be notified that (code|name|slug) is required$/
446
     */
447
    public function iShouldBeNotifiedThatIsRequired($element)
448
    {
449
        $this->assertValidationMessage($element, sprintf('Please enter product %s.', $element));
450
    }
451
452
    /**
453
     * @When I save my changes
454
     * @When I try to save my changes
455
     */
456
    public function iSaveMyChanges()
457
    {
458
        $currentPage = $this->resolveCurrentPage();
459
460
        $currentPage->saveChanges();
0 ignored issues
show
Bug introduced by
The method saveChanges does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
461
    }
462
463
    /**
464
     * @When /^I change its price to (?:€|£|\$)([^"]+) for "([^"]+)" channel$/
465
     */
466
    public function iChangeItsPriceTo(string $price, $channelName)
467
    {
468
        $this->updateSimpleProductPage->specifyPrice($channelName, $price);
469
    }
470
471
    /**
472
     * @When /^I change its original price to "(?:€|£|\$)([^"]+)" for "([^"]+)" channel$/
473
     */
474
    public function iChangeItsOriginalPriceTo(string $price, $channelName)
475
    {
476
        $this->updateSimpleProductPage->specifyOriginalPrice($channelName, $price);
477
    }
478
479
    /**
480
     * @Given I add the :optionName option to it
481
     */
482
    public function iAddTheOptionToIt($optionName)
483
    {
484
        $this->createConfigurableProductPage->selectOption($optionName);
485
    }
486
487
    /**
488
     * @When I set its :attribute attribute to :value
489
     * @When I set its :attribute attribute to :value in :language
490
     * @When I do not set its :attribute attribute in :language
491
     */
492
    public function iSetItsAttributeTo($attribute, $value = null, $language = 'en_US')
493
    {
494
        $this->createSimpleProductPage->addAttribute($attribute, $value ?? '', $language);
495
    }
496
497
    /**
498
     * @When I remove its :attribute attribute
499
     * @When I remove its :attribute attribute from :language
500
     */
501
    public function iRemoveItsAttribute($attribute, $language = 'en_US')
502
    {
503
        $this->createSimpleProductPage->removeAttribute($attribute, $language);
504
    }
505
506
    /**
507
     * @When I try to add new attributes
508
     */
509
    public function iTryToAddNewAttributes()
510
    {
511
        $this->updateSimpleProductPage->addSelectedAttributes();
512
    }
513
514
    /**
515
     * @When I do not want to have shipping required for this product
516
     */
517
    public function iDoNotWantToHaveShippingRequiredForThisProduct()
518
    {
519
        $this->createSimpleProductPage->setShippingRequired(false);
520
    }
521
522
    /**
523
     * @Then attribute :attributeName of product :product should be :value
524
     * @Then attribute :attributeName of product :product should be :value in :language
525
     */
526
    public function itsAttributeShouldBe($attributeName, ProductInterface $product, $value, $language = 'en_US')
527
    {
528
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
529
530
        Assert::same($this->updateSimpleProductPage->getAttributeValue($attributeName, $language), $value);
531
    }
532
533
    /**
534
     * @Then /^(product "[^"]+") should not have a "([^"]+)" attribute$/
535
     */
536
    public function productShouldNotHaveAttribute(ProductInterface $product, $attribute)
537
    {
538
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
539
540
        Assert::false($this->updateSimpleProductPage->hasAttribute($attribute));
541
    }
542
543
    /**
544
     * @Then /^product "[^"]+" should not have any attributes$/
545
     * @Then /^product "[^"]+" should have (\d+) attributes?$/
546
     */
547
    public function productShouldNotHaveAnyAttributes($count = 0)
548
    {
549
        Assert::same($this->updateSimpleProductPage->getNumberOfAttributes(), (int) $count);
550
    }
551
552
    /**
553
     * @Given product with :element :value should not be added
554
     */
555
    public function productWithNameShouldNotBeAdded($element, $value)
556
    {
557
        $this->iWantToBrowseProducts();
558
559
        Assert::false($this->indexPage->isSingleResourceOnPage([$element => $value]));
560
    }
561
562
    /**
563
     * @When I remove its name from :language translation
564
     */
565
    public function iRemoveItsNameFromTranslation($language)
566
    {
567
        $currentPage = $this->resolveCurrentPage();
568
569
        $currentPage->nameItIn('', $language);
0 ignored issues
show
Bug introduced by
The method nameItIn does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
570
    }
571
572
    /**
573
     * @Then /^this product should have (?:a|an) "([^"]+)" option$/
574
     */
575
    public function thisProductShouldHaveOption($productOption)
576
    {
577
        $this->updateConfigurableProductPage->isProductOptionChosen($productOption);
578
    }
579
580
    /**
581
     * @Then the option field should be disabled
582
     */
583
    public function theOptionFieldShouldBeDisabled()
584
    {
585
        Assert::true($this->updateConfigurableProductPage->isProductOptionsDisabled());
586
    }
587
588
    /**
589
     * @When /^I choose main (taxon "[^"]+")$/
590
     */
591
    public function iChooseMainTaxon(TaxonInterface $taxon)
592
    {
593
        $currentPage = $this->resolveCurrentPage();
594
595
        $currentPage->selectMainTaxon($taxon);
0 ignored issues
show
Bug introduced by
The method selectMainTaxon does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
596
    }
597
598
    /**
599
     * @Then /^the slug of the ("[^"]+" product) should(?:| still) be "([^"]+)"$/
600
     * @Then /^the slug of the ("[^"]+" product) should(?:| still) be "([^"]+)" (in the "[^"]+" locale)$/
601
     */
602
    public function productSlugShouldBe(ProductInterface $product, $slug, $locale = 'en_US')
603
    {
604
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
605
606
        Assert::same($this->updateSimpleProductPage->getSlug($locale), $slug);
607
    }
608
609
    /**
610
     * @Then /^(this product) main taxon should be "([^"]+)"$/
611
     * @Then /^main taxon of (product "[^"]+") should be "([^"]+)"$/
612
     */
613
    public function thisProductMainTaxonShouldBe(ProductInterface $product, $taxonName)
614
    {
615
        $currentPage = $this->resolveCurrentPage();
616
        $currentPage->open(['id' => $product->getId()]);
617
618
        Assert::true($currentPage->isMainTaxonChosen($taxonName));
0 ignored issues
show
Bug introduced by
The method isMainTaxonChosen does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
619
    }
620
621
    /**
622
     * @Then /^inventory of (this product) should not be tracked$/
623
     */
624
    public function thisProductShouldNotBeTracked(ProductInterface $product)
625
    {
626
        $this->iWantToModifyAProduct($product);
627
628
        Assert::false($this->updateSimpleProductPage->isTracked());
629
    }
630
631
    /**
632
     * @Then /^inventory of (this product) should be tracked$/
633
     */
634
    public function thisProductShouldBeTracked(ProductInterface $product)
635
    {
636
        $this->iWantToModifyAProduct($product);
637
638
        Assert::true($this->updateSimpleProductPage->isTracked());
639
    }
640
641
    /**
642
     * @When I attach the :path image with :type type
643
     * @When I attach the :path image
644
     */
645
    public function iAttachImageWithType($path, $type = null)
646
    {
647
        $currentPage = $this->resolveCurrentPage();
648
649
        $currentPage->attachImage($path, $type);
0 ignored issues
show
Bug introduced by
The method attachImage does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
650
    }
651
652
    /**
653
     * @When I associate as :productAssociationType the :productName product
654
     * @When I associate as :productAssociationType the :firstProductName and :secondProductName products
655
     */
656
    public function iAssociateProductsAsProductAssociation(
657
        ProductAssociationTypeInterface $productAssociationType,
658
        ...$productsNames
659
    ) {
660
        $currentPage = $this->resolveCurrentPage();
661
662
        $currentPage->associateProducts($productAssociationType, $productsNames);
0 ignored issues
show
Bug introduced by
The method associateProducts does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...bleProductPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
663
    }
664
665
    /**
666
     * @When I remove an associated product :productName from :productAssociationType
667
     */
668
    public function iRemoveAnAssociatedProductFromProductAssociation(
669
        $productName,
670
        ProductAssociationTypeInterface $productAssociationType
671
    ) {
672
        $currentPage = $this->resolveCurrentPage();
673
674
        $currentPage->removeAssociatedProduct($productName, $productAssociationType);
0 ignored issues
show
Bug introduced by
The method removeAssociatedProduct does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...bleProductPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
675
    }
676
677
    /**
678
     * @When I go to the variants list
679
     */
680
    public function iGoToTheVariantsList(): void
681
    {
682
        $this->resolveCurrentPage()->goToVariantsList();
0 ignored issues
show
Bug introduced by
The method goToVariantsList does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
683
    }
684
685
    /**
686
     * @When I go to the variant creation page
687
     */
688
    public function iGoToTheVariantCreationPage(): void
689
    {
690
        $this->resolveCurrentPage()->goToVariantCreation();
0 ignored issues
show
Bug introduced by
The method goToVariantCreation does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
691
    }
692
693
    /**
694
     * @When I go to the variant generation page
695
     */
696
    public function iGoToTheVariantGenerationPage(): void
697
    {
698
        $this->resolveCurrentPage()->goToVariantGeneration();
0 ignored issues
show
Bug introduced by
The method goToVariantGeneration does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
699
    }
700
701
    /**
702
     * @Then /^(?:this product|the product "[^"]+"|it) should(?:| also) have an image with "([^"]*)" type$/
703
     */
704
    public function thisProductShouldHaveAnImageWithType($type)
705
    {
706
        $currentPage = $this->resolveCurrentPage();
707
708
        Assert::true($currentPage->isImageWithTypeDisplayed($type));
0 ignored issues
show
Bug introduced by
The method isImageWithTypeDisplayed does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
709
    }
710
711
    /**
712
     * @Then /^the (product "[^"]+") should still have an accessible image$/
713
     */
714
    public function productShouldStillHaveAnAccessibleImage(ProductInterface $product): void
715
    {
716
        Assert::true($this->indexPage->hasProductAccessibleImage($product->getCode()));
717
    }
718
719
    /**
720
     * @Then /^(?:this product|it)(?:| also) should not have any images with "([^"]*)" type$/
721
     */
722
    public function thisProductShouldNotHaveAnyImagesWithType($code)
723
    {
724
        $currentPage = $this->resolveCurrentPage();
725
726
        Assert::false($currentPage->isImageWithTypeDisplayed($code));
0 ignored issues
show
Bug introduced by
The method isImageWithTypeDisplayed does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
727
    }
728
729
    /**
730
     * @When I change the image with the :type type to :path
731
     */
732
    public function iChangeItsImageToPathForTheType($type, $path)
733
    {
734
        $currentPage = $this->resolveCurrentPage();
735
736
        $currentPage->changeImageWithType($type, $path);
0 ignored issues
show
Bug introduced by
The method changeImageWithType does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
737
    }
738
739
    /**
740
     * @When /^I(?:| also) remove an image with "([^"]*)" type$/
741
     */
742
    public function iRemoveAnImageWithType($code)
743
    {
744
        $currentPage = $this->resolveCurrentPage();
745
746
        $currentPage->removeImageWithType($code);
0 ignored issues
show
Bug introduced by
The method removeImageWithType does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
747
    }
748
749
    /**
750
     * @When I remove the first image
751
     */
752
    public function iRemoveTheFirstImage()
753
    {
754
        $currentPage = $this->resolveCurrentPage();
755
756
        $currentPage->removeFirstImage();
0 ignored issues
show
Bug introduced by
The method removeFirstImage does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
757
    }
758
759
    /**
760
     * @When I change the first image type to :type
761
     */
762
    public function iChangeTheFirstImageTypeTo($type)
763
    {
764
        $currentPage = $this->resolveCurrentPage();
765
766
        $currentPage->modifyFirstImageType($type);
0 ignored issues
show
Bug introduced by
The method modifyFirstImageType does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
767
    }
768
769
    /**
770
     * @Then /^(this product) should not have any images$/
771
     */
772
    public function thisProductShouldNotHaveImages(ProductInterface $product)
773
    {
774
        $this->iWantToModifyAProduct($product);
775
776
        $currentPage = $this->resolveCurrentPage();
777
778
        Assert::same($currentPage->countImages(), 0);
0 ignored issues
show
Bug introduced by
The method countImages does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
779
    }
780
781
    /**
782
     * @Then /^(this product) should(?:| still) have (?:only one|(\d+)) images?$/
783
     */
784
    public function thereShouldStillBeOnlyOneImageInThisProduct(ProductInterface $product, $count = 1)
785
    {
786
        $this->iWantToModifyAProduct($product);
787
788
        $currentPage = $this->resolveCurrentPage();
789
790
        Assert::same($currentPage->countImages(), (int) $count);
0 ignored issues
show
Bug introduced by
The method countImages does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...exPerTaxonPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
791
    }
792
793
    /**
794
     * @Then /^there should be no reviews of (this product)$/
795
     */
796
    public function thereAreNoProductReviews(ProductInterface $product)
797
    {
798
        $this->productReviewIndexPage->open();
799
800
        Assert::false($this->productReviewIndexPage->isSingleResourceOnPage(['reviewSubject' => $product->getName()]));
801
    }
802
803
    /**
804
     * @Then this product should( also) have an association :productAssociationType with product :productName
805
     * @Then this product should( also) have an association :productAssociationType with products :firstProductName and :secondProductName
806
     */
807
    public function theProductShouldHaveAnAssociationWithProducts(
808
        ProductAssociationTypeInterface $productAssociationType,
809
        ...$productsNames
810
    ) {
811
        foreach ($productsNames as $productName) {
812
            Assert::true(
813
                $this->updateSimpleProductPage->hasAssociatedProduct($productName, $productAssociationType),
814
                sprintf(
815
                    'This product should have an association %s with product %s.',
816
                    $productAssociationType->getName(),
817
                    $productName
818
                )
819
            );
820
        }
821
    }
822
823
    /**
824
     * @Then this product should not have an association :productAssociationType with product :productName
825
     */
826
    public function theProductShouldNotHaveAnAssociationWithProduct(
827
        ProductAssociationTypeInterface $productAssociationType,
828
        $productName
829
    ) {
830
        Assert::false($this->updateSimpleProductPage->hasAssociatedProduct($productName, $productAssociationType));
831
    }
832
833
    /**
834
     * @Then I should be notified that simple product code has to be unique
835
     */
836
    public function iShouldBeNotifiedThatSimpleProductCodeHasToBeUnique()
837
    {
838
        $this->assertValidationMessage('code', 'Simple product code must be unique among all products and product variants.');
839
    }
840
841
    /**
842
     * @Then I should be notified that slug has to be unique
843
     */
844
    public function iShouldBeNotifiedThatSlugHasToBeUnique()
845
    {
846
        $this->assertValidationMessage('slug', 'Product slug must be unique.');
847
    }
848
849
    /**
850
     * @Then I should be notified that code has to be unique
851
     */
852
    public function iShouldBeNotifiedThatCodeHasToBeUnique()
853
    {
854
        $this->assertValidationMessage('code', 'Product code must be unique.');
855
    }
856
857
    /**
858
     * @Then I should be notified that price must be defined for every channel
859
     */
860
    public function iShouldBeNotifiedThatPriceMustBeDefinedForEveryChannel()
861
    {
862
        $this->assertValidationMessage('channel_pricings', 'You must define price for every channel.');
863
    }
864
865
    /**
866
     * @Then they should have order like :firstProductName, :secondProductName and :thirdProductName
867
     */
868
    public function theyShouldHaveOrderLikeAnd(...$productNames)
869
    {
870
        Assert::true($this->indexPerTaxonPage->hasProductsInOrder($productNames));
871
    }
872
873
    /**
874
     * @When I save my new configuration
875
     */
876
    public function iSaveMyNewConfiguration()
877
    {
878
        $this->indexPerTaxonPage->savePositions();
879
    }
880
881
    /**
882
     * @When I set the position of :productName to :position
883
     */
884
    public function iSetThePositionOfTo(string $productName, string $position): void
885
    {
886
        $this->indexPerTaxonPage->setPositionOfProduct($productName, $position);
887
    }
888
889
    /**
890
     * @When I remove its price for :channelName channel
891
     */
892
    public function iRemoveItsPriceForChannel(string $channelName): void
893
    {
894
        $this->iSetItsPriceTo('',  $channelName);
895
    }
896
897
    /**
898
     * @Then this product should( still) have slug :value in :language
899
     */
900
    public function thisProductElementShouldHaveSlugIn($slug, $language)
901
    {
902
        Assert::same($this->updateSimpleProductPage->getSlug($language), $slug);
903
    }
904
905
    /**
906
     * @When I set its shipping category as :shippingCategoryName
907
     */
908
    public function iSetItsShippingCategoryAs($shippingCategoryName)
909
    {
910
        $this->createSimpleProductPage->selectShippingCategory($shippingCategoryName);
911
    }
912
913
    /**
914
     * @Then /^(it|this product) should be priced at (?:€|£|\$)([^"]+) for channel "([^"]+)"$/
915
     * @Then /^(product "[^"]+") should be priced at (?:€|£|\$)([^"]+) for channel "([^"]+)"$/
916
     */
917
    public function itShouldBePricedAtForChannel(ProductInterface $product, string $price, $channelName)
918
    {
919
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
920
921
        Assert::same($this->updateSimpleProductPage->getPriceForChannel($channelName), $price);
922
    }
923
924
    /**
925
     * @Then /^(its|this products) original price should be "(?:€|£|\$)([^"]+)" for channel "([^"]+)"$/
926
     */
927
    public function itsOriginalPriceForChannel(ProductInterface $product, $originalPrice, $channelName)
928
    {
929
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
930
931
        Assert::same(
932
            $this->updateSimpleProductPage->getOriginalPriceForChannel($channelName),
933
            $originalPrice
934
        );
935
    }
936
937
    /**
938
     * @Then /^(this product) should no longer have price for channel "([^"]+)"$/
939
     */
940
    public function thisProductShouldNoLongerHavePriceForChannel(ProductInterface $product, $channelName)
941
    {
942
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
943
944
        try {
945
            $this->updateSimpleProductPage->getPriceForChannel($channelName);
946
        } catch (ElementNotFoundException $exception) {
0 ignored issues
show
Bug introduced by
The class Behat\Mink\Exception\ElementNotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
947
            return;
948
        }
949
950
        throw new \Exception(
951
            sprintf('Product "%s" should not have price defined for channel "%s".', $product->getName(), $channelName)
952
        );
953
    }
954
955
    /**
956
     * @Then I should be notified that I have to define product variants' prices for newly assigned channels first
957
     */
958
    public function iShouldBeNotifiedThatIHaveToDefineProductVariantsPricesForNewlyAssignedChannelsFirst()
959
    {
960
        Assert::same(
961
            $this->updateConfigurableProductPage->getValidationMessage('channels'),
962
            'You have to define product variants\' prices for newly assigned channels first.'
963
        );
964
    }
965
966
    /**
967
     * @Then /^the (product "[^"]+") should not have shipping required$/
968
     */
969
    public function theProductWithCodeShouldNotHaveShippingRequired(ProductInterface $product)
970
    {
971
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
972
973
        Assert::false($this->updateSimpleProductPage->isShippingRequired());
974
    }
975
976
    /**
977
     * @Then I should be notified that I have to define the :attribute attribute in :language
978
     */
979
    public function iShouldBeNotifiedThatIHaveToDefineTheAttributeIn($attribute, $language)
980
    {
981
        Assert::same(
982
            $this->resolveCurrentPage()->getAttributeValidationErrors($attribute, $language),
0 ignored issues
show
Bug introduced by
The method getAttributeValidationErrors does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...bleProductPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
983
            'This value should not be blank.'
984
        );
985
    }
986
987
    /**
988
     * @Then I should be notified that the :attribute attribute in :language should be longer than :number
989
     */
990
    public function iShouldBeNotifiedThatTheAttributeInShouldBeLongerThan($attribute, $language, $number)
991
    {
992
        Assert::same(
993
            $this->resolveCurrentPage()->getAttributeValidationErrors($attribute, $language),
0 ignored issues
show
Bug introduced by
The method getAttributeValidationErrors does only exist in Sylius\Behat\Page\Admin\...pleProductPageInterface, but not in Sylius\Behat\Page\Admin\...bleProductPageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
994
            sprintf('This value is too short. It should have %s characters or more.', $number)
995
        );
996
    }
997
998
    /**
999
     * @Then /^I should be on the variant creation page for (this product)$/
1000
     */
1001
    public function iShouldBeOnTheVariantCreationPageForThisProduct(ProductInterface $product): void
1002
    {
1003
        Assert::true($this->variantCreatePage->isOpen(['productId' => $product->getId()]));
1004
    }
1005
1006
    /**
1007
     * @Then /^I should be on the variant generation page for (this product)$/
1008
     */
1009
    public function iShouldBeOnTheVariantGenerationPageForThisProduct(ProductInterface $product): void
1010
    {
1011
        Assert::true($this->variantGeneratePage->isOpen(['productId' => $product->getId()]));
1012
    }
1013
1014
    /**
1015
     * @Then I should see inventory of this product
1016
     */
1017
    public function iShouldSeeInventoryOfThisProduct(): void
1018
    {
1019
        Assert::true($this->updateSimpleProductPage->hasInventoryTab());
1020
    }
1021
1022
    /**
1023
     * @Then I should not see inventory of this product
1024
     */
1025
    public function iShouldNotSeeInventoryOfThisProduct(): void
1026
    {
1027
        Assert::false($this->updateConfigurableProductPage->hasInventoryTab());
1028
    }
1029
1030
    /**
1031
     * @Then I should be notified that the position :invalidPosition is invalid
1032
     */
1033
    public function iShouldBeNotifiedThatThePositionIsInvalid(string $invalidPosition): void
1034
    {
1035
        $this->notificationChecker->checkNotification(
1036
            sprintf('The position "%s" is invalid.', $invalidPosition),
1037
            NotificationType::failure()
1038
        );
1039
    }
1040
1041
    /**
1042
     * @Then I should not be able to show this product in shop
1043
     */
1044
    public function iShouldNotBeAbleToShowThisProductInShop(): void
1045
    {
1046
        Assert::true($this->updateSimpleProductPage->isShowInShopButtonDisabled());
1047
    }
1048
1049
    /**
1050
     * @Then I should not have configured price for :channelName channel
1051
     */
1052
    public function iShouldNotHaveConfiguredPriceForChannel(string $channelName): void
1053
    {
1054
        Assert::same($this->updateSimpleProductPage->getPriceForChannel($channelName), '');
1055
    }
1056
1057
    /**
1058
     * @param string $element
1059
     * @param string $value
1060
     */
1061
    private function assertElementValue($element, $value)
1062
    {
1063
        /** @var UpdatePageInterface $currentPage */
1064
        $currentPage = $this->resolveCurrentPage();
1065
1066
        Assert::isInstanceOf($currentPage, UpdatePageInterface::class);
1067
1068
        Assert::true(
1069
            $currentPage->hasResourceValues([$element => $value]),
1070
            sprintf('Product should have %s with %s value.', $element, $value)
1071
        );
1072
    }
1073
1074
    /**
1075
     * @param string $element
1076
     * @param string $message
1077
     */
1078
    private function assertValidationMessage($element, $message)
1079
    {
1080
        /** @var CreatePageInterface|UpdatePageInterface $currentPage */
1081
        $currentPage = $this->resolveCurrentPage();
1082
1083
        Assert::same($currentPage->getValidationMessage($element), $message);
1084
    }
1085
1086
    /**
1087
     * @return IndexPageInterface|IndexPerTaxonPageInterface|CreateSimpleProductPageInterface|CreateConfigurableProductPageInterface|UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface
1088
     */
1089
    private function resolveCurrentPage()
1090
    {
1091
        return $this->currentPageResolver->getCurrentPageWithForm([
1092
            $this->indexPage,
1093
            $this->indexPerTaxonPage,
1094
            $this->createSimpleProductPage,
1095
            $this->createConfigurableProductPage,
1096
            $this->updateSimpleProductPage,
1097
            $this->updateConfigurableProductPage,
1098
        ]);
1099
    }
1100
}
1101