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\Cart; |
15
|
|
|
|
16
|
|
|
use Behat\Mink\Exception\ElementNotFoundException; |
17
|
|
|
use FriendsOfBehat\PageObjectExtension\Page\SymfonyPage; |
18
|
|
|
use Sylius\Component\Core\Model\ProductInterface; |
19
|
|
|
|
20
|
|
|
class SummaryPage extends SymfonyPage implements SummaryPageInterface |
21
|
|
|
{ |
22
|
|
|
/** |
23
|
|
|
* {@inheritdoc} |
24
|
|
|
*/ |
25
|
|
|
public function getRouteName(): string |
26
|
|
|
{ |
27
|
|
|
return 'sylius_shop_cart_summary'; |
28
|
|
|
} |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* {@inheritdoc} |
32
|
|
|
*/ |
33
|
|
|
public function getGrandTotal() |
34
|
|
|
{ |
35
|
|
|
$totalElement = $this->getElement('grand_total'); |
36
|
|
|
|
37
|
|
|
return $totalElement->getText(); |
38
|
|
|
} |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* {@inheritdoc} |
42
|
|
|
*/ |
43
|
|
|
public function getBaseGrandTotal() |
44
|
|
|
{ |
45
|
|
|
$totalElement = $this->getElement('base_grand_total'); |
46
|
|
|
|
47
|
|
|
return $totalElement->getText(); |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
public function getIncludedTaxTotal(): string |
51
|
|
|
{ |
52
|
|
|
$includedTaxTotalElement = $this->getElement('tax_included'); |
53
|
|
|
|
54
|
|
|
return $includedTaxTotalElement->getText(); |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
public function getExcludedTaxTotal(): string |
58
|
|
|
{ |
59
|
|
|
$excludedTaxTotalElement = $this->getElement('tax_excluded'); |
60
|
|
|
|
61
|
|
|
return $excludedTaxTotalElement->getText(); |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
public function areTaxesCharged(): bool |
65
|
|
|
{ |
66
|
|
|
try { |
67
|
|
|
$this->getElement('no_taxes'); |
68
|
|
|
} catch (ElementNotFoundException $exception) { |
|
|
|
|
69
|
|
|
return true; |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
return false; |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* {@inheritdoc} |
77
|
|
|
*/ |
78
|
|
|
public function getShippingTotal() |
79
|
|
|
{ |
80
|
|
|
$shippingTotalElement = $this->getElement('shipping_total'); |
81
|
|
|
|
82
|
|
|
return $shippingTotalElement->getText(); |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
public function hasShippingTotal(): bool |
86
|
|
|
{ |
87
|
|
|
return $this->hasElement('shipping_total'); |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* {@inheritdoc} |
92
|
|
|
*/ |
93
|
|
|
public function getPromotionTotal() |
94
|
|
|
{ |
95
|
|
|
$shippingTotalElement = $this->getElement('promotion_total'); |
96
|
|
|
|
97
|
|
|
return $shippingTotalElement->getText(); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* {@inheritdoc} |
102
|
|
|
*/ |
103
|
|
|
public function getItemTotal($productName) |
104
|
|
|
{ |
105
|
|
|
$itemTotalElement = $this->getElement('product_total', ['%name%' => $productName]); |
106
|
|
|
|
107
|
|
|
return $itemTotalElement->getText(); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* {@inheritdoc} |
112
|
|
|
*/ |
113
|
|
|
public function getItemUnitRegularPrice($productName) |
114
|
|
|
{ |
115
|
|
|
$regularUnitPrice = $this->getElement('product_unit_regular_price', ['%name%' => $productName]); |
116
|
|
|
|
117
|
|
|
return $this->getPriceFromString(trim($regularUnitPrice->getText())); |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
/** |
121
|
|
|
* {@inheritdoc} |
122
|
|
|
*/ |
123
|
|
|
public function getItemUnitPrice($productName) |
124
|
|
|
{ |
125
|
|
|
$unitPrice = $this->getElement('product_unit_price', ['%name%' => $productName]); |
126
|
|
|
|
127
|
|
|
return $this->getPriceFromString(trim($unitPrice->getText())); |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
public function getItemImage(int $itemNumber): string |
131
|
|
|
{ |
132
|
|
|
$itemImage = $this->getElement('item_image', ['%number%' => $itemNumber]); |
133
|
|
|
|
134
|
|
|
return $itemImage->getAttribute('src'); |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
/** |
138
|
|
|
* {@inheritdoc} |
139
|
|
|
*/ |
140
|
|
|
public function isItemDiscounted($productName) |
141
|
|
|
{ |
142
|
|
|
return $this->hasElement('product_unit_regular_price', ['%name%' => $productName]); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* {@inheritdoc} |
147
|
|
|
*/ |
148
|
|
|
public function removeProduct($productName) |
149
|
|
|
{ |
150
|
|
|
$itemElement = $this->getElement('product_row', ['%name%' => $productName]); |
151
|
|
|
$itemElement->find('css', 'button.sylius-cart-remove-button')->press(); |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
/** |
155
|
|
|
* {@inheritdoc} |
156
|
|
|
*/ |
157
|
|
|
public function applyCoupon($couponCode) |
158
|
|
|
{ |
159
|
|
|
$this->getElement('coupon_field')->setValue($couponCode); |
160
|
|
|
$this->getElement('apply_coupon_button')->press(); |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* {@inheritdoc} |
165
|
|
|
*/ |
166
|
|
|
public function changeQuantity($productName, $quantity) |
167
|
|
|
{ |
168
|
|
|
$itemElement = $this->getElement('product_row', ['%name%' => $productName]); |
169
|
|
|
$itemElement->find('css', 'input[type=number]')->setValue($quantity); |
170
|
|
|
|
171
|
|
|
$this->getElement('save_button')->click(); |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
/** |
175
|
|
|
* {@inheritdoc} |
176
|
|
|
*/ |
177
|
|
|
public function isSingleItemOnPage() |
178
|
|
|
{ |
179
|
|
|
$items = $this->getElement('cart_items')->findAll('css', 'tbody > tr'); |
180
|
|
|
|
181
|
|
|
return 1 === count($items); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* {@inheritdoc} |
186
|
|
|
*/ |
187
|
|
|
public function hasItemNamed($name) |
188
|
|
|
{ |
189
|
|
|
return $this->hasItemWith($name, '.sylius-product-name'); |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
/** |
193
|
|
|
* {@inheritdoc} |
194
|
|
|
*/ |
195
|
|
|
public function hasItemWithVariantNamed($variantName) |
196
|
|
|
{ |
197
|
|
|
return $this->hasItemWith($variantName, '.sylius-product-variant-name'); |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
/** |
201
|
|
|
* {@inheritdoc} |
202
|
|
|
*/ |
203
|
|
|
public function hasItemWithOptionValue($productName, $optionName, $optionValue) |
204
|
|
|
{ |
205
|
|
|
$itemElement = $this->getElement('product_row', ['%name%' => $productName]); |
206
|
|
|
|
207
|
|
|
$selector = sprintf('.sylius-product-options > .item[data-sylius-option-name="%s"]', $optionName); |
208
|
|
|
$optionValueElement = $itemElement->find('css', $selector); |
209
|
|
|
|
210
|
|
|
if (null === $optionValueElement) { |
211
|
|
|
throw new ElementNotFoundException($this->getSession(), sprintf('ProductOption value of "%s"', $optionName), 'css', $selector); |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
return $optionValue === $optionValueElement->getText(); |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* {@inheritdoc} |
219
|
|
|
*/ |
220
|
|
|
public function hasItemWithCode($code) |
221
|
|
|
{ |
222
|
|
|
return $this->hasItemWith($code, '.sylius-product-variant-code'); |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
/** |
226
|
|
|
* {@inheritdoc} |
227
|
|
|
*/ |
228
|
|
|
public function hasProductOutOfStockValidationMessage(ProductInterface $product) |
229
|
|
|
{ |
230
|
|
|
$message = sprintf('%s does not have sufficient stock.', $product->getName()); |
231
|
|
|
|
232
|
|
|
try { |
233
|
|
|
return $this->getElement('validation_errors')->getText() === $message; |
234
|
|
|
} catch (ElementNotFoundException $exception) { |
|
|
|
|
235
|
|
|
return false; |
236
|
|
|
} |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
/** |
240
|
|
|
* {@inheritdoc} |
241
|
|
|
*/ |
242
|
|
|
public function isEmpty() |
243
|
|
|
{ |
244
|
|
|
return false !== strpos($this->getDocument()->find('css', '.message')->getText(), 'Your cart is empty'); |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* {@inheritdoc} |
249
|
|
|
*/ |
250
|
|
|
public function getQuantity($productName) |
251
|
|
|
{ |
252
|
|
|
$itemElement = $this->getElement('product_row', ['%name%' => $productName]); |
253
|
|
|
|
254
|
|
|
return (int) $itemElement->find('css', 'input[type=number]')->getValue(); |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
/** |
258
|
|
|
* {@inheritdoc} |
259
|
|
|
*/ |
260
|
|
|
public function getCartTotal() |
261
|
|
|
{ |
262
|
|
|
$cartTotalText = $this->getElement('cart_total')->getText(); |
263
|
|
|
|
264
|
|
|
if (strpos($cartTotalText, ',') !== false) { |
265
|
|
|
return strstr($cartTotalText, ',', true); |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
return trim($cartTotalText); |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
public function clearCart() |
272
|
|
|
{ |
273
|
|
|
$this->getElement('clear_button')->click(); |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
public function updateCart() |
277
|
|
|
{ |
278
|
|
|
$this->getElement('update_button')->click(); |
279
|
|
|
} |
280
|
|
|
|
281
|
|
|
/** |
282
|
|
|
* {@inheritdoc} |
283
|
|
|
*/ |
284
|
|
|
public function waitForRedirect($timeout) |
285
|
|
|
{ |
286
|
|
|
$this->getDocument()->waitFor($timeout, function () { |
287
|
|
|
return $this->isOpen(); |
288
|
|
|
}); |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
/** |
292
|
|
|
* {@inheritdoc} |
293
|
|
|
*/ |
294
|
|
|
public function getPromotionCouponValidationMessage() |
295
|
|
|
{ |
296
|
|
|
return $this->getElement('promotion_coupon_validation_message')->getText(); |
297
|
|
|
} |
298
|
|
|
|
299
|
|
|
/** |
300
|
|
|
* {@inheritdoc} |
301
|
|
|
*/ |
302
|
|
|
protected function getDefinedElements(): array |
303
|
|
|
{ |
304
|
|
|
return array_merge(parent::getDefinedElements(), [ |
305
|
|
|
'apply_coupon_button' => 'button:contains("Apply coupon")', |
306
|
|
|
'base_grand_total' => '#sylius-cart-base-grand-total', |
307
|
|
|
'cart_items' => '#sylius-cart-items', |
308
|
|
|
'cart_total' => '#sylius-cart-total', |
309
|
|
|
'clear_button' => '#sylius-cart-clear', |
310
|
|
|
'coupon_field' => '#sylius_cart_promotionCoupon', |
311
|
|
|
'grand_total' => '#sylius-cart-grand-total', |
312
|
|
|
'item_image' => '#sylius-cart-items tbody tr:nth-child(%number%) img', |
313
|
|
|
'no_taxes' => '#sylius-cart-tax-none', |
314
|
|
|
'product_discounted_total' => '#sylius-cart-items tr:contains("%name%") .sylius-discounted-total', |
315
|
|
|
'product_row' => '#sylius-cart-items tbody tr:contains("%name%")', |
316
|
|
|
'product_total' => '#sylius-cart-items tr:contains("%name%") .sylius-total', |
317
|
|
|
'product_unit_price' => '#sylius-cart-items tr:contains("%name%") .sylius-unit-price', |
318
|
|
|
'product_unit_regular_price' => '#sylius-cart-items tr:contains("%name%") .sylius-regular-unit-price', |
319
|
|
|
'promotion_coupon_validation_message' => '#sylius-coupon .sylius-validation-error', |
320
|
|
|
'promotion_total' => '#sylius-cart-promotion-total', |
321
|
|
|
'save_button' => '#sylius-save', |
322
|
|
|
'shipping_total' => '#sylius-cart-shipping-total', |
323
|
|
|
'tax_excluded' => '#sylius-cart-tax-excluded', |
324
|
|
|
'tax_included' => '#sylius-cart-tax-included', |
325
|
|
|
'update_button' => '#sylius-cart-update', |
326
|
|
|
'validation_errors' => '.sylius-validation-error', |
327
|
|
|
]); |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
/** |
331
|
|
|
* @param string $attributeName |
332
|
|
|
* @param string|array $selector |
333
|
|
|
* |
334
|
|
|
* @return bool |
335
|
|
|
* |
336
|
|
|
* @throws ElementNotFoundException |
337
|
|
|
*/ |
338
|
|
|
private function hasItemWith($attributeName, $selector) |
339
|
|
|
{ |
340
|
|
|
$itemsAttributes = $this->getElement('cart_items')->findAll('css', $selector); |
341
|
|
|
|
342
|
|
|
foreach ($itemsAttributes as $itemAttribute) { |
343
|
|
|
if ($attributeName === $itemAttribute->getText()) { |
344
|
|
|
return true; |
345
|
|
|
} |
346
|
|
|
} |
347
|
|
|
|
348
|
|
|
return false; |
349
|
|
|
} |
350
|
|
|
|
351
|
|
|
private function getPriceFromString(string $price): int |
352
|
|
|
{ |
353
|
|
|
return (int) round((float) str_replace(['€', '£', '$'], '', $price) * 100, 2); |
354
|
|
|
} |
355
|
|
|
} |
356
|
|
|
|
Scrutinizer analyzes your
composer.json
/composer.lock
file if available to determine the classes, and functions that are defined by your dependencies.It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.