Completed
Push — master ( 68b7da...429264 )
by Paweł
17s
created

SummaryPage::hasPromotionTotal()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
rs 10
cc 1
eloc 2
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\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 SummaryPage extends SymfonyPage implements SummaryPageInterface
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_summary';
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
        $productRowElement = $this->getProductRowElement($product);
127
        $discountedPriceElement = $productRowElement->find('css', 'td > s');
128
        if (null === $discountedPriceElement) {
129
            return false;
130
        }
131
        $priceElement = $discountedPriceElement->getParent();
132
        $prices = explode(' ', $priceElement->getText());
133
        $priceWithoutDiscount = $this->getPriceFromString($prices[0]);
134
        $priceWithDiscount = $this->getPriceFromString($prices[1]);
135
        $discount = $priceWithoutDiscount - $priceWithDiscount;
136
137
        return $discount === $amount;
138
    }
139
140
    /**
141
     * {@inheritdoc}
142
     */
143
    public function hasOrderTotal($total)
144
    {
145
        if (!$this->hasElement('order_total')) {
146
            return false;
147
        }
148
149
        return $this->getTotalFromString($this->getElement('order_total')->getText()) === $total;
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155
    public function hasPromotionTotal($promotionTotal)
156
    {
157
        return false !== strpos($this->getElement('promotion_total')->getText(), $promotionTotal);
158
    }
159
160
    /**
161
     * {@inheritdoc}
162
     */
163
    public function hasPromotion($promotionName)
164
    {
165
        return false !== stripos($this->getElement('promotion_discounts')->getText(), $promotionName);
166
    }
167
168
    /**
169
     * {@inheritdoc}
170
     */
171
    public function hasTaxTotal($taxTotal)
172
    {
173
        return false !== strpos($this->getElement('tax_total')->getText(), $taxTotal);
174
    }
175
176
    /**
177
     * {@inheritdoc}
178
     */
179
    public function hasShippingTotal($price)
180
    {
181
        return false !== strpos($this->getElement('shipping_total')->getText(), $price);
182
    }
183
184
    /**
185
     * {@inheritdoc}
186
     */
187
    protected function getDefinedElements()
188
    {
189
        return array_merge(parent::getDefinedElements(), [
190
            'billing_address' => '#addresses div:contains("Billing address") address',
191
            'shipping_address' => '#addresses div:contains("Shipping address") address',
192
            'items_table' => '#items table',
193
            'shipping_method' => '#sylius-checkout-summary-shipping-method',
194
            'payment_method' => '#sylius-checkout-summary-payment-method',
195
            'product_row' => 'tbody tr:contains("%name%")',
196
            'order_total' => 'td:contains("Total")',
197
            'promotion_total' => '#promotion-total',
198
            'promotion_discounts' => '#promotion-discounts',
199
            'tax_total' => '#tax-total',
200
            'shipping_total' => '#shipping-total',
201
        ]);
202
    }
203
204
    /**
205
     * @param ProductInterface $product
206
     *
207
     * @return NodeElement
208
     */
209
    private function getProductRowElement(ProductInterface $product)
210
    {
211
        return $this->getElement('product_row', ['%name%' => $product->getName()]);
212
    }
213
214
    /**
215
     * @param string $displayedAddress
216
     * @param AddressInterface $address
217
     *
218
     * @return bool
219
     */
220
    private function isAddressValid($displayedAddress, AddressInterface $address)
221
    {
222
        return
223
            $this->hasAddressPart($displayedAddress, $address->getCompany(), true) &&
224
            $this->hasAddressPart($displayedAddress, $address->getFirstName()) &&
225
            $this->hasAddressPart($displayedAddress, $address->getLastName()) &&
226
            $this->hasAddressPart($displayedAddress, $address->getPhoneNumber(), true) &&
227
            $this->hasAddressPart($displayedAddress, $address->getStreet()) &&
228
            $this->hasAddressPart($displayedAddress, $address->getCity()) &&
229
            $this->hasAddressPart($displayedAddress, $address->getProvinceCode(), true) &&
230
            $this->hasAddressPart($displayedAddress, $this->getCountryName($address->getCountryCode())) &&
231
            $this->hasAddressPart($displayedAddress, $address->getPostcode())
232
        ;
233
    }
234
235
    /**
236
     * @param string $address
237
     * @param string $addressPart
238
     *
239
     * @return bool
240
     */
241
    private function hasAddressPart($address, $addressPart, $optional = false)
242
    {
243
        if ($optional && null === $addressPart) {
244
            return true;
245
        }
246
247
        return false !== strpos($address, $addressPart);
248
    }
249
250
    /**
251
     * @param string $countryCode
252
     *
253
     * @return string
254
     */
255
    private function getCountryName($countryCode)
256
    {
257
        return strtoupper(Intl::getRegionBundle()->getCountryName($countryCode, 'en'));
258
    }
259
260
    /**
261
     * @param string $price
262
     *
263
     * @return int
264
     */
265
    private function getPriceFromString($price)
266
    {
267
        return (int) round((str_replace(['€', '£', '$'], '', $price) * 100), 2);
268
    }
269
270
    /**
271
     * @param string $total
272
     * 
273
     * @return int
274
     */
275
    private function getTotalFromString($total)
276
    {
277
        $total = str_replace('Total:', '', $total);
278
279
        return $this->getPriceFromString($total);
280
    }
281
}
282