Completed
Push — master ( d81c19...f57266 )
by Kamil
20s
created

Sylius/Behat/Context/Ui/Shop/AccountContext.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
declare(strict_types=1);
13
14
namespace Sylius\Behat\Context\Ui\Shop;
15
16
use Behat\Behat\Context\Context;
17
use Sylius\Behat\NotificationType;
18
use Sylius\Behat\Page\PageInterface;
19
use Sylius\Behat\Page\Shop\Account\ChangePasswordPageInterface;
20
use Sylius\Behat\Page\Shop\Account\DashboardPageInterface;
21
use Sylius\Behat\Page\Shop\Account\LoginPageInterface;
22
use Sylius\Behat\Page\Shop\Account\Order\IndexPageInterface;
23
use Sylius\Behat\Page\Shop\Account\Order\ShowPageInterface;
24
use Sylius\Behat\Page\Shop\Account\ProfileUpdatePageInterface;
25
use Sylius\Behat\Service\NotificationCheckerInterface;
26
use Sylius\Component\Core\Formatter\StringInflector;
27
use Sylius\Component\Core\Model\OrderInterface;
28
use Webmozart\Assert\Assert;
29
30
final class AccountContext implements Context
31
{
32
    /**
33
     * @var DashboardPageInterface
34
     */
35
    private $dashboardPage;
36
37
    /**
38
     * @var ProfileUpdatePageInterface
39
     */
40
    private $profileUpdatePage;
41
42
    /**
43
     * @var ChangePasswordPageInterface
44
     */
45
    private $changePasswordPage;
46
47
    /**
48
     * @var IndexPageInterface
49
     */
50
    private $orderIndexPage;
51
52
    /**
53
     * @var ShowPageInterface
54
     */
55
    private $orderShowPage;
56
57
    /**
58
     * @var LoginPageInterface
59
     */
60
    private $loginPage;
61
62
    /**
63
     * @var NotificationCheckerInterface
64
     */
65
    private $notificationChecker;
66
67
    /**
68
     * @param DashboardPageInterface $dashboardPage
69
     * @param ProfileUpdatePageInterface $profileUpdatePage
70
     * @param ChangePasswordPageInterface $changePasswordPage
71
     * @param IndexPageInterface $orderIndexPage
72
     * @param ShowPageInterface $orderShowPage
73
     * @param LoginPageInterface $loginPage
74
     * @param NotificationCheckerInterface $notificationChecker
75
     */
76
    public function __construct(
77
        DashboardPageInterface $dashboardPage,
78
        ProfileUpdatePageInterface $profileUpdatePage,
79
        ChangePasswordPageInterface $changePasswordPage,
80
        IndexPageInterface $orderIndexPage,
81
        ShowPageInterface $orderShowPage,
82
        LoginPageInterface $loginPage,
83
        NotificationCheckerInterface $notificationChecker
84
    ) {
85
        $this->dashboardPage = $dashboardPage;
86
        $this->profileUpdatePage = $profileUpdatePage;
87
        $this->changePasswordPage = $changePasswordPage;
88
        $this->orderIndexPage = $orderIndexPage;
89
        $this->orderShowPage = $orderShowPage;
90
        $this->loginPage = $loginPage;
91
        $this->notificationChecker = $notificationChecker;
92
    }
93
94
    /**
95
     * @When I want to modify my profile
96
     */
97
    public function iWantToModifyMyProfile()
98
    {
99
        $this->profileUpdatePage->open();
100
    }
101
102
    /**
103
     * @When I specify the first name as :firstName
104
     * @When I remove the first name
105
     */
106
    public function iSpecifyTheFirstName($firstName = null)
107
    {
108
        $this->profileUpdatePage->specifyFirstName($firstName);
109
    }
110
111
    /**
112
     * @When I specify the last name as :lastName
113
     * @When I remove the last name
114
     */
115
    public function iSpecifyTheLastName($lastName = null)
116
    {
117
        $this->profileUpdatePage->specifyLastName($lastName);
118
    }
119
120
    /**
121
     * @When I specify the customer email as :email
122
     * @When I remove the customer email
123
     */
124
    public function iSpecifyCustomerTheEmail($email = null)
125
    {
126
        $this->profileUpdatePage->specifyEmail($email);
127
    }
128
129
    /**
130
     * @When I save my changes
131
     * @When I try to save my changes
132
     */
133
    public function iSaveMyChanges()
134
    {
135
        $this->profileUpdatePage->saveChanges();
136
    }
137
138
    /**
139
     * @Then I should be notified that it has been successfully edited
140
     */
141
    public function iShouldBeNotifiedThatItHasBeenSuccessfullyEdited()
142
    {
143
        $this->notificationChecker->checkNotification('has been successfully updated.', NotificationType::success());
144
    }
145
146
    /**
147
     * @Then my name should be :name
148
     * @Then my name should still be :name
149
     */
150
    public function myNameShouldBe($name)
151
    {
152
        $this->dashboardPage->open();
153
154
        Assert::true($this->dashboardPage->hasCustomerName($name));
155
    }
156
157
    /**
158
     * @Then my email should be :email
159
     * @Then my email should still be :email
160
     */
161
    public function myEmailShouldBe($email)
162
    {
163
        $this->dashboardPage->open();
164
165
        Assert::true($this->dashboardPage->hasCustomerEmail($email));
166
    }
167
168
    /**
169
     * @Then /^I should be notified that the (email|password|city|street|first name|last name) is required$/
170
     */
171
    public function iShouldBeNotifiedThatElementIsRequired($element)
172
    {
173
        $this->assertFieldValidationMessage(
174
            $this->profileUpdatePage,
175
            StringInflector::nameToCode($element),
176
            sprintf('Please enter your %s.', $element)
177
        );
178
    }
179
180
    /**
181
     * @Then /^I should be notified that the (email) is invalid$/
182
     */
183
    public function iShouldBeNotifiedThatElementIsInvalid($element)
184
    {
185
        $this->assertFieldValidationMessage(
186
            $this->profileUpdatePage,
187
            StringInflector::nameToCode($element),
188
            sprintf('This %s is invalid.', $element)
189
        );
190
    }
191
192
    /**
193
     * @Then I should be notified that the email is already used
194
     */
195
    public function iShouldBeNotifiedThatTheEmailIsAlreadyUsed()
196
    {
197
        $this->assertFieldValidationMessage($this->profileUpdatePage, 'email', 'This email is already used.');
198
    }
199
200
    /**
201
     * @Given /^I want to change my password$/
202
     */
203
    public function iWantToChangeMyPassword()
204
    {
205
        $this->changePasswordPage->open();
206
    }
207
208
    /**
209
     * @Given I change password from :oldPassword to :newPassword
210
     */
211
    public function iChangePasswordTo($oldPassword, $newPassword)
212
    {
213
        $this->iSpecifyTheCurrentPasswordAs($oldPassword);
214
        $this->iSpecifyTheNewPasswordAs($newPassword);
215
        $this->iSpecifyTheConfirmationPasswordAs($newPassword);
216
    }
217
218
    /**
219
     * @Then I should be notified that my password has been successfully changed
220
     */
221
    public function iShouldBeNotifiedThatMyPasswordHasBeenSuccessfullyChanged()
222
    {
223
        $this->notificationChecker->checkNotification('has been changed successfully!', NotificationType::success());
224
    }
225
226
    /**
227
     * @Given I specify the current password as :password
228
     */
229
    public function iSpecifyTheCurrentPasswordAs($password)
230
    {
231
        $this->changePasswordPage->specifyCurrentPassword($password);
232
    }
233
234
    /**
235
     * @Given I specify the new password as :password
236
     */
237
    public function iSpecifyTheNewPasswordAs($password)
238
    {
239
        $this->changePasswordPage->specifyNewPassword($password);
240
    }
241
242
    /**
243
     * @Given I confirm this password as :password
244
     */
245
    public function iSpecifyTheConfirmationPasswordAs($password)
246
    {
247
        $this->changePasswordPage->specifyConfirmationPassword($password);
248
    }
249
250
    /**
251
     * @Then I should be notified that provided password is different than the current one
252
     */
253
    public function iShouldBeNotifiedThatProvidedPasswordIsDifferentThanTheCurrentOne()
254
    {
255
        $this->assertFieldValidationMessage(
256
            $this->changePasswordPage,
257
            'current_password',
258
            'Provided password is different than the current one.'
259
        );
260
    }
261
262
    /**
263
     * @Then I should be notified that the entered passwords do not match
264
     */
265
    public function iShouldBeNotifiedThatTheEnteredPasswordsDoNotMatch()
266
    {
267
        $this->assertFieldValidationMessage(
268
            $this->changePasswordPage,
269
            'new_password',
270
            'The entered passwords don\'t match'
271
        );
272
    }
273
274
    /**
275
     * @Then I should be notified that the password should be at least 4 characters long
276
     */
277
    public function iShouldBeNotifiedThatThePasswordShouldBeAtLeastCharactersLong()
278
    {
279
        $this->assertFieldValidationMessage(
280
            $this->changePasswordPage,
281
            'new_password',
282
            'Password must be at least 4 characters long.'
283
        );
284
    }
285
286
    /**
287
     * @When I browse my orders
288
     */
289
    public function iBrowseMyOrders()
290
    {
291
        $this->orderIndexPage->open();
292
    }
293
294
    /**
295
     * @Then I should see a single order in the list
296
     */
297
    public function iShouldSeeASingleOrderInTheList()
298
    {
299
        Assert::same($this->orderIndexPage->countOrders(), 1);
300
    }
301
302
    /**
303
     * @Then this order should have :order number
304
     */
305
    public function thisOrderShouldHaveNumber(OrderInterface $order)
306
    {
307
        Assert::true($this->orderIndexPage->isOrderWithNumberInTheList($order->getNumber()));
308
    }
309
310
    /**
311
     * @When I view the summary of the order :order
312
     */
313
    public function iViewTheSummaryOfTheOrder(OrderInterface $order)
314
    {
315
        $this->orderShowPage->open(['number' => $order->getNumber()]);
316
    }
317
318
    /**
319
     * @When I am viewing the summary of my last order
320
     */
321
    public function iViewingTheSummaryOfMyLastOrder()
322
    {
323
        $this->orderIndexPage->open();
324
        $this->orderIndexPage->openLastOrderPage();
325
    }
326
327
    /**
328
     * @Then it should has number :orderNumber
329
     */
330
    public function itShouldHasNumber($orderNumber)
331
    {
332
        Assert::same($this->orderShowPage->getNumber(), $orderNumber);
333
    }
334
335
    /**
336
     * @Then I should see :customerName, :street, :postcode, :city, :countryName as shipping address
337
     */
338
    public function iShouldSeeAsShippingAddress($customerName, $street, $postcode, $city, $countryName)
339
    {
340
        Assert::true($this->orderShowPage->hasShippingAddress($customerName, $street, $postcode, $city, $countryName));
341
    }
342
343
    /**
344
     * @Then I should see :customerName, :street, :postcode, :city, :countryName as billing address
345
     */
346
    public function itShouldBeShippedTo($customerName, $street, $postcode, $city, $countryName)
347
    {
348
        Assert::true($this->orderShowPage->hasBillingAddress($customerName, $street, $postcode, $city, $countryName));
349
    }
350
351
    /**
352
     * @Then I should see :total as order's total
353
     */
354
    public function iShouldSeeAsOrderSTotal($total)
355
    {
356
        Assert::same($this->orderShowPage->getTotal(), $total);
357
    }
358
359
    /**
360
     * @Then I should see :itemsTotal as order's subtotal
361
     */
362
    public function iShouldSeeAsOrderSSubtotal($subtotal)
363
    {
364
        Assert::same($this->orderShowPage->getSubtotal(), $subtotal);
365
    }
366
367
    /**
368
     * @Then I should see that I have to pay :paymentAmount for this order
369
     * @Then I should see :paymentTotal as payment total
370
     */
371
    public function iShouldSeeIHaveToPayForThisOrder($paymentAmount)
372
    {
373
        Assert::same($this->orderShowPage->getPaymentPrice(), $paymentAmount);
374
    }
375
376
    /**
377
     * @Then I should see :numberOfItems items in the list
378
     */
379
    public function iShouldSeeItemsInTheList($numberOfItems)
380
    {
381
        Assert::same($this->orderShowPage->countItems(), (int) $numberOfItems);
382
    }
383
384
    /**
385
     * @Then the product named :productName should be in the items list
386
     */
387
    public function theProductShouldBeInTheItemsList($productName)
388
    {
389
        Assert::true($this->orderShowPage->isProductInTheList($productName));
390
    }
391
392
    /**
393
     * @Then I should see :itemPrice as item price
394
     */
395
    public function iShouldSeeAsItemPrice($itemPrice)
396
    {
397
        Assert::same($this->orderShowPage->getItemPrice(), $itemPrice);
398
    }
399
400
    /**
401
     * @When I subscribe to the newsletter
402
     */
403
    public function iSubscribeToTheNewsletter()
404
    {
405
        $this->profileUpdatePage->subscribeToTheNewsletter();
406
    }
407
408
    /**
409
     * @Then I should be subscribed to the newsletter
410
     */
411
    public function iShouldBeSubscribedToTheNewsletter()
412
    {
413
        Assert::true($this->profileUpdatePage->isSubscribedToTheNewsletter());
414
    }
415
416
    /**
417
     * @Then I should see :provinceName as province in the shipping address
418
     */
419
    public function iShouldSeeAsProvinceInTheShippingAddress($provinceName)
420
    {
421
        Assert::true($this->orderShowPage->hasShippingProvinceName($provinceName));
422
    }
423
424
    /**
425
     * @Then I should see :provinceName as province in the billing address
426
     */
427
    public function iShouldSeeAsProvinceInTheBillingAddress($provinceName)
428
    {
429
        Assert::true($this->orderShowPage->hasBillingProvinceName($provinceName));
430
    }
431
432
    /**
433
     * @Then /^I should be able to change payment method for (this order)$/
434
     */
435
    public function iShouldBeAbleToChangePaymentMethodForThisOrder(OrderInterface $order)
436
    {
437
        Assert::true($this->orderIndexPage->isItPossibleToChangePaymentMethodForOrder($order));
438
    }
439
440
    /**
441
     * @Then I should be redirected to my account dashboard
442
     */
443
    public function iShouldBeRedirectedToMyAccountDashboard()
444
    {
445
        Assert::true($this->dashboardPage->isOpen(), 'User should be on the account panel dashboard page but they are not.');
446
    }
447
448
    /**
449
     * @When I want to log in
450
     */
451
    public function iWantToLogIn()
452
    {
453
        $this->loginPage->tryToOpen();
454
    }
455
456
    /**
457
     * @param PageInterface $page
458
     * @param string $element
459
     * @param string $expectedMessage
460
     */
461
    private function assertFieldValidationMessage(PageInterface $page, $element, $expectedMessage)
462
    {
463
        Assert::true($page->checkValidationMessageFor($element, $expectedMessage));
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Sylius\Behat\Page\PageInterface as the method checkValidationMessageFor() does only exist in the following implementations of said interface: Sylius\Behat\Page\Admin\Order\UpdatePage, Sylius\Behat\Page\Admin\...tionCoupon\GeneratePage, Sylius\Behat\Page\Shop\Account\ChangePasswordPage, Sylius\Behat\Page\Shop\Account\ProfileUpdatePage, Sylius\Behat\Page\Shop\Account\RegisterPage, Sylius\Behat\Page\Shop\Account\ResetPasswordPage, Sylius\Behat\Page\Shop\Checkout\AddressPage.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
464
    }
465
}
466