Completed
Push — api ( cecea0...116a36 )
by Kamil
29:57 queued 30s
created

CompletePage::getShippingPromotionDiscount()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
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
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\Session;
19
use FriendsOfBehat\PageObjectExtension\Page\SymfonyPage;
20
use Sylius\Behat\Service\Accessor\TableAccessorInterface;
21
use Sylius\Component\Core\Model\AddressInterface;
22
use Sylius\Component\Core\Model\ProductInterface;
23
use Sylius\Component\Core\Model\ShippingMethodInterface;
24
use Symfony\Component\Intl\Intl;
25
use Symfony\Component\Routing\RouterInterface;
26
27
class CompletePage extends SymfonyPage implements CompletePageInterface
28
{
29
    /** @var TableAccessorInterface */
30
    private $tableAccessor;
31
32
    public function __construct(
33
        Session $session,
34
        $minkParameters,
35
        RouterInterface $router,
36
        TableAccessorInterface $tableAccessor
37
    ) {
38
        parent::__construct($session, $minkParameters, $router);
39
40
        $this->tableAccessor = $tableAccessor;
41
    }
42
43
    public function getRouteName(): string
44
    {
45
        return 'sylius_shop_checkout_complete';
46
    }
47
48
    public function hasItemWithProductAndQuantity(string $productName, string $quantity): bool
49
    {
50
        $table = $this->getElement('items_table');
51
52
        try {
53
            $this->tableAccessor->getRowWithFields($table, ['item' => $productName, 'qty' => $quantity]);
54
        } catch (\InvalidArgumentException $exception) {
55
            return false;
56
        }
57
58
        return true;
59
    }
60
61
    public function hasShippingAddress(AddressInterface $address): bool
62
    {
63
        $shippingAddress = $this->getElement('shipping_address')->getText();
64
65
        return $this->isAddressValid($shippingAddress, $address);
66
    }
67
68
    public function hasBillingAddress(AddressInterface $address): bool
69
    {
70
        $billingAddress = $this->getElement('billing_address')->getText();
71
72
        return $this->isAddressValid($billingAddress, $address);
73
    }
74
75
    public function hasShippingMethod(ShippingMethodInterface $shippingMethod): bool
76
    {
77
        if (!$this->hasElement('shipping_method')) {
78
            return false;
79
        }
80
81
        return false !== strpos($this->getElement('shipping_method')->getText(), $shippingMethod->getName());
82
    }
83
84
    public function getPaymentMethodName(): string
85
    {
86
        return $this->getElement('payment_method')->getText();
87
    }
88
89
    public function hasPaymentMethod(): bool
90
    {
91
        return $this->hasElement('payment_method');
92
    }
93
94
    public function hasProductDiscountedUnitPriceBy(ProductInterface $product, int $amount): bool
95
    {
96
        $priceWithoutDiscount = $this->getPriceFromString($this->getElement('product_old_price', ['%name%' => $product->getName()])->getText());
97
        $priceWithDiscount = $this->getPriceFromString($this->getElement('product_unit_price', ['%name%' => $product->getName()])->getText());
98
        $discount = $priceWithoutDiscount - $priceWithDiscount;
99
100
        return $discount === $amount;
101
    }
102
103
    public function hasOrderTotal(int $total): bool
104
    {
105
        if (!$this->hasElement('order_total')) {
106
            return false;
107
        }
108
109
        return $this->getTotalFromString($this->getElement('order_total')->getText()) === $total;
110
    }
111
112
    public function getBaseCurrencyOrderTotal(): string
113
    {
114
        return (string) $this->getBaseTotalFromString($this->getElement('base_order_total')->getText());
115
    }
116
117
    public function addNotes(string $notes): void
118
    {
119
        $this->getElement('extra_notes')->setValue($notes);
120
    }
121
122
    public function hasPromotionTotal(string $promotionTotal): bool
123
    {
124
        return false !== strpos($this->getElement('promotion_total')->getText(), $promotionTotal);
125
    }
126
127
    public function hasPromotion(string $promotionName): bool
128
    {
129
        return false !== stripos($this->getElement('promotion_discounts')->getText(), $promotionName);
130
    }
131
132
    public function hasShippingPromotion(string $promotionName): bool
133
    {
134
        /** @var NodeElement $shippingPromotions */
135
        $shippingPromotions = $this->getElement('promotions_shipping_details');
136
137
        return false !== strpos($shippingPromotions->getAttribute('data-html'), $promotionName);
138
    }
139
140
    public function getTaxTotal(): string
141
    {
142
        return $this->getElement('tax_total')->getText();
143
    }
144
145
    public function getShippingTotal(): string
146
    {
147
        return $this->getElement('shipping_total')->getText();
148
    }
149
150
    public function hasShippingTotal(): bool
151
    {
152
        return $this->hasElement('shipping_total');
153
    }
154
155
    public function hasProductUnitPrice(ProductInterface $product, string $price): bool
156
    {
157
        return $this->getPriceFromString($this->getElement('product_unit_price', ['%name%' => $product->getName()])->getText()) === $this->getPriceFromString($price);
158
    }
159
160
    public function hasProductOutOfStockValidationMessage(ProductInterface $product): bool
161
    {
162
        $message = sprintf('%s does not have sufficient stock.', $product->getName());
163
164
        return $this->getElement('validation_errors')->getText() === $message;
165
    }
166
167
    public function getValidationErrors(): string
168
    {
169
        return $this->getElement('validation_errors')->getText();
170
    }
171
172
    public function hasLocale(string $localeName): bool
173
    {
174
        return false !== strpos($this->getElement('locale')->getText(), $localeName);
175
    }
176
177
    public function hasCurrency(string $currencyCode): bool
178
    {
179
        return false !== strpos($this->getElement('currency')->getText(), $currencyCode);
180
    }
181
182
    public function confirmOrder(): void
183
    {
184
        $this->getElement('confirm_button')->press();
185
    }
186
187
    public function changeAddress(): void
188
    {
189
        $this->getElement('addressing_step_label')->click();
190
    }
191
192
    public function changeShippingMethod(): void
193
    {
194
        $this->getElement('shipping_step_label')->click();
195
    }
196
197
    public function changePaymentMethod(): void
198
    {
199
        $this->getElement('payment_step_label')->click();
200
    }
201
202
    public function hasShippingProvinceName(string $provinceName): bool
203
    {
204
        $shippingAddressText = $this->getElement('shipping_address')->getText();
205
206
        return false !== stripos($shippingAddressText, $provinceName);
207
    }
208
209
    public function hasBillingProvinceName(string $provinceName): bool
210
    {
211
        $billingAddressText = $this->getElement('billing_address')->getText();
212
213
        return false !== stripos($billingAddressText, $provinceName);
214
    }
215
216
    public function hasShippingPromotionWithDiscount(string $promotionName, string $discount): bool
217
    {
218
        $promotionWithDiscount = sprintf('%s: %s', $promotionName, $discount);
219
220
        /** @var NodeElement $shippingPromotions */
221
        $shippingPromotions = $this->getElement('promotions_shipping_details');
222
223
        return false !== strpos($shippingPromotions->getAttribute('data-html'), $promotionWithDiscount);
224
    }
225
226
    public function hasOrderPromotion(string $promotionName): bool
227
    {
228
        /** @var NodeElement $shippingPromotions */
229
        $shippingPromotions = $this->getElement('order_promotions_details');
230
231
        return false !== strpos($shippingPromotions->getAttribute('data-html'), $promotionName);
232
    }
233
234
    public function tryToOpen(array $urlParameters = []): void
235
    {
236
        if ($this->getDriver() instanceof Selenium2Driver) {
237
            $start = microtime(true);
238
            $end = $start + 15;
239
            do {
240
                parent::tryToOpen($urlParameters);
241
                sleep(3);
242
            } while (!$this->isOpen() && microtime(true) < $end);
243
244
            return;
245
        }
246
247
        parent::tryToOpen($urlParameters);
248
    }
249
250
    protected function getDefinedElements(): array
251
    {
252
        return array_merge(parent::getDefinedElements(), [
253
            'addressing_step_label' => '[data-test-step-address]',
254
            'base_order_total' => '[data-test-summary-order-total]',
255
            'billing_address' => '[data-test-billing-address]',
256
            'confirm_button' => '[data-test-confirmation-button]',
257
            'currency' => '[data-test-order-currency-code]',
258
            'extra_notes' => '[data-test-extra-notes]',
259
            'items_table' => '[data-test-order-table]',
260
            'locale' => '[data-test-order-locale-name]',
261
            'order_promotions_details' => '[data-test-order-promotions-details]',
262
            'order_total' => '[data-test-order-total]',
263
            'payment_method' => '[data-test-payment-method]',
264
            'payment_step_label' => '[data-test-step-payment]',
265
            'product_old_price' => '[data-test-product-old-price="%name%"]',
266
            'product_row' => '[data-test-product-row="%name%"]',
267
            'product_unit_price' => '[data-test-product-unit-price="%name%"]',
268
            'promotion_discounts' => '[data-test-promotion-discounts]',
269
            'promotion_shipping_discounts' => '[data-test-promotion-shipping-discounts]',
270
            'promotion_total' => '[data-test-promotion-total]',
271
            'promotions_shipping_details' => '[data-test-shipping-promotion-details]',
272
            'shipping_address' => '[data-test-shipping-address]',
273
            'shipping_method' => '[data-test-shipping-method]',
274
            'shipping_step_label' => '[data-test-step-shipping]',
275
            'shipping_total' => '[data-test-shipping-total]',
276
            'tax_total' => '[data-test-tax-total]',
277
            'validation_errors' => '[data-test-validation-error]',
278
        ]);
279
    }
280
281
    private function isAddressValid(string $displayedAddress, AddressInterface $address): bool
282
    {
283
        return
284
            $this->hasAddressPart($displayedAddress, $address->getCompany(), true) &&
285
            $this->hasAddressPart($displayedAddress, $address->getFirstName()) &&
286
            $this->hasAddressPart($displayedAddress, $address->getLastName()) &&
287
            $this->hasAddressPart($displayedAddress, $address->getPhoneNumber(), true) &&
288
            $this->hasAddressPart($displayedAddress, $address->getStreet()) &&
289
            $this->hasAddressPart($displayedAddress, $address->getCity()) &&
290
            $this->hasAddressPart($displayedAddress, $address->getProvinceCode(), true) &&
291
            $this->hasAddressPart($displayedAddress, $this->getCountryName($address->getCountryCode())) &&
292
            $this->hasAddressPart($displayedAddress, $address->getPostcode())
293
        ;
294
    }
295
296
    private function hasAddressPart(string $address, ?string $addressPart, bool $optional = false): bool
297
    {
298
        if ($optional && null === $addressPart) {
299
            return true;
300
        }
301
302
        return false !== strpos($address, $addressPart);
303
    }
304
305
    private function getCountryName(string $countryCode): string
306
    {
307
        return strtoupper(Intl::getRegionBundle()->getCountryName($countryCode, 'en'));
0 ignored issues
show
Deprecated Code introduced by
The method Symfony\Component\Intl\Intl::getRegionBundle() has been deprecated with message: since Symfony 4.3, to be removed in 5.0. Use {@see Countries} instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
308
    }
309
310
    private function getPriceFromString(string $price): int
311
    {
312
        return (int) round((float) str_replace(['€', '£', '$'], '', $price) * 100, 2);
313
    }
314
315
    private function getTotalFromString(string $total): int
316
    {
317
        $total = str_replace('Total:', '', $total);
318
319
        return $this->getPriceFromString($total);
320
    }
321
322
    private function getBaseTotalFromString(string $total): int
323
    {
324
        $total = str_replace('Total in base currency:', '', $total);
325
326
        return $this->getPriceFromString($total);
327
    }
328
}
329