Completed
Push — master ( 78fd01...e243d3 )
by Paweł
11:06
created

ManagingPromotionsContext::iCheckThePromotion()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
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
declare(strict_types=1);
13
14
namespace Sylius\Behat\Context\Ui\Admin;
15
16
use Behat\Behat\Context\Context;
17
use Sylius\Behat\NotificationType;
18
use Sylius\Behat\Page\Admin\Promotion\CreatePageInterface;
19
use Sylius\Behat\Page\Admin\Promotion\IndexPageInterface;
20
use Sylius\Behat\Page\Admin\Promotion\UpdatePageInterface;
21
use Sylius\Behat\Service\NotificationCheckerInterface;
22
use Sylius\Behat\Service\Resolver\CurrentPageResolverInterface;
23
use Sylius\Behat\Service\SharedStorageInterface;
24
use Sylius\Component\Core\Model\PromotionInterface;
25
use Webmozart\Assert\Assert;
26
27
final class ManagingPromotionsContext implements Context
28
{
29
    /**
30
     * @var SharedStorageInterface
31
     */
32
    private $sharedStorage;
33
34
    /**
35
     * @var IndexPageInterface
36
     */
37
    private $indexPage;
38
39
    /**
40
     * @var CreatePageInterface
41
     */
42
    private $createPage;
43
44
    /**
45
     * @var UpdatePageInterface
46
     */
47
    private $updatePage;
48
49
    /**
50
     * @var CurrentPageResolverInterface
51
     */
52
    private $currentPageResolver;
53
54
    /**
55
     * @var NotificationCheckerInterface
56
     */
57
    private $notificationChecker;
58
59
    /**
60
     * @param SharedStorageInterface $sharedStorage
61
     * @param IndexPageInterface $indexPage
62
     * @param CreatePageInterface $createPage
63
     * @param UpdatePageInterface $updatePage
64
     * @param CurrentPageResolverInterface $currentPageResolver
65
     * @param NotificationCheckerInterface $notificationChecker
66
     */
67
    public function __construct(
68
        SharedStorageInterface $sharedStorage,
69
        IndexPageInterface $indexPage,
70
        CreatePageInterface $createPage,
71
        UpdatePageInterface $updatePage,
72
        CurrentPageResolverInterface $currentPageResolver,
73
        NotificationCheckerInterface $notificationChecker
74
    ) {
75
        $this->sharedStorage = $sharedStorage;
76
        $this->indexPage = $indexPage;
77
        $this->createPage = $createPage;
78
        $this->updatePage = $updatePage;
79
        $this->currentPageResolver = $currentPageResolver;
80
        $this->notificationChecker = $notificationChecker;
81
    }
82
83
    /**
84
     * @When I want to create a new promotion
85
     */
86
    public function iWantToCreateANewPromotion()
87
    {
88
        $this->createPage->open();
89
    }
90
91
    /**
92
     * @Given I want to browse promotions
93
     * @When I browse promotions
94
     */
95
    public function iWantToBrowsePromotions()
96
    {
97
        $this->indexPage->open();
98
    }
99
100
    /**
101
     * @When I specify its code as :code
102
     * @When I do not specify its code
103
     */
104
    public function iSpecifyItsCodeAs($code = null)
105
    {
106
        $this->createPage->specifyCode($code);
107
    }
108
109
    /**
110
     * @When I name it :name
111
     * @When I do not name it
112
     * @When I remove its name
113
     */
114
    public function iNameIt($name = null)
115
    {
116
        $this->createPage->nameIt($name);
117
    }
118
119
    /**
120
     * @When I remove its priority
121
     */
122
    public function iRemoveItsPriority()
123
    {
124
        $this->updatePage->setPriority(null);
125
    }
126
127
    /**
128
     * @Then I should see the promotion :promotionName in the list
129
     * @Then the :promotionName promotion should appear in the registry
130
     * @Then the :promotionName promotion should exist in the registry
131
     * @Then this promotion should still be named :promotionName
132
     * @Then promotion :promotionName should still exist in the registry
133
     */
134
    public function thePromotionShouldAppearInTheRegistry(string $promotionName): void
135
    {
136
        $this->indexPage->open();
137
138
        Assert::true($this->indexPage->isSingleResourceOnPage(['name' => $promotionName]));
139
    }
140
141
    /**
142
     * @When I add it
143
     * @When I try to add it
144
     */
145
    public function iAddIt()
146
    {
147
        $this->createPage->create();
148
    }
149
150
    /**
151
     * @When I add the "Has at least one from taxons" rule configured with :firstTaxon
152
     * @When I add the "Has at least one from taxons" rule configured with :firstTaxon and :secondTaxon
153
     */
154
    public function iAddTheHasTaxonRuleConfiguredWith(...$taxons)
155
    {
156
        $this->createPage->addRule('Has at least one from taxons');
157
158
        $this->createPage->selectAutocompleteRuleOption('Taxons', $taxons, true);
159
    }
160
161
    /**
162
     * @When /^I add the "Total price of items from taxon" rule configured with "([^"]+)" taxon and (?:€|£|\$)([^"]+) amount for "([^"]+)" channel$/
163
     */
164
    public function iAddTheRuleConfiguredWith($taxonName, $amount, $channelName)
165
    {
166
        $this->createPage->addRule('Total price of items from taxon');
167
        $this->createPage->selectAutocompleteRuleOption('Taxon', $taxonName);
168
        $this->createPage->fillRuleOptionForChannel($channelName, 'Amount', $amount);
169
    }
170
171
    /**
172
     * @When /^I add the "Item total" rule configured with (?:€|£|\$)([^"]+) amount for "([^"]+)" channel and (?:€|£|\$)([^"]+) amount for "([^"]+)" channel$/
173
     */
174
    public function iAddTheItemTotalRuleConfiguredWithTwoChannel(
175
        $firstAmount,
176
        $firstChannelName,
177
        $secondAmount,
178
        $secondChannelName
179
    ) {
180
        $this->createPage->addRule('Item total');
181
        $this->createPage->fillRuleOptionForChannel($firstChannelName, 'Amount', $firstAmount);
182
        $this->createPage->fillRuleOptionForChannel($secondChannelName, 'Amount', $secondAmount);
183
    }
184
185
    /**
186
     * @When /^I add the "([^"]+)" action configured with amount of "(?:€|£|\$)([^"]+)" for "([^"]+)" channel$/
187
     */
188
    public function iAddTheActionConfiguredWithAmountForChannel($actionType, $amount, $channelName)
189
    {
190
        $this->createPage->addAction($actionType);
191
        $this->createPage->fillActionOptionForChannel($channelName, 'Amount', $amount);
192
    }
193
194
    /**
195
     * @When /^it is(?:| also) configured with amount of "(?:€|£|\$)([^"]+)" for "([^"]+)" channel$/
196
     */
197
    public function itIsConfiguredWithAmountForChannel($amount, $channelName)
198
    {
199
        $this->createPage->fillActionOptionForChannel($channelName, 'Amount', $amount);
200
    }
201
202
    /**
203
     * @When /^I specify that on "([^"]+)" channel this action should be applied to items with price greater then "(?:€|£|\$)([^"]+)"$/
204
     */
205
    public function iAddAMinPriceFilterRangeForChannel($channelName, $minimum)
206
    {
207
        $this->createPage->fillActionOptionForChannel($channelName, 'Min', $minimum);
208
    }
209
210
    /**
211
     * @When /^I specify that on "([^"]+)" channel this action should be applied to items with price lesser then "(?:€|£|\$)([^"]+)"$/
212
     */
213
    public function iAddAMaxPriceFilterRangeForChannel($channelName, $maximum)
214
    {
215
        $this->createPage->fillActionOptionForChannel($channelName, 'Max', $maximum);
216
    }
217
218
    /**
219
     * @When /^I specify that on "([^"]+)" channel this action should be applied to items with price between "(?:€|£|\$)([^"]+)" and "(?:€|£|\$)([^"]+)"$/
220
     */
221
    public function iAddAMinMaxPriceFilterRangeForChannel($channelName, $minimum, $maximum)
222
    {
223
        $this->iAddAMinPriceFilterRangeForChannel($channelName, $minimum);
224
        $this->iAddAMaxPriceFilterRangeForChannel($channelName, $maximum);
225
    }
226
227
    /**
228
     * @When I specify that this action should be applied to items from :taxonName category
229
     */
230
    public function iSpecifyThatThisActionShouldBeAppliedToItemsFromCategory($taxonName)
231
    {
232
        $this->createPage->selectAutoCompleteFilterOption('Taxons', $taxonName);
233
    }
234
235
    /**
236
     * @When /^I add the "([^"]+)" action configured with a percentage value of (?:|-)([^"]+)% for ("[^"]+" channel)$/
237
     */
238
    public function iAddTheActionConfiguredWithAPercentageValueForChannel($actionType, $percentage = null, $channelName)
239
    {
240
        $this->createPage->addAction($actionType);
241
        $this->createPage->fillActionOptionForChannel($channelName, 'Percentage', $percentage);
242
    }
243
244
    /**
245
     * @When /^I add the "([^"]+)" action configured with a percentage value of (?:|-)([^"]+)%$/
246
     * @When I add the :actionType action configured without a percentage value
247
     */
248
    public function iAddTheActionConfiguredWithAPercentageValue($actionType, $percentage = null)
249
    {
250
        $this->createPage->addAction($actionType);
251
        $this->createPage->fillActionOption('Percentage', $percentage);
252
    }
253
254
    /**
255
     * @When I add the "Customer group" rule for :customerGroupName group
256
     */
257
    public function iAddTheCustomerGroupRuleConfiguredForGroup($customerGroupName)
258
    {
259
        $this->createPage->addRule('Customer group');
260
        $this->createPage->selectRuleOption('Customer group', $customerGroupName);
261
    }
262
263
    /**
264
     * @When I check (also) the :promotionName promotion
265
     */
266
    public function iCheckThePromotion(string $promotionName): void
267
    {
268
        $this->indexPage->checkResourceOnPage(['name' => $promotionName]);
269
    }
270
271
    /**
272
     * @When I delete them
273
     */
274
    public function iDeleteThem(): void
275
    {
276
        $this->indexPage->bulkDelete();
277
    }
278
279
    /**
280
     * @Then I should see a single promotion in the list
281
     * @Then there should be :amount promotions
282
     */
283
    public function thereShouldBePromotion(int $amount = 1): void
284
    {
285
        Assert::same($amount, $this->indexPage->countItems());
286
    }
287
288
    /**
289
     * @Then /^(this promotion) should be coupon based$/
290
     */
291
    public function thisPromotionShouldBeCouponBased(PromotionInterface $promotion)
292
    {
293
        Assert::true($this->indexPage->isCouponBasedFor($promotion));
294
    }
295
296
    /**
297
     * @Then /^I should be able to manage coupons for (this promotion)$/
298
     */
299
    public function iShouldBeAbleToManageCouponsForThisPromotion(PromotionInterface $promotion)
300
    {
301
        Assert::true($this->indexPage->isAbleToManageCouponsFor($promotion));
302
    }
303
304
    /**
305
     * @Then I should be notified that :element is required
306
     */
307
    public function iShouldBeNotifiedThatIsRequired($element)
308
    {
309
        $this->assertFieldValidationMessage($element, sprintf('Please enter promotion %s.', $element));
310
    }
311
312
    /**
313
     * @Then I should be notified that a :element value should be a numeric value
314
     */
315
    public function iShouldBeNotifiedThatAMinimalValueShouldBeNumeric($element)
316
    {
317
        $this->assertFieldValidationMessage($element, 'This value is not valid.');
318
    }
319
320
    /**
321
     * @Then I should be notified that promotion with this code already exists
322
     */
323
    public function iShouldBeNotifiedThatPromotionWithThisCodeAlreadyExists()
324
    {
325
        Assert::same($this->createPage->getValidationMessage('code'), 'The promotion with given code already exists.');
326
    }
327
328
    /**
329
     * @Then promotion with :element :name should not be added
330
     */
331
    public function promotionWithElementValueShouldNotBeAdded($element, $name)
332
    {
333
        $this->indexPage->open();
334
335
        Assert::false($this->indexPage->isSingleResourceOnPage([$element => $name]));
336
    }
337
338
    /**
339
     * @Then there should still be only one promotion with :element :value
340
     */
341
    public function thereShouldStillBeOnlyOnePromotionWith($element, $value)
342
    {
343
        $this->indexPage->open();
344
345
        Assert::true($this->indexPage->isSingleResourceOnPage([$element => $value]));
346
    }
347
348
    /**
349
     * @When I set its usage limit to :usageLimit
350
     */
351
    public function iSetItsUsageLimitTo($usageLimit)
352
    {
353
        $currentPage = $this->currentPageResolver->getCurrentPageWithForm([$this->createPage, $this->updatePage]);
354
355
        $currentPage->fillUsageLimit($usageLimit);
356
    }
357
358
    /**
359
     * @Then the :promotion promotion should be available to be used only :usageLimit times
360
     */
361
    public function thePromotionShouldBeAvailableToUseOnlyTimes(PromotionInterface $promotion, $usageLimit)
362
    {
363
        $this->iWantToModifyAPromotion($promotion);
364
365
        Assert::true($this->updatePage->hasResourceValues(['usage_limit' => $usageLimit]));
366
    }
367
368
    /**
369
     * @When I make it exclusive
370
     */
371
    public function iMakeItExclusive()
372
    {
373
        /** @var CreatePageInterface|UpdatePageInterface $currentPage */
374
        $currentPage = $this->currentPageResolver->getCurrentPageWithForm([$this->createPage, $this->updatePage]);
375
376
        $currentPage->makeExclusive();
377
    }
378
379
    /**
380
     * @Then the :promotion promotion should be exclusive
381
     */
382
    public function thePromotionShouldBeExclusive(PromotionInterface $promotion)
383
    {
384
        $this->assertIfFieldIsTrue($promotion, 'exclusive');
385
    }
386
387
    /**
388
     * @When I make it coupon based
389
     */
390
    public function iMakeItCouponBased()
391
    {
392
        /** @var CreatePageInterface|UpdatePageInterface $currentPage */
393
        $currentPage = $this->currentPageResolver->getCurrentPageWithForm([$this->createPage, $this->updatePage]);
394
395
        $currentPage->checkCouponBased();
396
    }
397
398
    /**
399
     * @Then the :promotion promotion should be coupon based
400
     */
401
    public function thePromotionShouldBeCouponBased(PromotionInterface $promotion)
402
    {
403
        $this->assertIfFieldIsTrue($promotion, 'coupon_based');
404
    }
405
406
    /**
407
     * @When I make it applicable for the :channelName channel
408
     */
409
    public function iMakeItApplicableForTheChannel($channelName)
410
    {
411
        /** @var CreatePageInterface|UpdatePageInterface $currentPage */
412
        $currentPage = $this->currentPageResolver->getCurrentPageWithForm([$this->createPage, $this->updatePage]);
413
414
        $currentPage->checkChannel($channelName);
415
    }
416
417
    /**
418
     * @Then the :promotion promotion should be applicable for the :channelName channel
419
     */
420
    public function thePromotionShouldBeApplicableForTheChannel(PromotionInterface $promotion, $channelName)
421
    {
422
        $this->iWantToModifyAPromotion($promotion);
423
424
        Assert::true($this->updatePage->checkChannelsState($channelName));
425
    }
426
427
    /**
428
     * @Given I want to modify a :promotion promotion
429
     * @Given /^I want to modify (this promotion)$/
430
     * @Then I should be able to modify a :promotion promotion
431
     */
432
    public function iWantToModifyAPromotion(PromotionInterface $promotion)
433
    {
434
        $this->updatePage->open(['id' => $promotion->getId()]);
435
    }
436
437
    /**
438
     * @Then the code field should be disabled
439
     */
440
    public function theCodeFieldShouldBeDisabled()
441
    {
442
        Assert::true($this->updatePage->isCodeDisabled());
443
    }
444
445
    /**
446
     * @When I save my changes
447
     * @When I try to save my changes
448
     */
449
    public function iSaveMyChanges()
450
    {
451
        $this->updatePage->saveChanges();
452
    }
453
454
    /**
455
     * @When /^I delete a ("([^"]+)" promotion)$/
456
     * @When /^I try to delete a ("([^"]+)" promotion)$/
457
     */
458
    public function iDeletePromotion(PromotionInterface $promotion)
459
    {
460
        $this->sharedStorage->set('promotion', $promotion);
461
462
        $this->indexPage->open();
463
        $this->indexPage->deleteResourceOnPage(['name' => $promotion->getName()]);
464
    }
465
466
    /**
467
     * @Then /^(this promotion) should no longer exist in the promotion registry$/
468
     */
469
    public function promotionShouldNotExistInTheRegistry(PromotionInterface $promotion)
470
    {
471
        $this->indexPage->open();
472
473
        Assert::false($this->indexPage->isSingleResourceOnPage(['code' => $promotion->getCode()]));
474
    }
475
476
    /**
477
     * @Then I should be notified that it is in use and cannot be deleted
478
     */
479
    public function iShouldBeNotifiedOfFailure()
480
    {
481
        $this->notificationChecker->checkNotification(
482
            'Cannot delete, the promotion is in use.',
483
            NotificationType::failure()
484
        );
485
    }
486
487
    /**
488
     * @When I make it available from :startsDate to :endsDate
489
     */
490
    public function iMakeItAvailableFromTo(\DateTimeInterface $startsDate, \DateTimeInterface $endsDate)
491
    {
492
        /** @var CreatePageInterface|UpdatePageInterface $currentPage */
493
        $currentPage = $this->currentPageResolver->getCurrentPageWithForm([$this->createPage, $this->updatePage]);
494
495
        $currentPage->setStartsAt($startsDate);
496
        $currentPage->setEndsAt($endsDate);
497
    }
498
499
    /**
500
     * @Then the :promotion promotion should be available from :startsDate to :endsDate
501
     */
502
    public function thePromotionShouldBeAvailableFromTo(PromotionInterface $promotion, \DateTimeInterface $startsDate, \DateTimeInterface $endsDate)
503
    {
504
        $this->iWantToModifyAPromotion($promotion);
505
506
        Assert::true($this->updatePage->hasStartsAt($startsDate));
507
508
        Assert::true($this->updatePage->hasEndsAt($endsDate));
509
    }
510
511
    /**
512
     * @Then I should be notified that promotion cannot end before it start
513
     */
514
    public function iShouldBeNotifiedThatPromotionCannotEndBeforeItsEvenStart()
515
    {
516
        /** @var CreatePageInterface|UpdatePageInterface $currentPage */
517
        $currentPage = $this->currentPageResolver->getCurrentPageWithForm([$this->createPage, $this->updatePage]);
518
519
        Assert::same($currentPage->getValidationMessage('ends_at'), 'End date cannot be set prior start date.');
520
    }
521
522
    /**
523
     * @Then I should be notified that this value should not be blank
524
     */
525
    public function iShouldBeNotifiedThatThisValueShouldNotBeBlank()
526
    {
527
        Assert::same(
528
            $this->createPage->getValidationMessageForAction(),
529
            'This value should not be blank.'
530
        );
531
    }
532
533
    /**
534
     * @Then I should be notified that the maximum value of a percentage discount is 100%
535
     */
536
    public function iShouldBeNotifiedThatTheMaximumValueOfAPercentageDiscountIs100()
537
    {
538
        Assert::same(
539
            $this->createPage->getValidationMessageForAction(),
540
            'The maximum value of a percentage discount is 100%.'
541
        );
542
    }
543
544
    /**
545
     * @Then I should be notified that a percentage discount value must be at least 0%
546
     */
547
    public function iShouldBeNotifiedThatAPercentageDiscountValueMustBeAtLeast0()
548
    {
549
        Assert::same(
550
            $this->createPage->getValidationMessageForAction(),
551
            'The value of a percentage discount must be at least 0%.'
552
        );
553
    }
554
555
    /**
556
     * @Then the promotion :promotion should be used :usage time(s)
557
     * @Then the promotion :promotion should not be used
558
     */
559
    public function thePromotionShouldBeUsedTime(PromotionInterface $promotion, $usage = 0)
560
    {
561
        Assert::same(
562
            (int) $usage,
563
            $this->indexPage->getUsageNumber($promotion),
564
            'Promotion should be used %s times, but is %2$s.'
565
        );
566
    }
567
568
    /**
569
     * @When I add the "Contains product" rule configured with the :productName product
570
     */
571
    public function iAddTheRuleConfiguredWithTheProduct($productName)
572
    {
573
        $this->createPage->addRule('Contains product');
574
        $this->createPage->selectAutocompleteRuleOption('Product code', $productName);
575
    }
576
577
    /**
578
     * @When I specify that this action should be applied to the :productName product
579
     */
580
    public function iSpecifyThatThisActionShouldBeAppliedToTheProduct($productName)
581
    {
582
        $this->createPage->selectAutoCompleteFilterOption('Products', $productName);
583
    }
584
585
    /**
586
     * @Then I should see :count promotions on the list
587
     */
588
    public function iShouldSeePromotionsOnTheList($count)
589
    {
590
        $actualCount = $this->indexPage->countItems();
591
592
        Assert::same(
593
            (int) $count,
594
            $actualCount,
595
            'There should be %s promotion, but there\'s %2$s.'
596
        );
597
    }
598
599
    /**
600
     * @Then the first promotion on the list should have :field :value
601
     */
602
    public function theFirstPromotionOnTheListShouldHave($field, $value)
603
    {
604
        $fields = $this->indexPage->getColumnFields($field);
605
        $actualValue = reset($fields);
606
607
        Assert::same(
608
            $actualValue,
609
            $value,
610
            sprintf('Expected first promotion\'s %s to be "%s", but it is "%s".', $field, $value, $actualValue)
611
        );
612
    }
613
614
    /**
615
     * @Then the last promotion on the list should have :field :value
616
     */
617
    public function theLastPromotionOnTheListShouldHave($field, $value)
618
    {
619
        $fields = $this->indexPage->getColumnFields($field);
620
        $actualValue = end($fields);
621
622
        Assert::same(
623
            $actualValue,
624
            $value,
625
            sprintf('Expected last promotion\'s %s to be "%s", but it is "%s".', $field, $value, $actualValue)
626
        );
627
    }
628
629
    /**
630
     * @Given the :promotion promotion should have priority :priority
631
     */
632
    public function thePromotionsShouldHavePriority(PromotionInterface $promotion, $priority)
633
    {
634
        $this->iWantToModifyAPromotion($promotion);
635
636
        Assert::same($this->updatePage->getPriority(), $priority);
637
    }
638
639
    /**
640
     * @param string $element
641
     * @param string $expectedMessage
642
     */
643
    private function assertFieldValidationMessage($element, $expectedMessage)
644
    {
645
        /** @var CreatePageInterface|UpdatePageInterface $currentPage */
646
        $currentPage = $this->currentPageResolver->getCurrentPageWithForm([$this->createPage, $this->updatePage]);
647
648
        Assert::same($currentPage->getValidationMessage($element), $expectedMessage);
649
    }
650
651
    /**
652
     * @param PromotionInterface $promotion
653
     * @param string $field
654
     */
655
    private function assertIfFieldIsTrue(PromotionInterface $promotion, $field)
656
    {
657
        $this->iWantToModifyAPromotion($promotion);
658
659
        Assert::true($this->updatePage->hasResourceValues([$field => 1]));
660
    }
661
}
662