Passed
Push — develop ( 28c299...928e2a )
by Mathias
12:40
created

UserContext::tearDown()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 29
rs 9.456
c 0
b 0
f 0
cc 4
nc 4
nop 0
1
<?php
2
/**
3
 * YAWIK
4
 *
5
 * @filesource
6
 * @license MIT
7
 * @copyright  2013 - 2017 Cross Solution <http://cross-solution.de>
8
 */
9
10
namespace Yawik\Behat;
11
12
use Auth\Entity\User as User;
13
use Auth\Entity\UserInterface;
14
use Auth\Repository\User as UserRepository;
15
use Auth\Service\Register;
16
use Behat\Behat\Context\Context;
17
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
18
use Behat\Gherkin\Node\TableNode;
19
use Behat\MinkExtension\Context\MinkContext;
20
use Core\Entity\Permissions;
21
use Doctrine\Common\Util\Inflector;
22
use Doctrine\ODM\MongoDB\DocumentManager;
23
use Doctrine\ODM\MongoDB\Event\LifecycleEventArgs;
24
use Doctrine\ODM\MongoDB\Events;
25
use Organizations\Entity\Organization;
26
use Organizations\Entity\OrganizationName;
27
use Organizations\Repository\Organization as OrganizationRepository;
28
use Yawik\Behat\Exception\FailedExpectationException;
29
30
class UserContext implements Context
31
{
32
    use CommonContextTrait;
33
    
34
    /**
35
     * @var User[]
36
     */
37
    private static $users = [];
38
    
39
    /**
40
     * @var UserRepository
41
     */
42
    private static $userRepo;
43
    
44
    private $socialLoginInfo = [];
45
46
    /**
47
     * @var DocumentManager
48
     */
49
    private static $dm;
50
    
51
    /**
52
     * @var UserInterface
53
     */
54
    private $loggedInUser;
55
56
    /**
57
     * @var Organization
58
     */
59
    private $mainOrganization;
60
61
    /**
62
     * @var User
63
     */
64
    protected $currentUser;
65
    
66
    public function __construct($parameters=[])
67
    {
68
        $defaultLoginInfo = [
69
            'facebook' => [
70
                'email' => getenv('FACEBOOK_USER_EMAIL'),
71
                'pass' => getenv('FACEBOOK_USER_PASSWORD')
72
            ],
73
            'linkedin' => [
74
                'session_key-login' => getenv('LINKEDIN_USER_EMAIL'),
75
                'session_password-login' => getenv('LINKEDIN_USER_PASSWORD')
76
            ],
77
        ];
78
        $socialLoginConfig = isset($parameters['social_login_info']) ? $parameters['social_login_info']:[];
79
        $this->socialLoginInfo = array_merge($defaultLoginInfo, $socialLoginConfig);
80
    }
81
82
    /**
83
     * Empty all data every each tests
84
     *
85
     * @AfterSuite
86
     */
87
    public static function tearDown()
88
    {
89
        $dm = static::$dm;
90
91
        if (is_null($dm)) {
92
            return;
93
        }
94
95
        $documents = [
96
            'Applications\Entity\Application',
97
            'Cv\Entity\Cv',
98
            'Jobs\Entity\Job',
99
            'Organizations\Entity\Organization',
100
            'Auth\Entity\User',
101
            'Jobs\Entity\Category',
102
            'Auth\Entity\UserImage',
103
            'Organizations\Entity\OrganizationName',
104
        ];
105
        foreach ($documents as $document) {
106
            try {
107
                $dm->createQueryBuilder($document)
108
                    ->remove()
109
                    ->getQuery()
110
                    ->execute()
111
                ;
112
            } catch (\Exception $e) {
113
            }
114
        }
115
    }
116
117
    /**
118
     * @BeforeScenario
119
     * @param BeforeScenarioScope $scope
120
     */
121
    public function beforeScenario(BeforeScenarioScope $scope)
122
    {
123
        $this->minkContext = $scope->getEnvironment()->getContext(MinkContext::class);
124
        $this->coreContext = $scope->getEnvironment()->getContext(CoreContext::class);
125
        static::$userRepo = $this->getUserRepository();
126
        static::$dm = $this->getUserRepository()->getDocumentManager();
127
    }
128
    
129
    /**
130
     * @When I fill in login form with :provider user
131
     */
132
    public function iSignInWithSocialUser($provider)
133
    {
134
        $provider = strtolower($provider);
135
        $mink = $this->minkContext;
136
        foreach ($this->socialLoginInfo[$provider] as $field=>$value) {
137
            $mink->fillField($field, $value);
138
        }
139
    }
140
    
141
    /**
142
     * @Given I am logged in as a recruiter
143
     * @Given I am logged in as a recruiter with :organization as organization
144
     */
145
    public function iAmLoggedInAsARecruiter($organization=null)
146
    {
147
        $user = $this->thereIsAUserIdentifiedBy(
148
            '[email protected]',
149
            'test',
150
            User::ROLE_RECRUITER,
151
            'Test Recruiter',
152
            $organization
153
        );
154
        $this->startLogin($user, 'test');
155
        if (!is_null($organization)) {
156
            $this->iHaveMainOrganization($user, $organization);
157
        }
158
    }
159
160
    /**
161
     * @Given I am logged out
162
     */
163
    public function iHaveLoggedOut()
164
    {
165
        $url = $this->minkContext->locatePath('/logout');
166
        $this->minkContext->getSession()->visit($url);
167
    }
168
169
    
170
    /**
171
     * @Given I don't have :login user
172
     * @param string $login
173
     */
174
    public function iDonTHaveUser($login)
175
    {
176
        $repo = $this->getUserRepository();
177
        $user=$repo->findByLogin($login);
178
        if ($user instanceof UserInterface) {
179
            $repo->remove($user, true);
180
        }
181
    }
182
    
183
    /**
184
     * @Given I have a :role with the following:
185
     * @Given I have an :role with the following:
186
     *
187
     * @param $role
188
     * @param TableNode $fields
189
     */
190
    public function iHaveUserWithTheFollowing($role, TableNode $fields)
191
    {
192
        $normalizedFields = [
193
            'login' => '[email protected]',
194
            'fullName' => 'Test Login',
195
            'role' => $role,
196
            'password' => 'test',
197
            'organization' => 'Cross Solution'
198
        ];
199
        foreach ($fields->getRowsHash() as $field=>$value) {
200
            $field = Inflector::camelize($field);
201
            $normalizedFields[$field] = $value;
202
        }
203
        
204
        $this->thereIsAUserIdentifiedBy(
205
            $normalizedFields['login'],
206
            $normalizedFields['password'],
207
            $role,
208
            $normalizedFields['fullName'],
209
            $normalizedFields['organization']
210
        );
211
    }
212
    
213
    /**
214
     * @Given I am logged in as an administrator
215
     */
216
    public function iAmLoggedInAsAnAdmin()
217
    {
218
        $user = $this->thereIsAUserIdentifiedBy('[email protected]', 'test', User::ROLE_ADMIN);
219
        $this->startLogin($user, 'test');
220
    }
221
    
222
    private function startLogin(UserInterface $user, $password)
223
    {
224
        $currentUser = $this->currentUser;
225
        if (!is_object($currentUser) || $user->getId()!=$currentUser->getId()) {
226
            $this->iWantToLogIn();
227
            $this->iSpecifyTheUsernameAs($user->getLogin());
228
            $this->iSpecifyThePasswordAs($password);
229
            $this->iLogIn();
230
            $this->currentUser = $user;
231
        }
232
    }
233
    
234
    /**
235
     * @return UserRepository
236
     */
237
    public function getUserRepository()
238
    {
239
        return $this->coreContext->getRepositories()->get('Auth\Entity\User');
240
    }
241
    
242
    /**
243
     * @Given there is a user :email identified by :password
244
     */
245
    public function thereIsAUserIdentifiedBy($email, $password, $role=User::ROLE_RECRUITER, $fullname="Test Recruiter", $organization=null)
246
    {
247
        $repo = $this->getUserRepository();
248
        if (!is_object($user=$repo->findByEmail($email))) {
249
            $user = $this->createUser($email, $password, $role, $fullname, $organization);
250
        }
251
        
252
        if (!is_null($organization)) {
253
            $this->iHaveMainOrganization($user, $organization);
254
        }
255
        $this->addCreatedUser($user);
256
        $repo->getDocumentManager()->refresh($user);
257
        return $user;
258
    }
259
    
260
    /**
261
     * @param $email
262
     * @param $password
263
     * @param $username
264
     * @param string $fullname
265
     * @param string $role
266
     *
267
     * @return \Auth\Entity\UserInterface
268
     */
269
    public function createUser($email, $password, $role=User::ROLE_RECRUITER, $fullname="Test Recruiter")
270
    {
271
        /* @var Register $service */
272
        /* @var User $user */
273
        $repo = $this->getUserRepository();
274
        $user = $repo->create([]);
275
        $user->setLogin($email);
276
        $user->setPassword($password);
277
        $user->setRole($role);
278
        $settings = $user->getSettings('Applications');
279
        
280
        $expFullName = explode(' ', $fullname);
281
        $info = $user->getInfo();
282
        $info->setFirstName(array_shift($expFullName));
283
        $info->setLastName(count($expFullName)>0 ? implode(' ', $expFullName):'');
284
        $info->setEmail($email);
285
        $info->setEmailVerified(true);
286
        $repo->store($user);
287
        $repo->getDocumentManager()->refresh($user);
288
        
289
        $eventArgs = new LifecycleEventArgs($user, $repo->getDocumentManager());
290
        $repo->getDocumentManager()->getEventManager()->dispatchEvent(
291
            Events::postLoad,
292
            $eventArgs
293
        );
294
        /* @var \Core\EventManager\EventManager $events */
295
        /* @var \Auth\Listener\Events\AuthEvent $event */
296
        //@TODO: [Behat] event not working in travis
297
        //$events = $this->coreContext->getEventManager();
298
        //$event  = $events->getEvent(AuthEvent::EVENT_USER_REGISTERED, $this);
299
        //$event->setUser($user);
300
        //$events->triggerEvent($event);
301
        return $user;
302
    }
303
    
304
    /**
305
     * @When I have :organization as my main organization
306
     * @param $orgName
307
     */
308
    public function iHaveMainOrganization(UserInterface $user, $orgName)
309
    {
310
        /* @var $repoOrganization OrganizationRepository */
311
        $repoOrganization = $this->coreContext->getRepositories()->get('Organizations/Organization');
312
        $result = $repoOrganization->findByName($orgName);
313
        $organization = count($result) > 0 ? $result[0]:null;
314
        if (!$organization instanceof Organization) {
315
            $organization = new Organization();
316
            $organizationName = new OrganizationName($orgName);
317
            $organization->setOrganizationName($organizationName);
318
        }
319
        $organization->setProfileSetting(Organization::PROFILE_ALWAYS_ENABLE);
320
        $permissions = $organization->getPermissions();
321
        $permissions->grant($user, Permissions::PERMISSION_ALL);
322
323
        $organization->setUser($user);
324
        $repoOrganization->store($organization);
325
        $repoOrganization->getDocumentManager()->refresh($organization);
326
327
        $this->mainOrganization = $organization;
328
    }
329
330
    /**
331
     * @return Organization
332
     */
333
    public function getMainOrganization()
334
    {
335
        return $this->mainOrganization;
336
    }
337
338
    /**
339
     * @When I want to log in
340
     */
341
    public function iWantToLogIn()
342
    {
343
        $session = $this->minkContext->getSession();
344
        $url = $this->buildUrl('lang/auth');
345
        $session->visit($url);
346
    }
347
    
348
    /**
349
     * @When I specify the username as :username
350
     */
351
    public function iSpecifyTheUsernameAs($username)
352
    {
353
        $this->minkContext->fillField('Login name', $username);
354
    }
355
    
356
    /**
357
     * @When I specify the password as :password
358
     */
359
    public function iSpecifyThePasswordAs($password)
360
    {
361
        $this->minkContext->fillField('Password', $password);
362
    }
363
    
364
    /**
365
     * @Given I am logged in as :username identified by :password
366
     */
367
    public function iAmLoggedInAsIdentifiedBy($username, $password)
368
    {
369
        $repo = $this->getUserRepository();
370
        $user = $repo->findByLogin($username);
371
        
372
        if (!$user instanceof User) {
373
            throw new \Exception(sprintf('There is no user with this login: "%s"', $username));
374
        }
375
        $this->iWantToLogIn();
376
        $this->iSpecifyTheUsernameAs($username);
377
        $this->iSpecifyThePasswordAs($password);
378
        $this->iLogIn();
379
        $this->currentUser = $user;
380
    }
381
    
382
    /**
383
     * @When I log in
384
     */
385
    public function iLogIn()
386
    {
387
        $this->minkContext->pressButton('login');
388
    }
389
    
390
    /**
391
     * @When I press logout link
392
     */
393
    public function iPressLogoutLink()
394
    {
395
        $url = $this->buildUrl('auth-logout');
396
        $this->visit($url);
397
    }
398
    
399
    /**
400
     * @Given I log in with username :username and password :password
401
     */
402
    public function iLogInWith($username, $password)
403
    {
404
        $repo = $this->getUserRepository();
405
        $user = $repo->findByLogin($username);
406
        $this->iWantToLogIn();
407
        $this->iSpecifyTheUsernameAs($username);
408
        $this->iSpecifyThePasswordAs($password);
409
        $this->iLogIn();
410
        $this->loggedInUser = $user;
411
    }
412
    
413
    /**
414
     * @When I go to profile page
415
     */
416
    public function iGoToProfilePage()
417
    {
418
        $url = $this->buildUrl('lang/my');
419
        $this->visit($url);
420
    }
421
    
422
    /**
423
     * @Given there is a user with the following:
424
     */
425
    public function thereIsAUserWithTheFollowing(TableNode $table)
426
    {
427
        $repo = $this->getUserRepository();
428
        $data = $table->getRowsHash();
429
        $email = isset($data['email']) ? $data['email']:'[email protected]';
430
        $password = isset($data['password']) ? $data['password']:'test';
431
        $fullname = isset($data['fullname']) ? $data['fullname']:'Test User';
432
        $role = isset($data['role']) ? $data['role']:User::ROLE_RECRUITER;
433
        
434
        if (!is_object($user=$repo->findByLogin($email))) {
435
            $user = $this->createUser($email, $password, $role, $fullname);
436
        }
437
        $this->currentUser = $user;
438
        $this->addCreatedUser($user);
439
    }
440
    
441
    private function addCreatedUser(UserInterface $user)
442
    {
443
        if (!in_array($user, static::$users)) {
444
            static::$users[] = $user;
445
        }
446
    }
447
    
448
    /**
449
     * @When I want to change my password
450
     */
451
    public function iWantToChangeMyPassword()
452
    {
453
        $url = $this->buildUrl('lang/my-password');
454
        $this->visit($url);
455
    }
456
457
    /**
458
     * @return User
459
     * @throws FailedExpectationException
460
     */
461
    public function getCurrentUser()
462
    {
463
        if (!$this->currentUser instanceof User) {
464
            throw new FailedExpectationException('Need to login first before use this step');
465
        }
466
        return $this->currentUser;
467
    }
468
}
469