Completed
Push — master ( cfa808...648607 )
by Paweł
63:01 queued 48:26
created

AccountContext::iViewTheSummaryOfTheOrder()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
rs 10
cc 1
eloc 2
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\Shop;
13
14
use Behat\Behat\Context\Context;
15
use Sylius\Behat\NotificationType;
16
use Sylius\Behat\Page\PageInterface;
17
use Sylius\Behat\Page\Shop\Account\ChangePasswordPageInterface;
18
use Sylius\Behat\Page\Shop\Account\DashboardPageInterface;
19
use Sylius\Behat\Page\Shop\Account\Order\IndexPageInterface;
20
use Sylius\Behat\Page\Shop\Account\Order\ShowPageInterface;
21
use Sylius\Behat\Page\Shop\Account\ProfileUpdatePageInterface;
22
use Sylius\Behat\Service\NotificationCheckerInterface;
23
use Sylius\Component\Core\Formatter\StringInflector;
24
use Sylius\Component\Core\Model\OrderInterface;
25
use Webmozart\Assert\Assert;
26
27
/**
28
 * @author Grzegorz Sadowski <[email protected]>
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 NotificationCheckerInterface
59
     */
60
    private $notificationChecker;
61
62
    /**
63
     * @param DashboardPageInterface $dashboardPage
64
     * @param ProfileUpdatePageInterface $profileUpdatePage
65
     * @param ChangePasswordPageInterface $changePasswordPage
66
     * @param IndexPageInterface $orderIndexPage
67
     * @param ShowPageInterface $orderShowPage
68
     * @param NotificationCheckerInterface $notificationChecker
69
     */
70
    public function __construct(
71
        DashboardPageInterface $dashboardPage,
72
        ProfileUpdatePageInterface $profileUpdatePage,
73
        ChangePasswordPageInterface $changePasswordPage,
74
        IndexPageInterface $orderIndexPage,
75
        ShowPageInterface $orderShowPage,
76
        NotificationCheckerInterface $notificationChecker
77
    ) {
78
        $this->dashboardPage = $dashboardPage;
79
        $this->profileUpdatePage = $profileUpdatePage;
80
        $this->changePasswordPage = $changePasswordPage;
81
        $this->orderIndexPage = $orderIndexPage;
82
        $this->orderShowPage = $orderShowPage;
83
        $this->notificationChecker = $notificationChecker;
84
    }
85
86
    /**
87
     * @Given I want to modify my profile
88
     */
89
    public function iWantToModifyMyProfile()
90
    {
91
        $this->profileUpdatePage->open();
92
    }
93
94
    /**
95
     * @When I specify the first name as :firstName
96
     * @When I remove the first name
97
     */
98
    public function iSpecifyTheFirstName($firstName = null)
99
    {
100
        $this->profileUpdatePage->specifyFirstName($firstName);
101
    }
102
103
    /**
104
     * @When I specify the last name as :lastName
105
     * @When I remove the last name
106
     */
107
    public function iSpecifyTheLastName($lastName = null)
108
    {
109
        $this->profileUpdatePage->specifyLastName($lastName);
110
    }
111
112
    /**
113
     * @When I specify the email as :email
114
     * @When I remove the email
115
     */
116
    public function iSpecifyTheEmail($email = null)
117
    {
118
        $this->profileUpdatePage->specifyEmail($email);
119
    }
120
121
    /**
122
     * @When I save my changes
123
     * @When I try to save my changes
124
     */
125
    public function iSaveMyChanges()
126
    {
127
        $this->profileUpdatePage->saveChanges();
128
    }
129
130
    /**
131
     * @Then I should be notified that it has been successfully edited
132
     */
133
    public function iShouldBeNotifiedThatItHasBeenSuccessfullyEdited()
134
    {
135
        $this->notificationChecker->checkNotification('has been successfully updated.', NotificationType::success());
136
    }
