Completed
Push — checkout-context-cleanup ( c82d5d )
by Kamil
24:31
created

CheckoutContext::iShouldBeAbleToPayAgain()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 0
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;
13
14
use Behat\Behat\Context\Context;
15
use Sylius\Behat\Page\Shop\Checkout\AddressPageInterface;
16
use Sylius\Behat\Page\Shop\Checkout\CompletePageInterface;
17
use Sylius\Behat\Page\Shop\Checkout\SelectPaymentPageInterface;
18
use Sylius\Behat\Page\Shop\Checkout\SelectShippingPageInterface;
19
use Sylius\Behat\Page\Shop\HomePageInterface;
20
use Sylius\Behat\Page\SymfonyPageInterface;
21
use Sylius\Behat\Page\UnexpectedPageException;
22
use Sylius\Behat\Service\Resolver\CurrentPageResolverInterface;
23
use Sylius\Behat\Service\SharedStorageInterface;
24
use Sylius\Component\Addressing\Comparator\AddressComparatorInterface;
25
use Sylius\Component\Addressing\Model\CountryInterface;
26
use Sylius\Component\Core\Formatter\StringInflector;
27
use Sylius\Component\Core\Model\AddressInterface;
28
use Sylius\Component\Core\Model\OrderInterface;
29
use Sylius\Component\Core\Model\ProductInterface;
30
use Sylius\Component\Core\Model\ShippingMethodInterface;
31
use Sylius\Component\Payment\Model\PaymentMethodInterface;
32
use Sylius\Component\Promotion\Model\PromotionInterface;
33
use Sylius\Component\Resource\Factory\FactoryInterface;
34
use Webmozart\Assert\Assert;
35
36
/**
37
 * @author Arkadiusz Krakowiak <[email protected]>
38
 */
