Completed
Push — master ( 7fc704...cfa808 )
by Paweł
33:04 queued 17:47
created

CheckoutContext::thisUserBought()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sylius\Behat\Context\Ui;
13
14
use Behat\Behat\Context\Context;
15
use Sylius\Behat\Page\Shop\Checkout\AddressingPageInterface;
16
use Sylius\Behat\Page\Shop\Checkout\PaymentPageInterface;
17
use Sylius\Behat\Page\Shop\Checkout\ShippingPageInterface;
18
use Sylius\Behat\Page\Shop\Checkout\SummaryPageInterface;
19
use Sylius\Behat\Page\Shop\Order\OrderPaymentsPageInterface;
20
use Sylius\Behat\Page\Shop\Checkout\AddressingStepInterface;
21
use Sylius\Behat\Page\Shop\Checkout\FinalizeStepInterface;
22
use Sylius\Behat\Page\Shop\Checkout\PaymentStepInterface;
23
use Sylius\Behat\Page\Shop\Checkout\SecurityStepInterface;
24
use Sylius\Behat\Page\Shop\Checkout\ShippingStepInterface;
25
use Sylius\Behat\Page\Shop\Checkout\ThankYouPageInterface;
26
use Sylius\Component\Core\Formatter\StringInflector;
27
use Sylius\Behat\Service\SecurityServiceInterface;
28
use Sylius\Component\Core\Model\AddressInterface;
29
use Sylius\Component\Core\Model\OrderInterface;
30
use Sylius\Component\Core\Model\UserInterface;
31
use Sylius\Component\Core\Test\Services\SharedStorageInterface;
32
use Sylius\Component\Order\Repository\OrderRepositoryInterface;
33
use Sylius\Component\Payment\Model\PaymentInterface;
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 SecurityStepInterface
48
     */
49
    private $checkoutSecurityStep;
50
51
    /**
52
     * @var AddressingStepInterface
53
     */
54
    private $checkoutAddressingStep;
55
56
    /**
57
     * @var AddressingPageInterface
58
     */
59
    private $addressingPage;
60
61
    /**
62
     * @var ShippingStepInterface
63
     */
64
    private $checkoutShippingStep;
65
66
    /**
67
     * @var PaymentStepInterface
68
     */
69
    private $checkoutPaymentStep;
70
71
    /**
72
     * @var PaymentPageInterface
73
     */
74
    private $paymentPage;
75
76
    /**
77
     * @var FinalizeStepInterface
78
     */
79
    private $checkoutFinalizeStep;
80
81
    /**
82
     * @var ThankYouPageInterface
83
     */
84
    private $checkoutThankYouPage;
85
86
    /**
87
     * @var OrderPaymentsPageInterface
88
     */
89
    private $orderPaymentsPage;
90
91
    /**
92
     * @var ShippingPageInterface
93
     */
94
    private $shippingPage;
95
96
    /**
97
     * @var SummaryPageInterface
98
     */
99
    private $summaryPage;
100
101
    /**
102
     * @var OrderRepositoryInterface
103
     */
104
    private $orderRepository;
105
106
    /**
107
     * @var SecurityServiceInterface
108
     */
109
    private $securityService;
110
111
    /**
112
     * @param SharedStorageInterface $sharedStorage
113
     * @param SecurityStepInterface $checkoutSecurityStep
114
     * @param AddressingStepInterface $checkoutAddressingStep
115
     * @param AddressingPageInterface $addressingPage
116
     * @param ShippingStepInterface $checkoutShippingStep
117
     * @param ShippingPageInterface $shippingPage
118
     * @param PaymentStepInterface $checkoutPaymentStep
119
     * @param PaymentPageInterface $paymentPage
120
     * @param SummaryPageInterface $summaryPage
121
     * @param FinalizeStepInterface $checkoutFinalizeStep
122
     * @param ThankYouPageInterface $checkoutThankYouPage
123
     * @param OrderPaymentsPageInterface $orderPaymentsPage
124
     * @param OrderRepositoryInterface $orderRepository
125
     * @param SecurityServiceInterface $securityService
126
     */
