Completed
Push — master ( 52cd2c...047880 )
by Kamil
47:26 queued 26:32
created

ShowPage::hasAddToCartButton()   A

Complexity

Conditions 3
Paths 3

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 3
nc 3
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\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->getElement('add_to_cart_button')->click();
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->getElement('quantity')->setValue($quantity);
44
        $this->getElement('add_to_cart_button')->click();
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->getElement('add_to_cart_button')->click();
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->getElement('option_select', ['%optionCode%' => $option->getCode()]);
65
66
        $this->getDocument()->selectFieldOption($select->getAttribute('name'), $optionValue);
67
        $this->getElement('add_to_cart_button')->click();
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->hasAttribute('[data-test-active]')) {
79
                    $attributesTab->click();
80
                }
81
            } catch (ElementNotFoundException $exception) {
82
                return null;
83
            }
84
        }
85
86
        $nameTd = $attributesTable->find('css', sprintf('[data-test-product-attribute-name="%s"]', $name));
87
88
        if (null === $nameTd) {
89
            return null;
90
        }
91
92
        $row = $nameTd->getParent();
93
94
        return trim($row->find('css', 'td.sylius-product-attribute-value')->getText());
95
    }
96
97
    public function getAttributes(): array
98
    {
99
        $attributesTable = $this->getElement('attributes');
100
101
        return $attributesTable->findAll('css', 'tr > td[data-test-product-attribute-name]');
102
    }
103
104
    public function getAverageRating(): float
105
    {
106
        return (float) $this->getElement('average_rating')->getAttribute('data-test-average-rating');
107
    }
108
109
    public function getCurrentUrl(): string
110
    {
111
        return $this->getDriver()->getCurrentUrl();
112
    }
113
114
    public function getCurrentVariantName(): string
115
    {
116
        $currentVariantRow = $this->getElement('current_variant_input')->getParent()->getParent();
117
118
        return $currentVariantRow->find('css', 'td:first-child')->getText();
119
    }
120
121
    public function getName(): string
122
    {
123
        return $this->getElement('product_name')->getText();
124
    }
125
126
    public function getPrice(): string
127
    {
128
        return $this->getElement('product_price')->getText();
129
    }
130
131
    public function hasAddToCartButton(): bool
132
    {
133
        if (!$this->hasElement('add_to_cart_button')) {
134
            return false;
135
        }
136
137
        return $this->getElement('add_to_cart_button') !== null && false === $this->getElement('add_to_cart_button')->hasAttribute('disabled');
138
    }
139
140
    public function hasAssociation(string $productAssociationName): bool
141
    {
142
        try{
143
            $this->getElement('association', ['%associationName%' => $productAssociationName]);
144
        } catch (ElementNotFoundException $e) {
145
            return false;
146
        }
147
148
        return true;
149
    }
150
151
    public function hasProductInAssociation(string $productName, string $productAssociationName): bool
152
    {
153
        $products = $this->getElement('association', ['%associationName%' => $productAssociationName]);
154
155
        Assert::notNull($products);
156
157
        return $productName === $products->find('css', sprintf('[data-test-product-name="%s"]', $productName))->getText();
158
    }
159
160
    public function hasProductOutOfStockValidationMessage(ProductInterface $product): bool
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
    public function hasReviewTitled(string $title): bool
172
    {
173
        try{
174
            $element = $this->getElement('reviews_comment', ['%title%' => $title]);
175
        } catch (ElementNotFoundException $e) {
176
            return false;
177
        }
178
179
        return $title === $element->getAttribute('data-test-comment');
180
    }
181
182
    public function isOutOfStock(): bool
183
    {
184
        return $this->hasElement('out_of_stock');
185
    }
186
187
    public function isMainImageDisplayed(): bool
188
    {
189
        if ( !$this->hasElement('main_image')) {
190
            return false;
191
        }
192
193
        $imageUrl = $this->getElement('main_image')->getAttribute('src');
194
        $this->getDriver()->visit($imageUrl);
195
        $pageText = $this->getDocument()->getText();
196
        $this->getDriver()->back();
197
198
        return false === stripos($pageText, '404 Not Found');
199
    }
200
201
    public function countReviews(): int
202
    {
203
        return count($this->getElement('reviews')->findAll('css', '[data-test-comment]'));
204
    }
205
206
    public function selectOption(string $optionCode, string $optionValue): void
207
    {
208
        $optionElement = $this->getElement('option_select', ['%optionCode%' => strtoupper($optionCode)]);
209
        $optionElement->selectOption($optionValue);
210
    }
211
212
    public function selectVariant(string $variantName): void
213
    {
214
        $variantRadio = $this->getElement('variant_radio', ['%variantName%' => $variantName]);
215
216
        $driver = $this->getDriver();
217
        if ($driver instanceof Selenium2Driver) {
218
            $variantRadio->click();
219
220
            return;
221
        }
222
223
        $this->getDocument()->fillField($variantRadio->getAttribute('name'), $variantRadio->getAttribute('value'));
224
    }
225
226
    public function visit($url): void
227
    {
228
        $absoluteUrl = $this->makePathAbsolute($url);
229
        $this->getDriver()->visit($absoluteUrl);
230
    }
231
232
    public function open(array $urlParameters = []): void
233
    {
234
        $start = microtime(true);
235
        $end = $start + 5;
236
        do {
237
            try {
238
                parent::open($urlParameters);
239
                $isOpen = true;
240
            } catch (UnexpectedPageException $exception) {
241
                $isOpen = false;
242
                sleep(1);
243
            }
244
        } while (!$isOpen && microtime(true) < $end);
245
246
        if (!$isOpen) {
247
            throw new UnexpectedPageException();
248
        }
249
    }
250
251
    protected function getDefinedElements(): array
252
    {
253
        return array_merge(parent::getDefinedElements(), [
254
            'add_to_cart_button' => '[data-test-add-to-cart-button]',
255
            'association' => '[data-test-product-association="%associationName%"]',
256
            'attributes' => '[data-test-product-attributes]',
257
            'average_rating' => '[data-test-average-rating]',
258
            'current_variant_input' => '[data-test-product-variants] td input:checked',
259
            'main_image' => '[data-test-main-image]',
260
            'name' => '[data-test-product-name]',
261
            'option_select' => '#sylius_add_to_cart_cartItem_variant_%optionCode%',
262
            'out_of_stock' => '[data-test-product-out-of-stock]',
263
            'product_price' => '[data-test-product-price]',
264
            'product_name' => '[data-test-product-name]',
265
            'reviews' => '[data-test-product-reviews]',
266
            'reviews_comment' => '[data-test-comment="%title%"]',
267
            'selecting_variants' => '[data-test-product-selecting-variant]',
268
            'tab' => '[data-test-tab="%name%"]',
269
            'quantity' => '[data-test-quantity]',
270
            'validation_errors' => '[data-test-cart-validation-error]',
271
            'variant_radio' => '[data-test-product-variants] tbody tr:contains("%variantName%") input',
272
        ]);
273
    }
274
}
275