Completed
Push — master ( 881b3b...090ef2 )
by Michał
10:07
created

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