testPersistNewAccessTokenWithScopes()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 61
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 45
c 1
b 0
f 0
dl 0
loc 61
rs 9.2
cc 1
nc 1
nop 0

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 AbterPhp\Admin\Oauth2\Repository;
6
7
use AbterPhp\Admin\Exception\Database;
8
use AbterPhp\Admin\Oauth2\Entity\AccessToken as Entity;
9
use AbterPhp\Framework\TestCase\Database\QueryTestCase;
10
use AbterPhp\Framework\TestDouble\Database\MockStatementFactory;
11
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
12
use League\OAuth2\Server\Entities\ClientEntityInterface;
13
use League\OAuth2\Server\Entities\ScopeEntityInterface;
14
use Opulence\Orm\Ids\Generators\UuidV4Generator;
15
use PHPUnit\Framework\MockObject\MockObject;
16
17
class AccessTokenTest extends QueryTestCase
18
{
19
    /** @var AccessToken - System Under Test */
20
    protected $sut;
21
22
    /** @var UuidV4Generator|MockObject */
23
    protected $uuidGeneratorMock;
24
25
    public function setUp(): void
26
    {
27
        parent::setUp();
28
29
        $this->uuidGeneratorMock = $this->createMock(UuidV4Generator::class);
30
31
        $this->sut = new AccessToken($this->uuidGeneratorMock, $this->connectionPoolMock);
32
    }
33
34
    public function testGetNewToken()
35
    {
36
        /** @var ClientEntityInterface|MockObject $clientEntityStub */
37
        $clientEntityStub = $this->createMock(ClientEntityInterface::class);
38
39
        $scopes         = [];
40
        $userIdentifier = null;
41
42
        $actualResult = $this->sut->getNewToken($clientEntityStub, $scopes, $userIdentifier);
43
44
        $this->assertInstanceOf(Entity::class, $actualResult);
45
    }
46
47
    public function testPersistNewAccessToken()
48
    {
49
        $tokenId    = 'foo';
50
        $clientName = 'bar';
51
        $expiresAt  = new \DateTime();
52
53
        $accessTokenEntityMock = $this->createAccessTokenStub($tokenId, $clientName, $expiresAt, []);
54
55
        $sql0          = 'INSERT INTO tokens (id, api_client_id, expires_at) VALUES (?, ?, ?)'; // phpcs:ignore
56
        $valuesToBind0 = [
57
            [$tokenId, \PDO::PARAM_STR],
58
            [$clientName, \PDO::PARAM_STR],
59
            [$expiresAt->format('Y-m-d H:i:s'), \PDO::PARAM_STR],
60
        ];
61
        $statement0    = MockStatementFactory::createWriteStatement($this, $valuesToBind0);
62
63
        $this->writeConnectionMock
64
            ->expects($this->exactly(1))
65
            ->method('prepare')
66
            ->withConsecutive([$sql0])
67
            ->willReturnOnConsecutiveCalls($statement0);
68
69
        $this->sut->persistNewAccessToken($accessTokenEntityMock);
70
    }
71
72
    public function testPersistNewAccessTokenDbFailureThrowsException()
73
    {
74
        $expectedCode    = 17;
75
        $expectedMessage = 'Foo is great before: FROM api_clients AS ac';
76
77
        $this->expectException(Database::class);
78
        $this->expectExceptionCode($expectedCode);
79
        $this->expectExceptionMessage($expectedMessage);
80
81
        $tokenId    = 'foo';
82
        $clientName = 'bar';
83
        $expiresAt  = new \DateTime();
84
85
        $accessTokenEntityMock = $this->createAccessTokenStub($tokenId, $clientName, $expiresAt, []);
86
87
        $sql0          = 'INSERT INTO tokens (id, api_client_id, expires_at) VALUES (?, ?, ?)'; // phpcs:ignore
88
        $valuesToBind0 = [
89
            [$tokenId, \PDO::PARAM_STR],
90
            [$clientName, \PDO::PARAM_STR],
91
            [$expiresAt->format('Y-m-d H:i:s'), \PDO::PARAM_STR],
92
        ];
93
        $errorInfo0    = ['FOO', $expectedCode, $expectedMessage];
94
        $statement0    = MockStatementFactory::createErrorStatement($this, $valuesToBind0, $errorInfo0);
95
96
        $this->writeConnectionMock
97
            ->expects($this->exactly(1))
98
            ->method('prepare')
99
            ->withConsecutive([$sql0])
100
            ->willReturnOnConsecutiveCalls($statement0);
101
102
        $this->sut->persistNewAccessToken($accessTokenEntityMock);
103
    }
104
105
    public function testPersistNewAccessTokenWithScopes()
106
    {
107
        $tokenId    = 'foo';
108
        $clientName = 'bar';
109
        $expiresAt  = new \DateTime();
110
111
        $scopeId0 = '0c4554ca-c379-46ab-9389-bfc84790bb46';
112
        $scopeId1 = 'aa7076d8-02c1-4d79-becc-e754450a392f';
113
114
        $scopeIdentifier0 = 'scope-0';
115
        $scopeIdentifier1 = 'scope-1';
116
117
        $this->uuidGeneratorMock
118
            ->expects($this->exactly(2))
119
            ->method('generate')
120
            ->willReturnOnConsecutiveCalls($scopeId0, $scopeId1);
121
122
        $scope = $this->createMock(ScopeEntityInterface::class);
123
        $scope
124
            ->expects($this->any())
125
            ->method('getIdentifier')
126
            ->willReturn($scopeIdentifier0, $scopeIdentifier1);
127
128
        $accessTokenEntityMock = $this->createAccessTokenStub(
129
            $tokenId,
130
            $clientName,
131
            $expiresAt,
132
            [$scope, $scope]
133
        );
134
135
        $sql0          = 'INSERT INTO tokens (id, api_client_id, expires_at) VALUES (?, ?, ?)'; // phpcs:ignore
136
        $valuesToBind0 = [
137
            [$tokenId, \PDO::PARAM_STR],
138
            [$clientName, \PDO::PARAM_STR],
139
            [$expiresAt->format('Y-m-d H:i:s'), \PDO::PARAM_STR],
140
        ];
141
        $statement0    = MockStatementFactory::createWriteStatement($this, $valuesToBind0);
142
143
        $sql1          = 'INSERT INTO tokens_admin_resources (id, token_id, admin_resource_id) VALUES (?, ?, ?)'; // phpcs:ignore
144
        $valuesToBind1 = [
145
            [$scopeId0, \PDO::PARAM_STR],
146
            [$tokenId, \PDO::PARAM_STR],
147
            [$scopeIdentifier0, \PDO::PARAM_STR],
148
        ];
149
        $statement1    = MockStatementFactory::createWriteStatement($this, $valuesToBind1);
150
151
        $sql2          = 'INSERT INTO tokens_admin_resources (id, token_id, admin_resource_id) VALUES (?, ?, ?)'; // phpcs:ignore
152
        $valuesToBind2 = [
153
            [$scopeId1, \PDO::PARAM_STR],
154
            [$tokenId, \PDO::PARAM_STR],
155
            [$scopeIdentifier1, \PDO::PARAM_STR],
156
        ];
157
        $statement2    = MockStatementFactory::createWriteStatement($this, $valuesToBind2);
158
159
        $this->writeConnectionMock
160
            ->expects($this->exactly(3))
161
            ->method('prepare')
162
            ->withConsecutive([$sql0], [$sql1], [$sql2])
163
            ->willReturnOnConsecutiveCalls($statement0, $statement1, $statement2);
164
165
        $this->sut->persistNewAccessToken($accessTokenEntityMock);
166
    }
167
168
    public function testPersistNewAccessTokenWithScopesDbFailureThrowsException()
169
    {
170
        $expectedCode    = 17;
171
        $expectedMessage = 'Foo is great before: FROM api_clients AS ac';
172
173
        $this->expectException(Database::class);
174
        $this->expectExceptionCode($expectedCode);
175
        $this->expectExceptionMessage($expectedMessage);
176
177
        $tokenId    = 'foo';
178
        $clientName = 'bar';
179
        $expiresAt  = new \DateTime();
180
181
        $scopeId0 = '0c4554ca-c379-46ab-9389-bfc84790bb46';
182
183
        $scopeIdentifier0 = 'scope-0';
184
185
        $this->uuidGeneratorMock
186
            ->expects($this->exactly(1))
187
            ->method('generate')
188
            ->willReturnOnConsecutiveCalls($scopeId0);
189
190
        $scope = $this->createMock(ScopeEntityInterface::class);
191
        $scope
192
            ->expects($this->any())
193
            ->method('getIdentifier')
194
            ->willReturn($scopeIdentifier0);
195
196
        $accessTokenEntityMock = $this->createAccessTokenStub(
197
            $tokenId,
198
            $clientName,
199
            $expiresAt,
200
            [$scope]
201
        );
202
203
        $sql0          = 'INSERT INTO tokens (id, api_client_id, expires_at) VALUES (?, ?, ?)'; // phpcs:ignore
204
        $valuesToBind0 = [
205
            [$tokenId, \PDO::PARAM_STR],
206
            [$clientName, \PDO::PARAM_STR],
207
            [$expiresAt->format('Y-m-d H:i:s'), \PDO::PARAM_STR],
208
        ];
209
        $statement0    = MockStatementFactory::createWriteStatement($this, $valuesToBind0);
210
211
        $sql1          = 'INSERT INTO tokens_admin_resources (id, token_id, admin_resource_id) VALUES (?, ?, ?)'; // phpcs:ignore
212
        $valuesToBind1 = [
213
            [$scopeId0, \PDO::PARAM_STR],
214
            [$tokenId, \PDO::PARAM_STR],
215
            [$scopeIdentifier0, \PDO::PARAM_STR],
216
        ];
217
        $errorInfo1    = ['FOO', $expectedCode, $expectedMessage];
218
        $statement1    = MockStatementFactory::createErrorStatement($this, $valuesToBind1, $errorInfo1);
219
220
        $this->writeConnectionMock
221
            ->expects($this->exactly(2))
222
            ->method('prepare')
223
            ->withConsecutive([$sql0], [$sql1])
224
            ->willReturnOnConsecutiveCalls($statement0, $statement1);
225
226
        $this->sut->persistNewAccessToken($accessTokenEntityMock);
227
    }
228
229
    /**
230
     * @param string $scopeId
231
     * @param string $identifier
232
     * @param int    $at
233
     *
234
     * @return ScopeEntityInterface
235
     */
236
    protected function createScopeStub(string $scopeId, string $identifier, int $at): ScopeEntityInterface
237
    {
238
        $this->uuidGeneratorMock->expects($this->at($at))->method('generate')->willReturn($scopeId);
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\TestCase::at() has been deprecated: https://github.com/sebastianbergmann/phpunit/issues/4297 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

238
        $this->uuidGeneratorMock->expects(/** @scrutinizer ignore-deprecated */ $this->at($at))->method('generate')->willReturn($scopeId);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
239
240
        $scope = $this->createMock(ScopeEntityInterface::class);
241
        $scope->expects($this->any())->method('getIdentifier')->willReturn($identifier);
242
243
        return $scope;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $scope returns the type PHPUnit\Framework\MockObject\MockObject which is incompatible with the type-hinted return League\OAuth2\Server\Entities\ScopeEntityInterface.
Loading history...
244
    }
245
246
    /**
247
     * @param string                 $tokenId
248
     * @param string                 $clientName
249
     * @param \DateTime              $expiresAt
250
     * @param ScopeEntityInterface[] $scopes
251
     *
252
     * @return AccessTokenEntityInterface|MockObject
253
     */
254
    protected function createAccessTokenStub(
255
        string $tokenId,
256
        string $clientName,
257
        \DateTime $expiresAt,
258
        array $scopes
259
    ): AccessTokenEntityInterface {
260
        $clientStub = $this->createMock(ClientEntityInterface::class);
261
        $clientStub->expects($this->any())->method('getName')->willReturn($clientName);
262
263
        /** @var AccessTokenEntityInterface|MockObject $accessTokenEntityMock */
264
        $accessTokenEntityMock = $this->createMock(AccessTokenEntityInterface::class);
265
266
        $accessTokenEntityMock->expects($this->any())->method('getIdentifier')->willReturn($tokenId);
267
        $accessTokenEntityMock->expects($this->any())->method('getClient')->willReturn($clientStub);
268
        $accessTokenEntityMock->expects($this->any())->method('getExpiryDateTime')->willReturn($expiresAt);
269
        $accessTokenEntityMock->expects($this->any())->method('getScopes')->willReturn($scopes);
270
271
        return $accessTokenEntityMock;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $accessTokenEntityMock returns the type PHPUnit\Framework\MockObject\MockObject which is incompatible with the type-hinted return League\OAuth2\Server\Ent...essTokenEntityInterface.
Loading history...
272
    }
273
274
    public function testRevokeAccessToken()
275
    {
276
        $tokenId = 'foo';
277
278
        $this->sut->revokeAccessToken($tokenId);
279
280
        // This test is expected to break if there's anything happening in AccessToken::revokeAccessToken
281
        $this->assertTrue(true);
282
    }
283
284
    public function testIsAccessTokenRevoked()
285
    {
286
        $tokenId = 'foo';
287
288
        $actualResult = $this->sut->isAccessTokenRevoked($tokenId);
289
290
        $this->assertFalse($actualResult);
291
    }
292
}
293