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

CheckoutContext::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.3142
c 0
b 0
f 0
nc 1
cc 1
eloc 19
nop 9

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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