Completed
Push — symfony3-wololo-packages ( fecf70...6bf04d )
by Kamil
28:46 queued 11:35
created

CompletePage::getDefinedElements()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 24
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 8.9713
c 0
b 0
f 0
cc 1
eloc 21
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
namespace Sylius\Behat\Page\Shop\Checkout;
13
14
use Behat\Mink\Session;
15
use Behat\Mink\Element\NodeElement;
16
use Sylius\Behat\Page\SymfonyPage;
17
use Sylius\Behat\Service\Accessor\TableAccessorInterface;
18
use Sylius\Component\Core\Model\AddressInterface;
19
use Sylius\Component\Core\Model\ShippingMethodInterface;
20
use Sylius\Component\Payment\Model\PaymentMethodInterface;
21
use Sylius\Component\Core\Model\ProductInterface;
22
use Symfony\Component\Intl\Intl;
23
use Symfony\Component\Routing\RouterInterface;
24
25
/**
26
 * @author Mateusz Zalewski <[email protected]>
27
 */
28
class CompletePage extends SymfonyPage implements CompletePageInterface
29
{
30
    /**
31
     * @var TableAccessorInterface
32
     */
33
    private $tableAccessor;
34
35
    /**
36
     * @param Session $session
37
     * @param array $parameters
38
     * @param RouterInterface $router
39
     * @param TableAccessorInterface $tableAccessor
40
     */
41
    public function __construct(
42
        Session $session,
43
        array $parameters,
44
        RouterInterface $router,
45
        TableAccessorInterface $tableAccessor
46
    ) {
47
        parent::__construct($session, $parameters, $router);
48
49
        $this->tableAccessor = $tableAccessor;
50
    }
51
52
53
    /**
54
     * {@inheritdoc}
55
     */
56
    public function getRouteName()
57
    {
58
        return 'sylius_shop_checkout_complete';
59
    }
60
61
    /**
62
     * {@inheritdoc}
63
     */
64
    public function hasItemWithProductAndQuantity($productName, $quantity)
65
    {
66
        $table = $this->getElement('items_table');
67
68
        try {
69
            $this->tableAccessor->getRowWithFields($table, ['item' => $productName, 'qty' => $quantity]);
70
        } catch (\InvalidArgumentException $exception) {
71
            return false;
72
        }
73
74
        return true;
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     */
80
    public function hasShippingAddress(AddressInterface $address)
81
    {
82
        $shippingAddress = $this->getElement('shipping_address')->getText();
83
84
        return $this->isAddressValid($shippingAddress, $address);
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90
    public function hasBillingAddress(AddressInterface $address)
91
    {
92
        $billingAddress = $this->getElement('billing_address')->getText();
93
94
        return $this->isAddressValid($billingAddress, $address);
95
    }
96
97
    /**
98
     * {@inheritdoc}
99
     */
100
    public function hasShippingMethod(ShippingMethodInterface $shippingMethod)
101
    {
102
        if (!$this->hasElement('shipping_method')) {
103
            return false;
104
        }
105
106
        return false !== strpos($this->getElement('shipping_method')->getText(), $shippingMethod->getName());
107
    }
108
109
    /**
110
     * {@inheritdoc}
111
     */
112
    public function hasPaymentMethod(PaymentMethodInterface $paymentMethod)
113
    {
114
        if (!$this->hasElement('payment_method')) {
115
            return false;
116
        }
117
118
        return false !== strpos($this->getElement('payment_method')->getText(), $paymentMethod->getName());
119
    }
120
121
    /**
122
     * {@inheritdoc}
123
     */
124
    public function hasProductDiscountedUnitPriceBy(ProductInterface $product, $amount)
125
    {
126
        $columns = $this->getProductRowElement($product)->findAll('css', 'td');
127
        $priceWithoutDiscount = $this->getPriceFromString($columns[1]->getText());
128
        $priceWithDiscount = $this->getPriceFromString($columns[3]->getText());
129
        $discount = $priceWithoutDiscount - $priceWithDiscount;
130
131
        return $discount === $amount;
132
    }
133
134
    /**
135
     * {@inheritdoc}
136
     */
137
    public function hasOrderTotal($total)
138
    {
139
        if (!$this->hasElement('order_total')) {
140
            return false;
141
        }
142
143
        return $this->getTotalFromString($this->getElement('order_total')->getText()) === $total;
144
    }
145
146
    /**
147
     * {@inheritdoc}
148
     */
149
    public function getBaseCurrencyOrderTotal()
150
    {
151
        return $this->getBaseTotalFromString($this->getElement('base_order_total')->getText());
152
    }
153
154
    /**
155
     * {@inheritdoc}
156
     */
157
    public function addNotes($notes)
158
    {
159
        $this->getElement('extra_notes')->setValue($notes);
160
    }
161
162
    /**
163
     * {@inheritdoc}
164
     */
165
    public function hasPromotionTotal($promotionTotal)
166
    {
167
        return false !== strpos($this->getElement('promotion_total')->getText(), $promotionTotal);
168
    }
169
170
    /**
171
     * {@inheritdoc}
172
     */
173
    public function hasPromotion($promotionName)
174
    {
175
        return false !== stripos($this->getElement('promotion_discounts')->getText(), $promotionName);
176
    }
177
178
    /**
179
     * {@inheritdoc}
180
     */
181
    public function hasTaxTotal($taxTotal)
182
    {
183
        return false !== strpos($this->getElement('tax_total')->getText(), $taxTotal);
184
    }
185
186
    /**
187
     * {@inheritdoc}
188
     */
189
    public function hasShippingTotal($price)
190
    {
191
        return false !== strpos($this->getElement('shipping_total')->getText(), $price);
192
    }
193
194
    /**
195
     * {@inheritdoc}
196
     */
197
    public function hasProductUnitPrice(ProductInterface $product, $price)
198
    {
199
        $productRowElement = $this->getProductRowElement($product);
200
201
        return null !== $productRowElement->find('css', sprintf('td:contains("%s")', $price));
202
    }
203
204
    /**
205
     * {@inheritdoc}
206
     */
207
    public function hasProductOutOfStockValidationMessage(ProductInterface $product)
208
    {
209
        $message = sprintf('%s does not have sufficient stock.', $product->getName());
210
211
        return $this->getElement('validation_errors')->getText() === $message;
212
    }
213
214
    /**
215
     * {@inheritdoc}
216
     */
217
    public function hasLocale($localeName)
218
    {
219
        return false !== strpos($this->getElement('locale')->getText(), $localeName);
220
    }
221
222
    /**
223
     * {@inheritdoc}
224
     */
225
    public function hasCurrency($currencyCode)
226
    {
227
        return false !== strpos($this->getElement('currency')->getText(), $currencyCode);
228
    }
229
230
    public function confirmOrder()
231
    {
232
        $this->getDocument()->pressButton('Place order');
233
    }
234
235
    public function changeAddress()
236
    {
237
        $this->getElement('addressing_step_label')->click();
238
    }
239
240
    public function changeShippingMethod()
241
    {
242
        $this->getElement('shipping_step_label')->click();
243
    }
244
245
    public function changePaymentMethod()
246
    {
247
        $this->getElement('payment_step_label')->click();
248
    }
249
250
    /**
251
     * {@inheritdoc}
252
     */
253
    public function hasShippingProvinceName($provinceName)
254
    {
255
        $shippingAddressText = $this->getElement('shipping_address')->getText();
256
257
        return false !== stripos($shippingAddressText, $provinceName);
258
    }
259
260
    /**
261
     * {@inheritdoc}
262
     */
263
    public function hasBillingProvinceName($provinceName)
264
    {
265
        $billingAddressText = $this->getElement('billing_address')->getText();
266
267
        return false !== stripos($billingAddressText, $provinceName);
268
    }
269
270
    /**
271
     * {@inheritdoc}
272
     */
273
    protected function getDefinedElements()
274
    {
275
        return array_merge(parent::getDefinedElements(), [
276
            'addressing_step_label' => '.steps a:contains("Address")',
277
            'billing_address' => '#billing-address',
278
            'currency' => '#sylius-order-currency-code',
279
            'extra_notes' =>'#sylius_checkout_complete_notes',
280
            'items_table' => '#sylius-order',
281
            'locale' => '#sylius-order-locale-name',
282
            'order_total' => 'td:contains("Total")',
283
            'base_order_total' => '#base-total',
284
            'payment_method' => '#payment-method',
285
            'payment_step_label' => '.steps a:contains("Payment")',
286
            'product_row' => 'tbody tr:contains("%name%")',
287
            'promotion_discounts' => '#promotion-discounts',
288
            'promotion_total' => '#promotion-total',
289
            'shipping_address' => '#shipping-address',
290
            'shipping_method' => '#shipping-method',
291
            'shipping_step_label' => '.steps a:contains("Shipping")',
292
            'shipping_total' => '#shipping-total',
293
            'tax_total' => '#tax-total',
294
            'validation_errors' => '.sylius-validation-error',
295
        ]);
296
    }
297
298
    /**
299
     * @param ProductInterface $product
300
     *
301
     * @return NodeElement
302
     */
303
    private function getProductRowElement(ProductInterface $product)
304
    {
305
        return $this->getElement('product_row', ['%name%' => $product->getName()]);
306
    }
307
308
    /**
309
     * @param string $displayedAddress
310
     * @param AddressInterface $address
311
     *
312
     * @return bool
313
     */
314
    private function isAddressValid($displayedAddress, AddressInterface $address)
315
    {
316
        return
317
            $this->hasAddressPart($displayedAddress, $address->getCompany(), true) &&
318
            $this->hasAddressPart($displayedAddress, $address->getFirstName()) &&
319
            $this->hasAddressPart($displayedAddress, $address->getLastName()) &&
320
            $this->hasAddressPart($displayedAddress, $address->getPhoneNumber(), true) &&
321
            $this->hasAddressPart($displayedAddress, $address->getStreet()) &&
322
            $this->hasAddressPart($displayedAddress, $address->getCity()) &&
323
            $this->hasAddressPart($displayedAddress, $address->getProvinceCode(), true) &&
324
            $this->hasAddressPart($displayedAddress, $this->getCountryName($address->getCountryCode())) &&
325
            $this->hasAddressPart($displayedAddress, $address->getPostcode())
326
        ;
327
    }
328
329
    /**
330
     * @param string $address
331
     * @param string $addressPart
332
     *
333
     * @return bool
334
     */
335
    private function hasAddressPart($address, $addressPart, $optional = false)
336
    {
337
        if ($optional && null === $addressPart) {
338
            return true;
339
        }
340
341
        return false !== strpos($address, $addressPart);
342
    }
343
344
    /**
345
     * @param string $countryCode
346
     *
347
     * @return string
348
     */
349
    private function getCountryName($countryCode)
350
    {
351
        return strtoupper(Intl::getRegionBundle()->getCountryName($countryCode, 'en'));
352
    }
353
354
    /**
355
     * @param string $price
356
     *
357
     * @return int
358
     */
359
    private function getPriceFromString($price)
360
    {
361
        return (int) round((str_replace(['€', '£', '$'], '', $price) * 100), 2);
362
    }
363
364
    /**
365
     * @param string $total
366
     *
367
     * @return int
368
     */
369
    private function getTotalFromString($total)
370
    {
371
        $total = str_replace('Total:', '', $total);
372
373
        return $this->getPriceFromString($total);
374
    }
375
376
    /**
377
     * @param string $total
378
     *
379
     * @return int
380
     */
381
    private function getBaseTotalFromString($total)
382
    {
383
        $total = str_replace('Total in base currency:', '', $total);
384
385
        return $this->getPriceFromString($total);
386
    }
387
}
388