Completed
Push — master ( 429264...faaec3 )
by Paweł
25s
created

SummaryPage::addNotes()   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 addNotes($notes)
156
    {
157
        $this->getElement('extra_notes')->setValue($notes);
158
    }
159
160
    /**
161
     * {@inheritdoc}
162
     */
163
    public function hasPromotionTotal($promotionTotal)
164
    {
165
        return false !== strpos($this->getElement('promotion_total')->getText(), $promotionTotal);
166
    }
167
168
    /**
169
     * {@inheritdoc}
170
     */
171
    public function hasPromotion($promotionName)
172
    {
173
        return false !== stripos($this->getElement('promotion_discounts')->getText(), $promotionName);
174
    }
175
176
    /**
177
     * {@inheritdoc}
178
     */
179
    public function hasTaxTotal($taxTotal)
180
    {
181
        return false !== strpos($this->getElement('tax_total')->getText(), $taxTotal);
182
    }
183
184
    /**
185
     * {@inheritdoc}
186
     */
187
    public function hasShippingTotal($price)
188
    {
189
        return false !== strpos($this->getElement('shipping_total')->getText(), $price);
190
    }
191
192
    /**
193
     * {@inheritdoc}
194
     */
195
    protected function getDefinedElements()
196
    {
197
        return array_merge(parent::getDefinedElements(), [
198
            'billing_address' => '#addresses div:contains("Billing address") address',
199
            'extra_notes' =>'#sylius_checkout_summary_notes',
200
            'shipping_address' => '#addresses div:contains("Shipping address") address',
201
            'items_table' => '#items table',
202
            'shipping_method' => '#sylius-checkout-summary-shipping-method',
203
            'payment_method' => '#sylius-checkout-summary-payment-method',
204
            'product_row' => 'tbody tr:contains("%name%")',
205
            'order_total' => 'td:contains("Total")',
206
            'promotion_total' => '#promotion-total',
207
            'promotion_discounts' => '#promotion-discounts',
208
            'tax_total' => '#tax-total',
209
            'shipping_total' => '#shipping-total',
210
        ]);
211
    }
212
213
    /**
214
     * @param ProductInterface $product
215
     *
216
     * @return NodeElement
217
     */
218
    private function getProductRowElement(ProductInterface $product)
219
    {
220
        return $this->getElement('product_row', ['%name%' => $product->getName()]);
221
    }
222
223
    /**
224
     * @param string $displayedAddress
225
     * @param AddressInterface $address
226
     *
227
     * @return bool
228
     */
229
    private function isAddressValid($displayedAddress, AddressInterface $address)
230
    {
231
        return
232
            $this->hasAddressPart($displayedAddress, $address->getCompany(), true) &&
233
            $this->hasAddressPart($displayedAddress, $address->getFirstName()) &&
234
            $this->hasAddressPart($displayedAddress, $address->getLastName()) &&
235
            $this->hasAddressPart($displayedAddress, $address->getPhoneNumber(), true) &&
236
            $this->hasAddressPart($displayedAddress, $address->getStreet()) &&
237
            $this->hasAddressPart($displayedAddress, $address->getCity()) &&
238
            $this->hasAddressPart($displayedAddress, $address->getProvinceCode(), true) &&
239
            $this->hasAddressPart($displayedAddress, $this->getCountryName($address->getCountryCode())) &&
240
            $this->hasAddressPart($displayedAddress, $address->getPostcode())
241
        ;
242
    }
243
244
    /**
245
     * @param string $address
246
     * @param string $addressPart
247
     *
248
     * @return bool
249
     */
250
    private function hasAddressPart($address, $addressPart, $optional = false)
251
    {
252
        if ($optional && null === $addressPart) {
253
            return true;
254
        }
255
256
        return false !== strpos($address, $addressPart);
257
    }
258
259
    /**
260
     * @param string $countryCode
261
     *
262
     * @return string
263
     */
264
    private function getCountryName($countryCode)
265
    {
266
        return strtoupper(Intl::getRegionBundle()->getCountryName($countryCode, 'en'));
267
    }
268
269
    /**
270
     * @param string $price
271
     *
272
     * @return int
273
     */
274
    private function getPriceFromString($price)
275
    {
276
        return (int) round((str_replace(['€', '£', '$'], '', $price) * 100), 2);
277
    }
278
279
    /**
280
     * @param string $total
281
     * 
282
     * @return int
283
     */
284
    private function getTotalFromString($total)
285
    {
286
        $total = str_replace('Total:', '', $total);
287
288
        return $this->getPriceFromString($total);
289
    }
290
}
291