Issues (244)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

Behat/Context/Ui/Admin/ManagingProductsContext.php (21 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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\Service\NotificationCheckerInterface;
29
use Sylius\Behat\Service\Resolver\CurrentPageResolverInterface;
30
use Sylius\Behat\Service\SharedStorageInterface;
31
use Sylius\Component\Core\Model\ProductInterface;
32
use Sylius\Component\Core\Model\TaxonInterface;
33
use Sylius\Component\Product\Model\ProductAssociationTypeInterface;
34
use Webmozart\Assert\Assert;
35
36
final class ManagingProductsContext implements Context
37
{
38
    /**
39
     * @var SharedStorageInterface
40
     */
41
    private $sharedStorage;
42
43
    /**
44
     * @var CreateSimpleProductPageInterface
45
     */
46
    private $createSimpleProductPage;
47
48
    /**
49
     * @var CreateConfigurableProductPageInterface
50
     */
51
    private $createConfigurableProductPage;
52
53
    /**
54
     * @var IndexPageInterface
55
     */
56
    private $indexPage;
57
58
    /**
59
     * @var UpdateSimpleProductPageInterface
60
     */
61
    private $updateSimpleProductPage;
62
63
    /**
64
     * @var UpdateConfigurableProductPageInterface
65
     */
66
    private $updateConfigurableProductPage;
67
68
    /**
69
     * @var ProductReviewIndexPageInterface
70
     */
71
    private $productReviewIndexPage;
72
73
    /**
74
     * @var IndexPerTaxonPageInterface
75
     */
76
    private $indexPerTaxonPage;
77
78
    /**
79
     * @var CurrentPageResolverInterface
80
     */
81
    private $currentPageResolver;
82
83
    /**
84
     * @var NotificationCheckerInterface
85
     */
86
    private $notificationChecker;
87
88
    /**
89
     * @param SharedStorageInterface $sharedStorage
90
     * @param CreateSimpleProductPageInterface $createSimpleProductPage
91
     * @param CreateConfigurableProductPageInterface $createConfigurableProductPage
92
     * @param IndexPageInterface $indexPage
93
     * @param UpdateSimpleProductPageInterface $updateSimpleProductPage
94
     * @param UpdateConfigurableProductPageInterface $updateConfigurableProductPage
95
     * @param ProductReviewIndexPageInterface $productReviewIndexPage
96
     * @param IndexPerTaxonPageInterface $indexPerTaxonPage
97
     * @param CurrentPageResolverInterface $currentPageResolver
98
     * @param NotificationCheckerInterface $notificationChecker
99
     */
100
    public function __construct(
101
        SharedStorageInterface $sharedStorage,
102
        CreateSimpleProductPageInterface $createSimpleProductPage,
103
        CreateConfigurableProductPageInterface $createConfigurableProductPage,
104
        IndexPageInterface $indexPage,
105
        UpdateSimpleProductPageInterface $updateSimpleProductPage,
106
        UpdateConfigurableProductPageInterface $updateConfigurableProductPage,
107
        ProductReviewIndexPageInterface $productReviewIndexPage,
108
        IndexPerTaxonPageInterface $indexPerTaxonPage,
109
        CurrentPageResolverInterface $currentPageResolver,
110
        NotificationCheckerInterface $notificationChecker
111
    ) {
112
        $this->sharedStorage = $sharedStorage;
113
        $this->createSimpleProductPage = $createSimpleProductPage;
114
        $this->createConfigurableProductPage = $createConfigurableProductPage;
115
        $this->indexPage = $indexPage;
116
        $this->updateSimpleProductPage = $updateSimpleProductPage;
117
        $this->updateConfigurableProductPage = $updateConfigurableProductPage;
118
        $this->productReviewIndexPage = $productReviewIndexPage;
119
        $this->indexPerTaxonPage = $indexPerTaxonPage;
120
        $this->currentPageResolver = $currentPageResolver;
121
        $this->notificationChecker = $notificationChecker;
122
    }
123
124
    /**
125
     * @Given I want to create a new simple product
126
     */
127
    public function iWantToCreateANewSimpleProduct()
128
    {
129
        $this->createSimpleProductPage->open();
130
    }
131
132
    /**
133
     * @Given I want to create a new configurable product
134
     */
135
    public function iWantToCreateANewConfigurableProduct()
136
    {
137
        $this->createConfigurableProductPage->open();
138
    }
139
140
    /**
141
     * @When I specify its code as :code
142
     * @When I do not specify its code
143
     */
144
    public function iSpecifyItsCodeAs($code = null)
145
    {
146
        $currentPage = $this->resolveCurrentPage();
147
148
        $currentPage->specifyCode($code);
0 ignored issues
show
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...
149
    }
150
151
    /**
152
     * @When I name it :name in :language
153
     * @When I rename it to :name in :language
154
     */
155
    public function iRenameItToIn($name, $language)
156
    {
157
        $currentPage = $this->resolveCurrentPage();
158
159
        $currentPage->nameItIn($name, $language);
0 ignored issues
show
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...
160
    }
161
162
    /**
163
     * @When I add it
164
     * @When I try to add it
165
     */
166
    public function iAddIt()
167
    {
168
        /** @var CreatePageInterface $currentPage */
169
        $currentPage = $this->resolveCurrentPage();
170
171
        $currentPage->create();
172
    }
173
174
    /**
175
     * @When I disable its inventory tracking
176
     */
177
    public function iDisableItsTracking()
178
    {
179
        $this->updateSimpleProductPage->disableTracking();
180
    }
181
182
    /**
183
     * @When I enable its inventory tracking
184
     */
185
    public function iEnableItsTracking()
186
    {
187
        $this->updateSimpleProductPage->enableTracking();
188
    }
189
190
    /**
191
     * @When /^I set its(?:| default) price to "(?:€|£|\$)([^"]+)" for "([^"]+)" channel$/
192
     */
193
    public function iSetItsPriceTo($price, $channelName)
194
    {
195
        $this->createSimpleProductPage->specifyPrice($channelName, $price);
196
    }
197
198
    /**
199
     * @When /^I set its original price to "(?:€|£|\$)([^"]+)" for "([^"]+)" channel$/
200
     */
201
    public function iSetItsOriginalPriceTo($originalPrice, $channelName)
202
    {
203
        $this->createSimpleProductPage->specifyOriginalPrice($channelName, $originalPrice);
204
    }
205
206
    /**
207
     * @When I make it available in channel :channel
208
     */
209
    public function iMakeItAvailableInChannel($channel)
210
    {
211
        $this->createSimpleProductPage->checkChannel($channel);
212
    }
213
214
    /**
215
     * @When I assign it to channel :channel
216
     */
217
    public function iAssignItToChannel($channel)
218
    {
219
        // Temporary solution until we will make current page resolver work with product pages
220
        $this->updateConfigurableProductPage->checkChannel($channel);
221
    }
222
223
    /**
224
     * @When I choose :calculatorName calculator
225
     */
226
    public function iChooseCalculator($calculatorName)
227
    {
228
        $this->createSimpleProductPage->choosePricingCalculator($calculatorName);
229
    }
230
231
    /**
232
     * @When I set its slug to :slug
233
     * @When I set its slug to :slug in :language
234
     * @When I remove its slug
235
     */
236
    public function iSetItsSlugToIn($slug = null, $language = 'en_US')
237
    {
238
        $this->createSimpleProductPage->specifySlugIn($slug, $language);
239
    }
240
241
    /**
242
     * @When I enable slug modification
243
     * @When I enable slug modification in :localeCode
244
     */
245
    public function iEnableSlugModification($localeCode = 'en_US')
246
    {
247
        $this->updateSimpleProductPage->activateLanguageTab($localeCode);
248
        $this->updateSimpleProductPage->enableSlugModification($localeCode);
249
    }
250
251
    /**
252
     * @Then I should see the product :productName in the list
253
     * @Then the product :productName should appear in the store
254
     * @Then the product :productName should be in the shop
255
     * @Then this product should still be named :productName
256
     */
257
    public function theProductShouldAppearInTheShop(string $productName): void
258
    {
259
        $this->iWantToBrowseProducts();
260
261
        Assert::true($this->indexPage->isSingleResourceOnPage(['name' => $productName]));
262
    }
263
264
    /**
265
     * @Given I am browsing products
266
     * @When I browse products
267
     * @When I want to browse products
268
     */
269
    public function iWantToBrowseProducts()
270
    {
271
        $this->indexPage->open();
272
    }
273
274
    /**
275
     * @When /^I am browsing products from ("([^"]+)" taxon)$/
276
     */
277
    public function iAmBrowsingProductsFromTaxon(TaxonInterface $taxon)
278
    {
279
        $this->indexPerTaxonPage->open(['taxonId' => $taxon->getId()]);
280
    }
281
282
    /**
283
     * @When I filter them by :taxonName taxon
284
     */
285
    public function iFilterThemByTaxon($taxonName)
286
    {
287
        $this->indexPage->filterByTaxon($taxonName);
288
    }
289
290
    /**
291
     * @When I check (also) the :productName product
292
     */
293
    public function iCheckTheProduct(string $productName): void
294
    {
295
        $this->indexPage->checkResourceOnPage(['name' => $productName]);
296
    }
297
298
    /**
299
     * @When I delete them
300
     */
301
    public function iDeleteThem(): void
302
    {
303
        $this->indexPage->bulkDelete();
304
    }
305
306
    /**
307
     * @Then I should( still) see a product with :field :value
308
     */
309
    public function iShouldSeeProductWith($field, $value)
310
    {
311
        Assert::true($this->indexPage->isSingleResourceOnPage([$field => $value]));
312
    }
313
314
    /**
315
     * @Then I should not see any product with :field :value
316
     */
317
    public function iShouldNotSeeAnyProductWith($field, $value)
318
    {
319
        Assert::false($this->indexPage->isSingleResourceOnPage([$field => $value]));
320
    }
321
322
    /**
323
     * @Then the first product on the list should have :field :value
324
     */
325
    public function theFirstProductOnTheListShouldHave($field, $value)
326
    {
327
        $currentPage = $this->resolveCurrentPage();
328
329
        Assert::same($currentPage->getColumnFields($field)[0], $value);
0 ignored issues
show
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...
330
    }
331
332
    /**
333
     * @Then the last product on the list should have :field :value
334
     */
335
    public function theLastProductOnTheListShouldHave($field, $value)
336
    {
337
        $values = $this->indexPerTaxonPage->getColumnFields($field);
338
339
        Assert::same(end($values), $value);
340
    }
341
342
    /**
343
     * @When I switch the way products are sorted by :field
344
     * @When I start sorting products by :field
345
     * @Given the products are already sorted by :field
346
     */
347
    public function iSortProductsBy($field)
348
    {
349
        $this->indexPage->sortBy($field);
350
    }
351
352
    /**
353
     * @Then I should see a single product in the list
354
     * @Then I should see :numberOfProducts products in the list
355
     */
356
    public function iShouldSeeProductsInTheList(int $numberOfProducts = 1): void
357
    {
358
        Assert::same($this->indexPage->countItems(), (int) $numberOfProducts);
359
    }
360
361
    /**
362
     * @When I delete the :product product
363
     * @When I try to delete the :product product
364
     */
365
    public function iDeleteProduct(ProductInterface $product)
366
    {
367
        $this->sharedStorage->set('product', $product);
368
369
        $this->iWantToBrowseProducts();
370
        $this->indexPage->deleteResourceOnPage(['name' => $product->getName()]);
371
    }
372
373
    /**
374
     * @Then /^(this product) should not exist in the product catalog$/
375
     */
376
    public function productShouldNotExist(ProductInterface $product)
377
    {
378
        $this->iWantToBrowseProducts();
379
380
        Assert::false($this->indexPage->isSingleResourceOnPage(['code' => $product->getCode()]));
381
    }
382
383
    /**
384
     * @Then I should be notified that this product is in use and cannot be deleted
385
     */
386
    public function iShouldBeNotifiedOfFailure()
387
    {
388
        $this->notificationChecker->checkNotification(
389
            'Cannot delete, the product is in use.',
390
            NotificationType::failure()
391
        );
392
    }
393
394
    /**
395
     * @Then /^(this product) should still exist in the product catalog$/
396
     */
397
    public function productShouldExistInTheProductCatalog(ProductInterface $product)
398
    {
399
        $this->theProductShouldAppearInTheShop($product->getName());
400
    }
401
402
    /**
403
     * @When I want to modify the :product product
404
     * @When /^I want to modify (this product)$/
405
     */
406
    public function iWantToModifyAProduct(ProductInterface $product)
407
    {
408
        $this->sharedStorage->set('product', $product);
409
410
        if ($product->isSimple()) {
411
            $this->updateSimpleProductPage->open(['id' => $product->getId()]);
412
413
            return;
414
        }
415
416
        $this->updateConfigurableProductPage->open(['id' => $product->getId()]);
417
    }
418
419
    /**
420
     * @Then the code field should be disabled
421
     */
422
    public function theCodeFieldShouldBeDisabled()
423
    {
424
        $currentPage = $this->resolveCurrentPage();
425
426
        Assert::true($currentPage->isCodeDisabled());
0 ignored issues
show
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...
427
    }
428
429
    /**
430
     * @Then the slug field should not be editable
431
     * @Then the slug field in :localeCode (also )should not be editable
432
     */
433
    public function theSlugFieldShouldNotBeEditable($localeCode = 'en_US')
434
    {
435
        Assert::true($this->updateSimpleProductPage->isSlugReadonlyIn($localeCode));
436
    }
437
438
    /**
439
     * @Then this product name should be :name
440
     */
441
    public function thisProductElementShouldBe($name)
442
    {
443
        $this->assertElementValue('name', $name);
444
    }
445
446
    /**
447
     * @Then /^I should be notified that (code|name|slug) is required$/
448
     */
449
    public function iShouldBeNotifiedThatIsRequired($element)
450
    {
451
        $this->assertValidationMessage($element, sprintf('Please enter product %s.', $element));
452
    }
453
454
    /**
455
     * @When I save my changes
456
     * @When I try to save my changes
457
     */
458
    public function iSaveMyChanges()
459
    {
460
        $currentPage = $this->resolveCurrentPage();
461
462
        $currentPage->saveChanges();
0 ignored issues
show
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...
463
    }
464
465
    /**
466
     * @When /^I change its price to (?:€|£|\$)([^"]+) for "([^"]+)" channel$/
467
     */
468
    public function iChangeItsPriceTo($price, $channelName)
469
    {
470
        $this->updateSimpleProductPage->specifyPrice($channelName, $price);
471
    }
472
473
    /**
474
     * @When /^I change its original price to "(?:€|£|\$)([^"]+)" for "([^"]+)" channel$/
475
     */
476
    public function iChangeItsOriginalPriceTo($price, $channelName)
477
    {
478
        $this->updateSimpleProductPage->specifyOriginalPrice($channelName, $price);
479
    }
480
481
    /**
482
     * @Given I add the :optionName option to it
483
     */
484
    public function iAddTheOptionToIt($optionName)
485
    {
486
        $this->createConfigurableProductPage->selectOption($optionName);
487
    }
488
489
    /**
490
     * @When I set its :attribute attribute to :value
491
     * @When I set its :attribute attribute to :value in :language
492
     * @When I do not set its :attribute attribute in :language
493
     */
494
    public function iSetItsAttributeTo($attribute, $value = null, $language = 'en_US')
495
    {
496
        $this->createSimpleProductPage->addAttribute($attribute, $value, $language);
497
    }
498
499
    /**
500
     * @When I remove its :attribute attribute
501
     * @When I remove its :attribute attribute from :language
502
     */
503
    public function iRemoveItsAttribute($attribute, $language = 'en_US')
504
    {
505
        $this->createSimpleProductPage->removeAttribute($attribute, $language);
506
    }
507
508
    /**
509
     * @When I try to add new attributes
510
     */
511
    public function iTryToAddNewAttributes()
512
    {
513
        $this->updateSimpleProductPage->addSelectedAttributes();
514
    }
515
516
    /**
517
     * @When I do not want to have shipping required for this product
518
     */
519
    public function iDoNotWantToHaveShippingRequiredForThisProduct()
520
    {
521
        $this->createSimpleProductPage->setShippingRequired(false);
522
    }
523
524
    /**
525
     * @Then attribute :attributeName of product :product should be :value
526
     * @Then attribute :attributeName of product :product should be :value in :language
527
     */
528
    public function itsAttributeShouldBe($attributeName, ProductInterface $product, $value, $language = 'en_US')
529
    {
530
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
531
532
        Assert::same($this->updateSimpleProductPage->getAttributeValue($attributeName, $language), $value);
533
    }
534
535
    /**
536
     * @Then /^(product "[^"]+") should not have a "([^"]+)" attribute$/
537
     */
538
    public function productShouldNotHaveAttribute(ProductInterface $product, $attribute)
539
    {
540
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
541
542
        Assert::false($this->updateSimpleProductPage->hasAttribute($attribute));
543
    }
544
545
    /**
546
     * @Then /^product "[^"]+" should not have any attributes$/
547
     * @Then /^product "[^"]+" should have (\d+) attributes?$/
548
     */
549
    public function productShouldNotHaveAnyAttributes($count = 0)
550
    {
551
        Assert::same($this->updateSimpleProductPage->getNumberOfAttributes(), (int) $count);
552
    }
553
554
    /**
555
     * @Given product with :element :value should not be added
556
     */
557
    public function productWithNameShouldNotBeAdded($element, $value)
558
    {
559
        $this->iWantToBrowseProducts();
560
561
        Assert::false($this->indexPage->isSingleResourceOnPage([$element => $value]));
562
    }
563
564
    /**
565
     * @When I remove its name from :language translation
566
     */
567
    public function iRemoveItsNameFromTranslation($language)
568
    {
569
        $currentPage = $this->resolveCurrentPage();
570
571
        $currentPage->nameItIn('', $language);
0 ignored issues
show
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...
572
    }
573
574
    /**
575
     * @Then /^this product should have (?:a|an) "([^"]+)" option$/
576
     */
577
    public function thisProductShouldHaveOption($productOption)
578
    {
579
        $this->updateConfigurableProductPage->isProductOptionChosen($productOption);
580
    }
581
582
    /**
583
     * @Then the option field should be disabled
584
     */
585
    public function theOptionFieldShouldBeDisabled()
586
    {
587
        Assert::true($this->updateConfigurableProductPage->isProductOptionsDisabled());
588
    }
589
590
    /**
591
     * @When /^I choose main (taxon "[^"]+")$/
592
     */
593
    public function iChooseMainTaxon(TaxonInterface $taxon)
594
    {
595
        $currentPage = $this->resolveCurrentPage();
596
597
        $currentPage->selectMainTaxon($taxon);
0 ignored issues
show
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...
598
    }
599
600
    /**
601
     * @Then /^the slug of the ("[^"]+" product) should(?:| still) be "([^"]+)"$/
602
     * @Then /^the slug of the ("[^"]+" product) should(?:| still) be "([^"]+)" (in the "[^"]+" locale)$/
603
     */
604
    public function productSlugShouldBe(ProductInterface $product, $slug, $locale = 'en_US')
605
    {
606
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
607
608
        Assert::same($this->updateSimpleProductPage->getSlug($locale), $slug);
609
    }
610
611
    /**
612
     * @Then /^(this product) main taxon should be "([^"]+)"$/
613
     */
614
    public function thisProductMainTaxonShouldBe(ProductInterface $product, $taxonName)
615
    {
616
        $currentPage = $this->resolveCurrentPage();
617
        $currentPage->open(['id' => $product->getId()]);
618
619
        Assert::true($currentPage->isMainTaxonChosen($taxonName));
0 ignored issues
show
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...
620
    }
621
622
    /**
623
     * @Then /^inventory of (this product) should not be tracked$/
624
     */
625
    public function thisProductShouldNotBeTracked(ProductInterface $product)
626
    {
627
        $this->iWantToModifyAProduct($product);
628
629
        Assert::false($this->updateSimpleProductPage->isTracked());
630
    }
631
632
    /**
633
     * @Then /^inventory of (this product) should be tracked$/
634
     */
635
    public function thisProductShouldBeTracked(ProductInterface $product)
636
    {
637
        $this->iWantToModifyAProduct($product);
638
639
        Assert::true($this->updateSimpleProductPage->isTracked());
640
    }
641
642
    /**
643
     * @When I attach the :path image with :type type
644
     * @When I attach the :path image
645
     */
646
    public function iAttachImageWithType($path, $type = null)
647
    {
648
        $currentPage = $this->resolveCurrentPage();
649
650
        $currentPage->attachImage($path, $type);
0 ignored issues
show
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...
651
    }
652
653
    /**
654
     * @When I associate as :productAssociationType the :productName product
655
     * @When I associate as :productAssociationType the :firstProductName and :secondProductName products
656
     */
657
    public function iAssociateProductsAsProductAssociation(
658
        ProductAssociationTypeInterface $productAssociationType,
659
        ...$productsNames
660
    ) {
661
        $currentPage = $this->resolveCurrentPage();
662
663
        $currentPage->associateProducts($productAssociationType, $productsNames);
0 ignored issues
show
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...
664
    }
665
666
    /**
667
     * @When I remove an associated product :productName from :productAssociationType
668
     */
669
    public function iRemoveAnAssociatedProductFromProductAssociation(
670
        $productName,
671
        ProductAssociationTypeInterface $productAssociationType
672
    ) {
673
        $currentPage = $this->resolveCurrentPage();
674
675
        $currentPage->removeAssociatedProduct($productName, $productAssociationType);
0 ignored issues
show
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...
676
    }
677
678
    /**
679
     * @Then /^(?:this product|the product "[^"]+"|it) should(?:| also) have an image with "([^"]*)" type$/
680
     */
681
    public function thisProductShouldHaveAnImageWithType($type)
682
    {
683
        $currentPage = $this->resolveCurrentPage();
684
685
        Assert::true($currentPage->isImageWithTypeDisplayed($type));
0 ignored issues
show
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...
686
    }
687
688
    /**
689
     * @Then /^(?:this product|it)(?:| also) should not have any images with "([^"]*)" type$/
690
     */
691
    public function thisProductShouldNotHaveAnyImagesWithType($code)
692
    {
693
        $currentPage = $this->resolveCurrentPage();
694
695
        Assert::false($currentPage->isImageWithTypeDisplayed($code));
0 ignored issues
show
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...
696
    }
697
698
    /**
699
     * @When I change the image with the :type type to :path
700
     */
701
    public function iChangeItsImageToPathForTheType($type, $path)
702
    {
703
        $currentPage = $this->resolveCurrentPage();
704
705
        $currentPage->changeImageWithType($type, $path);
0 ignored issues
show
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...
706
    }
707
708
    /**
709
     * @When /^I(?:| also) remove an image with "([^"]*)" type$/
710
     */
711
    public function iRemoveAnImageWithType($code)
712
    {
713
        $currentPage = $this->resolveCurrentPage();
714
715
        $currentPage->removeImageWithType($code);
0 ignored issues
show
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...
716
    }
717
718
    /**
719
     * @When I remove the first image
720
     */
721
    public function iRemoveTheFirstImage()
722
    {
723
        $currentPage = $this->resolveCurrentPage();
724
725
        $currentPage->removeFirstImage();
0 ignored issues
show
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...
726
    }
727
728
    /**
729
     * @When I change the first image type to :type
730
     */
731
    public function iChangeTheFirstImageTypeTo($type)
732
    {
733
        $currentPage = $this->resolveCurrentPage();
734
735
        $currentPage->modifyFirstImageType($type);
0 ignored issues
show
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...
736
    }
737
738
    /**
739
     * @Then /^(this product) should not have any images$/
740
     */
741
    public function thisProductShouldNotHaveImages(ProductInterface $product)
742
    {
743
        $this->iWantToModifyAProduct($product);
744
745
        $currentPage = $this->resolveCurrentPage();
746
747
        Assert::same($currentPage->countImages(), 0);
0 ignored issues
show
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...
748
    }
749
750
    /**
751
     * @Then /^(this product) should(?:| still) have (?:only one|(\d+)) images?$/
752
     */
753
    public function thereShouldStillBeOnlyOneImageInThisProduct(ProductInterface $product, $count = 1)
754
    {
755
        $this->iWantToModifyAProduct($product);
756
757
        $currentPage = $this->resolveCurrentPage();
758
759
        Assert::same($currentPage->countImages(), (int) $count);
0 ignored issues
show
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...
760
    }
761
762
    /**
763
     * @Then /^there should be no reviews of (this product)$/
764
     */
765
    public function thereAreNoProductReviews(ProductInterface $product)
766
    {
767
        $this->productReviewIndexPage->open();
768
769
        Assert::false($this->productReviewIndexPage->isSingleResourceOnPage(['reviewSubject' => $product->getName()]));
770
    }
771
772
    /**
773
     * @Then this product should( also) have an association :productAssociationType with product :productName
774
     * @Then this product should( also) have an association :productAssociationType with products :firstProductName and :secondProductName
775
     */
776
    public function theProductShouldHaveAnAssociationWithProducts(
777
        ProductAssociationTypeInterface $productAssociationType,
778
        ...$productsNames
779
    ) {
780
        foreach ($productsNames as $productName) {
781
            Assert::true(
782
                $this->updateSimpleProductPage->hasAssociatedProduct($productName, $productAssociationType),
783
                sprintf(
784
                    'This product should have an association %s with product %s.',
785
                    $productAssociationType->getName(),
786
                    $productName
787
                )
788
            );
789
        }
790
    }
791
792
    /**
793
     * @Then this product should not have an association :productAssociationType with product :productName
794
     */
795
    public function theProductShouldNotHaveAnAssociationWithProduct(
796
        ProductAssociationTypeInterface $productAssociationType,
797
        $productName
798
    ) {
799
        Assert::false($this->updateSimpleProductPage->hasAssociatedProduct($productName, $productAssociationType));
800
    }
801
802
    /**
803
     * @Then I should be notified that simple product code has to be unique
804
     */
805
    public function iShouldBeNotifiedThatSimpleProductCodeHasToBeUnique()
806
    {
807
        $this->assertValidationMessage('code', 'Simple product code must be unique among all products and product variants.');
808
    }
809
810
    /**
811
     * @Then I should be notified that slug has to be unique
812
     */
813
    public function iShouldBeNotifiedThatSlugHasToBeUnique()
814
    {
815
        $this->assertValidationMessage('slug', 'Product slug must be unique.');
816
    }
817
818
    /**
819
     * @Then I should be notified that code has to be unique
820
     */
821
    public function iShouldBeNotifiedThatCodeHasToBeUnique()
822
    {
823
        $this->assertValidationMessage('code', 'Product code must be unique.');
824
    }
825
826
    /**
827
     * @Then I should be notified that price must be defined for every channel
828
     */
829
    public function iShouldBeNotifiedThatPriceMustBeDefinedForEveryChannel()
830
    {
831
        $this->assertValidationMessage('channel_pricings', 'You must define price for every channel.');
832
    }
833
834
    /**
835
     * @Then they should have order like :firstProductName, :secondProductName and :thirdProductName
836
     */
837
    public function theyShouldHaveOrderLikeAnd(...$productNames)
838
    {
839
        Assert::true($this->indexPerTaxonPage->hasProductsInOrder($productNames));
840
    }
841
842
    /**
843
     * @When I save my new configuration
844
     */
845
    public function iSaveMyNewConfiguration()
846
    {
847
        $this->indexPerTaxonPage->savePositions();
848
    }
849
850
    /**
851
     * @When I set the position of :productName to :position
852
     */
853
    public function iSetThePositionOfTo($productName, $position)
854
    {
855
        $this->indexPerTaxonPage->setPositionOfProduct($productName, (int) $position);
856
    }
857
858
    /**
859
     * @Then this product should( still) have slug :value in :language
860
     */
861
    public function thisProductElementShouldHaveSlugIn($slug, $language)
862
    {
863
        Assert::same($this->updateSimpleProductPage->getSlug($language), $slug);
864
    }
865
866
    /**
867
     * @When I set its shipping category as :shippingCategoryName
868
     */
869
    public function iSetItsShippingCategoryAs($shippingCategoryName)
870
    {
871
        $this->createSimpleProductPage->selectShippingCategory($shippingCategoryName);
872
    }
873
874
    /**
875
     * @Then /^(it|this product) should be priced at (?:€|£|\$)([^"]+) for channel "([^"]+)"$/
876
     * @Then /^(product "[^"]+") should be priced at (?:€|£|\$)([^"]+) for channel "([^"]+)"$/
877
     */
878
    public function itShouldBePricedAtForChannel(ProductInterface $product, $price, $channelName)
879
    {
880
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
881
882
        Assert::same($this->updateSimpleProductPage->getPriceForChannel($channelName), $price);
883
    }
884
885
    /**
886
     * @Then /^(its|this products) original price should be "(?:€|£|\$)([^"]+)" for channel "([^"]+)"$/
887
     */
888
    public function itsOriginalPriceForChannel(ProductInterface $product, $originalPrice, $channelName)
889
    {
890
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
891
892
        Assert::same(
893
            $this->updateSimpleProductPage->getOriginalPriceForChannel($channelName),
894
            $originalPrice
895
        );
896
    }
897
898
    /**
899
     * @Then /^(this product) should no longer have price for channel "([^"]+)"$/
900
     */
901
    public function thisProductShouldNoLongerHavePriceForChannel(ProductInterface $product, $channelName)
902
    {
903
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
904
905
        try {
906
            $this->updateSimpleProductPage->getPriceForChannel($channelName);
907
        } catch (ElementNotFoundException $exception) {
908
            return;
909
        }
910
911
        throw new \Exception(
912
            sprintf('Product "%s" should not have price defined for channel "%s".', $product->getName(), $channelName)
913
        );
914
    }
915
916
    /**
917
     * @Then I should be notified that I have to define product variants' prices for newly assigned channels first
918
     */
919
    public function iShouldBeNotifiedThatIHaveToDefineProductVariantsPricesForNewlyAssignedChannelsFirst()
920
    {
921
        Assert::same(
922
            $this->updateConfigurableProductPage->getValidationMessage('channels'),
923
            'You have to define product variants\' prices for newly assigned channels first.'
924
        );
925
    }
926
927
    /**
928
     * @Then /^the (product "[^"]+") should not have shipping required$/
929
     */
930
    public function theProductWithCodeShouldNotHaveShippingRequired(ProductInterface $product)
931
    {
932
        $this->updateSimpleProductPage->open(['id' => $product->getId()]);
933
934
        Assert::false($this->updateSimpleProductPage->isShippingRequired());
935
    }
936
937
    /**
938
     * @Then I should be notified that I have to define the :attribute attribute in :language
939
     */
940
    public function iShouldBeNotifiedThatIHaveToDefineTheAttributeIn($attribute, $language)
941
    {
942
        Assert::same(
943
            $this->resolveCurrentPage()->getAttributeValidationErrors($attribute, $language),
0 ignored issues
show
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...
944
            'This value should not be blank.'
945
        );
946
    }
947
948
    /**
949
     * @Then I should be notified that the :attribute attribute in :language should be longer than :number
950
     */
951
    public function iShouldBeNotifiedThatTheAttributeInShouldBeLongerThan($attribute, $language, $number)
952
    {
953
        Assert::same(
954
            $this->resolveCurrentPage()->getAttributeValidationErrors($attribute, $language),
0 ignored issues
show
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...
955
            sprintf('This value is too short. It should have %s characters or more.', $number)
956
        );
957
    }
958
959
    /**
960
     * @param string $element
961
     * @param string $value
962
     */
963
    private function assertElementValue($element, $value)
964
    {
965
        /** @var UpdatePageInterface $currentPage */
966
        $currentPage = $this->resolveCurrentPage();
967
968
        Assert::isInstanceOf($currentPage, UpdatePageInterface::class);
969
970
        Assert::true(
971
            $currentPage->hasResourceValues([$element => $value]),
972
            sprintf('Product should have %s with %s value.', $element, $value)
973
        );
974
    }
975
976
    /**
977
     * @param string $element
978
     * @param string $message
979
     */
980
    private function assertValidationMessage($element, $message)
981
    {
982
        /** @var CreatePageInterface|UpdatePageInterface $currentPage */
983
        $currentPage = $this->resolveCurrentPage();
984
985
        Assert::same($currentPage->getValidationMessage($element), $message);
986
    }
987
988
    /**
989
     * @return IndexPageInterface|IndexPerTaxonPageInterface|CreateSimpleProductPageInterface|CreateConfigurableProductPageInterface|UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface
990
     */
991
    private function resolveCurrentPage()
992
    {
993
        return $this->currentPageResolver->getCurrentPageWithForm([
994
            $this->indexPage,
995
            $this->indexPerTaxonPage,
996
            $this->createSimpleProductPage,
997
            $this->createConfigurableProductPage,
998
            $this->updateSimpleProductPage,
999
            $this->updateConfigurableProductPage,
1000
        ]);
1001
    }
1002
}
1003