127
    public function __construct(
128
        SharedStorageInterface $sharedStorage,
129
        SecurityStepInterface $checkoutSecurityStep,
130
        AddressingStepInterface $checkoutAddressingStep,
131
        AddressingPageInterface $addressingPage,
132
        ShippingStepInterface $checkoutShippingStep,
133
        ShippingPageInterface $shippingPage,
134
        PaymentStepInterface $checkoutPaymentStep,
135
        PaymentPageInterface $paymentPage,
136
        SummaryPageInterface $summaryPage,
137
        FinalizeStepInterface $checkoutFinalizeStep,
138
        ThankYouPageInterface $checkoutThankYouPage,
139
        OrderPaymentsPageInterface $orderPaymentsPage,
140
        OrderRepositoryInterface $orderRepository,
141
        SecurityServiceInterface $securityService
142
    ) {
143
        $this->sharedStorage = $sharedStorage;
144
        $this->checkoutSecurityStep = $checkoutSecurityStep;
145
        $this->checkoutAddressingStep = $checkoutAddressingStep;
146
        $this->addressingPage = $addressingPage;
147
        $this->checkoutShippingStep = $checkoutShippingStep;
148
        $this->shippingPage = $shippingPage;
149
        $this->checkoutPaymentStep = $checkoutPaymentStep;
150
        $this->paymentPage = $paymentPage;
151
        $this->summaryPage = $summaryPage;
152
        $this->checkoutFinalizeStep = $checkoutFinalizeStep;
153
        $this->checkoutThankYouPage = $checkoutThankYouPage;
154
        $this->orderPaymentsPage = $orderPaymentsPage;
155
        $this->orderRepository = $orderRepository;
156
        $this->securityService = $securityService;
157
    }
158
159
    /**
160
     * @Given /^I proceed without selecting shipping address$/
161
     */
162
    public function iProceedWithoutSelectingShippingAddress()
163
    {
164
        $this->checkoutAddressingStep->open();
165
        $this->checkoutAddressingStep->continueCheckout();
166
    }
167
168
    /**
169
     * @Given I am at the checkout addressing step
170
     */
171
    public function iAmAtTheCheckoutAddressingStep()
172
    {
173
        $this->addressingPage->open();
174
    }
175
176
    /**
177
     * @Given /^(this user) bought this product$/
178
     */
179
    public function thisUserBought(UserInterface $user)
180
    {
181
        $this->securityService->performActionAs($user, function () {
182
            $this->iProceedSelectingOfflinePaymentMethod();
183
            $this->iConfirmMyOrder();
184
        });
185
    }
186
187
    /**
188
     * @When /^I specify the shipping (address as "([^"]+)", "([^"]+)", "([^"]+)", "([^"]+)" for "([^"]+)")$/
189
     * @When /^I (do not specify any shipping address) information$/
190
     */
191
    public function iSpecifyTheShippingAddressAs(AddressInterface $address)
192
    {
193
        $key = sprintf(
194
            'shipping_address_%s_%s',
195
            strtolower($address->getFirstName()),
196
            strtolower($address->getLastName())
197
        );
198
        $this->sharedStorage->set($key, $address);
199
200
        $this->addressingPage->specifyShippingAddress($address);
201
    }
202
203
    /**
204
     * @When /^I specify the billing (address as "([^"]+)", "([^"]+)", "([^"]+)", "([^"]+)" for "([^"]+)")$/
205
     * @When /^I (do not specify any billing address) information$/
206
     */
207
    public function iSpecifyTheBillingAddressAs(AddressInterface $address)
208
    {
209
        $this->iChooseTheDifferentBillingAddress();
210
        $key = sprintf(
211
            'billing_address_%s_%s',
212
            strtolower($address->getFirstName()),
213
            strtolower($address->getLastName())
214
        );
215
        $this->sharedStorage->set($key, $address);
216
217
        $this->addressingPage->specifyBillingAddress($address);
218
    }
