Completed
Push — symfony3-fqcn ( fc44dc...d46cdc )
by Kamil
34:08 queued 14:53
created

ProductContext::theFirstAttributeShouldBe()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 7
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\Shop;
13
14
use Behat\Behat\Context\Context;
15
use Behat\Mink\Element\NodeElement;
16
use Sylius\Behat\Page\Shop\Product\ShowPageInterface;
17
use Sylius\Behat\Page\Shop\ProductReview\IndexPageInterface;
18
use Sylius\Behat\Page\Shop\Taxon\ShowPageInterface as TaxonShowPageInterface;
19
use Sylius\Component\Core\Model\ProductInterface;
20
use Sylius\Component\Core\Model\TaxonInterface;
21
use Webmozart\Assert\Assert;
22
23
/**
24
 * @author Kamil Kokot <[email protected]>
25
 * @author Magdalena Banasiak <[email protected]>
26
 * @author Anna Walasek <[email protected]>
27
 */
28
final class ProductContext implements Context
29
{
30
    /**
31
     * @var ShowPageInterface
32
     */
33
    private $showPage;
34
35
    /**
36
     * @var TaxonShowPageInterface
37
     */
38
    private $taxonShowPage;
39
40
    /**
41
     * @var IndexPageInterface
42
     */
43
    private $productReviewsIndexPage;
44
45
    /**
46
     * @param ShowPageInterface $showPage
47
     * @param TaxonShowPageInterface $taxonShowPage
48
     * @param IndexPageInterface $productReviewsIndexPage
49
     */
50
    public function __construct(
51
        ShowPageInterface $showPage,
52
        TaxonShowPageInterface $taxonShowPage,
53
        IndexPageInterface $productReviewsIndexPage
54
    ) {
55
        $this->showPage = $showPage;
56
        $this->taxonShowPage = $taxonShowPage;
57
        $this->productReviewsIndexPage = $productReviewsIndexPage;
58
    }
59
60
    /**
61
     * @Then I should be able to access product :product
62
     */
63
    public function iShouldBeAbleToAccessProduct(ProductInterface $product)
64
    {
65
        $this->showPage->tryToOpen(['slug' => $product->getSlug()]);
66
67
        Assert::true(
68
            $this->showPage->isOpen(['slug' => $product->getSlug()]),
69
            'Product show page should be open, but it does not.'
70
        );
71
    }
72
73
    /**
74
     * @Then I should not be able to access product :product
75
     */
76
    public function iShouldNotBeAbleToAccessProduct(ProductInterface $product)
77
    {
78
        $this->showPage->tryToOpen(['slug' => $product->getSlug()]);
79
80
        Assert::false(
81
            $this->showPage->isOpen(['slug' => $product->getSlug()]),
82
            'Product show page should not be open, but it does.'
83
        );
84
    }
85
86
    /**
87
     * @When /^I check (this product)'s details/
88
     * @When I view product :product
89
     */
90
    public function iOpenProductPage(ProductInterface $product)
91
    {
92
        $this->showPage->open(['slug' => $product->getSlug()]);
93
    }
94
95
    /**
96
     * @Given I should see the product name :name
97
     */
98
    public function iShouldSeeProductName($name)
99
    {
100
        Assert::same(
101
            $name,
102
            $this->showPage->getName(),
103
            'Product should have name %2$s, but it has %s'
104
        );
105
    }
106
107
    /**
108
     * @When I open page :url
109
     */
110
    public function iOpenPage($url)
111
    {
112
        $this->showPage->visit($url);
113
    }
114
115
    /**
116
     * @Then I should be on :product product detailed page
117
     * @Then I should still be on product :product page
118
     */
119
    public function iShouldBeOnProductDetailedPage(ProductInterface $product)
120
    {
121
        Assert::true(
122
            $this->showPage->isOpen(['slug' => $product->getSlug()]),
123
            sprintf('Product %s show page should be open, but it does not.', $product->getName())
124
        );
125
    }
126
127
    /**
128
     * @Then I should see the product attribute :attributeName with value :expectedAttribute
129
     */
130
    public function iShouldSeeTheProductAttributeWithValue($attributeName, $expectedAttribute)
131
    {
132
        $certainAttribute = $this->showPage->getAttributeByName($attributeName);
133
        Assert::same(
134
            $certainAttribute,
135
            $expectedAttribute,
136
            sprintf(
137
                'Product should have attribute %s with value %s, but has %s.',
138
                $attributeName,
139
                $expectedAttribute,
140
                $certainAttribute
141
            )
142
        );
143
    }
144
145
    /**
146
     * @Then I should see :count attributes
147
     */
148
    public function iShouldSeeAttributes($count)
149
    {
150
        $attributes = $this->getProductAttributes();
151
152
        Assert::same(
153
            count($attributes),
154
            (int) $count,
155
            'Product should have %2$d attributes, but has %d instead.'
156
        );
157
    }
158
159
    /**
160
     * @Then the first attribute should be :name
161
     */
162
    public function theFirstAttributeShouldBe($name)
163
    {
164
        $attributes = $this->getProductAttributes();
165
        $firstAttribute = reset($attributes);
166
167
        Assert::same(
168
            $firstAttribute->getText(),
169
            $name,
170
            'Expected the first attribute to be %2$s, found %s instead.'
171
        );
172
    }
173
174
    /**
175
     * @Then the last attribute should be :name
176
     */
177
    public function theLastAttributeShouldBe($name)
178
    {
179
        $attributes = $this->getProductAttributes();
180
        $lastAttribute = end($attributes);
181
182
        Assert::same(
183
            $lastAttribute->getText(),
184
            $name,
185
            'Expected the first attribute to be %2$s, found %s instead.'
186
        );
187
    }
188
189
    /**
190
     * @When /^I browse products from (taxon "([^"]+)")$/
191
     */
192
    public function iCheckListOfProductsForTaxon(TaxonInterface $taxon)
193
    {
194
        $this->taxonShowPage->open(['slug' => $taxon->getSlug()]);
195
    }
196
197
    /**
198
     * @When I search for products with name :name
199
     */
200
    public function iSearchForProductsWithName($name)
201
    {
202
        $this->taxonShowPage->search($name);
203
    }
204
205
    /**
206
     * @When I clear filter
207
     */
208
    public function iClearFilter()
209
    {
210
        $this->taxonShowPage->clearFilter();
211
    }
212
213
    /**
214
     * @Then I should see the product :productName
215
     */
216
    public function iShouldSeeProduct($productName)
217
    {
218
        Assert::true(
219
            $this->taxonShowPage->isProductOnList($productName),
220
            sprintf("The product %s should appear on page, but it does not.", $productName)
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal The product %s should ap... page, but it does not. 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...
221
        );
222
    }
223
224
    /**
225
     * @Then I should not see the product :productName
226
     */
227
    public function iShouldNotSeeProduct($productName)
228
    {
229
        Assert::false(
230
            $this->taxonShowPage->isProductOnList($productName),
231
            sprintf("The product %s should not appear on page, but it does.", $productName)
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal The product %s should no...r on page, but it does. 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...
232
        );
233
    }
234
235
    /**
236
     * @Then I should see empty list of products
237
     */
238
    public function iShouldSeeEmptyListOfProducts()
239
    {
240
        Assert::true(
241
            $this->taxonShowPage->isEmpty(),
242
            'There should appear information about empty list of products, but it does not.'
243
        );
244
    }
245
246
    /**
247
     * @Then I should see that it is out of stock
248
     */
249
    public function iShouldSeeItIsOutOfStock()
250
    {
251
        Assert::true(
252
            $this->showPage->isOutOfStock(),
253
            'Out of stock label should be visible.'
254
        );
255
    }
256
257
    /**
258
     * @Then I should be unable to add it to the cart
259
     */
260
    public function iShouldBeUnableToAddItToTheCart()
261
    {
262
        Assert::false(
263
            $this->showPage->hasAddToCartButton(),
264
            'Add to cart button should not be visible.'
265
        );
266
    }
267
268
    /**
269
     * @Then the product price should be :price
270
     * @Then I should see the product price :price
271
     */
272
    public function iShouldSeeTheProductPrice($price)
273
    {
274
        Assert::same(
275
            $price,
276
            $this->showPage->getPrice(),
277
            'Product should have price %2$s, but it has %s'
278
        );
279
    }
280
281
    /**
282
     * @When I set its :optionName to :optionValue
283
     */
284
    public function iSetItsOptionTo($optionName, $optionValue)
285
    {
286
        $this->showPage->selectOption($optionName, $optionValue);
287
    }
288
289
    /**
290
     * @When I select :variantName variant
291
     */
292
    public function iSelectVariant($variantName)
293
    {
294
        $this->showPage->selectVariant($variantName);
295
    }
296
297
    /**
298
     * @Then I should see the product :productName with price :productPrice
299
     */
300
    public function iShouldSeeTheProductWithPrice($productName, $productPrice)
301
    {
302
        Assert::true(
303
            $this->taxonShowPage->isProductWithPriceOnList($productName, $productPrice),
304
            sprintf("The product %s with price %s should appear on page, but it does not.", $productName, $productPrice)
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal The product %s with pric... page, but it does not. 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...
305
        );
306
    }
307
308
    /**
309
     * @Then /^I should be notified that (this product) does not have sufficient stock$/
310
     */
311
    public function iShouldBeNotifiedThatThisProductDoesNotHaveSufficientStock(ProductInterface $product)
312
    {
313
       $this->showPage->waitForValidationErrors(3);
314
315
        Assert::true(
316
            $this->showPage->hasProductOutOfStockValidationMessage($product),
317
            sprintf('I should see validation message for %s product', $product->getName())
318
        );
319
    }
320
321
    /**
322
     * @Then /^I should not be notified that (this product) does not have sufficient stock$/
323
     */
324
    public function iShouldNotBeNotifiedThatThisProductDoesNotHaveSufficientStock(ProductInterface $product)
325
    {
326
        Assert::false(
327
            $this->showPage->hasProductOutOfStockValidationMessage($product),
328
            sprintf('I should see validation message for %s product', $product->getName())
329
        );
330
    }
331
332
    /**
333
     * @Then I should see a main image
334
     */
335
    public function iShouldSeeAMainImage()
336
    {
337
        Assert::true(
338
            $this->showPage->isMainImageDisplayed(),
339
            'The main image should have been displayed.'
340
        );
341
    }
342
343
    /**
344
     * @When /^I view (oldest|newest) products from (taxon "([^"]+)")$/
345
     */
346
    public function iViewSortedProductsFromTaxon($sortDirection, TaxonInterface $taxon)
347
    {
348
        $sorting = ['createdAt' => 'oldest' === $sortDirection ? 'asc' : 'desc'];
349
350
        $this->taxonShowPage->open(['slug' => $taxon->getSlug(), 'sorting' => $sorting]);
351
    }
352
353
    /**
354
     * @Then I should see :numberOfProducts products in the list
355
     */
356
    public function iShouldSeeProductsInTheList($numberOfProducts)
357
    {
358
        $foundRows = $this->taxonShowPage->countProductsItems();
359
360
        Assert::same(
361
            (int) $numberOfProducts,
362
            $foundRows,
363
            '%s rows with products should appear on page, %s rows has been found'
364
        );
365
    }
366
367
    /**
368
     * @Then I should see a product with name :name
369
     */
370
    public function iShouldSeeProductWithName($name)
371
    {
372
        Assert::true(
373
            $this->taxonShowPage->isProductOnPageWithName($name),
374
            sprintf('The product with name "%s" has not been found.', $name)
375
        );
376
    }
377
378
    /**
379
     * @Then the first product on the list should have name :name
380
     */
381
    public function theFirstProductOnTheListShouldHaveName($name)
382
    {
383
        $actualName = $this->taxonShowPage->getFirstProductNameFromList();
384
385
        Assert::same(
386
            $actualName,
387
            $name,
388
            sprintf('Expected first product\'s name to be "%s", but it is "%s".', $name, $actualName)
389
        );
390
    }
391
392
    /**
393
     * @Then I should see :count product reviews
394
     */
395
    public function iShouldSeeProductReviews($count)
396
    {
397
        Assert::same(
398
            (int) $count,
399
            $this->showPage->countReviews(),
400
            'Product has %2$s reviews, but should have %s.'
401
        );
402
    }
403
404
    /**
405
     * @Then I should see reviews titled :firstReview, :secondReview and :thirdReview
406
     */
407
    public function iShouldSeeReviewsTitled(...$reviews)
408
    {
409
        foreach ($reviews as $review) {
410
            Assert::true(
411
                $this->showPage->hasReviewTitled($review),
412
                sprintf('Product should have review titled "%s" but it does not.', $review)
413
            );
414
        }
415
    }
416
417
    /**
418
     * @Then I should not see review titled :title
419
     */
420
    public function iShouldNotSeeReviewTitled($title)
421
    {
422
        Assert::false(
423
            $this->showPage->hasReviewTitled($title),
424
            sprintf('Product should not have review titled "%s" but it does.', $title)
425
        );
426
    }
427
428
    /**
429
     * @When /^I check (this product)'s reviews$/
430
     */
431
    public function iCheckThisProductSReviews(ProductInterface $product)
432
    {
433
        $this->productReviewsIndexPage->open(['slug' => $product->getSlug()]);
434
    }
435
436
    /**
437
     * @Then /^I should see (\d+) product reviews in the list$/
438
     */
439
    public function iShouldSeeNumberOfProductReviewsInTheList($count)
440
    {
441
        Assert::same(
442
            (int) $count,
443
            $this->productReviewsIndexPage->countReviews(),
444
            'Product has %2$s reviews in the list, but should have %s.'
445
        );
446
    }
447
448
    /**
449
     * @Then I should not see review titled :title in the list
450
     */
451
    public function iShouldNotSeeReviewTitledInTheList($title)
452
    {
453
        Assert::false(
454
            $this->productReviewsIndexPage->hasReviewTitled($title),
455
            sprintf('Product should not have review titled "%s" but it does.', $title)
456
        );
457
    }
458
459
    /**
460
     * @Then /^I should be notified that there are no reviews$/
461
     */
462
    public function iShouldBeNotifiedThatThereAreNoReviews()
463
    {
464
        Assert::true(
465
            $this->productReviewsIndexPage->hasNoReviewMessage(),
466
            'There should be message about no reviews but there is not.'
467
        );
468
    }
469
470
    /**
471
     * @Then I should see :rating as its average rating
472
     */
473
    public function iShouldSeeAsItsAverageRating($rating)
474
    {
475
        $averageRating = $this->showPage->getAverageRating();
476
477
        Assert::same(
478
            (float) $rating,
479
            $averageRating,
480
            'Product should have average rating %2$s but has %s.'
481
        );
482
    }
483
484
    /**
485
     * @Then /^I should(?:| also) see the product association "([^"]+)" with (products "[^"]+" and "[^"]+")$/
486
     */
487
    public function iShouldSeeTheProductAssociationWithProducts($productAssociationName, array $products)
488
    {
489
        Assert::true(
490
            $this->showPage->hasAssociation($productAssociationName),
491
            sprintf('There should be an association named "%s" but it does not.', $productAssociationName)
492
        );
493
494
        foreach ($products as $product) {
495
            $this->assertIsProductIsInAssociation($product->getName(), $productAssociationName);
496
        }
497
    }
498
499
    /**
500
     * @Then /^average rating of (product "[^"]+") should be (\d+)$/
501
     */
502
    public function thisProductAverageRatingShouldBe(ProductInterface $product, $averageRating)
503
    {
504
        $this->showPage->tryToOpen(['slug' => $product->getSlug()]);
505
        $this->iShouldSeeAsItsAverageRating($averageRating);
506
    }
507
508
    /**
509
     * @Then they should have order like :firstProductName, :secondProductName and :thirdProductName
510
     */
511
    public function theyShouldHaveOrderLikeAnd(...$productNames)
512
    {
513
        Assert::true(
514
            $this->taxonShowPage->hasProductsInOrder($productNames),
515
            'The products have wrong order.'
516
        );
517
    }
518
519
    /**
520
     * @param string $productName
521
     * @param string $productAssociationName
522
     *
523
     * @throws \InvalidArgumentException
524
     */
525
    private function assertIsProductIsInAssociation($productName, $productAssociationName)
526
    {
527
        Assert::true(
528
            $this->showPage->hasProductInAssociation($productName, $productAssociationName),
529
            sprintf(
530
                'There should be an associated product "%s" under association "%s" but it does not.',
531
                $productName,
532
                $productAssociationName
533
            )
534
        );
535
    }
536
537
    /**
538
     * @return NodeElement[]
539
     *
540
     * @throws \InvalidArgumentException
541
     */
542
    private function getProductAttributes()
543
    {
544
        $attributes = $this->showPage->getAttributes();
545
        Assert::notNull($attributes, 'The product has no attributes.');
546
547
        return $attributes;
548
    }
549
}
550