137
138
    /**
139
     * @Then my name should be :name
140
     * @Then my name should still be :name
141
     */
142
    public function myNameShouldBe($name)
143
    {
144
        $this->dashboardPage->open();
145
146
        Assert::true(
147
            $this->dashboardPage->hasCustomerName($name),
148
            sprintf('Cannot find customer name "%s".', $name)
149
        );
150
    }
151
152
    /**
153
     * @Then my email should be :email
154
     * @Then my email should still be :email
155
     */
156
    public function myEmailShouldBe($email)
157
    {
158
        $this->dashboardPage->open();
159
160
        Assert::true(
161
            $this->dashboardPage->hasCustomerEmail($email),
162
            sprintf('Cannot find customer email "%s".', $email)
163
        );
164
    }
165
166
    /**
167
     * @Then /^I should be notified that the ([^"]+) is required$/
168
     */
169
    public function iShouldBeNotifiedThatElementIsRequired($element)
170
    {
171
        $this->assertFieldValidationMessage($this->profileUpdatePage, StringInflector::nameToCode($element), sprintf('Please enter your %s.', $element));
172
    }
173
174
    /**
175
     * @Then /^I should be notified that the ([^"]+) is invalid$/
176
     */
177
    public function iShouldBeNotifiedThatElementIsInvalid($element)
178
    {
179
        $this->assertFieldValidationMessage($this->profileUpdatePage, StringInflector::nameToCode($element), sprintf('This %s is invalid.', $element));
180
    }
181
182
    /**
183
     * @Then I should be notified that the email is already used
184
     */
185
    public function iShouldBeNotifiedThatTheEmailIsAlreadyUsed()
186
    {
187
        $this->assertFieldValidationMessage($this->profileUpdatePage, 'email', 'This email is already used.');
188
    }
189
190
    /**
191
     * @Given /^I want to change my password$/
192
     */
193
    public function iWantToChangeMyPassword()
194
    {
195
        $this->changePasswordPage->open();
196
    }
197
198
    /**
199
     * @Given I change password from :oldPassword to :newPassword
200
     */
201
    public function iChangePasswordTo($oldPassword, $newPassword)
202
    {
203
        $this->iSpecifyTheCurrentPasswordAs($oldPassword);
204
        $this->iSpecifyTheNewPasswordAs($newPassword);
205
        $this->iSpecifyTheConfirmationPasswordAs($newPassword);
206
    }
207
208
    /**
209
     * @Then I should be notified that my password has been successfully changed
210
     */
211
    public function iShouldBeNotifiedThatMyPasswordHasBeenSuccessfullyChanged()
212
    {
213
        $this->notificationChecker->checkNotification('has been changed successfully!', NotificationType::success());
214
    }
215
216
    /**
217
     * @Given I specify the current password as :password
218
     */
219
    public function iSpecifyTheCurrentPasswordAs($password)
220
    {
221
        $this->changePasswordPage->specifyCurrentPassword($password);
222
    }
223
224
    /**
225
     * @Given I specify the new password as :password
226
     */
227
    public function iSpecifyTheNewPasswordAs($password)
228
    {
229
        $this->changePasswordPage->specifyNewPassword($password);
230
    }
231
232
    /**
233
     * @Given I confirm this password as :password
234
     */
235
    public function iSpecifyTheConfirmationPasswordAs($password)
236
    {
237
        $this->changePasswordPage->specifyConfirmationPassword($password);
238
    }
239
240
    /**
241
     * @Then I should be notified that provided password is different than the current one
242
     */
243
    public function iShouldBeNotifiedThatProvidedPasswordIsDifferentThanTheCurrentOne()
244
    {
245
        $this->assertFieldValidationMessage($this->changePasswordPage, 'current_password', 'Provided password is different than the current one.');
246
    }
247
248
    /**
249
     * @Then I should be notified that the entered passwords do not match
250
     */
