Completed
Push — master ( 968507...279808 )
by Paweł
10:20
created

theVariantWithCodeShouldNotHaveShippingRequired()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
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
namespace Sylius\Behat\Context\Ui\Admin;
13
14
use Behat\Behat\Context\Context;
15
use Sylius\Behat\NotificationType;
16
use Sylius\Behat\Page\Admin\ProductVariant\CreatePageInterface;
17
use Sylius\Behat\Page\Admin\ProductVariant\GeneratePageInterface;
18
use Sylius\Behat\Page\Admin\ProductVariant\IndexPageInterface;
19
use Sylius\Behat\Page\Admin\ProductVariant\UpdatePageInterface;
20
use Sylius\Behat\Service\NotificationCheckerInterface;
21
use Sylius\Behat\Service\Resolver\CurrentPageResolverInterface;
22
use Sylius\Behat\Service\SharedStorageInterface;
23
use Sylius\Component\Core\Model\ProductInterface;
24
use Sylius\Component\Core\Model\ProductVariantInterface;
25
use Webmozart\Assert\Assert;
26
27
/**
28
 * @author Łukasz Chruściel <[email protected]>
29
 * @author Gorka Laucirica <[email protected]>
30
 */
31
final class ManagingProductVariantsContext implements Context
32
{
33
    /**
34
     * @var SharedStorageInterface
35
     */
36
    private $sharedStorage;
37
38
    /**
39
     * @var CreatePageInterface
40
     */
41
    private $createPage;
42
43
    /**
44
     * @var IndexPageInterface
45
     */
46
    private $indexPage;
47
48
    /**
49
     * @var UpdatePageInterface
50
     */
51
    private $updatePage;
52
53
    /**
54
     * @var GeneratePageInterface
55
     */
56
    private $generatePage;
57
58
    /**
59
     * @var CurrentPageResolverInterface
60
     */
61
    private $currentPageResolver;
62
63
    /**
64
     * @var NotificationCheckerInterface
65
     */
66
    private $notificationChecker;
67
68
    /**
69
     * @param SharedStorageInterface $sharedStorage
70
     * @param CreatePageInterface $createPage
71
     * @param IndexPageInterface $indexPage
72
     * @param UpdatePageInterface $updatePage
73
     * @param GeneratePageInterface $generatePage
74
     * @param CurrentPageResolverInterface $currentPageResolver
75
     * @param NotificationCheckerInterface $notificationChecker
76
     */
77
    public function __construct(
78
        SharedStorageInterface $sharedStorage,
79
        CreatePageInterface $createPage,
80
        IndexPageInterface $indexPage,
81
        UpdatePageInterface $updatePage,
82
        GeneratePageInterface $generatePage,
83
        CurrentPageResolverInterface $currentPageResolver,
84
        NotificationCheckerInterface $notificationChecker
85
    ) {
86
        $this->sharedStorage = $sharedStorage;
87
        $this->createPage = $createPage;
88
        $this->indexPage = $indexPage;
89
        $this->updatePage = $updatePage;
90
        $this->generatePage = $generatePage;
91
        $this->currentPageResolver = $currentPageResolver;
92
        $this->notificationChecker = $notificationChecker;
93
    }
94
95
    /**
96
     * @Given /^I want to create a new variant of (this product)$/
97
     */
98
    public function iWantToCreateANewProduct(ProductInterface $product)
99
    {
100
        $this->createPage->open(['productId' => $product->getId()]);
101
    }
102
103
    /**
104
     * @When I specify its code as :code
105
     * @When I do not specify its code
106
     */
107
    public function iSpecifyItsCodeAs($code = null)
108
    {
109
        $this->createPage->specifyCode($code);
110
    }
111
112
    /**
113
     * @When I name it :name in :language
114
     */
115
    public function iNameItIn($name, $language)
116
    {
117
        $this->createPage->nameItIn($name, $language);
118
    }
119
120
    /**
121
     * @When I rename it to :name
122
     */
123
    public function iRenameItTo($name)
124
    {
125
        $this->updatePage->nameIt($name);
0 ignored issues
show
Bug introduced by
The method nameIt() does not seem to exist on object<Sylius\Behat\Page...nt\UpdatePageInterface>.

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

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

Loading history...
126
    }
127
128
    /**
129
     * @When I add it
130
     * @When I try to add it
131
     */
132
    public function iAddIt()
133
    {
134
        $this->createPage->create();
135
    }
136
137
    /**
138
     * @When I disable its inventory tracking
139
     */
140
    public function iDisableItsTracking()
141
    {
142
        $this->updatePage->disableTracking();
143
    }
144
145
    /**
146
     * @When I enable its inventory tracking
147
     */
148
    public function iEnableItsTracking()
149
    {
150
        $this->updatePage->enableTracking();
151
    }
152
153
    /**
154
     * @When /^I set its(?:| default) price to "(?:€|£|\$)([^"]+)" for "([^"]+)" channel$/
155
     * @When I do not set its price
156
     */
157
    public function iSetItsPriceTo($price = null, $channelName = null)
158
    {
159
        $this->createPage->specifyPrice($price, (null === $channelName) ? $this->sharedStorage->get('channel') :$channelName);
160
    }
161
162
    /**
163
     * @When /^I set its original price to "(?:€|£|\$)([^"]+)" for "([^"]+)" channel$/
164
     */
165
    public function iSetItsOriginalPriceTo($originalPrice, $channelName)
166
    {
167
        $this->createPage->specifyOriginalPrice($originalPrice, $channelName);
168
    }
169
170
    /**
171
     * @When I set its height, width, depth and weight to :number
172
     */
173
    public function iSetItsDimensionsTo($value)
174
    {
175
        $this->createPage->specifyHeightWidthDepthAndWeight($value, $value, $value, $value);
176
    }
177
178
    /**
179
     * @When I do not specify its current stock
180
     */
181
    public function iDoNetSetItsCurrentStockTo()
182
    {
183
        $this->createPage->specifyCurrentStock('');
184
    }
185
186
    /**
187
     * @When I choose :calculatorName calculator
188
     */
189
    public function iChooseCalculator($calculatorName)
190
    {
191
        $this->createPage->choosePricingCalculator($calculatorName);
192
    }
193
194
    /**
195
     * @When I set its :optionName option to :optionValue
196
     */
197
    public function iSetItsOptionAs($optionName, $optionValue)
198
    {
199
        $this->createPage->selectOption($optionName, $optionValue);
200
    }
201
202
    /**
203
     * @When I set the position of :name to :position
204
     */
205
    public function iSetThePositionOfTo($name, $position)
206
    {
207
        $this->indexPage->setPosition($name, (int) $position);
208
    }
209
210
    /**
211
     * @When I save my new configuration
212
     */
213
    public function iSaveMyNewConfiguration()
214
    {
215
        $this->indexPage->savePositions();
216
    }
217
218
    /**
219
     * @When I do not want to have shipping required for this product
220
     */
221
    public function iDoNotWantToHaveShippingRequiredForThisProduct()
222
    {
223
        $this->createPage->setShippingRequired(false);
224
    }
225
226
    /**
227
     * @Then /^the (variant with code "[^"]+") should be priced at (?:€|£|\$)([^"]+) for channel "([^"]+)"$/
228
     */
229
    public function theVariantWithCodeShouldBePricedAtForChannel(ProductVariantInterface $productVariant, $price, $channelName)
230
    {
231
        $this->updatePage->open(['id' => $productVariant->getId(), 'productId' => $productVariant->getProduct()->getId()]);
232
233
        Assert::same($this->updatePage->getPriceForChannel($channelName), $price);
234
    }
235
236
    /**
237
     * @Then /^the (variant with code "[^"]+") should be named "([^"]+)" in ("([^"]+)" locale)$/
238
     */
239
    public function theVariantWithCodeShouldBeNamedIn(ProductVariantInterface $productVariant, $name, $language)
240
    {
241
        $this->updatePage->open(['id' => $productVariant->getId(), 'productId' => $productVariant->getProduct()->getId()]);
242
243
        Assert::same($this->updatePage->getNameInLanguage($language), $name);
244
    }
245
246
    /**
247
     * @Then /^the (variant with code "[^"]+") should have an original price of (?:€|£|\$)([^"]+) for channel "([^"]+)"$/
248
     */
249
    public function theVariantWithCodeShouldHaveAnOriginalPriceOfForChannel(ProductVariantInterface $productVariant, $originalPrice, $channelName)
250
    {
251
        $this->updatePage->open(['id' => $productVariant->getId(), 'productId' => $productVariant->getProduct()->getId()]);
252
253
        Assert::same(
254
            $this->updatePage->getOriginalPriceForChannel($channelName),
255
            $originalPrice
256
        );
257
    }
258
259
    /**
260
     * @When /^I delete the ("[^"]+" variant of product "[^"]+")$/
261
     * @When /^I try to delete the ("[^"]+" variant of product "[^"]+")$/
262
     */
263
    public function iDeleteTheVariantOfProduct(ProductVariantInterface $productVariant)
264
    {
265
        $this->indexPage->open(['productId' => $productVariant->getProduct()->getId()]);
266
267
        $this->indexPage->deleteResourceOnPage(['code' => $productVariant->getCode()]);
268
    }
269
270
    /**
271
     * @Then I should be notified that this variant is in use and cannot be deleted
272
     */
273
    public function iShouldBeNotifiedOfFailure()
274
    {
275
        $this->notificationChecker->checkNotification(
276
            'Cannot delete, the product variant is in use.',
277
            NotificationType::failure()
278
        );
279
    }
280
281
    /**
282
     * @When /^I want to modify the ("[^"]+" product variant)$/
283
     */
284
    public function iWantToModifyAProduct(ProductVariantInterface $productVariant)
285
    {
286
        $this->updatePage->open(['id' => $productVariant->getId(), 'productId' => $productVariant->getProduct()->getId()]);
287
    }
288
289
    /**
290
     * @Then the code field should be disabled
291
     */
292
    public function theCodeFieldShouldBeDisabled()
293
    {
294
        Assert::true($this->updatePage->isCodeDisabled());
295
    }
296
297
    /**
298
     * @Then I should be notified that :element is required
299
     */
300
    public function iShouldBeNotifiedThatIsRequired($element)
301
    {
302
        $this->assertValidationMessage($element, sprintf('Please enter the %s.', $element));
303
    }
304
305
    /**
306
     * @Then I should be notified that code has to be unique
307
     */
308
    public function iShouldBeNotifiedThatCodeHasToBeUnique()
309
    {
310
        $this->assertValidationMessage('code', 'Product variant code must be unique.');
311
    }
312
313
    /**
314
     * @Then I should be notified that current stock is required
315
     */
316
    public function iShouldBeNotifiedThatOnHandIsRequired()
317
    {
318
        $this->assertValidationMessage('on_hand', 'Please enter on hand.');
319
    }
320
321
    /**
322
     * @Then I should be notified that height, width, depth and weight cannot be lower than 0
323
     */
324
    public function iShouldBeNotifiedThatIsHeightWidthDepthWeightCannotBeLowerThan()
325
    {
326
        $this->assertValidationMessage('height', 'Height cannot be negative.');
327
        $this->assertValidationMessage('width', 'Width cannot be negative.');
328
        $this->assertValidationMessage('depth', 'Depth cannot be negative.');
329
        $this->assertValidationMessage('weight', 'Weight cannot be negative.');
330
    }
331
332
    /**
333
     * @Then I should be notified that price cannot be lower than 0.01
334
     */
335
    public function iShouldBeNotifiedThatPriceCannotBeLowerThen()
336
    {
337
        /** @var CreatePageInterface|UpdatePageInterface $currentPage */
338
        $currentPage = $this->currentPageResolver->getCurrentPageWithForm([$this->createPage, $this->updatePage]);
339
340
        Assert::contains($currentPage->getPricesValidationMessage(), 'Price must be at least 0.01.');
0 ignored issues
show
Bug introduced by
The method getPricesValidationMessage does only exist in Sylius\Behat\Page\Admin\...ant\CreatePageInterface, but not in Sylius\Behat\Page\Admin\...ant\UpdatePageInterface.

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...
341
    }
342
343
    /**
344
     * @Then I should be notified that this variant already exists
345
     */
346
    public function iShouldBeNotifiedThatThisVariantAlreadyExists()
347
    {
348
        /** @var CreatePageInterface|UpdatePageInterface $currentPage */
349
        $currentPage = $this->currentPageResolver->getCurrentPageWithForm([$this->createPage, $this->updatePage]);
350
351
        Assert::same($currentPage->getValidationMessageForForm(), 'Variant with this option set already exists.');
0 ignored issues
show
Bug introduced by
The method getValidationMessageForForm does only exist in Sylius\Behat\Page\Admin\...ant\CreatePageInterface, but not in Sylius\Behat\Page\Admin\...ant\UpdatePageInterface.

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...
352
    }
353
354
    /**
355
     * @Then /^I should be notified that code is required for the (\d)(?:st|nd|rd|th) variant$/
356
     */
357
    public function iShouldBeNotifiedThatCodeIsRequiredForVariant($position)
358
    {
359
        Assert::same(
360
            $this->generatePage->getValidationMessage('code', $position - 1),
361
            'Please enter the code.'
362
        );
363
    }
364
365
    /**
366
     * @Then /^I should be notified that prices in all channels must be defined for the (\d)(?:st|nd|rd|th) variant$/
367
     */
368
    public function iShouldBeNotifiedThatPricesInAllChannelsMustBeDefinedForTheVariant($position)
369
    {
370
        Assert::same(
371
            $this->generatePage->getPricesValidationMessage($position - 1),
372
            'You must define price for every channel.'
373
        );
374
    }
375
376
    /**
377
     * @Then /^I should be notified that variant code must be unique within this product for the (\d)(?:st|nd|rd|th) variant$/
378
     */
379
    public function iShouldBeNotifiedThatVariantCodeMustBeUniqueWithinThisProductForYheVariant($position)
380
    {
381
        Assert::same(
382
            $this->generatePage->getValidationMessage('code', $position - 1),
383
            'This code must be unique within this product.'
384
        );
385
    }
386
387
    /**
388
     * @Then I should be notified that prices in all channels must be defined
389
     */
390
    public function iShouldBeNotifiedThatPricesInAllChannelsMustBeDefined()
391
    {
392
        Assert::contains(
393
            $this->createPage->getPricesValidationMessage(),
394
            'You must define price for every channel.'
395
        );
396
    }
397
398
    /**
399
     * @When I save my changes
400
     * @When I try to save my changes
401
     */
402
    public function iSaveMyChanges()
403
    {
404
        $this->updatePage->saveChanges();
405
    }
406
407
    /**
408
     * @When I remove its name
409
     */
410
    public function iRemoveItsNameFromTranslation()
411
    {
412
        $this->updatePage->nameIt('');
0 ignored issues
show
Bug introduced by
The method nameIt() does not seem to exist on object<Sylius\Behat\Page...nt\UpdatePageInterface>.

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

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

Loading history...
413
    }
414
415
    /**
416
     * @Then /^inventory of (this variant) should not be tracked$/
417
     */
418
    public function thisProductVariantShouldNotBeTracked(ProductVariantInterface $productVariant)
419
    {
420
        $this->iWantToModifyAProduct($productVariant);
421
422
        Assert::false($this->updatePage->isTracked());
423
    }
424
425
    /**
426
     * @Then /^inventory of (this variant) should be tracked$/
427
     */
428
    public function thisProductVariantShouldBeTracked(ProductVariantInterface $productVariant)
429
    {
430
        $this->iWantToModifyAProduct($productVariant);
431
432
        Assert::true($this->updatePage->isTracked());
433
    }
434
435
    /**
436
     * @When /^I want to generate new variants for (this product)$/
437
     */
438
    public function iWantToGenerateNewVariantsForThisProduct(ProductInterface $product)
439
    {
440
        $this->generatePage->open(['productId' => $product->getId()]);
441
    }
442
443
    /**
444
     * @When I generate it
445
     * @When I try to generate it
446
     */
447
    public function iClickGenerate()
448
    {
449
        $this->generatePage->generate();
450
    }
451
452
    /**
453
     * @When /^I specify that the (\d)(?:st|nd|rd|th) variant is identified by "([^"]+)" code and costs "(?:€|£|\$)([^"]+)" in ("[^"]+") channel$/
454
     */
455
    public function iSpecifyThereAreVariantsIdentifiedByCodeWithCost($nthVariant, $code, $price, $channelName)
456
    {
457
        $this->generatePage->specifyCode($nthVariant - 1, $code);
458
        $this->generatePage->specifyPrice($nthVariant - 1, $price, $channelName);
459
    }
460
461
    /**
462
     * @When /^I specify that the (\d)(?:st|nd|rd|th) variant is identified by "([^"]+)" code$/
463
     */
464
    public function iSpecifyThereAreVariantsIdentifiedByCode($nthVariant, $code)
465
    {
466
        $this->generatePage->specifyCode($nthVariant - 1, $code);
467
    }
468
469
    /**
470
     * @When /^I specify that the (\d)(?:st|nd|rd|th) variant costs "(?:€|£|\$)([^"]+)" in ("[^"]+") channel$/
471
     */
472
    public function iSpecifyThereAreVariantsWithCost($nthVariant, $price, $channelName)
473
    {
474
        $this->generatePage->specifyPrice($nthVariant - 1, $price, $channelName);
475
    }
476
477
    /**
478
     * @When /^I remove (\d)(?:st|nd|rd|th) variant from the list$/
479
     */
480
    public function iRemoveVariantFromTheList($nthVariant)
481
    {
482
        $this->generatePage->removeVariant($nthVariant - 1);
483
    }
484
485
    /**
486
     * @Then I should be notified that it has been successfully generated
487
     */
488
    public function iShouldBeNotifiedThatItHasBeenSuccessfullyGenerated()
489
    {
490
        $this->notificationChecker->checkNotification('Success Product variants have been successfully generated.', NotificationType::success());
491
    }
492
493
    /**
494
     * @When I set its shipping category as :shippingCategoryName
495
     */
496
    public function iSetItsShippingCategoryAs($shippingCategoryName)
497
    {
498
        $this->createPage->selectShippingCategory($shippingCategoryName);
499
    }
500
501
    /**
502
     * @When I do not specify any information about variants
503
     */
504
    public function iDoNotSpecifyAnyInformationAboutVariants()
505
    {
506
        // Intentionally left blank to fulfill context expectation
507
    }
508
509
    /**
510
     * @When I change its quantity of inventory to :amount
511
     */
512
    public function iChangeItsQuantityOfInventoryTo($amount)
513
    {
514
        $this->updatePage->specifyCurrentStock($amount);
515
    }
516
517
    /**
518
     * @Then /^the (variant with code "[^"]+") should not have shipping required$/
519
     */
520
    public function theVariantWithCodeShouldNotHaveShippingRequired(ProductVariantInterface $productVariant)
521
    {
522
        $this->updatePage->open(['productId' => $productVariant->getProduct()->getId(),'id' => $productVariant->getId()]);
523
524
        Assert::false($this->updatePage->isShippingRequired());
525
    }
526
527
    /**
528
     * @Then I should be notified that on hand quantity must be greater than the number of on hold units
529
     */
530
    public function iShouldBeNotifiedThatOnHandQuantityMustBeGreaterThanTheNumberOfOnHoldUnits()
531
    {
532
        Assert::same(
533
            $this->updatePage->getValidationMessage('on_hand'),
534
            'On hand must be greater than the number of on hold units'
535
        );
536
    }
537
538
    /**
539
     * @param string $element
540
     * @param $message
541
     */
542
    private function assertValidationMessage($element, $message)
543
    {
544
        /** @var CreatePageInterface|UpdatePageInterface $currentPage */
545
        $currentPage = $this->currentPageResolver->getCurrentPageWithForm([$this->createPage, $this->updatePage]);
546
547
        Assert::same($currentPage->getValidationMessage($element), $message);
548
    }
549
}
550