219
220
    /**
221
     * @When /^I specified the shipping (address as "([^"]+)", "([^"]+)", "([^"]+)", "([^"]+)" for "([^"]+)")$/
222
     */
223
    public function iSpecifiedTheShippingAddress(AddressInterface $address)
224
    {
225
        $this->addressingPage->open();
226
        $this->iSpecifyTheShippingAddressAs($address);
227
228
        $key = sprintf('billing_address_%s_%s', strtolower($address->getFirstName()), strtolower($address->getLastName()));
229
        $this->sharedStorage->set($key, $address);
230
231
        $this->iCompleteTheAddressingStep();
232
    }
233
234
    /**
235
     * @When I choose the different billing address
236
     */
237
    public function iChooseTheDifferentBillingAddress()
238
    {
239
        $this->addressingPage->chooseDifferentBillingAddress();
240
    }
241
242
    /**
243
     * @When I specify the email as :email
244
     * @When I do not specify the email
245
     */
246
    public function iSpecifyTheEmail($email = null)
247
    {
248
        $this->addressingPage->specifyEmail($email);
249
    }
250
251
    /**
252
     * @When I select :shippingMethod shipping method
253
     */
254
    public function iSelectShippingMethod($shippingMethod)
255
    {
256
        $this->shippingPage->selectShippingMethod($shippingMethod);
257
    }
258
259
    /**
260
     * @Then I should not be able to select :shippingMethod shipping method
261
     */
262
    public function iShouldNotBeAbleToSelectShippingMethod($shippingMethod)
263
    {
264
        Assert::false(
265
            $this->shippingPage->hasShippingMethod($shippingMethod),
266
            sprintf('Shipping method "%s" should not be available but it does.', $shippingMethod)
267
        );
268
    }
269
270
    /**
271
     * @When I complete the addressing step
272
     * @When I try to complete the addressing step
273
     */
274
    public function iCompleteTheAddressingStep()
275
    {
276
        $this->addressingPage->nextStep();
277
    }
278
279
    /**
280
     * @When I complete the shipping step
281
     */
282
    public function iCompleteTheShippingStep()
283
    {
284
        $this->shippingPage->nextStep();
285
    }
286
287
    /**
288
     * @When /^I proceed selecting "([^"]*)" as shipping country$/
289
     */
290
    public function iProceedSelectingShippingCountry($shippingCountry)
291
    {
292
        $this->checkoutAddressingStep->open();
293
        $this->checkoutAddressingStep->fillAddressingDetails([
294
            'firstName' => 'John',
295
            'lastName' => 'Doe',
296
            'country' => $shippingCountry ?: 'France',
297
            'street' => '0635 Myron Hollow Apt. 711',
298
            'city' => 'North Bridget',
299
            'postcode' => '93-554',
300
            'phoneNumber' => '321123456',
301
        ]);
302
        $this->checkoutAddressingStep->continueCheckout();
303
    }
304
305
    /**
306
     * @When /^I proceed selecting "([^"]*)" as shipping country with "([^"]*)" method$/
307
     */
308
    public function iProceedSelectingShippingCountryAndShippingMethod($shippingCountry, $shippingMethodName)
309
    {
310
        $this->iProceedSelectingShippingCountry($shippingCountry);
311
312
        $this->checkoutShippingStep->selectShippingMethod($shippingMethodName ?: 'Free');
313
        $this->checkoutShippingStep->continueCheckout();
314
    }
315
316
    /**
317
     * @When /^I proceed selecting "([^"]+)" shipping method$/
318
     * @Given /^I chose "([^"]*)" shipping method$/
319
     */
320
    public function iProceedSelectingShippingMethod($shippingMethodName)
321
    {
322
        $this->iProceedSelectingShippingCountryAndShippingMethod(null, $shippingMethodName);
323
    }
