Completed
Push — remove-specs ( 8265db )
by Kamil
18:10
created

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