251
    public function iShouldBeNotifiedThatTheEnteredPasswordsDoNotMatch()
252
    {
253
        $this->assertFieldValidationMessage($this->changePasswordPage, 'new_password', 'The entered passwords don\'t match');
254
    }
255
256
    /**
257
     * @Then I should be notified that the password should be at least 4 characters long
258
     */
259
    public function iShouldBeNotifiedThatThePasswordShouldBeAtLeastCharactersLong()
260
    {
261
        $this->assertFieldValidationMessage($this->changePasswordPage, 'new_password', 'Password must be at least 4 characters long.');
262
    }
263
264
    /**
265
     * @When I browse my orders
266
     */
267
    public function iBrowseMyOrders()
268
    {
269
        $this->orderIndexPage->open();
270
    }
271
272
    /**
273
     * @Then I should see a single order in the list
274
     */
275
    public function iShouldSeeASingleOrderInTheList()
276
    {
277
        Assert::same(
278
            1,
279
            $this->orderIndexPage->countOrders(),
280
            '%s rows with orders should appear on page, %s rows have been found.'
281
        );
282
    }
283
284
    /**
285
     * @Then this order should have :order number
286
     */
287
    public function thisOrderShouldHaveNumber(OrderInterface $order)
288
    {
289
        Assert::true(
290
            $this->orderIndexPage->isOrderWithNumberInTheList($order->getNumber()),
291
            sprintf('Cannot find order with number "%s" in the list.', $order->getNumber())
292
        );
293
    }
294
295
    /**
296
     * @When I view the summary of the order :order
297
     */
298
    public function iViewTheSummaryOfTheOrder(OrderInterface $order)
299
    {
300
        $this->orderShowPage->open(['number' => $order->getNumber()]);
301
    }
302
303
    /**
304
     * @Then it should has number :orderNumber
305
     */
306
    public function itShouldHasNumber($orderNumber)
307
    {
308
        Assert::same(
309
            $this->orderShowPage->getNumber(),
310
            $orderNumber,
311
            'The number of an order is %s, but should be %s.'
312
        );
313
    }
314
315
    /**
316
     * @Then I should see :customerName, :street, :postcode, :city, :countryName as shiping address
317
     */
318
    public function iShouldSeeAsShipingAddress($customerName, $street, $postcode, $city, $countryName)
319
    {
320
        Assert::true(
321
            $this->orderShowPage->hasShippingAddress($customerName, $street, $postcode, $city, $countryName),
322
            sprintf('Cannot find shipping address "%s, %s %s, %s".', $street, $postcode, $city, $countryName)
323
        );
324
    }
325
326
    /**
327
     * @Then I should see :customerName, :street, :postcode, :city, :countryName as billing address
328
     */
329
    public function itShouldBeShippedTo($customerName, $street, $postcode, $city, $countryName)
330
    {
331
        Assert::true(
332
            $this->orderShowPage->hasBillingAddress($customerName, $street, $postcode, $city, $countryName),
333
            sprintf('Cannot find shipping address "%s, %s %s, %s".', $street, $postcode, $city, $countryName)
334
        );
335
    }
336
337
    /**
338
     * @Then I should see :total as order's total
339
     */
340
    public function iShouldSeeAsOrderSTotal($total)
341
    {
342
        Assert::same(
343
            $this->orderShowPage->getTotal(),
344
            $total,
345
            'Total is %s, but should be %s.'
346
        );
347
    }
348
349
    /**
350
     * @Then I should see :itemsTotal as order's subtotal
351
     */
352
    public function iShouldSeeAsOrderSSubtotal($subtotal)
353
    {
354
        Assert::same(
355
            $this->orderShowPage->getSubtotal(),
356
            $subtotal,
357
            'Subtotal is %s, but should be %s.'
358
        );
359
    }
360
361
    /**
362
     * @Then I should see :numberOfItems items in the list
363
     */