324
325
    /**
326
     * @When /^I choose "([^"]*)" payment method$/
327
     */
328
    public function iChoosePaymentMethod($paymentMethodName)
329
    {
330
        $this->checkoutPaymentStep->verify([]);
331
        $this->checkoutPaymentStep->selectPaymentMethod($paymentMethodName ?: 'Offline');
332
        $this->checkoutPaymentStep->continueCheckout();
333
    }
334
335
    /**
336
     * @When /^I proceed selecting "([^"]*)" as shipping country with "([^"]*)" payment method$/
337
     */
338
    public function iProceedSelectingShippingCountryAndPaymentMethod($shippingCountry, $paymentMethodName)
339
    {
340
        $this->iProceedSelectingShippingCountryAndShippingMethod($shippingCountry, null);
341
342
        $this->iChoosePaymentMethod($paymentMethodName);
343
    }
344
345
    /**
346
     * @When I proceed selecting :paymentMethodName payment method
347
     */
348
    public function iProceedSelectingOfflinePaymentMethod($paymentMethodName = 'Offline')
349
    {
350
        $this->iProceedSelectingShippingCountryAndPaymentMethod(null, $paymentMethodName);
351
    }
352
353
    /**
354
     * @When /^I change shipping method to "([^"]*)"$/
355
     */
356
    public function iChangeShippingMethod($shippingMethodName)
357
    {
358
        $this->checkoutShippingStep->open();
359
        $this->checkoutShippingStep->selectShippingMethod($shippingMethodName);
360
        $this->checkoutShippingStep->continueCheckout();
361
    }
362
363
    /**
364
     * @Given /^I proceed logging as "([^"]*)" with "([^"]*)" password$/
365
     */
366
    public function iProceedLoggingAs($login, $password)
367
    {
368
        $this->checkoutSecurityStep->open();
369
        $this->checkoutSecurityStep->logInAsExistingUser($login, $password);
370
371
        $this->checkoutAddressingStep->continueCheckout();
372
    }
373
374
    /**
375
     * @When /^I proceed as guest "([^"]*)" with "([^"]*)" as shipping country$/
376
     */
377
    public function iProceedLoggingAsGuestWithAsShippingCountry($email, $shippingCountry)
378
    {
379
        $this->checkoutSecurityStep->open();
380
        $this->checkoutSecurityStep->proceedAsGuest($email);
381
382
        $this->iProceedSelectingShippingCountry($shippingCountry);
383
    }
384
385
    /**
386
     * @When I confirm my order
387
     */
388
    public function iConfirmMyOrder()
389
    {
390
        $this->checkoutFinalizeStep->confirmOrder();
391
    }
392
393
    /**
394
     * @When I specify the password as :password
395
     */
396
    public function iSpecifyThePasswordAs($password)
397
    {
398
        $this->addressingPage->specifyPassword($password);
399
    }
400
401
    /**
402
     * @When I sign in
403
     */
404
    public function iSignIn()
405
    {
406
        $this->addressingPage->signIn();
407
    }
408
409
    /**
410
     * @Then I should see the thank you page
411
     */
412
    public function iShouldSeeTheThankYouPage()
413
    {
414
        /** @var UserInterface $user */
415
        $user = $this->sharedStorage->get('user');
416
        $customer = $user->getCustomer();
417
418
        expect($this->checkoutThankYouPage->hasThankYouMessageFor($customer->getFullName()))->toBe(true);
419
    }
420
421
    /**
422
     * @Then I should be redirected back to the thank you page
423
     */
424
    public function iShouldBeRedirectedBackToTheThankYouPage()
425
    {
426
        $this->checkoutThankYouPage->waitForResponse(5);
427
428
        expect($this->checkoutThankYouPage->isOpen())->toBe(true);
429
    }
430
431
    /**
432
     * @Then I should be redirected back to the order payment page
433
     */
434
    public function iShouldBeRedirectedBackToTheOrderPaymentPage()
