Completed
Push — remove-content-bundle ( 201341...8d07b3 )
by Kamil
52:29 queued 32:39
created

ManagingProductVariantsContext   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 439
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 11

Importance

Changes 0
Metric Value
wmc 36
c 0
b 0
f 0
lcom 3
cbo 11
dl 0
loc 439
rs 8.8

36 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 17 1
A iWantToCreateANewProduct() 0 4 1
A iSpecifyItsCodeAs() 0 4 1
A iNameItIn() 0 4 1
A iRenameItTo() 0 4 1
A iAddIt() 0 4 1
A iDisableItsTracking() 0 4 1
A iEnableItsTracking() 0 4 1
A iSetItsPriceTo() 0 4 1
A theProductVariantShouldAppearInTheShop() 0 9 1
A iWantToViewAllVariantsOfThisProduct() 0 4 1
A iShouldSeeProductsInTheList() 0 10 1
A iDeleteTheVariantOfProduct() 0 6 1
A productVariantShouldNotExist() 0 9 1
A iShouldBeNotifiedOfFailure() 0 7 1
A productShouldExistInTheProductCatalog() 0 4 1
A iWantToModifyAProduct() 0 4 1
A theCodeFieldShouldBeDisabled() 0 7 1
A iShouldBeNotifiedThatPriceIsRequired() 0 4 1
A iSaveMyChanges() 0 4 1
A iChangeItsPriceTo() 0 4 1
A iRemoveItsNameFromTranslation() 0 4 1
A thisVariantShouldHaveItemsOnHand() 0 7 1
A theVariantOfProductShouldHaveItemsOnHand() 0 9 1
A thisProductVariantShouldNotBeTracked() 0 9 1
A thisProductVariantShouldBeTracked() 0 9 1
A iShouldSeeThatIsNotTracked() 0 7 1
A iShouldSeeThatTheVariantHasZeroOnHandQuantity() 0 7 1
A unitsOfThisProductShouldBeOnHold() 0 7 1
A unitsOfThisProductShouldBeOnHand() 0 17 1
A thereShouldBeNoUnitsOfThisProductOnHold() 0 7 1
A thisVariantShouldHaveItemsOnHold() 0 4 1
A theVariantOfProductShouldHaveItemsOnHold() 0 6 1
A iSetItsOptionAs() 0 4 1
A assertValidationMessage() 0 7 1
A assertOnHoldQuantityOfVariant() 0 15 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\IndexPageInterface;
18
use Sylius\Behat\Page\Admin\ProductVariant\UpdatePageInterface;
19
use Sylius\Behat\Service\NotificationCheckerInterface;
20
use Sylius\Behat\Service\Resolver\CurrentPageResolverInterface;
21
use Sylius\Component\Core\Model\ProductInterface;
22
use Sylius\Component\Core\Model\ProductVariantInterface;
23
use Sylius\Behat\Service\SharedStorageInterface;
24
use Sylius\Component\Product\Resolver\DefaultProductVariantResolver;
25
use Webmozart\Assert\Assert;
26
27
/**
28
 * @author Łukasz Chruściel <[email protected]>
29
 */
