Completed
Push — security-checker-symfony-cli ( 5cc469 )
by Kamil
18:08
created

ShowPage::waitForValidationErrors()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Sylius\Behat\Page\Shop\Product;
15
16
use Behat\Mink\Driver\Selenium2Driver;
17
use Behat\Mink\Exception\ElementNotFoundException;
18
use FriendsOfBehat\PageObjectExtension\Page\SymfonyPage;
19
use FriendsOfBehat\PageObjectExtension\Page\UnexpectedPageException;
20
use Sylius\Behat\Service\JQueryHelper;
21
use Sylius\Component\Product\Model\ProductInterface;
22
use Sylius\Component\Product\Model\ProductOptionInterface;
23
use Webmozart\Assert\Assert;
24
25
class ShowPage extends SymfonyPage implements ShowPageInterface
26
{
27
    public function getRouteName(): string
28
    {
29
        return 'sylius_shop_product_show';
30
    }
31
32
    public function addToCart(): void
33
    {
34
        $this->getDocument()->pressButton('Add to cart');
35
36
        if ($this->getDriver() instanceof Selenium2Driver) {
37
            JQueryHelper::waitForAsynchronousActionsToFinish($this->getSession());
38
        }
39
    }
40
41
    public function addToCartWithQuantity(string $quantity): void
42
    {
43
        $this->getDocument()->fillField('Quantity', $quantity);
44
        $this->getDocument()->pressButton('Add to cart');
45
46
        if ($this->getDriver() instanceof Selenium2Driver) {
47
            JQueryHelper::waitForAsynchronousActionsToFinish($this->getSession());
48
        }
49
    }
50
51
    public function addToCartWithVariant(string $variant): void
52
    {
53
        $this->selectVariant($variant);
54
55
        $this->getDocument()->pressButton('Add to cart');
56
57
        if ($this->getDriver() instanceof Selenium2Driver) {
58
            JQueryHelper::waitForAsynchronousActionsToFinish($this->getSession());
59
        }
60
    }
61
62
    public function addToCartWithOption(ProductOptionInterface $option, string $optionValue): void
63
    {
64
        $select = $this->getDocument()->find('css', sprintf('select#sylius_add_to_cart_cartItem_variant_%s', $option->getCode()));
65
66
        $this->getDocument()->selectFieldOption($select->getAttribute('name'), $optionValue);
67
        $this->getDocument()->pressButton('Add to cart');
68
    }
69
70
    public function getAttributeByName(string $name): ?string
71
    {
72
        $attributesTable = $this->getElement('attributes');
73
74
        $driver = $this->getDriver();
75
        if ($driver instanceof Selenium2Driver) {
76
            try {
77
                $attributesTab = $this->getElement('tab', ['%name%' => 'attributes']);
78
                if (!$attributesTab->hasClass('active')) {
79
                    $attributesTab->click();
80
                }
81
            } catch (ElementNotFoundException $exception) {
82
                return null;
83
            }
84
        }
85
86
        $nameTdSelector = sprintf('tr > td.sylius-product-attribute-name:contains("%s")', $name);
87
        $nameTd = $attributesTable->find('css', $nameTdSelector);
88
89
        if (null === $nameTd) {
90
            return null;
91
        }
92
93
        $row = $nameTd->getParent();
94
95
        return trim($row->find('css', 'td.sylius-product-attribute-value')->getText());
96
    }
97
98
    public function getAttributes(): array
99
    {
100
        $attributesTable = $this->getElement('attributes');
101
102
        return $attributesTable->findAll('css', 'tr > td.sylius-product-attribute-name');
103
    }
104
105
    public function getAverageRating(): float
106
    {
107
        return (float) $this->getElement('average_rating')->getAttribute('data-average-rating');
108
    }
109
110
    public function getCurrentUrl(): string
111
    {
112
        return $this->getDriver()->getCurrentUrl();
113
    }
114
115
    public function getCurrentVariantName(): string
116
    {
117
        $currentVariantRow = $this->getElement('current_variant_input')->getParent()->getParent();
118
119
        return $currentVariantRow->find('css', 'td:first-child')->getText();
120
    }
121
122
    public function getName(): string
123
    {
124
        return $this->getElement('name')->getText();
125
    }
126
127
    public function getPrice(): string
128
    {
129
        return $this->getElement('product_price')->getText();
130
    }
131
132
    public function hasAddToCartButton(): bool
133
    {
134
        return $this->getDocument()->hasButton('Add to cart')
135
            && false === $this->getDocument()->findButton('Add to cart')->hasAttribute('disabled');
136
    }
137
138
    public function hasAssociation(string $productAssociationName): bool
139
    {
140
        return $this->hasElement('association', ['%association-name%' => $productAssociationName]);
141
    }
142
143
    public function hasProductInAssociation(string $productName, string $productAssociationName): bool
144
    {
145
        $products = $this->getElement('association', ['%association-name%' => $productAssociationName]);
146
147
        Assert::notNull($products);
148
149
        return null !== $products->find('css', sprintf('.sylius-product-name:contains("%s")', $productName));
150
    }
151
152
    public function hasProductOutOfStockValidationMessage(ProductInterface $product): bool
153
    {
154
        $message = sprintf('%s does not have sufficient stock.', $product->getName());
155
156
        if (!$this->hasElement('validation_errors')) {
157
            return false;
158
        }
159
160
        return $this->getElement('validation_errors')->getText() === $message;
161
    }
162
163
    public function hasReviewTitled(string $title): bool
164
    {
165
        return null !== $this->getElement('reviews')->find('css', sprintf('.comment:contains("%s")', $title));
166
    }
167
168
    public function isOutOfStock(): bool
169
    {
170
        return $this->hasElement('out_of_stock');
171
    }
172
173
    public function isMainImageDisplayed(): bool
174
    {
175
        $imageElement = $this->getElement('main_image');
176
177
        if (null === $imageElement) {
178
            return false;
179
        }
180
181
        $imageUrl = $imageElement->getAttribute('src');
182
        $this->getDriver()->visit($imageUrl);
183
        $pageText = $this->getDocument()->getText();
184
        $this->getDriver()->back();
185
186
        return false === stripos($pageText, '404 Not Found');
187
    }
188
189
    public function countReviews(): int
190
    {
191
        return count($this->getElement('reviews')->findAll('css', '.comment'));
192
    }
193
194
    public function selectOption(string $optionName, string $optionValue): void
195
    {
196
        $optionElement = $this->getElement('option_select', ['%option-name%' => strtoupper($optionName)]);
197
        $optionElement->selectOption($optionValue);
198
    }
199
200
    public function selectVariant(string $variantName): void
201
    {
202
        $variantRadio = $this->getElement('variant_radio', ['%variant-name%' => $variantName]);
203
204
        $driver = $this->getDriver();
205
        if ($driver instanceof Selenium2Driver) {
206
            $variantRadio->click();
207
208
            return;
209
        }
210
211
        $this->getDocument()->fillField($variantRadio->getAttribute('name'), $variantRadio->getAttribute('value'));
212
    }
213
214
    public function visit($url): void
215
    {
216
        $absoluteUrl = $this->makePathAbsolute($url);
217
        $this->getDriver()->visit($absoluteUrl);
218
    }
219
220
    public function open(array $urlParameters = []): void
221
    {
222
        $start = microtime(true);
223
        $end = $start + 5;
224
        do {
225
            try {
226
                parent::open($urlParameters);
227
                $isOpen = true;
228
            } catch (UnexpectedPageException $exception) {
229
                $isOpen = false;
230
                sleep(1);
231
            }
232
        } while (!$isOpen && microtime(true) < $end);
233
234
        if (!$isOpen) {
235
            throw new UnexpectedPageException();
236
        }
237
    }
238
239
    protected function getDefinedElements(): array
240
    {
241
        return array_merge(parent::getDefinedElements(), [
242
            'association' => '#sylius-product-association-%association-name%',
243
            'attributes' => '#sylius-product-attributes',
244
            'average_rating' => '#average-rating',
245
            'current_variant_input' => '#sylius-product-variants td input:checked',
246
            'main_image' => '#main-image',
247
            'name' => '#sylius-product-name',
248
            'option_select' => '#sylius_add_to_cart_cartItem_variant_%option-name%',
249
            'out_of_stock' => '#sylius-product-out-of-stock',
250
            'product_price' => '#product-price',
251
            'reviews' => '[data-tab="reviews"] .comments',
252
            'selecting_variants' => '#sylius-product-selecting-variant',
253
            'tab' => '.menu [data-tab="%name%"]',
254
            'validation_errors' => '.sylius-validation-error',
255
            'variant_radio' => '#sylius-product-variants tbody tr:contains("%variant-name%") input',
256
        ]);
257
    }
258
}
259