435
    {
436
        $this->orderPaymentsPage->waitForResponse(5, ['number' => $this->getLastOrder()->getNumber()]);
437
438
        expect($this->orderPaymentsPage->isOpen(['number' => $this->getLastOrder()->getNumber()]))->toBe(true);
439
    }
440
441
    /**
442
     * @Then I should be on the checkout shipping step
443
     */
444
    public function iShouldBeOnTheCheckoutShippingStep()
445
    {
446
        Assert::true(
447
            $this->shippingPage->isOpen(),
448
            'Checkout shipping page should be opened, but it is not.'
449
        );
450
    }
451
452
    /**
453
     * @Then I should be on the checkout summary step
454
     */
455
    public function iShouldBeOnTheCheckoutSummaryStep()
456
    {
457
        Assert::true(
458
            $this->summaryPage->isOpen(),
459
            'Checkout summary page should be opened, but it is not.'
460
        );
461
    }
462
463
    /**
464
     * @Then I should see two cancelled payments and new one ready to be paid
465
     */
466
    public function iShouldSeeTwoCancelledPaymentsAndNewOneReadyToBePaid()
467
    {
468
        expect($this->orderPaymentsPage->countPaymentWithSpecificState(PaymentInterface::STATE_CANCELLED))->toBe(2);
469
        expect($this->orderPaymentsPage->countPaymentWithSpecificState(PaymentInterface::STATE_NEW))->toBe(1);
470
    }
471
472
    /**
473
     * @Then /^I should(?:| also) be notified that the "([^"]+)" and the "([^"]+)" in (shipping|billing) details are required$/
474
     */
475
    public function iShouldBeNotifiedThatTheAndTheInShippingDetailsAreRequired($firstElement, $secondElement, $type)
476
    {
477
        $this->assertElementValidationMessage($type, $firstElement, sprintf('Please enter %s.', $firstElement));
478
        $this->assertElementValidationMessage($type, $secondElement, sprintf('Please enter %s.', $secondElement));
479
    }
480
481
    /**
482
     * @Then I should be informed that my order cannot be shipped to this address
483
     */
484
    public function iShouldBeInformedThatMyOrderCannotBeShippedToThisAddress()
485
    {
486
        Assert::true(
487
            $this->shippingPage->hasNoShippingMethodsMessage(),
488
            'Shipping page should have no shipping methods message but it does not.'
489
        );
490
    }
491
492
    /**
493
     * @Then I should be able to log in
494
     */
495
    public function iShouldBeAbleToLogIn()
496
    {
497
        Assert::true(
498
            $this->addressingPage->canSignIn(),
499
            'I should be able to login, but I am not.'
500
        );
501
    }
502
503
    /**
504
     * @Then the login form should no longer be accessible
505
     */
506
    public function theLoginFormShouldNoLongerBeAccessible()
507
    {
508
        Assert::false(
509
            $this->addressingPage->canSignIn(),
510
            'I should not be able to login, but I am.'
511
        );
512
    }
513
514
    /**
515
     * @Then I should be notified about bad credentials
516
     */
517
    public function iShouldBeNotifiedAboutBadCredentials()
518
    {
519
        Assert::true(
520
            $this->addressingPage->checkInvalidCredentialsValidation(),
521
            'I should see validation error, but I do not.'
522
        );
523
    }
524
525
    /**
526
     * @Then my order's shipping address should be to :fullName
527
     */
528
    public function iShouldSeeThisShippingAddressAsShippingAddress($fullName)
529
    {
530
        $address = $this->sharedStorage->get('shipping_address_'.StringInflector::nameToLowercaseCode($fullName));
531
        Assert::true(
532
            $this->summaryPage->hasShippingAddress($address),
533
            'Shipping address is improper.'
534
        );
535
    }
536
537
    /**
538
     * @Then my order's billing address should be to :fullName
539
     */
540
    public function iShouldSeeThisBillingAddressAsBillingAddress($fullName)
