Completed
Push — master ( b55ca8...f3fba8 )
by Kamil
20:16 queued 07:20
created

ShowPage::getAttributeByName()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 8.439
c 0
b 0
f 0
cc 5
eloc 16
nc 9
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 Sylius\Behat\Page\SymfonyPage;
19
use Sylius\Behat\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
/**
26
 * @author Arkadiusz Krakowiak <[email protected]>
27
 * @author Anna Walasek <[email protected]>
28
 */
29
class ShowPage extends SymfonyPage implements ShowPageInterface
30
{
31
    /**
32
     * {@inheritdoc}
33
     */
34
    public function getRouteName()
35
    {
36
        return 'sylius_shop_product_show';
37
    }
38
39
    /**
40
     * {@inheritdoc}
41
     */
42
    public function addToCart()
43
    {
44
        $this->getDocument()->pressButton('Add to cart');
45
46
        if ($this->getDriver() instanceof Selenium2Driver) {
47
            JQueryHelper::waitForAsynchronousActionsToFinish($this->getSession());
48
        }
49
    }
50
51
    /**
52
     * {@inheritdoc}
53
     */
54
    public function addToCartWithQuantity($quantity)
55
    {
56
        $this->getDocument()->fillField('Quantity', $quantity);
57
        $this->getDocument()->pressButton('Add to cart');
58
59
        if ($this->getDriver() instanceof Selenium2Driver) {
60
            JQueryHelper::waitForAsynchronousActionsToFinish($this->getSession());
61
        }
62
    }
63
64
    /**
65
     * {@inheritdoc}
66
     */
67
    public function addToCartWithVariant($variant)
68
    {
69
        $this->selectVariant($variant);
70
71
        $this->getDocument()->pressButton('Add to cart');
72
73
        if ($this->getDriver() instanceof Selenium2Driver) {
74
            JQueryHelper::waitForAsynchronousActionsToFinish($this->getSession());
75
        }
76
    }
77
78
    /**
79
     * {@inheritdoc}
80
     */
81
    public function addToCartWithOption(ProductOptionInterface $option, $optionValue)
82
    {
83
        $select = $this->getDocument()->find('css', sprintf('select#sylius_add_to_cart_cartItem_variant_%s', $option->getCode()));
84
85
        $this->getDocument()->selectFieldOption($select->getAttribute('name'), $optionValue);
86
        $this->getDocument()->pressButton('Add to cart');
87
    }
88
89
    /**
90
     * {@inheritdoc}
91
     */
92
    public function visit($url)
93
    {
94
        $absoluteUrl = $this->makePathAbsolute($url);
95
        $this->getDriver()->visit($absoluteUrl);
96
    }
97
98
    /**
99
     * {@inheritdoc}
100
     */
101
    public function getName()
102
    {
103
        return $this->getElement('name')->getText();
104
    }
105
106
    /**
107
     * {@inheritdoc}
108
     */
109
    public function getCurrentVariantName()
110
    {
111
        $currentVariantRow = $this->getElement('current_variant_input')->getParent()->getParent();
112
113
        return $currentVariantRow->find('css', 'td:first-child')->getText();
114
    }
115
116
    /**
117
     * {@inheritdoc}
118
     */
119
    public function getAttributeByName(string $name): ?string
120
    {
121
        $attributesTable = $this->getElement('attributes');
122
123
        $driver = $this->getDriver();
124
        if ($driver instanceof Selenium2Driver) {
125
            try {
126
                $attributesTab = $this->getElement('tab', ['%name%' => 'attributes']);
127
                if (!$attributesTab->hasClass('active')) {
128
                    $attributesTab->click();
129
                }
130
            } catch (ElementNotFoundException $exception) {
131
                return null;
132
            }
133
        }
134
135
        $nameTdSelector = sprintf('tr > td.sylius-product-attribute-name:contains("%s")', $name);
136
        $nameTd = $attributesTable->find('css', $nameTdSelector);
137
138
        if (null === $nameTd) {
139
            return null;
140
        }
141
142
        $row = $nameTd->getParent();
143
144
        return trim($row->find('css', 'td.sylius-product-attribute-value')->getText());
145
    }
146
147
    /**
148
     * {@inheritdoc}
149
     */
150
    public function getAttributes()
151
    {
152
        $attributesTable = $this->getElement('attributes');
153
154
        return $attributesTable->findAll('css', 'tr > td.sylius-product-attribute-name');
155
    }
156
157
    /**
158
     * {@inheritdoc}
159
     */
160
    public function hasProductOutOfStockValidationMessage(ProductInterface $product)
161
    {
162
        $message = sprintf('%s does not have sufficient stock.', $product->getName());
163
164
        if (!$this->hasElement('validation_errors')) {
165
            return false;
166
        }
167
168
        return $this->getElement('validation_errors')->getText() === $message;
169
    }
170
171
    /**
172
     * {@inheritdoc}
173
     */
174
    public function waitForValidationErrors($timeout)
175
    {
176
        $errorsContainer = $this->getElement('selecting_variants');
177
178
        $this->getDocument()->waitFor($timeout, function () use ($errorsContainer) {
179
            return false !== $errorsContainer->has('css', '[class ~="sylius-validation-error"]');
180
        });
181
    }
182
183
    /**
184
     * {@inheritdoc}
185
     */
186
    public function getPrice()
187
    {
188
        return $this->getElement('product_price')->getText();
189
    }
190
191
    /**
192
     * {@inheritdoc}
193
     */
194
    public function countReviews()
195
    {
196
        return count($this->getElement('reviews')->findAll('css', '.comment'));
197
    }
198
199
    /**
200
     * {@inheritdoc}
201
     */
202
    public function hasReviewTitled($title)
203
    {
204
        return null !== $this->getElement('reviews')->find('css', sprintf('.comment:contains("%s")', $title));
205
    }
206
207
    /**
208
     * {@inheritdoc}
209
     */
210
    public function getAverageRating()
211
    {
212
        return (float) $this->getElement('average_rating')->getAttribute('data-average-rating');
213
    }
214
215
    /**
216
     * {@inheritdoc}
217
     */
218
    public function selectOption($optionName, $optionValue)
219
    {
220
        $optionElement = $this->getElement('option_select', ['%option-name%' => strtoupper($optionName)]);
221
        $optionElement->selectOption($optionValue);
222
    }
223
224
    /**
225
     * {@inheritdoc}
226
     */
227
    public function selectVariant($variantName)
228
    {
229
        $variantRadio = $this->getElement('variant_radio', ['%variant-name%' => $variantName]);
230
231
        $driver = $this->getDriver();
232
        if ($driver instanceof Selenium2Driver) {
233
            $variantRadio->click();
234
235
            return;
236
        }
237
238
        $this->getDocument()->fillField($variantRadio->getAttribute('name'), $variantRadio->getAttribute('value'));
239
    }
240
241
    /**
242
     * {@inheritdoc}
243
     */
244
    public function isOutOfStock()
245
    {
246
        return $this->hasElement('out_of_stock');
247
    }
248
249
    /**
250
     * {@inheritdoc}
251
     */
252
    public function hasAddToCartButton()
253
    {
254
        return $this->getDocument()->hasButton('Add to cart')
255
            && false === $this->getDocument()->findButton('Add to cart')->hasAttribute('disabled');
256
    }
257
258
    /**
259
     * {@inheritdoc}
260
     */
261
    public function isMainImageDisplayed()
262
    {
263
        $imageElement = $this->getElement('main_image');
264
265
        if (null === $imageElement) {
266
            return false;
267
        }
268
269
        $imageUrl = $imageElement->getAttribute('src');
270
        $this->getDriver()->visit($imageUrl);
271
        $pageText = $this->getDocument()->getText();
272
        $this->getDriver()->back();
273
274
        return false === stripos($pageText, '404 Not Found');
275
    }
276
277
    /**
278
     * {@inheritdoc}
279
     */
280
    public function hasAssociation($productAssociationName)
281
    {
282
        return $this->hasElement('association', ['%association-name%' => $productAssociationName]);
283
    }
284
285
    /**
286
     * {@inheritdoc}
287
     */
288
    public function hasProductInAssociation($productName, $productAssociationName)
289
    {
290
        $products = $this->getElement('association', ['%association-name%' => $productAssociationName]);
291
292
        Assert::notNull($products);
293
294
        return null !== $products->find('css', sprintf('.sylius-product-name:contains("%s")', $productName));
295
    }
296
297
    /**
298
     * {@inheritdoc}
299
     */
300
    public function open(array $urlParameters = [])
301
    {
302
        $start = microtime(true);
303
        $end = $start + 5;
304
        do {
305
            try {
306
                parent::open($urlParameters);
307
                $isOpen = true;
308
            } catch (UnexpectedPageException $exception) {
309
                $isOpen = false;
310
                sleep(1);
311
            }
312
        } while (!$isOpen && microtime(true) < $end);
313
314
        if (!$isOpen) {
315
            throw new UnexpectedPageException();
316
        }
317
    }
318
319
    /**
320
     * {@inheritdoc}
321
     */
322
    protected function getDefinedElements()
323
    {
324
        return array_merge(parent::getDefinedElements(), [
325
            'association' => '#sylius-product-association-%association-name%',
326
            'attributes' => '#sylius-product-attributes',
327
            'average_rating' => '#average-rating',
328
            'current_variant_input' => '#sylius-product-variants td input:checked',
329
            'main_image' => '#main-image',
330
            'name' => '#sylius-product-name',
331
            'option_select' => '#sylius_add_to_cart_cartItem_variant_%option-name%',
332
            'out_of_stock' => '#sylius-product-out-of-stock',
333
            'product_price' => '#product-price',
334
            'reviews' => '[data-tab="reviews"] .comments',
335
            'selecting_variants' => '#sylius-product-selecting-variant',
336
            'tab' => '.menu [data-tab="%name%"]',
337
            'validation_errors' => '.sylius-validation-error',
338
            'variant_radio' => '#sylius-product-variants tbody tr:contains("%variant-name%") input',
339
        ]);
340
    }
341
}
342