Completed
Push — a-bulwa-travis-is-2 ( 7c64aa )
by Kamil
41:24
created

AddressPage::getPreFilledAddress()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 11
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
namespace Sylius\Behat\Page\Shop\Checkout;
13
14
use Behat\Mink\Driver\Selenium2Driver;
15
use Behat\Mink\Element\NodeElement;
16
use Behat\Mink\Exception\ElementNotFoundException;
17
use Behat\Mink\Session;
18
use Sylius\Behat\Page\SymfonyPage;
19
use Sylius\Component\Core\Factory\AddressFactoryInterface;
20
use Sylius\Component\Core\Model\AddressInterface;
21
use Sylius\Component\Locale\Context\LocaleContextInterface;
22
use Symfony\Component\Intl\Intl;
23
use Symfony\Component\Routing\RouterInterface;
24
use Webmozart\Assert\Assert;
25
26
/**
27
 * @author Arkadiusz Krakowiak <[email protected]>
28
 */
29
class AddressPage extends SymfonyPage implements AddressPageInterface
30
{
31
    const TYPE_BILLING = 'billing';
32
    const TYPE_SHIPPING = 'shipping';
33
34
    /**
35
     * @var AddressFactoryInterface
36
     */
37
    private $addressFactory;
38
39
    /**
40
     * @param Session $session
41
     * @param array $parameters
42
     * @param RouterInterface $router
43
     * @param AddressFactoryInterface $addressFactory
44
     */
45
    public function __construct(
46
        Session $session,
47
        array $parameters,
48
        RouterInterface $router,
49
        AddressFactoryInterface $addressFactory
50
    ){
51
        parent::__construct($session, $parameters, $router);
52
53
        $this->addressFactory = $addressFactory;
54
    }
55
56
    /**
57
     * {@inheritdoc}
58
     */
59
    public function getRouteName()
60
    {
61
        return 'sylius_shop_checkout_address';
62
    }
63
64
    /**
65
     * {@inheritdoc}
66
     */
67
    public function chooseDifferentBillingAddress()
68
    {
69
        $driver = $this->getDriver();
70
        if ($driver instanceof Selenium2Driver) {
71
            $this->getElement('different_billing_address_label')->click();
72
73
            return;
74
        }
75
76
        $billingAddressSwitch = $this->getElement('different_billing_address');
77
        Assert::false(
78
            $billingAddressSwitch->isChecked(),
79
            'Previous state of different billing address switch was true expected to be false'
80
        );
81
82
        $billingAddressSwitch->check();
83
    }
84
85
    /**
86
     * {@inheritdoc}
87
     */
88
    public function checkInvalidCredentialsValidation()
89
    {
90
        $this->getElement('login_password')->waitFor(5, function () {
91
            $validationElement = $this->getElement('login_password')->getParent()->find('css', '.red.label');
92
            if (null === $validationElement) {
93
                return false;
94
            }
95
96
            return $validationElement->isVisible();
97
        });
98
99
        return $this->checkValidationMessageFor('login_password', 'Invalid credentials.');
100
    }
101
102
    /**
103
     * {@inheritdoc}
104
     *
105
     * @throws ElementNotFoundException
106
     */
107
    public function checkValidationMessageFor($element, $message)
108
    {
109
        $foundElement = $this->getFieldElement($element);
110
        if (null === $foundElement) {
111
            throw new ElementNotFoundException($this->getSession(), 'Validation message', 'css', '.sylius-validation-error');
112
        }
113
114
        $validationMessage = $foundElement->find('css', '.sylius-validation-error');
115
        if (null === $validationMessage) {
116
            throw new ElementNotFoundException($this->getSession(), 'Validation message', 'css', '.sylius-validation-error');
117
        }
118
119
        return $message === $validationMessage->getText();
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125
    public function specifyShippingAddress(AddressInterface $shippingAddress)
126
    {
127
        $this->specifyAddress($shippingAddress, self::TYPE_SHIPPING);
128
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133
    public function selectShippingAddressProvince($province)
134
    {
135
        $this->waitForElement(5, 'shipping_country_province');
136
        $this->getElement('shipping_country_province')->selectOption($province);
137
    }
138
139
    /**
140
     * {@inheritdoc}
141
     */
142
    public function specifyBillingAddress(AddressInterface $billingAddress)
143
    {
144
        $this->specifyAddress($billingAddress, self::TYPE_BILLING);
145
    }
146
147
    /**
148
     * {@inheritdoc}
149
     */
150
    public function selectBillingAddressProvince($province)
151
    {
152
        $this->waitForElement(5, 'billing_country_province');
153
        $this->getElement('billing_country_province')->selectOption($province);
154
    }
155
156
    /**
157
     * {@inheritdoc}
158
     */
159
    public function specifyEmail($email)
160
    {
161
        $this->getElement('customer_email')->setValue($email);
162
    }
163
164
    /**
165
     * {@inheritdoc}
166
     */
167
    public function canSignIn()
168
    {
169
        return $this->waitForElement(5, 'login_button');
170
    }
171
172
    /**
173
     * {@inheritdoc}
174
     */
175
    public function signIn()
176
    {
177
        $this->waitForElement(5, 'login_button');
178
        try {
179
            $this->getElement('login_button')->press();
180
        } catch (ElementNotFoundException $elementNotFoundException) {
0 ignored issues
show
Comprehensibility Naming introduced by
The variable name $elementNotFoundException exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
181
            $this->getElement('login_button')->click();
182
        }
183
184
        $this->waitForLoginAction();
185
    }
186
187
    /**
188
     * {@inheritdoc}
189
     */
190
    public function specifyPassword($password)
191
    {
192
        $this->getDocument()->waitFor(5, function () {
193
            return $this->getElement('login_password')->isVisible();
194
        });
195
196
        $this->getElement('login_password')->setValue($password);
197
    }
198
199
    /**
200
     * {@inheritdoc}
201
     */
202
    public function getItemSubtotal($itemName)
203
    {
204
        $itemSlug = strtolower(str_replace('\"', '', str_replace(' ', '-', $itemName)));
205
206
        $subtotalTable = $this->getElement('checkout_subtotal');
207
208
        return $subtotalTable->find('css', sprintf('#item-%s-subtotal', $itemSlug))->getText();
209
    }
210
211
    /**
212
     * {@inheritdoc}
213
     */
214
    public function getShippingAddressCountry()
215
    {
216
        return $this->getElement('shipping_country')->find('css', 'option:selected')->getText();
217
    }
218
219
    public function nextStep()
220
    {
221
        $this->getElement('next_step')->press();
222
    }
223
224
    public function backToStore()
225
    {
226
        $this->getDocument()->clickLink('Back to store');
227
    }
228
229
    /**
230
     * {@inheritdoc}
231
     */
232
    public function specifyBillingAddressProvince($provinceName)
233
    {
234
        $this->waitForElement(5, 'billing_province');
235
        $this->getElement('billing_province')->setValue($provinceName);
236
    }
237
238
    /**
239
     * {@inheritdoc}
240
     */
241
    public function specifyShippingAddressProvince($provinceName)
242
    {
243
        $this->waitForElement(5, 'shipping_province');
244
        $this->getElement('shipping_province')->setValue($provinceName);
245
    }
246
247
    /**
248
     * {@inheritdoc}
249
     */
250
    public function hasShippingAddressInput()
251
    {
252
        return $this->waitForElement(5, 'shipping_province');
253
    }
254
255
    /**
256
     * {@inheritdoc}
257
     */
258
    public function hasBillingAddressInput()
259
    {
260
        return $this->waitForElement(5, 'billing_province');
261
    }
262
263
    /**
264
     * @inheritDoc
265
     */
266
    public function selectShippingAddressFromAddressBook(AddressInterface $address)
267
    {
268
        $addressBookSelect = $this->getElement('shipping_address_book');
269
270
        $addressBookSelect->click();
271
        $addressBookSelect->waitFor(5, function () use ($address, $addressBookSelect) {
272
            return $addressBookSelect->find('css', sprintf('.item[data-value="%s"]', $address->getId()));
273
        })->click();
274
    }
275
276
    /**
277
     * @inheritDoc
278
     */
279
    public function selectBillingAddressFromAddressBook(AddressInterface $address)
280
    {
281
        $addressBookSelect = $this->getElement('billing_address_book');
282
283
        $addressBookSelect->click();
284
        $addressBookSelect->waitFor(5, function () use ($address, $addressBookSelect) {
285
            return $addressBookSelect->find('css', sprintf('.item[data-value="%s"]', $address->getId()));
286
        })->click();
287
    }
288
289
    /**
290
     * @inheritDoc
291
     */
292
    public function getPreFilledShippingAddress()
293
    {
294
        return $this->getPreFilledAddress(self::TYPE_SHIPPING);
295
    }
296
297
    /**
298
     * @inheritDoc
299
     */
300
    public function getPreFilledBillingAddress()
301
    {
302
        return $this->getPreFilledAddress(self::TYPE_BILLING);
303
    }
304
305
    /**
306
     * {@inheritdoc}
307
     */
308
    protected function getDefinedElements()
309
    {
310
        return array_merge(parent::getDefinedElements(), [
311
            'billing_address_book' => '#sylius-billing-address .ui.dropdown',
312
            'billing_first_name' => '#sylius_checkout_address_billingAddress_firstName',
313
            'billing_last_name' => '#sylius_checkout_address_billingAddress_lastName',
314
            'billing_street' => '#sylius_checkout_address_billingAddress_street',
315
            'billing_city' => '#sylius_checkout_address_billingAddress_city',
316
            'billing_country' => '#sylius_checkout_address_billingAddress_countryCode',
317
            'billing_country_province' => '[name="sylius_checkout_address[billingAddress][provinceCode]"]',
318
            'billing_postcode' => '#sylius_checkout_address_billingAddress_postcode',
319
            'billing_province' => '[name="sylius_checkout_address[billingAddress][provinceName]"]',
320
            'checkout_subtotal' => '#checkout-subtotal',
321
            'customer_email' => '#sylius_checkout_address_customer_email',
322
            'different_billing_address' => '#sylius_checkout_address_differentBillingAddress',
323
            'different_billing_address_label' => '#sylius_checkout_address_differentBillingAddress ~ label',
324
            'login_button' => '#sylius-api-login-submit',
325
            'login_password' => 'input[type=\'password\']',
326
            'next_step' => '#next-step',
327
            'shipping_address_book' => '#sylius-shipping-address .ui.dropdown',
328
            'shipping_city' => '#sylius_checkout_address_shippingAddress_city',
329
            'shipping_country' => '#sylius_checkout_address_shippingAddress_countryCode',
330
            'shipping_country_province' => '[name="sylius_checkout_address[shippingAddress][provinceCode]"]',
331
            'shipping_first_name' => '#sylius_checkout_address_shippingAddress_firstName',
332
            'shipping_last_name' => '#sylius_checkout_address_shippingAddress_lastName',
333
            'shipping_postcode' => '#sylius_checkout_address_shippingAddress_postcode',
334
            'shipping_province' => '[name="sylius_checkout_address[shippingAddress][provinceName]"]',
335
            'shipping_street' => '#sylius_checkout_address_shippingAddress_street',
336
        ]);
337
    }
338
339
    /**
340
     * @param string $type
341
     *
342
     * @return AddressInterface
343
     */
344
    private function getPreFilledAddress($type)
345
    {
346
        $this->assertAddressType($type);
347
348
        /** @var AddressInterface $address */
349
        $address = $this->addressFactory->createNew();
350
351
        $address->setFirstName($this->getElement(sprintf('%s_first_name', $type))->getValue());
352
        $address->setLastName($this->getElement(sprintf('%s_last_name', $type))->getValue());
353
        $address->setStreet($this->getElement(sprintf('%s_street', $type))->getValue());
354
        $address->setCountryCode($this->getElement(sprintf('%s_country', $type))->getValue());
355
        $address->setCity($this->getElement(sprintf('%s_city', $type))->getValue());
356
        $address->setPostcode($this->getElement(sprintf('%s_postcode', $type))->getValue());
357
        $address->setProvinceName($this->getElement(sprintf('%s_province', $type))->getValue());
358
359
        return $address;
360
    }
361
362
    /**
363
     * @param AddressInterface $address
364
     * @param string $type
365
     */
366
    private function specifyAddress(AddressInterface $address, $type)
367
    {
368
        $this->assertAddressType($type);
369
370
        $this->getElement(sprintf('%s_first_name', $type))->setValue($address->getFirstName());
371
        $this->getElement(sprintf('%s_last_name', $type))->setValue($address->getLastName());
372
        $this->getElement(sprintf('%s_street', $type))->setValue($address->getStreet());
373
        $this->getElement(sprintf('%s_country', $type))->selectOption($address->getCountryCode() ?: 'Select');
374
        $this->getElement(sprintf('%s_city', $type))->setValue($address->getCity());
375
        $this->getElement(sprintf('%s_postcode', $type))->setValue($address->getPostcode());
376
377
        if (null !== $address->getProvinceName()) {
378
            $this->waitForElement(5, sprintf('%s_province', $type));
379
            $this->getElement(sprintf('%s_province', $type))->setValue($address->getProvinceName());
380
        }
381
    }
382
383
    /**
384
     * @param string $element
385
     *
386
     * @return NodeElement|null
387
     *
388
     * @throws ElementNotFoundException
389
     */
390
    private function getFieldElement($element)
391
    {
392
        $element = $this->getElement($element);
393
        while (null !== $element && !($element->hasClass('field'))) {
394
            $element = $element->getParent();
395
        }
396
397
        return $element;
398
    }
399
400
    /**
401
     * @return bool
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
402
     */
403
    private function waitForLoginAction()
404
    {
405
        $this->getDocument()->waitFor(5, function () {
406
            return !$this->hasElement('login_password');
407
        });
408
    }
409
410
    /**
411
     * @return bool
412
     */
413
    private function waitForElement($timeout, $elementName)
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...
414
    {
415
        return $this->getDocument()->waitFor($timeout, function () use ($elementName){
416
            return $this->hasElement($elementName);
417
        });
418
    }
419
420
    /**
421
     * @param string $type
422
     */
423
    private function assertAddressType($type)
424
    {
425
        $availableTypes = [self::TYPE_BILLING, self::TYPE_SHIPPING];
426
427
        Assert::oneOf($type, $availableTypes, sprintf('There are only two available types %s, %s. %s given', self::TYPE_BILLING, self::TYPE_SHIPPING, $type));
428
    }
429
}
430