39
final class CheckoutContext implements Context
40
{
41
    /**
42
     * @var SharedStorageInterface
43
     */
44
    private $sharedStorage;
45
46
    /**
47
     * @var HomePageInterface
48
     */
49
    private $homePage;
50
51
    /**
52
     * @var AddressPageInterface
53
     */
54
    private $addressPage;
55
56
    /**
57
     * @var SelectPaymentPageInterface
58
     */
59
    private $selectPaymentPage;
60
61
    /**
62
     * @var SelectShippingPageInterface
63
     */
64
    private $selectShippingPage;
65
66
    /**
67
     * @var CompletePageInterface
68
     */
69
    private $completePage;
70
71
    /**
72
     * @var FactoryInterface
73
     */
74
    private $addressFactory;
75
76
    /**
77
     * @var CurrentPageResolverInterface
78
     */
79
    private $currentPageResolver;
80
81
    /**
82
     * @var AddressComparatorInterface
83
     */
84
    private $addressComparator;
85
86
    /**
87
     * @param SharedStorageInterface $sharedStorage
88
     * @param HomePageInterface $homePage
89
     * @param AddressPageInterface $addressPage
90
     * @param SelectPaymentPageInterface $selectPaymentPage
91
     * @param SelectShippingPageInterface $selectShippingPage
92
     * @param CompletePageInterface $completePage
93
     * @param FactoryInterface $addressFactory
94
     * @param CurrentPageResolverInterface $currentPageResolver
95
     * @param AddressComparatorInterface $addressComparator
96
     */
97
    public function __construct(
98
        SharedStorageInterface $sharedStorage,
99
        HomePageInterface $homePage,
100
        AddressPageInterface $addressPage,
101
        SelectPaymentPageInterface $selectPaymentPage,
102
        SelectShippingPageInterface $selectShippingPage,
103
        CompletePageInterface $completePage,
104
        FactoryInterface $addressFactory,
105
        CurrentPageResolverInterface $currentPageResolver,
106
        AddressComparatorInterface $addressComparator
107
    ) {
108
        $this->sharedStorage = $sharedStorage;
109
        $this->homePage = $homePage;
110
        $this->addressPage = $addressPage;
111
        $this->selectPaymentPage = $selectPaymentPage;
112
        $this->selectShippingPage = $selectShippingPage;
113
        $this->completePage = $completePage;
114
        $this->addressFactory = $addressFactory;
115
        $this->currentPageResolver = $currentPageResolver;
116
        $this->addressComparator = $addressComparator;
117
    }
118
119
    /**
120
     * @Given I was at the checkout summary step
121
     */
122
    public function iWasAtTheCheckoutSummaryStep()
123
    {
124
        $this->iSpecifiedTheShippingAddress($this->createDefaultAddress());
125
        $this->iProceedOrderWithShippingMethodAndPayment('Free', 'Offline');
126
    }
127
128
    /**
129
     * @Given I have proceeded selecting :shippingMethodName shipping method
130
     */
131
    public function iHaveProceededSelectingShippingMethod($shippingMethodName)
132
    {
133
        $this->iSelectShippingMethod($shippingMethodName);
134
        $this->selectShippingPage->nextStep();
135
    }
136
137
    /**
138
     * @Given I am at the checkout addressing step
139
     * @When I go back to addressing step of the checkout
140
     */
141
    public function iAmAtTheCheckoutAddressingStep()
142
    {
143
        $this->addressPage->open();
144
    }
145
146
    /**
147
     * @When I try to open checkout addressing page
148
     */
149
    public function iTryToOpenCheckoutAddressingPage()
150
    {
151
        $this->addressPage->tryToOpen();
152
    }
153
154
    /**
155
     * @When I try to open checkout shipping page
156
     */
157
    public function iTryToOpenCheckoutShippingPage()
158
    {
159
        $this->selectShippingPage->tryToOpen();
160
    }
161
162
    /**
163
     * @When I try to open checkout payment page
164
     */
165
    public function iTryToOpenCheckoutPaymentPage()
166
    {
167
        $this->selectPaymentPage->tryToOpen();
168
    }
169
170
    /**
171
     * @When I try to open checkout complete page
172
     */
173
    public function iTryToOpenCheckoutCompletePage()
174
    {
175
        $this->completePage->tryToOpen();
176
    }
177
178
    /**
179
     * @When /^I choose ("[^"]+" street) for shipping address$/
180
     */
181
    public function iChooseForShippingAddress(AddressInterface $address)
182
    {
183
        $this->addressPage->selectShippingAddressFromAddressBook($address);
184
    }
185
186
    /**
187
     * @When /^I choose ("[^"]+" street) for billing address$/
188
     */
189
    public function iChooseForBillingAddress(AddressInterface $address)
190
    {
191
        $this->addressPage->chooseDifferentBillingAddress();
192
        $this->addressPage->selectBillingAddressFromAddressBook($address);
193
    }
194
195
    /**
196
     * @When /^I specify the shipping (address as "[^"]+", "[^"]+", "[^"]+", "[^"]+" for "[^"]+")$/
197
     * @When /^I specify the shipping (address for "[^"]+" from "[^"]+", "[^"]+", "[^"]+", "[^"]+", "[^"]+")$/
198
     * @When /^I (do not specify any shipping address) information$/
199
     * @When /^I change the shipping (address to "[^"]+", "[^"]+", "[^"]+", "[^"]+" for "[^"]+")$/
200
     */
201
    public function iSpecifyTheShippingAddressAs(AddressInterface $address)
202
    {
203
        $key = sprintf(
204
            'shipping_address_%s_%s',
205
            strtolower($address->getFirstName()),
206
            strtolower($address->getLastName())
207
        );
208
        $this->sharedStorage->set($key, $address);
209
210
        $this->addressPage->specifyShippingAddress($address);
211
    }
212
213
    /**
214
     * @When I specify shipping country province as :province
215
     */
216
    public function iSpecifyShippingCountryProvinceAs($province)
217
    {
218
        $this->addressPage->selectShippingAddressProvince($province);
219
    }
220
221
    /**
222
     * @When I specify billing country province as :province
223
     */
224
    public function iSpecifyBillingCountryProvinceAs($province)
225
    {
226
        $this->addressPage->selectBillingAddressProvince($province);
227
    }
228
229
    /**
230
     * @When /^I specify the billing (address as "([^"]+)", "([^"]+)", "([^"]+)", "([^"]+)" for "([^"]+)")$/
231
     * @When /^I specify the billing (address for "([^"]+)" from "([^"]+)", "([^"]+)", "([^"]+)", "([^"]+)", "([^"]+)")$/
232
     * @When /^I (do not specify any billing address) information$/
233
     */
234
    public function iSpecifyTheBillingAddressAs(AddressInterface $address)
235
    {
236
        $this->addressPage->chooseDifferentBillingAddress();
237
238
        $key = sprintf(
239
            'billing_address_%s_%s',
240
            strtolower($address->getFirstName()),
241
            strtolower($address->getLastName())
242
        );
243
        $this->sharedStorage->set($key, $address);
244
245
        $this->addressPage->specifyBillingAddress($address);
246
    }
247
248
    /**
249
     * @When /^I specified the shipping (address as "[^"]+", "[^"]+", "[^"]+", "[^"]+" for "[^"]+")$/
250
     */
251
    public function iSpecifiedTheShippingAddress(AddressInterface $address)
252
    {
253
        $this->addressPage->open();
254
        $this->iSpecifyTheShippingAddressAs($address);
255
256
        $key = sprintf('billing_address_%s_%s', strtolower($address->getFirstName()), strtolower($address->getLastName()));
257
        $this->sharedStorage->set($key, $address);
258
259
        $this->iCompleteTheAddressingStep();
260
    }
261
262
    /**
263
     * @When I specify the email as :email
264
     * @When I do not specify the email
265
     */
266
    public function iSpecifyTheEmail($email = null)
267
    {
268
        $this->addressPage->specifyEmail($email);
269
    }
270
271
    /**
272
     * @Given I have selected :shippingMethod shipping method
273
     * @When I select :shippingMethod shipping method
274
     */
275
    public function iSelectShippingMethod($shippingMethod)
276
    {
277
        $this->selectShippingPage->selectShippingMethod($shippingMethod);
278
    }
279
280
    /**
281
     * @Then I should not be able to select :shippingMethodName shipping method
282
     */
283
    public function iShouldNotBeAbleToSelectShippingMethod($shippingMethodName)
284
    {
285
        Assert::false(
286
            in_array($shippingMethodName, $this->selectShippingPage->getShippingMethods(), true),
287
            sprintf('Shipping method "%s" should not be available but it does.', $shippingMethodName)
288
        );
289
    }
290
291
    /**
292
     * @Then I should have :shippingMethodName shipping method available as the first choice
293
     */
294
    public function iShouldHaveShippingMethodAvailableAsFirstChoice($shippingMethodName)
295
    {
296
        $shippingMethods = $this->selectShippingPage->getShippingMethods();
297
        $firstShippingMethod = reset($shippingMethods);
298
299
        Assert::same($shippingMethodName, $firstShippingMethod);
300
    }
301
302
    /**
303
     * @Then I should have :shippingMethodName shipping method available as the last choice
304
     */
305
    public function iShouldHaveShippingMethodAvailableAsLastChoice($shippingMethodName)
306
    {
307
        $shippingMethods = $this->selectShippingPage->getShippingMethods();
308
        $lastShippingMethod = end($shippingMethods);
309
310
        Assert::same($shippingMethodName, $lastShippingMethod);
311
    }
312
313
    /**
314
     * @Then I should have :countryName selected as country
315
     */
316
    public function iShouldHaveSelectedAsCountry($countryName)
317
    {
318
        Assert::eq(
319
            $countryName,
320
            $this->addressPage->getShippingAddressCountry(),
321
            sprintf('Shipping country should be %s but is not.', $countryName)
322
        );
323
    }
324
325
    /**
326
     * @Then I should have no country selected
327
     */
328
    public function iShouldHaveNoCountrySelected()
329
    {
330
        Assert::eq(
331
            'Select',
332
            $this->addressPage->getShippingAddressCountry(),
333
            'Shipping country should not be selected.'
334
        );
335
    }
336
337
    /**
338
     * @When I complete the addressing step
339
     * @When I try to complete the addressing step
340
     */
341
    public function iCompleteTheAddressingStep()
342
    {
343
        $this->addressPage->nextStep();
344
    }
345
346
    /**
347
     * @When I go back to store
348
     */
349
    public function iGoBackToStore()
350
    {
351
        $this->addressPage->backToStore();
352
    }
353
354
    /**
355
     * @When /^I(?:| try to) complete the shipping step$/
356
     */
357
    public function iCompleteTheShippingStep()
358
    {
359
        $this->selectShippingPage->nextStep();
360
    }
361
362
    /**
363
     * @When I decide to change my address
364
     */
365
    public function iDecideToChangeMyAddress()
366
    {
367
        $this->selectShippingPage->changeAddress();
368
    }
369
370
    /**
371
     * @When I decide to change order shipping method
372
     */
373
    public function iDecideToChangeMyShippingMethod()
374
    {
375
        $this->selectPaymentPage->changeShippingMethod();
376
    }
377
378
    /**
379
     * @When I go to the addressing step
380
     */
381
    public function iGoToTheAddressingStep()
382
    {
383
        if ($this->selectShippingPage->isOpen()) {
384
            $this->selectShippingPage->changeAddressByStepLabel();
385
386
            return;
387
        }
388
389
        if ($this->selectPaymentPage->isOpen()) {
390
            $this->selectPaymentPage->changeAddressByStepLabel();
391
392
            return;
393
        }
394
395
        if ($this->completePage->isOpen()) {
396
            $this->completePage->changeAddress();
397
398
            return;
399
        }
400
401
        throw new UnexpectedPageException('It is impossible to go to addressing step from current page.');
402
    }
403
404
    /**
405
     * @When I go to the shipping step
406
     */
407
    public function iGoToTheShippingStep()
408
    {
409
        if ($this->selectPaymentPage->isOpen()) {
410
            $this->selectPaymentPage->changeShippingMethodByStepLabel();
411
412
            return;
413
        }
414
415
        if ($this->completePage->isOpen()) {
416
            $this->completePage->changeShippingMethod();
417
418
            return;
419
        }
420
421
        throw new UnexpectedPageException('It is impossible to go to shipping step from current page.');
422
    }
423
424
    /**
425
     * @When I decide to change the payment method
426
     */
427
    public function iGoToThePaymentStep()
428
    {
429
        $this->completePage->changePaymentMethod();
430
    }
431
432
    /**
433
     * @When /^I proceed selecting ("[^"]+" as shipping country)$/
434
     */
435
    public function iProceedSelectingShippingCountry(CountryInterface $shippingCountry = null)
436
    {
437
        $this->addressPage->open();
438
        $shippingAddress = $this->createDefaultAddress();
439
        if (null !== $shippingCountry) {
440
            $shippingAddress->setCountryCode($shippingCountry->getCode());
441
        }
442
443
        $this->addressPage->specifyShippingAddress($shippingAddress);
444
        $this->addressPage->nextStep();
445
    }
446
447
    /**
448
     * @When /^I proceed selecting ("[^"]+" as shipping country) with "([^"]+)" method$/
449
     */
450
    public function iProceedSelectingShippingCountryAndShippingMethod(CountryInterface $shippingCountry = null, $shippingMethodName = null)
451
    {
452
        $this->iProceedSelectingShippingCountry($shippingCountry);
453
454
        $this->selectShippingPage->selectShippingMethod($shippingMethodName ?: 'Free');
455
        $this->selectShippingPage->nextStep();
456
    }
457
458
    /**
459
     * @When /^I proceed selecting "([^"]+)" shipping method$/
460
     * @Given /^I chose "([^"]*)" shipping method$/
461
     */
462
    public function iProceedSelectingShippingMethod($shippingMethodName)
463
    {
464
        $this->iProceedSelectingShippingCountryAndShippingMethod(null, $shippingMethodName);
465
    }
466
467
    /**
468
     * @When /^I choose "([^"]*)" payment method$/
469
     */
470
    public function iChoosePaymentMethod($paymentMethodName)
471
    {
472
        $this->selectPaymentPage->selectPaymentMethod($paymentMethodName ?: 'Offline');
473
        $this->selectPaymentPage->nextStep();
474
    }
475
476
    /**
477
     * @When I go back to shipping step of the checkout
478
     */
479
    public function iGoBackToShippingStepOfTheCheckout()
480
    {
481
        $this->selectShippingPage->open();
482
    }
483
484
    /**
485
     * @Given I have proceeded selecting :paymentMethodName payment method
486
     * @When /^I (?:proceed|proceeded) selecting "([^"]+)" payment method$/
487
     */
488
    public function iProceedSelectingPaymentMethod($paymentMethodName = 'Offline')
489
    {
490
        $this->iProceedSelectingShippingCountryAndShippingMethod();
491
        $this->iChoosePaymentMethod($paymentMethodName);
492
    }
493
494
    /**
495
     * @When /^I change shipping method to "([^"]*)"$/
496
     */
497
    public function iChangeShippingMethod($shippingMethodName)
498
    {
499
        $this->selectPaymentPage->changeShippingMethod();
500
        $this->selectShippingPage->selectShippingMethod($shippingMethodName);
501
        $this->selectShippingPage->nextStep();
502
    }
503
504
    /**
505
     * @When /^I provide additional note like "([^"]+)"$/
506
     */
507
    public function iProvideAdditionalNotesLike($notes)
508
    {
509
        $this->sharedStorage->set('additional_note', $notes);
510
        $this->completePage->addNotes($notes);
511
    }
512
513
    /**
514
     * @When /^I proceed as guest "([^"]*)" with ("[^"]+" as shipping country)$/
515
     */
516
    public function iProceedLoggingAsGuestWithAsShippingCountry($email, CountryInterface $shippingCountry = null)
517
    {
518
        $this->addressPage->open();
519
        $this->addressPage->specifyEmail($email);
520
        $shippingAddress = $this->createDefaultAddress();
521
        if (null !== $shippingCountry) {
522
            $shippingAddress->setCountryCode($shippingCountry->getCode());
523
        }
524
525
        $this->addressPage->specifyShippingAddress($shippingAddress);
526
        $this->addressPage->nextStep();
527
    }
528
529
    /**
530
     * @When I return to the checkout summary step
531
     */
532
    public function iReturnToTheCheckoutSummaryStep()
533
    {
534
        $this->completePage->open();
535
    }
536
537
    /**
538
     * @When I want to complete checkout
539
     */
540
    public function iWantToCompleteCheckout()
541
    {
542
        $this->completePage->tryToOpen();
543
    }
544
545
    /**
546
     * @When I want to pay for order
547
     */
548
    public function iWantToPayForOrder()
549
    {
550
        $this->selectPaymentPage->tryToOpen();
551
    }
552
553
    /**
554
     * @When I confirm my order
555
     */
556
    public function iConfirmMyOrder()
557
    {
558
        $this->completePage->confirmOrder();
559
    }
560
561
    /**
562
     * @When I specify the password as :password
563
     */
564
    public function iSpecifyThePasswordAs($password)
565
    {
566
        $this->addressPage->specifyPassword($password);
567
    }
568
569
    /**
570
     * @When I sign in
571
     */
572
    public function iSignIn()
573
    {
574
        $this->addressPage->signIn();
575
    }
576
577
    /**
578
     * @Then I should be on the checkout shipping step
579
     */
580
    public function iShouldBeOnTheCheckoutShippingStep()
581
    {
582
        Assert::true(
583
            $this->selectShippingPage->isOpen(),
584
            'Checkout shipping page should be opened, but it is not.'
585
        );
586
    }
587
588
    /**
589
     * @Then I should be on the checkout complete step
590
     */
591
    public function iShouldBeOnTheCheckoutCompleteStep()
592
    {
593
        Assert::true($this->completePage->isOpen());
594
    }
595
596
    /**
597
     * @Then I should be on the checkout payment step
598
     */
599
    public function iShouldBeOnTheCheckoutPaymentStep()
600
    {
601
        Assert::true(
602
            $this->selectPaymentPage->isOpen(),
603
            'Checkout payment page should be opened, but it is not.'
604
        );
605
    }
606
607
    /**
608
     * @Then I should be on the checkout summary step
609
     */
610
    public function iShouldBeOnTheCheckoutSummaryStep()
611
    {
612
        Assert::true(
613
            $this->completePage->isOpen(),
614
            'Checkout summary page should be opened, but it is not.'
615
        );
616
    }
617
618
    /**
619
     * @Then /^I should(?:| also) be notified that the "([^"]+)" and the "([^"]+)" in (shipping|billing) details are required$/
620
     */
621
    public function iShouldBeNotifiedThatTheAndTheInShippingDetailsAreRequired($firstElement, $secondElement, $type)
622
    {
623
        $this->assertElementValidationMessage($type, $firstElement, sprintf('Please enter %s.', $firstElement));
624
        $this->assertElementValidationMessage($type, $secondElement, sprintf('Please enter %s.', $secondElement));
625
    }
626
627
    /**
628
     * @Then I should be informed that my order cannot be shipped to this address
629
     */
630
    public function iShouldBeInformedThatMyOrderCannotBeShippedToThisAddress()
631
    {
632
        Assert::true(
633
            $this->selectShippingPage->hasNoShippingMethodsMessage(),
634
            'Shipping page should have no shipping methods message but it does not.'
635
        );
636
    }
637
638
    /**
639
     * @Then I should be able to log in
640
     */
641
    public function iShouldBeAbleToLogIn()
642
    {
643
        Assert::true(
644
            $this->addressPage->canSignIn(),
645
            'I should be able to login, but I am not.'
646
        );
647
    }
648
649
    /**
650
     * @Then the login form should no longer be accessible
651
     */
652
    public function theLoginFormShouldNoLongerBeAccessible()
653
    {
654
        Assert::false(
655
            $this->addressPage->canSignIn(),
656
            'I should not be able to login, but I am.'
657
        );
658
    }
659
660
    /**
661
     * @Then I should be notified about bad credentials
662
     */
663
    public function iShouldBeNotifiedAboutBadCredentials()
664
    {
665
        Assert::true(
666
            $this->addressPage->checkInvalidCredentialsValidation(),
667
            'I should see validation error, but I do not.'
668
        );
669
    }
670
671
    /**
672
     * @Then my order's shipping address should be to :fullName
673
     */
674
    public function iShouldSeeThisShippingAddressAsShippingAddress($fullName)
675
    {
676
        $address = $this->sharedStorage->get('shipping_address_'.StringInflector::nameToLowercaseCode($fullName));
677
        Assert::true(
678
            $this->completePage->hasShippingAddress($address),
679
            'Shipping address is improper.'
680
        );
681
    }
682
683
    /**
684
     * @Then my order's billing address should be to :fullName
685
     */
686
    public function iShouldSeeThisBillingAddressAsBillingAddress($fullName)
687
    {
688
        $address = $this->sharedStorage->get('billing_address_'.StringInflector::nameToLowercaseCode($fullName));
689
        Assert::true(
690
            $this->completePage->hasBillingAddress($address),
691
            'Billing address is improper.'
692
        );
693
    }
694
695
    /**
696
     * @Then address to :fullName should be used for both shipping and billing of my order
697
     */
698
    public function iShouldSeeThisShippingAddressAsShippingAndBillingAddress($fullName)
699
    {
700
        $this->iShouldSeeThisShippingAddressAsShippingAddress($fullName);
701
        $this->iShouldSeeThisBillingAddressAsBillingAddress($fullName);
702
    }
703
704
    /**
705
     * @When I go back to payment step of the checkout
706
     */
707
    public function iAmAtTheCheckoutPaymentStep()
708
    {
709
        $this->selectPaymentPage->open();
710
    }
711
712
    /**
713
     * @When I complete the payment step
714
     */
715
    public function iCompleteThePaymentStep()
716
    {
717
        $this->selectPaymentPage->nextStep();
718
    }
719
720
    /**
721
     * @When I select :name payment method
722
     */
723
    public function iSelectPaymentMethod($name)
724
    {
725
        $this->selectPaymentPage->selectPaymentMethod($name);
726
    }
727
728
    /**
729
     * @When /^I do not modify anything$/
730
     */
731
    public function iDoNotModifyAnything()
732
    {
733
        // Intentionally left blank to fulfill context expectation
734
    }
735
736
    /**
737
     * @Then I should not be able to select :paymentMethodName payment method
738
     */
739
    public function iShouldNotBeAbleToSelectPaymentMethod($paymentMethodName)
740
    {
741
        Assert::false(
742
            $this->selectPaymentPage->hasPaymentMethod($paymentMethodName),
743
            sprintf('Payment method "%s" should not be available, but it does.', $paymentMethodName)
744
        );
745
    }
746
747
    /**
748
     * @Then I should be able to select :paymentMethodName payment method
749
     */
750
    public function iShouldBeAbleToSelectPaymentMethod($paymentMethodName)
751
    {
752
        Assert::true(
753
            $this->selectPaymentPage->hasPaymentMethod($paymentMethodName),
754
            sprintf('Payment method "%s" should be available, but it does not.', $paymentMethodName)
755
        );
756
    }
757
758
    /**
759
     * @Given I have proceeded order with :shippingMethod shipping method and :paymentMethod payment
760
     * @When I proceed with :shippingMethod shipping method and :paymentMethod payment
761
     */
762
    public function iProceedOrderWithShippingMethodAndPayment($shippingMethod, $paymentMethod)
763
    {
764
        $this->iSelectShippingMethod($shippingMethod);
765
        $this->iCompleteTheShippingStep();
766
        $this->iSelectPaymentMethod($paymentMethod);
767
        $this->iCompleteThePaymentStep();
768
    }
769
770
    /**
771
     * @When I proceed with :shippingMethod shipping method
772
     */
773
    public function iProceedOrderWithShippingMethod($shippingMethod)
774
    {
775
        $this->iSelectShippingMethod($shippingMethod);
776
        $this->iCompleteTheShippingStep();
777
    }
778
779
    /**
780
     * @Given I should have :quantity :productName products in the cart
781
     */
782
    public function iShouldHaveProductsInTheCart($quantity, $productName)
783
    {
784
        Assert::true(
785
            $this->completePage->hasItemWithProductAndQuantity($productName, $quantity),
786
            sprintf('There is no "%s" with quantity %s on order summary page, but it should.', $productName, $quantity)
787
        );
788
    }
789
790
    /**
791
     * @Then my order shipping should be :price
792
     */
793
    public function myOrderShippingShouldBe($price)
794
    {
795
        Assert::true(
796
            $this->completePage->hasShippingTotal($price),
797
            sprintf('The shipping total should be %s, but it is not.', $price)
798
        );
799
    }
800
801
    /**
802
     * @Then /^the ("[^"]+" product) should have unit price discounted by ("\$\d+")$/
803
     */
804
    public function theShouldHaveUnitPriceDiscountedFor(ProductInterface $product, $amount)
805
    {
806
        Assert::true(
807
            $this->completePage->hasProductDiscountedUnitPriceBy($product, $amount),
808
            sprintf('Product %s should have discounted price by %s, but it does not have.', $product->getName(), $amount)
809
        );
810
    }
811
812
    /**
813
     * @Then /^my order total should be ("(?:\£|\$)\d+(?:\.\d+)?")$/
814
     */
815
    public function myOrderTotalShouldBe($total)
816
    {
817
        Assert::true(
818
            $this->completePage->hasOrderTotal($total),
819
            sprintf('Order total should have %s total, but it does not have.', $total)
820
        );
821
    }
822
823
    /**
824
     * @Then my order promotion total should be :promotionTotal
825
     */
826
    public function myOrderPromotionTotalShouldBe($promotionTotal)
827
    {
828
        Assert::true(
829
            $this->completePage->hasPromotionTotal($promotionTotal),
830
            sprintf('The total discount should be %s, but it does not.', $promotionTotal)
831
        );
832
    }
833
834
    /**
835
     * @Then :promotionName should be applied to my order
836
     */
837
    public function shouldBeAppliedToMyOrder($promotionName)
838
    {
839
        Assert::true(
840
            $this->completePage->hasPromotion($promotionName),
841
            sprintf('The promotion %s should appear on the page, but it does not.', $promotionName)
842
        );
843
    }
844
845
    /**
846
     * @Then :promotionName should be applied to my order shipping
847
     */
848
    public function shouldBeAppliedToMyOrderShipping($promotionName)
849
    {
850
        Assert::true($this->completePage->hasShippingPromotion($promotionName));
851
    }
852
853
    /**
854
     * @Given my tax total should be :taxTotal
855
     */
856
    public function myTaxTotalShouldBe($taxTotal)
857
    {
858
        Assert::true(
859
            $this->completePage->hasTaxTotal($taxTotal),
860
            sprintf('The tax total should be %s, but it does not.', $taxTotal)
861
        );
862
    }
863
864
    /**
865
     * @Then my order's shipping method should be :shippingMethod
866
     */
867
    public function myOrderSShippingMethodShouldBe(ShippingMethodInterface $shippingMethod)
868
    {
869
        Assert::true(
870
            $this->completePage->hasShippingMethod($shippingMethod),
871
            sprintf('I should see %s shipping method, but I do not.', $shippingMethod->getName())
872
        );
873
    }
874
875
    /**
876
     * @Then my order's payment method should be :paymentMethod
877
     */
878
    public function myOrderSPaymentMethodShouldBe(PaymentMethodInterface $paymentMethod)
879
    {
880
        Assert::same(
881
            $this->completePage->getPaymentMethodName(),
882
            $paymentMethod->getName()
883
        );
884
    }
885
886
    /**
887
     * @Then I should be redirected to the homepage
888
     */
889
    public function iShouldBeRedirectedToTheHomepage()
890
    {
891
        Assert::true(
892
            $this->homePage->isOpen(),
893
            'Shop homepage should be opened, but it is not.'
894
        );
895
    }
896
897
    /**
898
     * @Then I should be redirected to the addressing step
899
     */
900
    public function iShouldBeRedirectedToTheAddressingStep()
901
    {
902
        Assert::true(
903
            $this->addressPage->isOpen(),
904
            'Checkout addressing step should be opened, but it is not.'
905
        );
906
    }
907
908
    /**
909
     * @Then I should be able to go to the shipping step again
910
     */
911
    public function iShouldBeAbleToGoToTheShippingStepAgain()
912
    {
913
        $this->addressPage->nextStep();
914
915
        Assert::true(
916
            $this->selectShippingPage->isOpen(),
917
            'Checkout shipping step should be opened, but it is not.'
918
        );
919
    }
920
921
    /**
922
     * @Then I should be able to go to the complete step again
923
     */
924
    public function iShouldBeAbleToGoToTheCompleteStepAgain()
925
    {
926
        $this->selectShippingPage->nextStep();
927
928
        Assert::true($this->completePage->isOpen());
929
    }
930
931
    /**
932
     * @Then I should be redirected to the shipping step
933
     */
934
    public function iShouldBeRedirectedToTheShippingStep()
935
    {
936
        Assert::true(
937
            $this->selectShippingPage->isOpen(),
938
            'Checkout shipping step should be opened, but it is not.'
939
        );
940
    }
941
942
    /**
943
     * @Given I should be able to go to the payment step again
944
     */
945
    public function iShouldBeAbleToGoToThePaymentStepAgain()
946
    {
947
        $this->selectShippingPage->nextStep();
948
949
        Assert::true(
950
            $this->selectPaymentPage->isOpen(),
951
            'Checkout payment step should be opened, but it is not.'
952
        );
953
    }
954
955
    /**
956
     * @Then I should be redirected to the payment step
957
     */
958
    public function iShouldBeRedirectedToThePaymentStep()
959
    {
960
        Assert::true(
961
            $this->selectPaymentPage->isOpen(),
962
            'Checkout payment step should be opened, but it is not.'
963
        );
964
    }
965
966
    /**
967
     * @Given I should be able to go to the summary page again
968
     */
969
    public function iShouldBeAbleToGoToTheSummaryPageAgain()
970
    {
971
        $this->selectPaymentPage->nextStep();
972
973
        Assert::true(
974
            $this->completePage->isOpen(),
975
            'Checkout summary page should be opened, but it is not.'
976
        );
977
    }
978
979
    /**
980
     * @Given I should see shipping method :shippingMethodName with fee :fee
981
     */
982
    public function iShouldSeeShippingFee($shippingMethodName, $fee)
983
    {
984
        Assert::true(
985
            $this->selectShippingPage->hasShippingMethodFee($shippingMethodName, $fee),
986
            sprintf('The shipping fee should be %s, but it does not.', $fee)
987
        );
988
    }
989
990
    /**
991
     * @Given /^I have completed addressing step with email "([^"]+)" and ("[^"]+" based shipping address)$/
992
     * @When /^I complete addressing step with email "([^"]+)" and ("[^"]+" based shipping address)$/
993
     */
994
    public function iCompleteAddressingStepWithEmail($email, AddressInterface $address)
995
    {
996
        $this->addressPage->open();
997
        $this->iSpecifyTheEmail($email);
998
        $this->iSpecifyTheShippingAddressAs($address);
999
        $this->iCompleteTheAddressingStep();
1000
    }
1001
1002
    /**
1003
     * @Then the subtotal of :item item should be :price
1004
     */
1005
    public function theSubtotalOfItemShouldBe($item, $price)
1006
    {
1007
        $currentPage = $this->resolveCurrentStepPage();
1008
        $actualPrice = $currentPage->getItemSubtotal($item);
1009
1010
        Assert::eq(
1011
            $actualPrice,
1012
            $price,
1013
            sprintf('The %s subtotal should be %s, but is %s', $item, $price, $actualPrice)
1014
        );
1015
    }
1016
1017
    /**
1018
     * @Then the :product product should have unit price :price
1019
     */
1020
    public function theProductShouldHaveUnitPrice(ProductInterface $product, $price)
1021
    {
1022
        Assert::true(
1023
            $this->completePage->hasProductUnitPrice($product, $price),
1024
            sprintf('Product %s should have unit price %s, but it does not have.', $product->getName(), $price)
1025
        );
1026
    }
1027
1028
    /**
1029
     * @Given /^I should be notified that (this product) does not have sufficient stock$/
1030
     */
1031
    public function iShouldBeNotifiedThatThisProductDoesNotHaveSufficientStock(ProductInterface $product)
1032
    {
1033
        Assert::true(
1034
            $this->completePage->hasProductOutOfStockValidationMessage($product),
1035
            sprintf('I should see validation message for %s product', $product->getName())
1036
        );
1037
    }
1038
1039
    /**
1040
     * @Then my order's locale should be :localeName
1041
     */
1042
    public function myOrderSLocaleShouldBe($localeName)
1043
    {
1044
        Assert::true(
1045
            $this->completePage->hasLocale($localeName),
1046
            'Order locale code is improper.'
1047
        );
1048
    }
1049
1050
    /**
1051
     * @Then /^I should not be notified that (this product) does not have sufficient stock$/
1052
     */
1053
    public function iShouldNotBeNotifiedThatThisProductDoesNotHaveSufficientStock(ProductInterface $product)
1054
    {
1055
        Assert::false(
1056
            $this->completePage->hasProductOutOfStockValidationMessage($product),
1057
            sprintf('I should see validation message for %s product', $product->getName())
1058
        );
1059
    }
1060
1061
    /**
1062
     * @Then I should be on the checkout addressing step
1063
     */
1064
    public function iShouldBeOnTheCheckoutAddressingStep()
1065
    {
1066
        Assert::true(
1067
            $this->addressPage->isOpen(),
1068
            'Checkout addressing page should be opened, but it is not.'
1069
        );
1070
    }
1071
1072
    /**
1073
     * @When I specify the province name manually as :provinceName for shipping address
1074
     */
1075
    public function iSpecifyTheProvinceNameManuallyAsForShippingAddress($provinceName)
1076
    {
1077
        $this->addressPage->specifyShippingAddressProvince($provinceName);
1078
    }
1079
1080
    /**
1081
     * @When I specify the province name manually as :provinceName for billing address
1082
     */
1083
    public function iSpecifyTheProvinceNameManuallyAsForBillingAddress($provinceName)
1084
    {
1085
        $this->addressPage->specifyBillingAddressProvince($provinceName);
1086
    }
1087
1088
    /**
1089
     * @Then I should not be able to specify province name manually for shipping address
1090
     */
1091
    public function iShouldNotBeAbleToSpecifyProvinceNameManuallyForShippingAddress()
1092
    {
1093
        Assert::false(
1094
            $this->addressPage->hasShippingAddressInput(),
1095
            'I should not be able to specify manually the province for shipping address, but I can.'
1096
        );
1097
    }
1098
1099
    /**
1100
     * @Then I should not be able to specify province name manually for billing address
1101
     */
1102
    public function iShouldNotBeAbleToSpecifyProvinceNameManuallyForBillingAddress()
1103
    {
1104
        Assert::false(
1105
            $this->addressPage->hasBillingAddressInput(),
1106
            'I should not be able to specify manually the province for billing address, but I can.'
1107
        );
1108
    }
1109
1110
    /**
1111
     * @Then I should see :provinceName in the shipping address
1112
     */
1113
    public function iShouldSeeInTheShippingAddress($provinceName)
1114
    {
1115
        Assert::true(
1116
            $this->completePage->hasShippingProvinceName($provinceName),
1117
            sprintf('Cannot find shipping address with province %s', $provinceName)
1118
        );
1119
    }
1120
1121
    /**
1122
     * @Then I should see :provinceName in the billing address
1123
     */
1124
    public function iShouldSeeInTheBillingAddress($provinceName)
1125
    {
1126
        Assert::true(
1127
            $this->completePage->hasBillingProvinceName($provinceName),
1128
            sprintf('Cannot find billing address with province %s', $provinceName)
1129
        );
1130
    }
1131
1132
    /**
1133
     * @Then there should be information about no available shipping methods
1134
     */
1135
    public function thereShouldBeInformationAboutNoShippingMethodsAvailableForMyShippingAddress()
1136
    {
1137
        Assert::true(
1138
            $this->selectShippingPage->hasNoAvailableShippingMethodsWarning(),
1139
            'There should be warning about no available shipping methods, but it does not.'
1140
        );
1141
    }
1142
1143
    /**
1144
     * @Then /^(address "[^"]+", "[^"]+", "[^"]+", "[^"]+", "[^"]+", "[^"]+") should be filled as shipping address$/
1145
     */
1146
    public function addressShouldBeFilledAsShippingAddress(AddressInterface $address)
1147
    {
1148
        Assert::true($this->addressComparator->equal($address, $this->addressPage->getPreFilledShippingAddress()));
1149
    }
1150
1151
    /**
1152
     * @Then /^(address "[^"]+", "[^"]+", "[^"]+", "[^"]+", "[^"]+", "[^"]+") should be filled as billing address$/
1153
     */
1154
    public function addressShouldBeFilledAsBillingAddress(AddressInterface $address)
1155
    {
1156
        Assert::true($this->addressComparator->equal($address, $this->addressPage->getPreFilledBillingAddress()));
1157
    }
1158
1159
    /**
1160
     * @Then I should have :paymentMethodName payment method available as the first choice
1161
     */
1162
    public function iShouldHavePaymentMethodAvailableAsFirstChoice($paymentMethodName)
1163
    {
1164
        $paymentMethods = $this->selectPaymentPage->getPaymentMethods();
1165
        $firstPaymentMethod = reset($paymentMethods);
1166
1167
        Assert::same($paymentMethodName, $firstPaymentMethod);
1168
    }
1169
1170
    /**
1171
     * @Then I should have :paymentMethodName payment method available as the last choice
1172
     */
1173
    public function iShouldHavePaymentMethodAvailableAsLastChoice($paymentMethodName)
1174
    {
1175
        $paymentMethods = $this->selectPaymentPage->getPaymentMethods();
1176
        $lastPaymentMethod = end($paymentMethods);
1177
1178
        Assert::same($paymentMethodName, $lastPaymentMethod);
1179
    }
1180
1181
    /**
1182
     * @Then I should see :shippingMethodName shipping method
1183
     */
1184
    public function iShouldSeeShippingMethod($shippingMethodName)
1185
    {
1186
        Assert::true(
1187
            $this->selectShippingPage->hasShippingMethod($shippingMethodName),
1188
            sprintf('There should be %s shipping method, but it is not.', $shippingMethodName)
1189
        );
1190
    }
1191
1192
    /**
1193
     * @Then I should not see :shippingMethodName shipping method
1194
     */
1195
    public function iShouldNotSeeShippingMethod($shippingMethodName)
1196
    {
1197
        Assert::false(
1198
            $this->selectShippingPage->hasShippingMethod($shippingMethodName),
1199
            sprintf('There should not be %s shipping method, but it is.', $shippingMethodName)
1200
        );
1201
    }
1202
1203
    /**
1204
     * @Then I should be checking out as :email
1205
     */
1206
    public function iShouldBeCheckingOutAs($email)
1207
    {
1208
        Assert::same(
1209
            'Checking out as '.$email.'.',
1210
            $this->selectShippingPage->getPurchaserEmail()
1211
        );
1212
    }
1213
1214
    /**
1215
     * @Then I should not see any information about payment method
1216
     */
1217
    public function iShouldNotSeeAnyInformationAboutPaymentMethod()
1218
    {
1219
        Assert::false(
1220
            $this->completePage->hasPaymentMethod(),
1221
            'There should be no information about payment method, but it is.'
1222
        );
1223
    }
1224
1225
    /**
1226
     * @Then /^(this promotion) should give "([^"]+)" discount$/
1227
     */
1228
    public function thisPromotionShouldGiveDiscount(PromotionInterface $promotion, $discount)
1229
    {
1230
        Assert::same(
1231
            $discount,
1232
            $this->completePage->getShippingPromotionDiscount($promotion->getName())
1233
        );
1234
    }
1235
1236
    /**
1237
     * @return AddressInterface
1238
     */
1239
    private function createDefaultAddress()
1240
    {
1241
        /** @var AddressInterface $address */
1242
        $address = $this->addressFactory->createNew();
1243
        $address->setFirstName('John');
1244
        $address->setLastName('Doe');
1245
        $address->setCountryCode('US');
1246
        $address->setCity('North Bridget');
1247
        $address->setPostcode('93-554');
1248
        $address->setStreet('0635 Myron Hollow Apt. 711');
1249
        $address->setPhoneNumber('321123456');
1250
1251
        return $address;
1252
    }
1253
1254
    /**
1255
     * @param string $type
1256
     * @param string $element
1257
     * @param string $expectedMessage
1258
     *
1259
     * @throws \InvalidArgumentException
1260
     */
1261
    private function assertElementValidationMessage($type, $element, $expectedMessage)
1262
    {
1263
        $element = sprintf('%s_%s', $type, implode('_', explode(' ', $element)));
1264
        Assert::true(
1265
            $this->addressPage->checkValidationMessageFor($element, $expectedMessage),
1266
            sprintf('The %s should be required.', $element)
1267
        );
1268
    }
1269
1270
    /**
1271
     * @return SymfonyPageInterface
1272
     */
1273
    private function resolveCurrentStepPage()
1274
    {
1275
        $possiblePages = [
1276
            $this->addressPage,
1277
            $this->selectPaymentPage,
1278
            $this->selectShippingPage,
1279
            $this->completePage,
1280
        ];
1281
1282
        return $this->currentPageResolver->getCurrentPageWithForm($possiblePages);
1283
    }
1284
}
1285