Passed
Push — master ( 95d3b3...37ba81 )
by Adrien
07:02
created

UserTest::testGetGlobalPermissions()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 106
Code Lines 68

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 68
nc 1
nop 0
dl 0
loc 106
rs 8.6981
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A UserTest::providerSetOwner() 0 19 1
A UserTest::testSetRole() 0 16 3
A UserTest::providerSetRole() 0 11 1
A UserTest::testSetPassword() 0 18 1
A UserTest::testSetOwner() 0 16 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace ApplicationTest\Model;
6
7
use Application\Model\Booking;
8
use Application\Model\User;
9
use Cake\Chronos\Chronos;
10
use PHPUnit\Framework\TestCase;
11
12
class UserTest extends TestCase
13
{
14
    public function tearDown(): void
15
    {
16
        User::setCurrent(null);
17
    }
18
19
    /**
20
     * @dataProvider providerSetRole
21
     *
22
     * @param string $currentRole
23
     * @param string $oldRole
24
     * @param string $newRole
25
     * @param null|string $exception
26
     */
27
    public function testSetRole(string $currentRole, string $oldRole, string $newRole, ?string $exception): void
28
    {
29
        User::setCurrent(null);
30
        if ($currentRole !== User::ROLE_ANONYMOUS) {
31
            $currentUser = new User($currentRole);
32
            User::setCurrent($currentUser);
33
        }
34
35
        $user2 = new User($oldRole);
36
37
        if ($exception) {
38
            $this->expectExceptionMessage($exception);
39
        }
40
41
        $user2->setRole($newRole);
42
        self::assertSame($newRole, $user2->getRole());
43
    }
44
45
    public function providerSetRole(): array
46
    {
47
        return [
48
            [User::ROLE_ANONYMOUS, User::ROLE_ADMINISTRATOR, User::ROLE_MEMBER, 'anonymous is not allowed to change role from administrator to member'],
49
            [User::ROLE_ANONYMOUS, User::ROLE_MEMBER, User::ROLE_ADMINISTRATOR, 'anonymous is not allowed to change role from member to administrator'],
50
51
            [User::ROLE_MEMBER, User::ROLE_MEMBER, User::ROLE_MEMBER, null],
52
            [User::ROLE_MEMBER, User::ROLE_MEMBER, User::ROLE_ADMINISTRATOR, 'member is not allowed to change role from member to administrator'],
53
54
            [User::ROLE_ADMINISTRATOR, User::ROLE_MEMBER, User::ROLE_ADMINISTRATOR, null],
55
            [User::ROLE_ADMINISTRATOR, User::ROLE_ADMINISTRATOR, User::ROLE_MEMBER, null],
56
        ];
57
    }
58
59
    public function testSetPassword(): void
60
    {
61
        $user = new User();
62
        self::assertSame('', $user->getPassword(), 'should have no password at first');
63
64
        $user->setPassword('12345');
65
        $actual1 = $user->getPassword();
66
        self::assertNotSame('', $actual1, 'should be able to change password ');
67
        self::assertTrue(password_verify('12345', $actual1), 'password must have been hashed');
68
69
        $user->setPassword('');
70
        $actual2 = $user->getPassword();
71
        self::assertSame($actual1, $actual2, 'should ignore empty password');
72
73
        $user->setPassword('money');
74
        $actual3 = $user->getPassword();
75
        self::assertNotSame($actual1, $actual3, 'should be able to change to something else');
76
        self::assertTrue(password_verify('money', $actual3), 'password must have been hashed again');
77
    }
78
79
    /**
80
     * @dataProvider providerSetOwner
81
     */
82
    public function testSetOwner(?User $currentUser, ?User $originalOwner, ?User $newOwner, ?string $exception = null): void
83
    {
84
        User::setCurrent($currentUser);
85
86
        $subject = new Booking();
87
        self::assertNull($subject->getOwner());
88
89
        $subject->setOwner($originalOwner);
90
        self::assertSame($originalOwner, $subject->getOwner());
91
92
        if ($exception) {
93
            $this->expectExceptionMessage($exception);
94
        }
95
96
        $subject->setOwner($newOwner);
97
        self::assertSame($newOwner, $subject->getOwner());
98
    }
99
100
    public function providerSetOwner(): array
101
    {
102
        $u1 = new User();
103
        $u1->setLogin('u1');
104
        $u2 = new User();
105
        $u2->setLogin('u2');
106
        $u3 = new User();
107
        $u3->setLogin('u3');
108
        $admin = new User(User::ROLE_ADMINISTRATOR);
109
        $admin->setLogin('admin');
110
111
        return [
112
            'can change nothing' => [null, null, null],
113
            'can set owner for first time' => [null, null, $u3],
114
            'can set owner for first time to myself' => [$u1, null, $u1],
115
            'can set owner for first time even if it is not myself' => [$u1, null, $u3],
116
            'can donate my stuff' => [$u1, $u1, $u3],
117
            'cannot donate stuff that are not mine' => [$u1, $u2, $u3, 'u1 is not allowed to change owner to u3 because it belongs to u2'],
118
            'admin cannot donate stuff that are not mine' => [$admin, $u2, $u3],
119
        ];
120
    }
121
122
    public function testIndividualCannotOwnUsers(): void
123
    {
124
        $u1 = new User();
125
        $u2 = new User();
126
        $u3 = new User();
127
128
        $u1->setOwner($u1);
129
        $u2->setOwner($u1);
130
131
        $this->expectExceptionMessage('This user cannot be owned by a user who is himself owned by somebody else');
132
        $u3->setOwner($u2);
133
    }
134
135
    public function testIndividualCannotOwnUsers2(): void
136
    {
137
        $u1 = new User();
138
        $u2 = new User();
139
        $u3 = new User();
140
141
        $u1->setOwner($u1);
142
        $u3->setOwner($u2);
143
144
        $this->expectExceptionMessage('This user owns other users, so he cannot himself be owned by somebody else');
145
        $u2->setOwner($u1);
146
    }
147
148
    public function testSetStatus(): void
149
    {
150
        $u1 = new User();
151
        $u2 = new User();
152
153
        // Initial status
154
        self::assertSame(User::STATUS_NEW, $u1->getStatus());
155
        self::assertSame(User::STATUS_NEW, $u2->getStatus());
156
157
        $u1->setOwner($u1);
158
        $u2->setOwner($u1);
159
        $u1->setStatus(User::STATUS_INACTIVE);
160
161
        // Status is propagated to existing users
162
        self::assertSame(User::STATUS_INACTIVE, $u1->getStatus());
163
        self::assertSame(User::STATUS_INACTIVE, $u2->getStatus());
164
165
        $u1->setStatus(user::STATUS_ACTIVE);
166
        self::assertSame(User::STATUS_ACTIVE, $u1->getStatus());
167
        self::assertSame(User::STATUS_ACTIVE, $u2->getStatus());
168
169
        // Status is propagated on new users too
170
        $u3 = new User();
171
        self::assertSame(User::STATUS_NEW, $u3->getStatus());
172
        $u3->setOwner($u1);
173
        self::assertSame(User::STATUS_ACTIVE, $u3->getStatus());
174
    }
175
176
    public function testToken(): void
177
    {
178
        $user = new User();
179
        self::assertFalse($user->isTokenValid(), 'new user should not be valid');
180
181
        $token1 = $user->createToken();
182
        self::assertEquals(32, mb_strlen($token1), 'must be exactly the length of DB field');
183
        self::assertTrue($user->isTokenValid(), 'brand new token is valid');
184
185
        $token2 = $user->createToken();
186
        self::assertEquals(32, mb_strlen($token2), 'must be exactly the length of DB field');
187
        self::assertTrue($user->isTokenValid(), 'second created token is valid');
188
189
        $user->setLastLogin(new Chronos());
190
        self::assertFalse($user->isTokenValid(), 'once user is logged in token is invalid');
191
192
        $token3 = $user->createToken();
193
        self::assertEquals(32, mb_strlen($token3), 'must be exactly the length of DB field');
194
        self::assertTrue($user->isTokenValid(), 'third created token is valid');
195
196
        $user->setStatus(User::STATUS_ACTIVE);
197
        self::assertFalse($user->isTokenValid(), 'once user is activated token is invalid');
198
199
        $token4 = $user->createToken();
200
        self::assertEquals(32, mb_strlen($token4), 'must be exactly the length of DB field');
201
        self::assertTrue($user->isTokenValid(), 'third created token is valid');
202
203
        $user->setPassword('money');
204
        self::assertFalse($user->isTokenValid(), 'after password change token is invalid');
205
206
        Chronos::setTestNow((new Chronos())->subDay(1));
207
        $token5 = $user->createToken();
208
        Chronos::setTestNow(null);
209
        self::assertEquals(32, mb_strlen($token5), 'must be exactly the length of DB field');
210
        self::assertFalse($user->isTokenValid(), 'too old token is invalid');
211
212
        $allTokens = [
213
            $token1,
214
            $token2,
215
            $token3,
216
            $token4,
217
            $token5,
218
        ];
219
220
        self::assertCount(5, array_unique($allTokens), 'all tokens must be unique');
221
    }
222
}
223