Completed
Push — master ( 047880...b09c02 )
by Kamil
92:08 queued 74:48
created

AddressPage::chooseDifferentShippingAddress()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.7
c 0
b 0
f 0
cc 2
nc 2
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\Checkout;
15
16
use Behat\Mink\Driver\Selenium2Driver;
17
use Behat\Mink\Element\NodeElement;
18
use Behat\Mink\Exception\ElementNotFoundException;
19
use Behat\Mink\Session;
20
use FriendsOfBehat\PageObjectExtension\Page\SymfonyPage;
21
use Sylius\Behat\Service\JQueryHelper;
22
use Sylius\Component\Core\Factory\AddressFactoryInterface;
23
use Sylius\Component\Core\Model\AddressInterface;
24
use Symfony\Component\Routing\RouterInterface;
25
use Webmozart\Assert\Assert;
26
27
class AddressPage extends SymfonyPage implements AddressPageInterface
28
{
29
    public const TYPE_BILLING = 'billing';
30
31
    public const TYPE_SHIPPING = 'shipping';
32
33
    /** @var AddressFactoryInterface */
34
    private $addressFactory;
35
36
    public function __construct(
37
        Session $session,
38
        $minkParameters,
39
        RouterInterface $router,
40
        AddressFactoryInterface $addressFactory
41
    ) {
42
        parent::__construct($session, $minkParameters, $router);
43
44
        $this->addressFactory = $addressFactory;
45
    }
46
47
    public function getRouteName(): string
48
    {
49
        return 'sylius_shop_checkout_address';
50
    }
51
52
    public function chooseDifferentShippingAddress(): void
53
    {
54
        $driver = $this->getDriver();
55
        if ($driver instanceof Selenium2Driver) {
56
            $this->getElement('different_shipping_address_label')->click();
57
58
            return;
59
        }
60
61
        $billingAddressSwitch = $this->getElement('different_shipping_address');
62
        Assert::false(
63
            $billingAddressSwitch->isChecked(),
64
            'Previous state of different billing address switch was true expected to be false'
65
        );
66
67
        $billingAddressSwitch->check();
68
    }
69
70
    public function checkInvalidCredentialsValidation(): bool
71
    {
72
        $this->getElement('login_password')->waitFor(5, function () {
73
            $validationElement = $this->getElement('login_password')->getParent()->find('css', '[data-test-login-errors]');
74
            if (null === $validationElement) {
75
                return false;
76
            }
77
78
            return $validationElement->isVisible();
79
        });
80
81
        return $this->checkValidationMessageFor('login_password', 'Invalid credentials.');
82
    }
83
84
    public function checkValidationMessageFor(string $element, string $message): bool
85
    {
86
        $foundElement = $this->getFieldElement($element);
87
        if (null === $foundElement) {
88
            throw new ElementNotFoundException($this->getSession(), 'Validation message', 'css', '[data-test-validation-error]');
89
        }
90
91
        $validationMessage = $foundElement->find('css', '.sylius-validation-error');
92
        if (null === $validationMessage) {
93
            throw new ElementNotFoundException($this->getSession(), 'Validation message', 'css', '[data-test-validation-error]');
94
        }
95
96
        return $message === $validationMessage->getText();
97
    }
98
99
    public function specifyShippingAddress(AddressInterface $shippingAddress): void
100
    {
101
        $this->specifyAddress($shippingAddress, self::TYPE_SHIPPING);
102
    }
103
104
    public function selectShippingAddressProvince(string $province): void
105
    {
106
        $this->waitForElement(5, 'shipping_country_province');
107
        $this->getElement('shipping_country_province')->selectOption($province);
108
    }
109
110
    public function specifyBillingAddress(AddressInterface $billingAddress): void
111
    {
112
        $this->specifyAddress($billingAddress, self::TYPE_BILLING);
113
    }
114
115
    public function selectBillingAddressProvince(string $province): void
116
    {
117
        $this->waitForElement(5, 'billing_country_province');
118
        $this->getElement('billing_country_province')->selectOption($province);
119
    }
120
121
    public function specifyEmail(?string $email): void
122
    {
123
        $this->getElement('customer_email')->setValue($email);
124
    }
125
126
    public function specifyBillingAddressFullName(string $fullName): void
127
    {
128
        $names = explode(' ', $fullName);
129
130
        $this->getElement('billing_first_name')->setValue($names[0]);
131
        $this->getElement('billing_last_name')->setValue($names[1]);
132
    }
133
134
    public function canSignIn(): bool
135
    {
136
        return $this->waitForElement(5, 'login_button');
137
    }
138
139
    public function signIn(): void
140
    {
141
        $this->waitForElement(5, 'login_button');
142
143
        try {
144
            $this->getElement('login_button')->press();
145
        } catch (ElementNotFoundException $elementNotFoundException) {
146
            $this->getElement('login_button')->click();
147
        }
148
149
        $this->waitForLoginAction();
150
    }
151
152
    public function specifyPassword(string $password): void
153
    {
154
        $this->getDocument()->waitFor(5, function () {
155
            return $this->getElement('login_password')->isVisible();
156
        });
157
158
        $this->getElement('login_password')->setValue($password);
159
    }
160
161
    public function getItemSubtotal(string $itemName): string
162
    {
163
        $itemSlug = strtolower(str_replace('\"', '', str_replace(' ', '-', $itemName)));
164
165
        $subtotalTable = $this->getElement('checkout_subtotal');
166
167
        return $subtotalTable->find('css', sprintf('[data-test-item-subtotal="%s"]', $itemSlug))->getText();
168
    }
169
170
    public function getShippingAddressCountry(): string
171
    {
172
        return $this->getElement('shipping_country')->find('css', 'option:selected')->getText();
173
    }
174
175
    public function nextStep(): void
176
    {
177
        $this->getElement('next_step')->press();
178
    }
179
180
    public function backToStore(): void
181
    {
182
        $this->getDocument()->clickLink('Back to store');
183
    }
184
185
    public function specifyBillingAddressProvince(string $provinceName): void
186
    {
187
        $this->waitForElement(5, 'billing_province');
188
        $this->getElement('billing_province')->setValue($provinceName);
189
    }
190
191
    public function specifyShippingAddressProvince(string $provinceName): void
192
    {
193
        $this->waitForElement(5, 'shipping_province');
194
        $this->getElement('shipping_province')->setValue($provinceName);
195
    }
196
197
    public function hasShippingAddressInput(): bool
198
    {
199
        return $this->waitForElement(5, 'shipping_province');
200
    }
201
202
    public function hasBillingAddressInput(): bool
203
    {
204
        return $this->waitForElement(5, 'billing_province');
205
    }
206
207
    public function selectShippingAddressFromAddressBook(AddressInterface $address): void
208
    {
209
        $this->waitForElement(2, sprintf('%s_province', self::TYPE_SHIPPING));
210
        $addressBookSelect = $this->getElement('shipping_address_book');
211
212
        $addressBookSelect->click();
213
        $addressOption = $addressBookSelect->waitFor(5, function () use ($address, $addressBookSelect) {
214
            return $addressBookSelect->find('css', sprintf('.item[data-id="%s"]', $address->getId()));
215
        });
216
217
        if (null === $addressOption) {
218
            throw new ElementNotFoundException($this->getDriver(), 'option', 'css', sprintf('.item[data-id="%s"]', $address->getId()));
219
        }
220
221
        $addressOption->click();
222
    }
223
224
    public function selectBillingAddressFromAddressBook(AddressInterface $address): void
225
    {
226
        $this->waitForElement(2, sprintf('%s_province', self::TYPE_BILLING));
227
        $addressBookSelect = $this->getElement('billing_address_book');
228
229
        $addressBookSelect->click();
230
        $addressOption = $addressBookSelect->waitFor(5, function () use ($address, $addressBookSelect) {
231
            return $addressBookSelect->find('css', sprintf('.item[data-id="%s"]', $address->getId()));
232
        });
233
234
        if (null === $addressOption) {
235
            throw new ElementNotFoundException($this->getDriver(), 'option', 'css', sprintf('.item[data-id="%s"]', $address->getId()));
236
        }
237
238
        $addressOption->click();
239
240
        JQueryHelper::waitForFormToStopLoading($this->getDocument());
241
    }
242
243
    public function getPreFilledShippingAddress(): AddressInterface
244
    {
245
        return $this->getPreFilledAddress(self::TYPE_SHIPPING);
246
    }
247
248
    public function getPreFilledBillingAddress(): AddressInterface
249
    {
250
        return $this->getPreFilledAddress(self::TYPE_BILLING);
251
    }
252
253
    protected function getDefinedElements(): array
254
    {
255
        return array_merge(parent::getDefinedElements(), [
256
            'billing_address_book' => '[data-test-billing-address] [data-test-address-book]',
257
            'billing_city' => '[data-test-billing-city]',
258
            'billing_country' => '[data-test-billing-country]',
259
            'billing_country_province' => '[data-test-billing-address] [data-test-province-code]',
260
            'billing_first_name' => '[data-test-billing-first-name]',
261
            'billing_last_name' => '[data-test-billing-last-name]',
262
            'billing_postcode' => '[data-test-billing-postcode]',
263
            'billing_province' => '[data-test-billing-address] [data-test-province-name]',
264
            'billing_street' => '[data-test-billing-street]',
265
            'checkout_subtotal' => '[data-test-checkout-subtotal]',
266
            'customer_email' => '[data-test-login-email]',
267
            'different_billing_address' => '[data-test-different-billing-address]',
268
            'different_billing_address_label' => '[data-test-different-billing-address-label]',
269
            'different_shipping_address' => '[data-test-different-shipping-address]',
270
            'different_shipping_address_label' => '[data-test-different-shipping-address-label]',
271
            'login_button' => '[data-test-login-button]',
272
            'login_password' => '[data-test-password-input]',
273
            'next_step' => '[data-test-next-step]',
274
            'shipping_address_book' => '[data-test-shipping-address] [data-test-address-book]',
275
            'shipping_city' => '[data-test-shipping-city]',
276
            'shipping_country' => '[data-test-shipping-country]',
277
            'shipping_country_province' => '[data-test-shipping-address] [data-test-province-code]',
278
            'shipping_first_name' => '[data-test-shipping-first-name]',
279
            'shipping_last_name' => '[data-test-shipping-last-name]',
280
            'shipping_postcode' => '[data-test-shipping-postcode]',
281
            'shipping_province' => '[data-test-shipping-address] [data-test-province-name]',
282
            'shipping_street' => '[data-test-shipping-street]',
283
        ]);
284
    }
285
286
    private function getPreFilledAddress(string $type): AddressInterface
287
    {
288
        $this->assertAddressType($type);
289
290
        /** @var AddressInterface $address */
291
        $address = $this->addressFactory->createNew();
292
293
        $address->setFirstName($this->getElement(sprintf('%s_first_name', $type))->getValue());
294
        $address->setLastName($this->getElement(sprintf('%s_last_name', $type))->getValue());
295
        $address->setStreet($this->getElement(sprintf('%s_street', $type))->getValue());
296
        $address->setCountryCode($this->getElement(sprintf('%s_country', $type))->getValue());
297
        $address->setCity($this->getElement(sprintf('%s_city', $type))->getValue());
298
        $address->setPostcode($this->getElement(sprintf('%s_postcode', $type))->getValue());
299
        $this->waitForElement(5, sprintf('%s_province', $type));
300
301
        try {
302
            $address->setProvinceName($this->getElement(sprintf('%s_province', $type))->getValue());
303
        } catch (ElementNotFoundException $exception) {
304
            $address->setProvinceCode($this->getElement(sprintf('%s_country_province', $type))->getValue());
305
        }
306
307
        return $address;
308
    }
309
310
    private function specifyAddress(AddressInterface $address, string $type): void
311
    {
312
        $this->assertAddressType($type);
313
314
        $this->getElement(sprintf('%s_first_name', $type))->setValue($address->getFirstName());
315
        $this->getElement(sprintf('%s_last_name', $type))->setValue($address->getLastName());
316
        $this->getElement(sprintf('%s_street', $type))->setValue($address->getStreet());
317
        $this->getElement(sprintf('%s_country', $type))->selectOption($address->getCountryCode() ?: 'Select');
318
        $this->getElement(sprintf('%s_city', $type))->setValue($address->getCity());
319
        $this->getElement(sprintf('%s_postcode', $type))->setValue($address->getPostcode());
320
321
        JQueryHelper::waitForFormToStopLoading($this->getDocument());
322
323
        if (null !== $address->getProvinceName()) {
324
            $this->waitForElement(5, sprintf('%s_province', $type));
325
            $this->getElement(sprintf('%s_province', $type))->setValue($address->getProvinceName());
326
        }
327
        if (null !== $address->getProvinceCode()) {
328
            $this->waitForElement(5, sprintf('%s_country_province', $type));
329
            $this->getElement(sprintf('%s_country_province', $type))->selectOption($address->getProvinceCode());
330
        }
331
    }
332
333
    private function getFieldElement(string $element): ?NodeElement
334
    {
335
        $element = $this->getElement($element);
336
        while (null !== $element && !$element->hasClass('field')) {
337
            $element = $element->getParent();
338
        }
339
340
        return $element;
341
    }
342
343
    private function waitForLoginAction(): bool
0 ignored issues
show
Coding Style introduced by
function waitForLoginAction() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
344
    {
345
        return $this->getDocument()->waitFor(5, function () {
346
            return !$this->hasElement('login_password');
347
        });
348
    }
349
350
    private function waitForElement(int $timeout, string $elementName): bool
0 ignored issues
show
Coding Style introduced by
function waitForElement() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
351
    {
352
        return $this->getDocument()->waitFor($timeout, function () use ($elementName) {
353
            return $this->hasElement($elementName);
354
        });
355
    }
356
357
    private function assertAddressType(string $type): void
358
    {
359
        $availableTypes = [self::TYPE_BILLING, self::TYPE_SHIPPING];
360
361
        Assert::oneOf($type, $availableTypes, sprintf('There are only two available types %s, %s. %s given', self::TYPE_BILLING, self::TYPE_SHIPPING, $type));
362
    }
363
}
364