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\Context\Ui\Admin; |
13
|
|
|
|
14
|
|
|
use Behat\Behat\Context\Context; |
15
|
|
|
use Sylius\Behat\NotificationType; |
16
|
|
|
use Sylius\Behat\Page\Admin\Crud\CreatePageInterface; |
17
|
|
|
use Sylius\Behat\Page\Admin\Crud\UpdatePageInterface; |
18
|
|
|
use Sylius\Behat\Page\Admin\Product\CreateConfigurableProductPageInterface; |
19
|
|
|
use Sylius\Behat\Page\Admin\Product\CreateSimpleProductPageInterface; |
20
|
|
|
use Sylius\Behat\Page\Admin\Product\IndexPageInterface; |
21
|
|
|
use Sylius\Behat\Page\Admin\Product\UpdateConfigurableProductPageInterface; |
22
|
|
|
use Sylius\Behat\Page\Admin\Product\UpdateSimpleProductPageInterface; |
23
|
|
|
use Sylius\Behat\Service\NotificationCheckerInterface; |
24
|
|
|
use Sylius\Behat\Service\Resolver\CurrentProductPageResolverInterface; |
25
|
|
|
use Sylius\Component\Core\Model\ProductInterface; |
26
|
|
|
use Sylius\Behat\Service\SharedStorageInterface; |
27
|
|
|
use Sylius\Component\Taxonomy\Model\TaxonInterface; |
28
|
|
|
use Webmozart\Assert\Assert; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* @author Kamil Kokot <[email protected]> |
32
|
|
|
* @author Magdalena Banasiak <[email protected]> |
33
|
|
|
* @author Łukasz Chruściel <[email protected]> |
34
|
|
|
*/ |
35
|
|
|
final class ManagingProductsContext implements Context |
36
|
|
|
{ |
37
|
|
|
/** |
38
|
|
|
* @var SharedStorageInterface |
39
|
|
|
*/ |
40
|
|
|
private $sharedStorage; |
41
|
|
|
|
42
|
|
|
/**x |
43
|
|
|
* @var CreateSimpleProductPageInterface |
44
|
|
|
*/ |
45
|
|
|
private $createSimpleProductPage; |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @var CreateConfigurableProductPageInterface |
49
|
|
|
*/ |
50
|
|
|
private $createConfigurableProductPage; |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* @var IndexPageInterface |
54
|
|
|
*/ |
55
|
|
|
private $indexPage; |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* @var UpdateSimpleProductPageInterface |
59
|
|
|
*/ |
60
|
|
|
private $updateSimpleProductPage; |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* @var UpdateConfigurableProductPageInterface |
64
|
|
|
*/ |
65
|
|
|
private $updateConfigurableProductPage; |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* @var CurrentProductPageResolverInterface |
69
|
|
|
*/ |
70
|
|
|
private $currentPageResolver; |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* @var NotificationCheckerInterface |
74
|
|
|
*/ |
75
|
|
|
private $notificationChecker; |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* @param SharedStorageInterface $sharedStorage |
79
|
|
|
* @param CreateSimpleProductPageInterface $createSimpleProductPage |
80
|
|
|
* @param CreateConfigurableProductPageInterface $createConfigurableProductPage |
81
|
|
|
* @param IndexPageInterface $indexPage |
82
|
|
|
* @param UpdateSimpleProductPageInterface $updateSimpleProductPage |
83
|
|
|
* @param UpdateConfigurableProductPageInterface $updateConfigurableProductPage |
84
|
|
|
* @param CurrentProductPageResolverInterface $currentPageResolver |
85
|
|
|
* @param NotificationCheckerInterface $notificationChecker |
86
|
|
|
*/ |
87
|
|
|
public function __construct( |
88
|
|
|
SharedStorageInterface $sharedStorage, |
89
|
|
|
CreateSimpleProductPageInterface $createSimpleProductPage, |
90
|
|
|
CreateConfigurableProductPageInterface $createConfigurableProductPage, |
91
|
|
|
IndexPageInterface $indexPage, |
92
|
|
|
UpdateSimpleProductPageInterface $updateSimpleProductPage, |
93
|
|
|
UpdateConfigurableProductPageInterface $updateConfigurableProductPage, |
94
|
|
|
CurrentProductPageResolverInterface $currentPageResolver, |
95
|
|
|
NotificationCheckerInterface $notificationChecker |
96
|
|
|
) { |
97
|
|
|
$this->sharedStorage = $sharedStorage; |
98
|
|
|
$this->createSimpleProductPage = $createSimpleProductPage; |
99
|
|
|
$this->createConfigurableProductPage = $createConfigurableProductPage; |
100
|
|
|
$this->indexPage = $indexPage; |
101
|
|
|
$this->updateSimpleProductPage = $updateSimpleProductPage; |
102
|
|
|
$this->updateConfigurableProductPage = $updateConfigurableProductPage; |
103
|
|
|
$this->currentPageResolver = $currentPageResolver; |
104
|
|
|
$this->notificationChecker = $notificationChecker; |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @Given I want to create a new simple product |
109
|
|
|
*/ |
110
|
|
|
public function iWantToCreateANewSimpleProduct() |
111
|
|
|
{ |
112
|
|
|
$this->createSimpleProductPage->open(); |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
/** |
116
|
|
|
* @Given I want to create a new configurable product |
117
|
|
|
*/ |
118
|
|
|
public function iWantToCreateANewConfigurableProduct() |
119
|
|
|
{ |
120
|
|
|
$this->createConfigurableProductPage->open(); |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* @When I specify its code as :code |
125
|
|
|
* @When I do not specify its code |
126
|
|
|
*/ |
127
|
|
|
public function iSpecifyItsCodeAs($code = null) |
128
|
|
|
{ |
129
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
130
|
|
|
$this->createSimpleProductPage, |
131
|
|
|
$this->createConfigurableProductPage, |
132
|
|
|
]); |
133
|
|
|
|
134
|
|
|
$currentPage->specifyCode($code); |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
/** |
138
|
|
|
* @When I name it :name in :language |
139
|
|
|
*/ |
140
|
|
|
public function iNameItIn($name, $language) |
141
|
|
|
{ |
142
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
143
|
|
|
$this->createSimpleProductPage, |
144
|
|
|
$this->createConfigurableProductPage, |
145
|
|
|
]); |
146
|
|
|
|
147
|
|
|
$currentPage->nameItIn($name, $language); |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* @When I rename it to :name in :language |
152
|
|
|
*/ |
153
|
|
|
public function iRenameItToIn($name, $language) |
154
|
|
|
{ |
155
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
156
|
|
|
$this->updateSimpleProductPage, |
157
|
|
|
$this->updateConfigurableProductPage, |
158
|
|
|
], $this->sharedStorage->get('product')); |
159
|
|
|
|
160
|
|
|
$currentPage->nameItIn($name, $language); |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* @When I add it |
165
|
|
|
* @When I try to add it |
166
|
|
|
*/ |
167
|
|
|
public function iAddIt() |
168
|
|
|
{ |
169
|
|
|
/** @var CreatePageInterface $currentPage */ |
170
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
171
|
|
|
$this->createSimpleProductPage, |
172
|
|
|
$this->createConfigurableProductPage, |
173
|
|
|
]); |
174
|
|
|
|
175
|
|
|
Assert::isInstanceOf($currentPage, CreatePageInterface::class); |
176
|
|
|
|
177
|
|
|
$currentPage->create(); |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* @When I disable its inventory tracking |
182
|
|
|
*/ |
183
|
|
|
public function iDisableItsTracking() |
184
|
|
|
{ |
185
|
|
|
$this->updateSimpleProductPage->disableTracking(); |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
/** |
189
|
|
|
* @When I enable its inventory tracking |
190
|
|
|
*/ |
191
|
|
|
public function iEnableItsTracking() |
192
|
|
|
{ |
193
|
|
|
$this->updateSimpleProductPage->enableTracking(); |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* @When /^I set its price to ("(?:€|£|\$)[^"]+")$/ |
198
|
|
|
*/ |
199
|
|
|
public function iSetItsPriceTo($price) |
200
|
|
|
{ |
201
|
|
|
$this->createSimpleProductPage->specifyPrice($price); |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* @Then the product :productName should appear in the shop |
206
|
|
|
* @Then the product :productName should be in the shop |
207
|
|
|
* @Then this product should still be named :productName |
208
|
|
|
*/ |
209
|
|
|
public function theProductShouldAppearInTheShop($productName) |
210
|
|
|
{ |
211
|
|
|
$this->iWantToBrowseProducts(); |
212
|
|
|
|
213
|
|
|
Assert::true( |
214
|
|
|
$this->indexPage->isSingleResourceOnPage(['name' => $productName]), |
215
|
|
|
sprintf('The product with name %s has not been found.', $productName) |
216
|
|
|
); |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
/** |
220
|
|
|
* @Given I am browsing products |
221
|
|
|
* @When I want to browse products |
222
|
|
|
*/ |
223
|
|
|
public function iWantToBrowseProducts() |
224
|
|
|
{ |
225
|
|
|
$this->indexPage->open(); |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
/** |
229
|
|
|
* @When I filter them by :taxonName taxon |
230
|
|
|
*/ |
231
|
|
|
public function iFilterThemByTaxon($taxonName) |
232
|
|
|
{ |
233
|
|
|
$this->indexPage->filterByTaxon($taxonName); |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
/** |
237
|
|
|
* @Then I should( still) see a product with :field :value |
238
|
|
|
*/ |
239
|
|
|
public function iShouldSeeProductWith($field, $value) |
240
|
|
|
{ |
241
|
|
|
Assert::true( |
242
|
|
|
$this->indexPage->isSingleResourceOnPage([$field => $value]), |
243
|
|
|
sprintf('The product with %s "%s" has not been found.', $field, $value) |
244
|
|
|
); |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* @Then I should not see any product with :field :value |
249
|
|
|
*/ |
250
|
|
|
public function iShouldNotSeeAnyProductWith($field, $value) |
251
|
|
|
{ |
252
|
|
|
Assert::false( |
253
|
|
|
$this->indexPage->isSingleResourceOnPage([$field => $value]), |
254
|
|
|
sprintf('The product with %s "%s" has been found.', $field, $value) |
255
|
|
|
); |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
/** |
259
|
|
|
* @Then the first product on the list should have :field :value |
260
|
|
|
*/ |
261
|
|
|
public function theFirstProductOnTheListShouldHave($field, $value) |
262
|
|
|
{ |
263
|
|
|
$actualValue = $this->indexPage->getColumnFields($field)[0]; |
264
|
|
|
|
265
|
|
|
Assert::same( |
266
|
|
|
$actualValue, |
267
|
|
|
$value, |
268
|
|
|
sprintf('Expected first product\'s %s to be "%s", but it is "%s".', $field, $value, $actualValue) |
269
|
|
|
); |
270
|
|
|
} |
271
|
|
|
|
272
|
|
|
/** |
273
|
|
|
* @When I switch the way products are sorted by :field |
274
|
|
|
* @When I start sorting products by :field |
275
|
|
|
* @Given the products are already sorted by :field |
276
|
|
|
*/ |
277
|
|
|
public function iSortProductsBy($field) |
278
|
|
|
{ |
279
|
|
|
$this->indexPage->sortBy($field); |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
/** |
283
|
|
|
* @Then I should see :numberOfProducts products in the list |
284
|
|
|
*/ |
285
|
|
|
public function iShouldSeeProductsInTheList($numberOfProducts) |
286
|
|
|
{ |
287
|
|
|
$foundRows = $this->indexPage->countItems(); |
288
|
|
|
|
289
|
|
|
Assert::same( |
290
|
|
|
(int) $numberOfProducts, |
291
|
|
|
$foundRows, |
292
|
|
|
'%s rows with products should appear on page, %s rows has been found' |
293
|
|
|
); |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
/** |
297
|
|
|
* @When I delete the :product product |
298
|
|
|
* @When I try to delete the :product product |
299
|
|
|
*/ |
300
|
|
|
public function iDeleteProduct(ProductInterface $product) |
301
|
|
|
{ |
302
|
|
|
$this->sharedStorage->set('product', $product); |
303
|
|
|
|
304
|
|
|
$this->iWantToBrowseProducts(); |
305
|
|
|
$this->indexPage->deleteResourceOnPage(['name' => $product->getName()]); |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
/** |
309
|
|
|
* @Then /^(this product) should not exist in the product catalog$/ |
310
|
|
|
*/ |
311
|
|
|
public function productShouldNotExist(ProductInterface $product) |
312
|
|
|
{ |
313
|
|
|
$this->iWantToBrowseProducts(); |
314
|
|
|
|
315
|
|
|
Assert::false( |
316
|
|
|
$this->indexPage->isSingleResourceOnPage(['code' => $product->getCode()]), |
317
|
|
|
sprintf('Product with code %s exists but should not.', $product->getCode()) |
318
|
|
|
); |
319
|
|
|
} |
320
|
|
|
|
321
|
|
|
/** |
322
|
|
|
* @Then I should be notified that this product is in use and cannot be deleted |
323
|
|
|
*/ |
324
|
|
|
public function iShouldBeNotifiedOfFailure() |
325
|
|
|
{ |
326
|
|
|
$this->notificationChecker->checkNotification( |
327
|
|
|
"Cannot delete, the product is in use.", |
328
|
|
|
NotificationType::failure() |
329
|
|
|
); |
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
/** |
333
|
|
|
* @Then /^(this product) should still exist in the product catalog$/ |
334
|
|
|
*/ |
335
|
|
|
public function productShouldExistInTheProductCatalog(ProductInterface $product) |
336
|
|
|
{ |
337
|
|
|
$this->theProductShouldAppearInTheShop($product->getName()); |
338
|
|
|
} |
339
|
|
|
|
340
|
|
|
/** |
341
|
|
|
* @When I want to modify the :product product |
342
|
|
|
* @When /^I want to modify (this product)$/ |
343
|
|
|
*/ |
344
|
|
|
public function iWantToModifyAProduct(ProductInterface $product) |
345
|
|
|
{ |
346
|
|
|
$this->sharedStorage->set('product', $product); |
347
|
|
|
|
348
|
|
|
if ($product->isSimple()) { |
349
|
|
|
$this->updateSimpleProductPage->open(['id' => $product->getId()]); |
350
|
|
|
return; |
351
|
|
|
} |
352
|
|
|
|
353
|
|
|
$this->updateConfigurableProductPage->open(['id' => $product->getId()]); |
354
|
|
|
} |
355
|
|
|
|
356
|
|
|
/** |
357
|
|
|
* @Then the code field should be disabled |
358
|
|
|
*/ |
359
|
|
|
public function theCodeFieldShouldBeDisabled() |
360
|
|
|
{ |
361
|
|
|
/** @var UpdatePageInterface $currentPage */ |
362
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
363
|
|
|
$this->updateSimpleProductPage, |
364
|
|
|
$this->updateConfigurableProductPage, |
365
|
|
|
], $this->sharedStorage->get('product')); |
366
|
|
|
|
367
|
|
|
Assert::true( |
368
|
|
|
$currentPage->isCodeDisabled(), |
369
|
|
|
'Code should be immutable, but it does not.' |
370
|
|
|
); |
371
|
|
|
} |
372
|
|
|
|
373
|
|
|
/** |
374
|
|
|
* @Then /^this product price should be "(?:€|£|\$)([^"]+)"$/ |
375
|
|
|
*/ |
376
|
|
|
public function thisProductPriceShouldBeEqualTo($price) |
377
|
|
|
{ |
378
|
|
|
$this->assertElementValue('price', $price); |
379
|
|
|
} |
380
|
|
|
|
381
|
|
|
/** |
382
|
|
|
* @Then this product name should be :name |
383
|
|
|
*/ |
384
|
|
|
public function thisProductElementShouldBe($name) |
385
|
|
|
{ |
386
|
|
|
$this->assertElementValue('name', $name); |
387
|
|
|
} |
388
|
|
|
|
389
|
|
|
/** |
390
|
|
|
* @Then /^I should be notified that (code|name) is required$/ |
391
|
|
|
*/ |
392
|
|
|
public function iShouldBeNotifiedThatIsRequired($element) |
393
|
|
|
{ |
394
|
|
|
$this->assertValidationMessage($element, sprintf('Please enter product %s.', $element)); |
395
|
|
|
} |
396
|
|
|
|
397
|
|
|
/** |
398
|
|
|
* @Then I should be notified that price is required |
399
|
|
|
*/ |
400
|
|
|
public function iShouldBeNotifiedThatPriceIsRequired() |
401
|
|
|
{ |
402
|
|
|
$this->assertValidationMessage('price', 'Please enter the price.'); |
403
|
|
|
} |
404
|
|
|
|
405
|
|
|
/** |
406
|
|
|
* @When I save my changes |
407
|
|
|
* @When I try to save my changes |
408
|
|
|
*/ |
409
|
|
|
public function iSaveMyChanges() |
410
|
|
|
{ |
411
|
|
|
/** @var UpdatePageInterface $currentPage */ |
412
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
413
|
|
|
$this->updateSimpleProductPage, |
414
|
|
|
$this->updateConfigurableProductPage, |
415
|
|
|
], $this->sharedStorage->get('product')); |
416
|
|
|
|
417
|
|
|
Assert::isInstanceOf($currentPage, UpdatePageInterface::class); |
418
|
|
|
|
419
|
|
|
$currentPage->saveChanges(); |
420
|
|
|
} |
421
|
|
|
|
422
|
|
|
/** |
423
|
|
|
* @When /^I change its price to "(?:€|£|\$)([^"]+)"$/ |
424
|
|
|
*/ |
425
|
|
|
public function iChangeItsPriceTo($price) |
426
|
|
|
{ |
427
|
|
|
$this->updateSimpleProductPage->specifyPrice($price); |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
/** |
431
|
|
|
* @Given I add the :optionName option to it |
432
|
|
|
*/ |
433
|
|
|
public function iAddTheOptionToIt($optionName) |
434
|
|
|
{ |
435
|
|
|
$this->createConfigurableProductPage->selectOption($optionName); |
436
|
|
|
} |
437
|
|
|
|
438
|
|
|
/** |
439
|
|
|
* @When I set its :attribute attribute to :value |
440
|
|
|
*/ |
441
|
|
|
public function iSetItsAttributeTo($attribute, $value) |
442
|
|
|
{ |
443
|
|
|
$this->createSimpleProductPage->addAttribute($attribute, $value); |
444
|
|
|
} |
445
|
|
|
|
446
|
|
|
/** |
447
|
|
|
* @When I remove its :attribute attribute |
448
|
|
|
*/ |
449
|
|
|
public function iRemoveItsAttribute($attribute) |
450
|
|
|
{ |
451
|
|
|
$this->createSimpleProductPage->removeAttribute($attribute); |
452
|
|
|
} |
453
|
|
|
|
454
|
|
|
/** |
455
|
|
|
* @Then /^attribute "([^"]+)" of (product "[^"]+") should be "([^"]+)"$/ |
456
|
|
|
*/ |
457
|
|
|
public function itsAttributeShouldBe($attribute, ProductInterface $product, $value) |
458
|
|
|
{ |
459
|
|
|
$this->updateSimpleProductPage->open(['id' => $product->getId()]); |
460
|
|
|
|
461
|
|
|
Assert::same( |
462
|
|
|
$value, |
463
|
|
|
$this->updateSimpleProductPage->getAttributeValue($attribute), |
464
|
|
|
sprintf('ProductAttribute "%s" should have value "%s" but it does not.', $attribute, $value) |
465
|
|
|
); |
466
|
|
|
} |
467
|
|
|
|
468
|
|
|
/** |
469
|
|
|
* @Then /^(product "[^"]+") should not have a "([^"]+)" attribute$/ |
470
|
|
|
*/ |
471
|
|
|
public function productShouldNotHaveAttribute(ProductInterface $product, $attribute) |
472
|
|
|
{ |
473
|
|
|
$this->updateSimpleProductPage->open(['id' => $product->getId()]); |
474
|
|
|
|
475
|
|
|
Assert::false( |
476
|
|
|
$this->updateSimpleProductPage->hasAttribute($attribute), |
477
|
|
|
sprintf('Product "%s" should not have attribute "%s" but it does.', $product->getName(), $attribute) |
478
|
|
|
); |
479
|
|
|
} |
480
|
|
|
|
481
|
|
|
/** |
482
|
|
|
* @Given product with :element :value should not be added |
483
|
|
|
*/ |
484
|
|
|
public function productWithNameShouldNotBeAdded($element, $value) |
485
|
|
|
{ |
486
|
|
|
$this->iWantToBrowseProducts(); |
487
|
|
|
|
488
|
|
|
Assert::false( |
489
|
|
|
$this->indexPage->isSingleResourceOnPage([$element => $value]), |
490
|
|
|
sprintf('Product with %s %s was created, but it should not.', $element, $value) |
491
|
|
|
); |
492
|
|
|
} |
493
|
|
|
|
494
|
|
|
/** |
495
|
|
|
* @When I remove its name from :language translation |
496
|
|
|
*/ |
497
|
|
|
public function iRemoveItsNameFromTranslation($language) |
498
|
|
|
{ |
499
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
500
|
|
|
$this->updateSimpleProductPage, |
501
|
|
|
$this->updateConfigurableProductPage, |
502
|
|
|
], $this->sharedStorage->get('product')); |
503
|
|
|
|
504
|
|
|
$currentPage->nameItIn('', $language); |
505
|
|
|
} |
506
|
|
|
|
507
|
|
|
/** |
508
|
|
|
* @Then /^this product should have (?:a|an) "([^"]+)" option$/ |
509
|
|
|
*/ |
510
|
|
|
public function thisProductShouldHaveOption($productOption) |
511
|
|
|
{ |
512
|
|
|
$this->updateConfigurableProductPage->isProductOptionChosen($productOption); |
513
|
|
|
} |
514
|
|
|
|
515
|
|
|
/** |
516
|
|
|
* @Then the option field should be disabled |
517
|
|
|
*/ |
518
|
|
|
public function theOptionFieldShouldBeDisabled() |
519
|
|
|
{ |
520
|
|
|
Assert::true( |
521
|
|
|
$this->updateConfigurableProductPage->isProductOptionsDisabled(), |
522
|
|
|
'Options field should be immutable, but it does not.' |
523
|
|
|
); |
524
|
|
|
} |
525
|
|
|
|
526
|
|
|
/** |
527
|
|
|
* @When /^I choose main (taxon "([^"]+)")$/ |
528
|
|
|
*/ |
529
|
|
|
public function iChooseMainTaxon(TaxonInterface $taxon) |
530
|
|
|
{ |
531
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
532
|
|
|
$this->updateSimpleProductPage, |
533
|
|
|
$this->updateConfigurableProductPage, |
534
|
|
|
], $this->sharedStorage->get('product')); |
535
|
|
|
|
536
|
|
|
$currentPage->selectMainTaxon($taxon); |
537
|
|
|
} |
538
|
|
|
|
539
|
|
|
/** |
540
|
|
|
* @Then /^(this product) main taxon should be "([^"]+)"$/ |
541
|
|
|
*/ |
542
|
|
|
public function thisProductMainTaxonShouldBe(ProductInterface $product, $taxonName) |
543
|
|
|
{ |
544
|
|
|
/** @var UpdatePageInterface $currentPage */ |
545
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
546
|
|
|
$this->updateSimpleProductPage, |
547
|
|
|
$this->updateConfigurableProductPage, |
548
|
|
|
], $this->sharedStorage->get('product')); |
549
|
|
|
|
550
|
|
|
$currentPage->open(['id' => $product->getId()]); |
551
|
|
|
|
552
|
|
|
Assert::true( |
553
|
|
|
$this->updateConfigurableProductPage->isMainTaxonChosen($taxonName), |
554
|
|
|
sprintf('The main taxon %s should be chosen, but it does not.', $taxonName) |
555
|
|
|
); |
556
|
|
|
} |
557
|
|
|
|
558
|
|
|
/** |
559
|
|
|
* @Then /^inventory of (this product) should not be tracked$/ |
560
|
|
|
*/ |
561
|
|
|
public function thisProductShouldNotBeTracked(ProductInterface $product) |
562
|
|
|
{ |
563
|
|
|
$this->iWantToModifyAProduct($product); |
564
|
|
|
|
565
|
|
|
Assert::false( |
566
|
|
|
$this->updateSimpleProductPage->isTracked(), |
567
|
|
|
'"%s" should not be tracked, but it is.' |
568
|
|
|
); |
569
|
|
|
} |
570
|
|
|
|
571
|
|
|
/** |
572
|
|
|
* @Then /^inventory of (this product) should be tracked$/ |
573
|
|
|
*/ |
574
|
|
|
public function thisProductShouldBeTracked(ProductInterface $product) |
575
|
|
|
{ |
576
|
|
|
$this->iWantToModifyAProduct($product); |
577
|
|
|
|
578
|
|
|
Assert::true( |
579
|
|
|
$this->updateSimpleProductPage->isTracked(), |
580
|
|
|
'"%s" should be tracked, but it is not.' |
581
|
|
|
); |
582
|
|
|
} |
583
|
|
|
|
584
|
|
|
/** |
585
|
|
|
* @When I attach the :path image with a code :code |
586
|
|
|
*/ |
587
|
|
|
public function iAttachImageWithACode($path, $code) |
588
|
|
|
{ |
589
|
|
|
/** @var CreatePageInterface|UpdatePageInterface $currentPage */ |
590
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
591
|
|
|
$this->createSimpleProductPage, |
592
|
|
|
$this->createConfigurableProductPage, |
593
|
|
|
$this->updateSimpleProductPage, |
594
|
|
|
$this->updateConfigurableProductPage, |
595
|
|
|
], $this->sharedStorage->has('product') ? $this->sharedStorage->get('product') : null); |
596
|
|
|
|
597
|
|
|
$currentPage->attachImageWithCode($code, $path); |
598
|
|
|
} |
599
|
|
|
|
600
|
|
|
/** |
601
|
|
|
* @Then /^(this product) should have(?:| also) an image with a code "([^"]*)"$/ |
602
|
|
|
* @Then /^the (product "[^"]+") should have(?:| also) an image with a code "([^"]*)"$/ |
603
|
|
|
*/ |
604
|
|
|
public function thisProductShouldHaveAnImageWithCode(ProductInterface $product, $code) |
605
|
|
|
{ |
606
|
|
|
$this->sharedStorage->set('product', $product); |
607
|
|
|
|
608
|
|
|
/** @var UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface $currentPage */ |
609
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
610
|
|
|
$this->updateSimpleProductPage, |
611
|
|
|
$this->updateConfigurableProductPage, |
612
|
|
|
], $product); |
613
|
|
|
|
614
|
|
|
Assert::true( |
615
|
|
|
$currentPage->isImageWithCodeDisplayed($code), |
616
|
|
|
sprintf('Image with a code %s should have been displayed.', $code) |
617
|
|
|
); |
618
|
|
|
} |
619
|
|
|
|
620
|
|
|
/** |
621
|
|
|
* @Then /^(this product) should not have(?:| also) an image with a code "([^"]*)"$/ |
622
|
|
|
*/ |
623
|
|
|
public function thisProductShouldNotHaveAnImageWithCode(ProductInterface $product, $code) |
624
|
|
|
{ |
625
|
|
|
/** @var UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface $currentPage */ |
626
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
627
|
|
|
$this->updateSimpleProductPage, |
628
|
|
|
$this->updateConfigurableProductPage, |
629
|
|
|
], $product); |
630
|
|
|
|
631
|
|
|
Assert::false( |
632
|
|
|
$currentPage->isImageWithCodeDisplayed($code), |
633
|
|
|
sprintf('Image with a code %s should not have been displayed.', $code) |
634
|
|
|
); |
635
|
|
|
} |
636
|
|
|
|
637
|
|
|
/** |
638
|
|
|
* @When I change the image with the :code code to :path |
639
|
|
|
*/ |
640
|
|
|
public function iChangeItsImageToPathForTheCode($path, $code) |
641
|
|
|
{ |
642
|
|
|
/** @var UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface $currentPage */ |
643
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
644
|
|
|
$this->updateSimpleProductPage, |
645
|
|
|
$this->updateConfigurableProductPage, |
646
|
|
|
], $this->sharedStorage->get('product')); |
647
|
|
|
|
648
|
|
|
$currentPage->changeImageWithCode($code, $path); |
649
|
|
|
} |
650
|
|
|
|
651
|
|
|
/** |
652
|
|
|
* @When /^I remove(?:| also) an image with a code "([^"]*)"$/ |
653
|
|
|
*/ |
654
|
|
|
public function iRemoveAnImageWithACode($code) |
655
|
|
|
{ |
656
|
|
|
/** @var UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface $currentPage */ |
657
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
658
|
|
|
$this->updateSimpleProductPage, |
659
|
|
|
$this->updateConfigurableProductPage, |
660
|
|
|
], $this->sharedStorage->get('product')); |
661
|
|
|
|
662
|
|
|
$currentPage->removeImageWithCode($code); |
663
|
|
|
} |
664
|
|
|
|
665
|
|
|
/** |
666
|
|
|
* @When I remove the first image |
667
|
|
|
*/ |
668
|
|
|
public function iRemoveTheFirstImage() |
669
|
|
|
{ |
670
|
|
|
/** @var UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface $currentPage */ |
671
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
672
|
|
|
$this->updateSimpleProductPage, |
673
|
|
|
$this->updateConfigurableProductPage, |
674
|
|
|
], $this->sharedStorage->get('product')); |
675
|
|
|
|
676
|
|
|
$currentPage->removeFirstImage(); |
677
|
|
|
} |
678
|
|
|
|
679
|
|
|
/** |
680
|
|
|
* @Then this product should not have images |
681
|
|
|
*/ |
682
|
|
|
public function thisProductShouldNotHaveImages() |
683
|
|
|
{ |
684
|
|
|
/** @var UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface $currentPage */ |
685
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
686
|
|
|
$this->updateSimpleProductPage, |
687
|
|
|
$this->updateConfigurableProductPage, |
688
|
|
|
], $this->sharedStorage->get('product')); |
689
|
|
|
|
690
|
|
|
Assert::same( |
691
|
|
|
0, |
692
|
|
|
$currentPage->countImages(), |
693
|
|
|
'This product has %2$s, but it should not have.' |
694
|
|
|
); |
695
|
|
|
} |
696
|
|
|
|
697
|
|
|
/** |
698
|
|
|
* @Then the image code field should be disabled |
699
|
|
|
*/ |
700
|
|
|
public function theImageCodeFieldShouldBeDisabled() |
701
|
|
|
{ |
702
|
|
|
/** @var UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface $currentPage */ |
703
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
704
|
|
|
$this->updateSimpleProductPage, |
705
|
|
|
$this->updateConfigurableProductPage, |
706
|
|
|
], $this->sharedStorage->get('product')); |
707
|
|
|
|
708
|
|
|
Assert::true( |
709
|
|
|
$currentPage->isImageCodeDisabled(), |
710
|
|
|
'Image code field should be disabled but it is not.' |
711
|
|
|
); |
712
|
|
|
} |
713
|
|
|
|
714
|
|
|
/** |
715
|
|
|
* @Then I should be notified that the image with this code already exists |
716
|
|
|
*/ |
717
|
|
|
public function iShouldBeNotifiedThatTheImageWithThisCodeAlreadyExists() |
718
|
|
|
{ |
719
|
|
|
Assert::same($this->updateSimpleProductPage->getValidationMessageForImage('code'), 'Image code must be unique within this product.'); |
|
|
|
|
720
|
|
|
} |
721
|
|
|
|
722
|
|
|
/** |
723
|
|
|
* @Then there should still be only one image in the :product product |
724
|
|
|
*/ |
725
|
|
|
public function thereShouldStillBeOnlyOneImageInThisTaxon(ProductInterface $product) |
726
|
|
|
{ |
727
|
|
|
$this->iWantToModifyAProduct($product); |
728
|
|
|
|
729
|
|
|
/** @var UpdateSimpleProductPageInterface|UpdateConfigurableProductPageInterface $currentPage */ |
730
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
731
|
|
|
$this->updateSimpleProductPage, |
732
|
|
|
$this->updateConfigurableProductPage, |
733
|
|
|
], $product); |
734
|
|
|
|
735
|
|
|
Assert::same( |
736
|
|
|
1, |
737
|
|
|
$currentPage->countImages(), |
738
|
|
|
'This product has %2$s images, but it should have only one.' |
739
|
|
|
); |
740
|
|
|
} |
741
|
|
|
|
742
|
|
|
/** |
743
|
|
|
* @param string $element |
744
|
|
|
* @param string $value |
745
|
|
|
*/ |
746
|
|
|
private function assertElementValue($element, $value) |
747
|
|
|
{ |
748
|
|
|
/** @var UpdatePageInterface $currentPage */ |
749
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
750
|
|
|
$this->updateSimpleProductPage, |
751
|
|
|
$this->updateConfigurableProductPage, |
752
|
|
|
], $this->sharedStorage->get('product')); |
753
|
|
|
|
754
|
|
|
Assert::isInstanceOf($currentPage, UpdatePageInterface::class); |
755
|
|
|
|
756
|
|
|
Assert::true( |
757
|
|
|
$currentPage->hasResourceValues( |
758
|
|
|
[$element => $value] |
759
|
|
|
), |
760
|
|
|
sprintf('Product should have %s with %s value.', $element, $value) |
761
|
|
|
); |
762
|
|
|
} |
763
|
|
|
|
764
|
|
|
/** |
765
|
|
|
* @param string $element |
766
|
|
|
* @param string $message |
767
|
|
|
*/ |
768
|
|
|
private function assertValidationMessage($element, $message) |
769
|
|
|
{ |
770
|
|
|
$product = $this->sharedStorage->has('product') ? $this->sharedStorage->get('product') : null; |
771
|
|
|
|
772
|
|
|
/** @var CreatePageInterface|UpdatePageInterface $currentPage */ |
773
|
|
|
$currentPage = $this->currentPageResolver->getCurrentPageWithForm([ |
774
|
|
|
$this->createSimpleProductPage, |
775
|
|
|
$this->createConfigurableProductPage, |
776
|
|
|
$this->updateSimpleProductPage, |
777
|
|
|
$this->updateConfigurableProductPage, |
778
|
|
|
], $product); |
779
|
|
|
|
780
|
|
|
Assert::same($currentPage->getValidationMessage($element), $message); |
781
|
|
|
} |
782
|
|
|
} |
783
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.