541
    {
542
        $address = $this->sharedStorage->get('billing_address_'.StringInflector::nameToLowercaseCode($fullName));
543
        Assert::true(
544
            $this->summaryPage->hasBillingAddress($address),
545
            'Billing address is improper.'
546
        );
547
    }
548
549
    /**
550
     * @Then address to :fullName should be used for both shipping and billing of my order`
551
     */
552
    public function iShouldSeeThisShippingAddressAsShippingAndBillingAddress($fullName)
553
    {
554
        $this->iShouldSeeThisShippingAddressAsShippingAddress($fullName);
555
        $this->iShouldSeeThisBillingAddressAsBillingAddress($fullName);
556
    }
557
558
    /**
559
     * @Given I am at the checkout payment step
560
     */
561
    public function iAmAtTheCheckoutPaymentStep()
562
    {
563
        $this->paymentPage->open();
564
    }
565
566
    /**
567
     * @When I complete the payment step
568
     */
569
    public function iCompleteThePaymentStep()
570
    {
571
        $this->paymentPage->nextStep();
572
    }
573
574
    /**
575
     * @When I select :paymentMethodName payment method
576
     */
577
    public function iSelectPaymentMethod($paymentMethodName)
578
    {
579
        $this->paymentPage->selectPaymentMethod($paymentMethodName);
580
    }
581
582
    /**
583
     * @Then I should not be able to select :paymentMethodName payment method
584
     */
585
    public function iShouldNotBeAbleToSelectPaymentMethod($paymentMethodName)
586
    {
587
        Assert::false(
588
            $this->paymentPage->hasPaymentMethod($paymentMethodName),
589
            sprintf('Payment method "%s" should not be available but it does.', $paymentMethodName)
590
        );
591
    }
592
593
    /**
594
     * @When I proceed order with :shippingMethod shipping method and :paymentMethod payment
595
     */
596
    public function iProceedOrderWithShippingMethodAndPayment($shippingMethod, $paymentMethod)
597
    {
598
        $this->iSelectShippingMethod($shippingMethod);
599
        $this->iCompleteTheShippingStep();
600
        $this->iSelectPaymentMethod($paymentMethod);
601
        $this->iCompleteThePaymentStep();
602
    }
603
604
    /**
605
     * @Given I should have :quantity :productName products in the cart
606
     */
607
    public function iShouldHaveProductsInTheCart($quantity, $productName)
608
    {
609
        Assert::true(
610
            $this->summaryPage->hasItemWithProductAndQuantity($productName, $quantity),
611
            sprintf('There is no "%s" with quantity %s on order summary page, but it should.', $productName, $quantity)
612
        );
613
    }
614
615
    /**
616
     * @param string $type
617
     * @param string $element
618
     * @param string $expectedMessage
619
     *
620
     * @throws \InvalidArgumentException
621
     */
622
    private function assertElementValidationMessage($type, $element, $expectedMessage)
623
    {
624
        $element = sprintf('%s_%s', $type, implode('_', explode(' ', $element)));
625
        Assert::true(
626
            $this->addressingPage->checkValidationMessageFor($element, $expectedMessage),
627
            sprintf('The %s should be required.', $element)
628
        );
629
    }
630
631
    /**
632
     * @return OrderInterface
633
     *
634
     * @throws \RuntimeException
635
     */
636
    private function getLastOrder()
637
    {
638
        $customer = $this->sharedStorage->get('user')->getCustomer();
639
        $orders = $this->orderRepository->findByCustomer($customer);
0 ignored issues
show
Bug introduced by
The method findByCustomer() does not exist on Sylius\Component\Order\R...rderRepositoryInterface. Did you maybe mean findBy()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
640
        $lastOrder = end($orders);
641
642
        if (false === $lastOrder) {
643
            throw new \RuntimeException(sprintf('There is no last order for %s', $customer->getFullName()));
644
        }
645
646
        return $lastOrder;
647
    }
648
}
649