Completed
Pull Request — example/managing-articles (#134)
by Loïc
02:30
created

RegistrationContext::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.6333
c 0
b 0
f 0
cc 1
nc 1
nop 8

How to fix   Many Parameters   

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/*
4
 * This file is part of AppName.
5
 *
6
 * (c) Monofony
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 App\Behat\Context\Ui\Frontend;
15
16
use Behat\Behat\Context\Context;
17
use App\Behat\NotificationType;
18
use App\Behat\Page\Frontend\Account\DashboardPage;
19
use App\Behat\Page\Frontend\Account\LoginPage;
20
use App\Behat\Page\Frontend\Account\ProfileUpdatePage;
21
use App\Behat\Page\Frontend\Account\RegisterPage;
22
use App\Behat\Page\Frontend\Account\VerificationPage;
23
use App\Behat\Page\Frontend\HomePage;
24
use App\Behat\Service\NotificationCheckerInterface;
25
use App\Behat\Service\SharedStorageInterface;
26
use Sylius\Component\Customer\Model\CustomerInterface;
27
use Sylius\Component\User\Model\UserInterface;
28
use Webmozart\Assert\Assert;
29
30
class RegistrationContext implements Context
31
{
32
    /**
33
     * @var SharedStorageInterface
34
     */
35
    private $sharedStorage;
36
37
    /**
38
     * @var DashboardPage
39
     */
40
    private $dashboardPage;
41
42
    /**
43
     * @var HomePage
44
     */
45
    private $homePage;
46
47
    /**
48
     * @var LoginPage
49
     */
50
    private $loginPage;
51
52
    /**
53
     * @var RegisterPage
54
     */
55
    private $registerPage;
56
57
    /**
58
     * @var VerificationPage
59
     */
60
    private $verificationPage;
61
62
    /**
63
     * @var ProfileUpdatePage
64
     */
65
    private $profileUpdatePage;
66
67
    /**
68
     * @var NotificationCheckerInterface
69
     */
70
    private $notificationChecker;
71
72
    /**
73
     * @param SharedStorageInterface       $sharedStorage
74
     * @param DashboardPage                $dashboardPage
75
     * @param HomePage                     $homePage
76
     * @param LoginPage                    $loginPage
77
     * @param RegisterPage                 $registerPage
78
     * @param VerificationPage             $verificationPage
79
     * @param ProfileUpdatePage            $profileUpdatePage
80
     * @param NotificationCheckerInterface $notificationChecker
81
     */
82
    public function __construct(
83
        SharedStorageInterface $sharedStorage,
84
        DashboardPage $dashboardPage,
85
        HomePage $homePage,
86
        LoginPage $loginPage,
87
        RegisterPage $registerPage,
88
        VerificationPage $verificationPage,
89
        ProfileUpdatePage $profileUpdatePage,
90
        NotificationCheckerInterface $notificationChecker
91
    ) {
92
        $this->sharedStorage = $sharedStorage;
93
        $this->dashboardPage = $dashboardPage;
94
        $this->homePage = $homePage;
95
        $this->loginPage = $loginPage;
96
        $this->registerPage = $registerPage;
97
        $this->verificationPage = $verificationPage;
98
        $this->profileUpdatePage = $profileUpdatePage;
99
        $this->notificationChecker = $notificationChecker;
100
    }
101
102
    /**
103
     * @When /^I want to(?:| again) register a new account$/
104
     */
105
    public function iWantToRegisterANewAccount()
106
    {
107
        $this->registerPage->open();
108
    }
109
110
    /**
111
     * @When I specify the first name as :firstName
112
     * @When I do not specify the first name
113
     */
114
    public function iSpecifyTheFirstName(?string $firstName = null): void
115
    {
116
        $this->registerPage->specifyFirstName($firstName);
117
    }
118
119
    /**
120
     * @When I specify the last name as :lastName
121
     * @When I do not specify the last name
122
     */
123
    public function iSpecifyTheLastName(?string $lastName = null): void
124
    {
125
        $this->registerPage->specifyLastName($lastName);
126
    }
127
128
129
    /**
130
     * @When I specify the email as :email
131
     * @When I do not specify the email
132
     */
133
    public function iSpecifyTheEmail($email = null)
134
    {
135
        $this->registerPage->specifyEmail($email);
136
    }
137
138
    /**
139
     * @When I specify the password as :password
140
     * @When I do not specify the password
141
     */
142
    public function iSpecifyThePasswordAs($password = null)
143
    {
144
        $this->registerPage->specifyPassword($password);
145
        $this->sharedStorage->set('password', $password);
146
    }
147
148
    /**
149
     * @When /^I confirm (this password)$/
150
     */
151
    public function iConfirmThisPassword($password)
152
    {
153
        $this->registerPage->verifyPassword($password);
154
    }
155
156
    /**
157
     * @Given I do not confirm the password
158
     */
159
    public function iDoNotConfirmPassword()
160
    {
161
        $this->registerPage->verifyPassword(null);
162
    }
163
164
    /**
165
     * @When I specify the phone number as :phoneNumber
166
     */
167
    public function iSpecifyThePhoneNumberAs($phoneNumber)
168
    {
169
        $this->registerPage->specifyPhoneNumber($phoneNumber);
0 ignored issues
show
Bug introduced by
The method specifyPhoneNumber() does not seem to exist on object<App\Behat\Page\Fr...d\Account\RegisterPage>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
170
    }
171
172
    /**
173
     * @When I register this account
174
     * @When I try to register this account
175
     */
176
    public function iRegisterThisAccount()
177
    {
178
        $this->registerPage->register();
179
    }
180
181
    /**
182
     * @Then my email should be :email
183
     * @Then my email should still be :email
184
     */
185
    public function myEmailShouldBe($email)
186
    {
187
        $this->dashboardPage->open();
188
189
        Assert::true($this->dashboardPage->hasCustomerEmail($email));
190
    }
191
192
    /**
193
     * @Then /^I should be notified that the ([^"]+) is required$/
194
     */
195
    public function iShouldBeNotifiedThatElementIsRequired($element)
196
    {
197
        $this->assertFieldValidationMessage($element, sprintf('Please enter your %s.', $element));
198
    }
199
200
    /**
201
     * @Then I should be notified that the email is already used
202
     */
203
    public function iShouldBeNotifiedThatTheEmailIsAlreadyUsed()
204
    {
205
        $this->assertFieldValidationMessage('email', 'This email is already used.');
206
    }
207
208
    /**
209
     * @Then I should be notified that the password do not match
210
     */
211
    public function iShouldBeNotifiedThatThePasswordDoNotMatch()
212
    {
213
        $this->assertFieldValidationMessage('password', 'The entered passwords don\'t match');
214
    }
215
216
    /**
217
     * @Then I should be notified that new account has been successfully created
218
     * @Then I should be notified that my account has been created and the verification email has been sent
219
     */
220
    public function iShouldBeNotifiedThatNewAccountHasBeenSuccessfullyCreated()
221
    {
222
        $this->notificationChecker->checkNotification(
223
            'Thank you for registering, check your email to verify your account.',
224
            NotificationType::success()
225
        );
226
    }
227
228
    /**
229
     * @Then I should be logged in
230
     */
231
    public function iShouldBeLoggedIn()
232
    {
233
        Assert::true($this->homePage->hasLogoutButton());
234
    }
235
236
    /**
237
     * @Then I should not be logged in
238
     */
239
    public function iShouldNotBeLoggedIn()
240
    {
241
        Assert::false($this->homePage->hasLogoutButton());
242
    }
243
244
    /**
245
     * @Then I should be able to log in as :email with :password password
246
     */
247
    public function iShouldBeAbleToLogInAsWithPassword($email, $password)
248
    {
249
        $this->iLogInAsWithPassword($email, $password);
250
        $this->iShouldBeLoggedIn();
251
    }
252
253
    /**
254
     * @Then I should not be able to log in as :email with :password password
255
     */
256
    public function iShouldNotBeAbleToLogInAsWithPassword($email, $password)
257
    {
258
        $this->iLogInAsWithPassword($email, $password);
259
260
        Assert::true($this->loginPage->hasValidationErrorWith('Error Account is disabled.'));
261
    }
262
263
    /**
264
     * @When I log in as :email with :password password
265
     */
266
    public function iLogInAsWithPassword($email, $password)
267
    {
268
        $this->loginPage->open();
269
        $this->loginPage->specifyUsername($email);
270
        $this->loginPage->specifyPassword($password);
271
        $this->loginPage->logIn();
272
    }
273
274
    /**
275
     * @When I register with email :email and password :password
276
     */
277
    public function iRegisterWithEmailAndPassword($email, $password)
278
    {
279
        $this->registerPage->open();
280
        $this->registerPage->specifyEmail($email);
281
        $this->registerPage->specifyPassword($password);
282
        $this->registerPage->verifyPassword($password);
283
        $this->registerPage->specifyFirstName('Carrot');
284
        $this->registerPage->specifyLastName('Ironfoundersson');
285
        $this->registerPage->register();
286
    }
287
288
    /**
289
     * @Then /^my account should be verified$/
290
     */
291
    public function myAccountShouldBeVerified()
292
    {
293
        Assert::true($this->dashboardPage->isVerified());
294
    }
295
296
    /**
297
     * @When /^(I) try to verify my account using the link from this email$/
298
     */
299
    public function iUseItToVerify(UserInterface $user)
300
    {
301
        $this->verificationPage->verifyAccount($user->getEmailVerificationToken());
302
    }
303
304
    /**
305
     * @When I verify my account using link sent to :customer
306
     */
307
    public function iVerifyMyAccount(CustomerInterface $customer)
308
    {
309
        $user = $customer->getUser();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Sylius\Component\Customer\Model\CustomerInterface as the method getUser() does only exist in the following implementations of said interface: App\Entity\Customer.

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...
310
        Assert::notNull($user, 'No account for given customer');
311
312
        $this->iUseItToVerify($user);
313
    }
314
315
    /**
316
     * @When I resend the verification email
317
     */
318
    public function iResendVerificationEmail()
319
    {
320
        $this->dashboardPage->open();
321
        $this->dashboardPage->pressResendVerificationEmail();
322
    }
323
324
    /**
325
     * @When I use the verification link from the first email to verify
326
     */
327
    public function iUseVerificationLinkFromFirstEmailToVerify()
328
    {
329
        $token = $this->sharedStorage->get('verification_token');
330
331
        $this->verificationPage->verifyAccount($token);
332
    }
333
334
    /**
335
     * @When I (try to )verify using :token token
336
     */
337
    public function iTryToVerifyUsing($token)
338
    {
339
        $this->verificationPage->verifyAccount($token);
340
    }
341
342
    /**
343
     * @Then /^(?:my|his|her) account should not be verified$/
344
     */
345
    public function myAccountShouldNotBeVerified()
346
    {
347
        $this->dashboardPage->open();
348
349
        Assert::false($this->dashboardPage->isVerified());
350
    }
351
352
    /**
353
     * @Then I should not be able to resend the verification email
354
     */
355
    public function iShouldBeUnableToResendVerificationEmail()
356
    {
357
        $this->dashboardPage->open();
358
359
        Assert::false($this->dashboardPage->hasResendVerificationEmailButton());
360
    }
361
362
    /**
363
     * @Then I should be notified that the verification was successful
364
     */
365
    public function iShouldBeNotifiedThatTheVerificationWasSuccessful()
366
    {
367
        $this->notificationChecker->checkNotification('has been successfully verified.', NotificationType::success());
368
    }
369
370
    /**
371
     * @Then I should be notified that the verification token is invalid
372
     */
373
    public function iShouldBeNotifiedThatTheVerificationTokenIsInvalid()
374
    {
375
        $this->notificationChecker->checkNotification('The verification token is invalid.', NotificationType::failure());
376
    }
377
378
    /**
379
     * @Then I should be notified that the verification email has been sent
380
     */
381
    public function iShouldBeNotifiedThatTheVerificationEmailHasBeenSent()
382
    {
383
        $this->notificationChecker->checkNotification(
384
            'An email with the verification link has been sent to your email address.',
385
            NotificationType::success()
386
        );
387
    }
388
389
    /**
390
     * @When I subscribe to the newsletter
391
     */
392
    public function iSubscribeToTheNewsletter()
393
    {
394
        $this->registerPage->subscribeToTheNewsletter();
395
    }
396
397
    /**
398
     * @Then I should be subscribed to the newsletter
399
     */
400
    public function iShouldBeSubscribedToTheNewsletter()
401
    {
402
        $this->profileUpdatePage->open();
403
404
        Assert::true($this->profileUpdatePage->isSubscribedToTheNewsletter());
405
    }
406
407
    /**
408
     * @param string $element
409
     * @param string $expectedMessage
410
     */
411
    private function assertFieldValidationMessage($element, $expectedMessage)
412
    {
413
        Assert::true($this->registerPage->checkValidationMessageFor($element, $expectedMessage));
414
    }
415
}
416