Completed
Push — travis-xenial ( 84a270...92e80e )
by Kamil
26:32 queued 04:30
created

ShowPage::getCurrentVariantName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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