30
final class ManagingProductVariantsContext implements Context
31
{
32
    /**
33
     * @var SharedStorageInterface
34
     */
35
    private $sharedStorage;
36
37
    /**
38
     * @var DefaultProductVariantResolver
39
     */
40
    private $defaultProductVariantResolver;
41
42
    /**
43
     * @var CreatePageInterface
44
     */
45
    private $createPage;
46
47
    /**
48
     * @var IndexPageInterface
49
     */
50
    private $indexPage;
51
52
    /**
53
     * @var UpdatePageInterface
54
     */
55
    private $updatePage;
56
57
    /**
58
     * @var CurrentPageResolverInterface
59
     */
60
    private $currentPageResolver;
61
62
    /**
63
     * @var NotificationCheckerInterface
64
     */
65
    private $notificationChecker;
66
67
    /**
68
     * @param SharedStorageInterface $sharedStorage
69
     * @param DefaultProductVariantResolver $defaultProductVariantResolver
70
     * @param CreatePageInterface $createPage
71
     * @param IndexPageInterface $indexPage
72
     * @param UpdatePageInterface $updatePage
73
     * @param CurrentPageResolverInterface $currentPageResolver
74
     * @param NotificationCheckerInterface $notificationChecker
75
     */
76
    public function __construct(
77
        SharedStorageInterface $sharedStorage,
78
        DefaultProductVariantResolver $defaultProductVariantResolver,
0 ignored issues
show
Comprehensibility Naming introduced by
The variable name $defaultProductVariantResolver exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
79
        CreatePageInterface $createPage,
80
        IndexPageInterface $indexPage,
81
        UpdatePageInterface $updatePage,
82
        CurrentPageResolverInterface $currentPageResolver,
83
        NotificationCheckerInterface $notificationChecker
84
    ) {
85
        $this->sharedStorage = $sharedStorage;
86
        $this->defaultProductVariantResolver = $defaultProductVariantResolver;
87
        $this->createPage = $createPage;
88
        $this->indexPage = $indexPage;
89
        $this->updatePage = $updatePage;
90
        $this->currentPageResolver = $currentPageResolver;
91
        $this->notificationChecker = $notificationChecker;
92
    }
93
94
    /**
95
     * @Given /^I want to create a new variant of (this product)$/
96
     */
97
    public function iWantToCreateANewProduct(ProductInterface $product)
98
    {
99
        $this->createPage->open(['productId' => $product->getId()]);
100
    }
101
102
    /**
103
     * @When I specify its code as :code
104
     * @When I do not specify its code
105
     */
106
    public function iSpecifyItsCodeAs($code = null)
107
    {
108
        $this->createPage->specifyCode($code);
109
    }
110
111
    /**
112
     * @When I name it :name
113
     */
114
    public function iNameItIn($name)
115
    {
116
        $this->createPage->nameIt($name);
117
    }
118
119
    /**
120
     * @When I rename it to :name
121
     */
122
    public function iRenameItTo($name)
123
    {
124
        $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...
125
    }
126
127
    /**
128
     * @When I add it
129
     * @When I try to add it
130
     */
131
    public function iAddIt()
132
    {
133
        $this->createPage->create();
134
    }
135
136
    /**
137
     * @When I disable its inventory tracking
138
     */
139
    public function iDisableItsTracking()
140
    {
141
        $this->updatePage->disableTracking();
142
    }
143
144
    /**
145
     * @When I enable its inventory tracking
146
     */
147
    public function iEnableItsTracking()
148
    {
149
        $this->updatePage->enableTracking();
150
    }
151
152
    /**
153
     * @When /^I set its price to ("(?:€|£|\$)[^"]+")$/
154
     */
155
    public function iSetItsPriceTo($price)
156
    {
157
        $this->createPage->specifyPrice($price);
158
    }
159
160
    /**
161
     * @Then the :productVariantCode variant of the :product product should appear in the shop
162
     */
163
    public function theProductVariantShouldAppearInTheShop($productVariantCode, ProductInterface $product)
164
    {
165
        $this->iWantToViewAllVariantsOfThisProduct($product);
166
167
        Assert::true(
168
            $this->indexPage->isSingleResourceOnPage(['code' => $productVariantCode]),
169
            sprintf('The product variant with code %s has not been found.', $productVariantCode)
170
        );
171
    }
172
173
    /**
174
     * @When /^I (?:|want to )view all variants of (this product)$/
175
     * @When /^I view(?:| all) variants of the (product "[^"]+")$/
176
     */
177
    public function iWantToViewAllVariantsOfThisProduct(ProductInterface $product)
178
    {
179
        $this->indexPage->open(['productId' => $product->getId()]);
180
    }
181
182
    /**
183
     * @Then I should see :numberOfProductVariants variants in the list
184
     * @Then I should see :numberOfProductVariants variant in the list
185
     */
186
    public function iShouldSeeProductsInTheList($numberOfProductVariants)
0 ignored issues
show
Comprehensibility Naming introduced by
The variable name $numberOfProductVariants exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
187
    {
188
        $foundRows = $this->indexPage->countItems();
189
190
        Assert::same(
191
            (int) $numberOfProductVariants,
192
            $foundRows,
193
            '%s rows with product variants should appear on page, %s rows has been found'
194
        );
195
    }
196
197
    /**
198
     * @When /^I delete the ("[^"]+" variant of product "[^"]+")$/
199
     * @When /^I try to delete the ("[^"]+" variant of product "[^"]+")$/
200
     */
201
    public function iDeleteTheVariantOfProduct(ProductVariantInterface $productVariant)
202
    {
203
        $this->iWantToViewAllVariantsOfThisProduct($productVariant->getProduct());
0 ignored issues
show
Compatibility introduced by
$productVariant->getProduct() of type object<Sylius\Component\...Model\ProductInterface> is not a sub-type of object<Sylius\Component\...Model\ProductInterface>. It seems like you assume a child interface of the interface Sylius\Component\Product\Model\ProductInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
204
205
        $this->indexPage->deleteResourceOnPage(['code' => $productVariant->getCode()]);
206
    }
207
208
    /**
209
     * @Then /^(this variant) should not exist in the product catalog$/
210
     */
211
    public function productVariantShouldNotExist(ProductVariantInterface $productVariant)
212
    {
213
        $this->iWantToViewAllVariantsOfThisProduct($productVariant->getProduct());
0 ignored issues
show
Compatibility introduced by
$productVariant->getProduct() of type object<Sylius\Component\...Model\ProductInterface> is not a sub-type of object<Sylius\Component\...Model\ProductInterface>. It seems like you assume a child interface of the interface Sylius\Component\Product\Model\ProductInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
214
215
        Assert::false(
216
            $this->indexPage->isSingleResourceOnPage(['name' => $productVariant->getName()]),
217
            sprintf('Product variant with code %s exists but should not.', $productVariant->getName())
218
        );
219
    }
220
221
    /**
222
     * @Then I should be notified that this variant is in use and cannot be deleted
223
     */
224
    public function iShouldBeNotifiedOfFailure()
225
    {
226
        $this->notificationChecker->checkNotification(
227
            "Cannot delete, the product variant is in use.",
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal Cannot delete, the product variant is in use. does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
228
            NotificationType::failure()
229
        );
230
    }
231
232
    /**
233
     * @Then /^(this variant) should still exist in the product catalog$/
234
     */
235
    public function productShouldExistInTheProductCatalog(ProductVariantInterface $productVariant)
236
    {
237
        $this->theProductVariantShouldAppearInTheShop($productVariant->getCode(), $productVariant->getProduct());
0 ignored issues
show
Compatibility introduced by
$productVariant->getProduct() of type object<Sylius\Component\...Model\ProductInterface> is not a sub-type of object<Sylius\Component\...Model\ProductInterface>. It seems like you assume a child interface of the interface Sylius\Component\Product\Model\ProductInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
238
    }
239
240
    /**
241
     * @When /^I want to modify the ("[^"]+" product variant)$/
242
     * @When /^I want to modify (this product variant)$/
243
     */
244
    public function iWantToModifyAProduct(ProductVariantInterface $productVariant)
245
    {
246
        $this->updatePage->open(['id' => $productVariant->getId(), 'productId' => $productVariant->getProduct()->getId()]);
247
    }
248
249
    /**
250
     * @Then the code field should be disabled
251
     */
252
    public function theCodeFieldShouldBeDisabled()
253
    {
254
        Assert::true(
255
            $this->updatePage->isCodeDisabled(),
256
            'Code should be immutable, but it does not.'
257
        );
258
    }
259
260
    /**
261
     * @Then I should be notified that price is required
262
     */
263
    public function iShouldBeNotifiedThatPriceIsRequired()
264
    {
265
        $this->assertValidationMessage('price', 'Please enter the price.');
266
    }
267
268
    /**
269
     * @When I save my changes
270
     * @When I try to save my changes
271
     */
272
    public function iSaveMyChanges()
273
    {
274
        $this->updatePage->saveChanges();
275
    }
276
277
    /**
278
     * @When /^I change its price to "(?:€|£|\$)([^"]+)"$/
279
     */
280
    public function iChangeItsPriceTo($price)
281
    {
282
        $this->updatePage->specifyPrice($price);
283
    }
284
285
    /**
286
     * @When I remove its name
287
     */
288
    public function iRemoveItsNameFromTranslation()
289
    {
290
        $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...
291
    }
292
293
    /**
294
     * @Then /^the variant "([^"]+)" should have (\d+) items on hand$/
295
     */
296
    public function thisVariantShouldHaveItemsOnHand($productVariantName, $quantity)
297
    {
298
        Assert::true(
299
            $this->indexPage->isSingleResourceWithSpecificElementOnPage(['name' => $productVariantName], sprintf('td > div.ui.label:contains("%s")', $quantity)),
300
            sprintf('The product variant %s should have %s items on hand, but it does not.',$productVariantName, $quantity)
301
        );
302
    }
303
304
    /**
305
     * @Then /^the "([^"]+)" variant of ("[^"]+" product) should have (\d+) items on hand$/
306
     */
307
    public function theVariantOfProductShouldHaveItemsOnHand($productVariantName, ProductInterface $product, $quantity)
308
    {
309
        $this->indexPage->open(['productId' => $product->getId()]);
310
311
        Assert::true(
312
            $this->indexPage->isSingleResourceWithSpecificElementOnPage(['name' => $productVariantName], sprintf('td > div.ui.label:contains("%s")', $quantity)),
313
            sprintf('The product variant %s should have %s items on hand, but it does not.',$productVariantName, $quantity)
314
        );
315
    }
316
317
    /**
318
     * @Then /^inventory of (this variant) should not be tracked$/
319
     */
320
    public function thisProductVariantShouldNotBeTracked(ProductVariantInterface $productVariant)
321
    {
322
        $this->iWantToModifyAProduct($productVariant);
323
324
        Assert::false(
325
            $this->updatePage->isTracked(),
326
            'This variant should not be tracked, but it is.'
327
        );
328
    }
329
330
    /**
331
     * @Then /^inventory of (this variant) should be tracked$/
332
     */
333
    public function thisProductVariantShouldBeTracked(ProductVariantInterface $productVariant)
334
    {
335
        $this->iWantToModifyAProduct($productVariant);
336
337
        Assert::true(
338
            $this->updatePage->isTracked(),
339
            'This variant should be tracked, but it is not.'
340
        );
341
    }
342
343
    /**
344
     * @Then /^I should see that the ("([^"]+)" variant) is not tracked$/
345
     */
346
    public function iShouldSeeThatIsNotTracked(ProductVariantInterface $productVariant)
347
    {
348
        Assert::true(
349
            $this->indexPage->isSingleResourceOnPage(['name' => $productVariant->getName(), 'inventory' => 'Not tracked']),
350
            sprintf('This "%s" variant should have label not tracked, but it does not have', $productVariant->getName())
351
        );
352
    }
353
354
    /**
355
     * @Then /^I should see that the ("[^"]+" variant) has zero on hand quantity$/
356
     */
357
    public function iShouldSeeThatTheVariantHasZeroOnHandQuantity(ProductVariantInterface $productVariant)
358
    {
359
        Assert::true(
360
            $this->indexPage->isSingleResourceOnPage(['name' => $productVariant->getName(), 'inventory' => '0 Available on hand']),
361
            sprintf('This "%s" variant should have 0 on hand quantity, but it does not.', $productVariant->getName())
362
        );
363
    }
364
365
    /**
366
     * @Then /^(\d+) units of (this product) should be on hold$/
367
     */
368
    public function unitsOfThisProductShouldBeOnHold($quantity, ProductInterface $product)
369
    {
370
        /** @var ProductVariantInterface $variant */
371
        $variant = $this->defaultProductVariantResolver->getVariant($product);
372
373
        $this->assertOnHoldQuantityOfVariant($quantity, $variant);
374
    }
375
376
    /**
377
     * @Then /^(\d+) units of (this product) should be on hand$/
378
     */
379
    public function unitsOfThisProductShouldBeOnHand($quantity, ProductInterface $product)
380
    {
381
        /** @var ProductVariantInterface $variant */
382
        $variant = $this->defaultProductVariantResolver->getVariant($product);
383
        $actualQuantity = $this->indexPage->getOnHandQuantityFor($variant);
384
385
        Assert::same(
386
            (int) $quantity,
387
            $actualQuantity,
388
            sprintf(
389
                'Unexpected on hand quantity for "%s" variant. It should be "%s" but is "%s"',
390
                $variant->getName(),
391
                $quantity,
392
                $actualQuantity
393
            )
394
        );
395
    }
396
397
    /**
398
     * @Then /^there should be no units of (this product) on hold$/
399
     */
400
    public function thereShouldBeNoUnitsOfThisProductOnHold(ProductInterface $product)
401
    {
402
        /** @var ProductVariantInterface $variant */
403
        $variant = $this->defaultProductVariantResolver->getVariant($product);
404
405
        $this->assertOnHoldQuantityOfVariant(0, $variant);
406
    }
407
408
    /**
409
     * @Then the :variant variant should have :amount items on hold
410
     * @Then /^(this variant) should have (\d+) items on hold$/
411
     */
412
    public function thisVariantShouldHaveItemsOnHold(ProductVariantInterface $variant, $amount)
413
    {
414
        $this->assertOnHoldQuantityOfVariant((int) $amount, $variant);
415
    }
416
417
    /**
418
     * @Then the :variant variant of :product product should have :amount items on hold
419
     */
420
    public function theVariantOfProductShouldHaveItemsOnHold(ProductVariantInterface $variant, ProductInterface $product, $amount)
421
    {
422
        $this->indexPage->open(['productId' => $product->getId()]);
423
424
        $this->assertOnHoldQuantityOfVariant((int) $amount, $variant);
425
    }
426
427
    /**
428
     * @When I set its :optionName option to :optionValue
429
     */
430
    public function iSetItsOptionAs($optionName, $optionValue)
431
    {
432
        $this->createPage->selectOption($optionName, $optionValue);
433
    }
434
435
    /**
436
     * @param string $element
437
     * @param $message
438
     */
439
    private function assertValidationMessage($element, $message)
440
    {
441
        /** @var CreatePageInterface|UpdatePageInterface $currentPage */
442
        $currentPage = $this->currentPageResolver->getCurrentPageWithForm([$this->createPage, $this->updatePage]);
443
444
        Assert::same($currentPage->getValidationMessage($element), $message);
445
    }
446
447
    /**
448
     * @param int $expectedAmount
449
     * @param ProductVariantInterface $variant
450
     *
451
     * @throws \InvalidArgumentException
452
     */
453
    private function assertOnHoldQuantityOfVariant($expectedAmount, $variant)
454
    {
455
        $actualAmount = $this->indexPage->getOnHoldQuantityFor($variant);
456
457
        Assert::same(
458
            (int) $expectedAmount,
459
            $actualAmount,
460
            sprintf(
461
                'Unexpected on hold quantity for "%s" variant. It should be "%s" but is "%s"',
462
                $variant->getName(),
463
                $expectedAmount,
464
                $actualAmount
465
            )
466
        );
467
    }
468
}
469