364
    public function iShouldSeeItemsInTheList($numberOfItems)
365
    {
366
        Assert::same(
367
            $numberOfItems,
368
            $this->orderShowPage->countItems(),
369
            '%s items should appear on order page, but %s rows has been found'
370
        );
371
    }
372
373
    /**
374
     * @Then the product named :productName should be in the items list
375
     */
376
    public function theProductShouldBeInTheItemsList($productName)
377
    {
378
        Assert::true(
379
            $this->orderShowPage->isProductInTheList($productName),
380
            sprintf('Product %s is not in the item list.', $productName)
381
        );
382
    }
383
384
    /**
385
     * @param PageInterface $page
386
     * @param string $element
387
     * @param string $expectedMessage
388
     */
389
    private function assertFieldValidationMessage(PageInterface $page, $element, $expectedMessage)
390
    {
391
        Assert::true(
392
            $page->checkValidationMessageFor($element, $expectedMessage),
0 ignored issues
show
Bug introduced by
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\Channel\CreatePage, Sylius\Behat\Page\Admin\Channel\UpdatePage, Sylius\Behat\Page\Admin\Country\CreatePage, Sylius\Behat\Page\Admin\Country\UpdatePage, Sylius\Behat\Page\Admin\Crud\CreatePage, Sylius\Behat\Page\Admin\Crud\UpdatePage, Sylius\Behat\Page\Admin\Currency\CreatePage, Sylius\Behat\Page\Admin\Currency\UpdatePage, Sylius\Behat\Page\Admin\Customer\CreatePage, Sylius\Behat\Page\Admin\Customer\UpdatePage, Sylius\Behat\Page\Admin\Locale\CreatePage, Sylius\Behat\Page\Admin\Locale\UpdatePage, Sylius\Behat\Page\Admin\PaymentMethod\CreatePage, Sylius\Behat\Page\Admin\PaymentMethod\UpdatePage, Sylius\Behat\Page\Admin\...uctAttribute\CreatePage, Sylius\Behat\Page\Admin\...uctAttribute\UpdatePage, Sylius\Behat\Page\Admin\ProductOption\CreatePage, Sylius\Behat\Page\Admin\ProductOption\UpdatePage, Sylius\Behat\Page\Admin\ProductVariant\CreatePage, Sylius\Behat\Page\Admin\ProductVariant\UpdatePage, Sylius\Behat\Page\Admin\...ConfigurableProductPage, Sylius\Behat\Page\Admin\...CreateSimpleProductPage, Sylius\Behat\Page\Admin\...ConfigurableProductPage, Sylius\Behat\Page\Admin\...UpdateSimpleProductPage, Sylius\Behat\Page\Admin\PromotionCoupon\CreatePage, Sylius\Behat\Page\Admin\...tionCoupon\GeneratePage, Sylius\Behat\Page\Admin\PromotionCoupon\UpdatePage, Sylius\Behat\Page\Admin\Promotion\CreatePage, Sylius\Behat\Page\Admin\Promotion\UpdatePage, Sylius\Behat\Page\Admin\ShippingMethod\CreatePage, Sylius\Behat\Page\Admin\ShippingMethod\UpdatePage, Sylius\Behat\Page\Admin\TaxCategory\CreatePage, Sylius\Behat\Page\Admin\TaxCategory\UpdatePage, Sylius\Behat\Page\Admin\TaxRate\CreatePage, Sylius\Behat\Page\Admin\TaxRate\UpdatePage, Sylius\Behat\Page\Admin\Taxon\CreatePage, Sylius\Behat\Page\Admin\Taxon\UpdatePage, Sylius\Behat\Page\Admin\Zone\CreatePage, Sylius\Behat\Page\Admin\Zone\UpdatePage, 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\AddressingPage.

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...
393
            sprintf('There should be a message: "%s".', $expectedMessage)
394
        );
395
    }
396
}
397