Completed
Pull Request — release-v2.1 (#15)
by Quentin
08:46 queued 01:14
created

ServerTest   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 261
Duplicated Lines 27.59 %

Coupling/Cohesion

Components 1
Dependencies 14
Metric Value
wmc 8
lcom 1
cbo 14
dl 72
loc 261
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
B grantSuccessCaseProvider() 31 31 1
B testSuccessGrant() 0 45 1
B refreshTokenCreationCaseProvider() 41 41 1
B testRefreshTokenOnGrant() 0 39 1
B errorCaseProvider() 0 43 1
B testGrantErrors() 0 30 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace Majora\Component\OAuth\Tests\Server;
4
5
use Majora\Component\OAuth\Entity\AccessToken;
6
use Majora\Component\OAuth\Entity\Account;
7
use Majora\Component\OAuth\Entity\Application;
8
use Majora\Component\OAuth\Entity\LoginAttempt;
9
use Majora\Component\OAuth\Entity\RefreshToken;
10
use Majora\Component\OAuth\Event\AccessTokenEvent;
11
use Majora\Component\OAuth\Event\AccessTokenEvents;
12
use Majora\Component\OAuth\Exception\InvalidGrantException;
13
use Majora\Component\OAuth\Generator\RandomTokenGenerator;
14
use Majora\Component\OAuth\GrantType\GrantExtensionInterface;
15
use Majora\Component\OAuth\Loader\ApplicationLoaderInterface;
16
use Majora\Component\OAuth\Model\AccessTokenInterface;
17
use Majora\Component\OAuth\Model\RefreshTokenInterface;
18
use Majora\Component\OAuth\Server\Server;
19
use Prophecy\Argument;
20
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
21
use Symfony\Component\OptionsResolver\OptionsResolver;
22
23
/**
24
 * Unit tests class for Majora\Component\OAuth\Server\Server.
25
 *
26
 * @see Majora\Component\OAuth\Server\Server
27
 */
28
class ServerTest extends \PHPUnit_Framework_TestCase
29
{
30
    /**
31
     * Success grant case provider.
32
     */
33 View Code Duplication
    public function grantSuccessCaseProvider()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
34
    {
35
        return array(
36
            'default_settings' => $defaultCase = array(
37
                array(),
38
                AccessToken::class,
39
                array(
40
                    array(
41
                        'grant_type' => 'mocked_grant_type',
42
                        'client_api_key' => 'mocked_key',
43
                        'client_secret' => 'mocked_secret',
44
                    ),
45
                    array(),
46
                    array(),
47
                ),
48
                new AccessToken(new Application(), new Account(), AccessTokenInterface::DEFAULT_TTL, 'mocked_hash'),
49
            ),
50
            'ttl_settings' => array_replace_recursive($defaultCase, array(
51
                array('access_token_ttl' => 123456),
52
                AccessToken::class,
53
                array(),
54
                new AccessToken(new Application(), new Account(), 123456, 'mocked_hash'),
55
            )),
56
            'class_settings' => array_replace_recursive($defaultCase, array(
57
                array('access_token_class' => MockedAccessToken::class),
58
                MockedAccessToken::class,
59
                array(),
60
                new MockedAccessToken(new Application(), new Account(), AccessTokenInterface::DEFAULT_TTL, 'mocked_hash'),
61
            )),
62
        );
63
    }
64
65
    /**
66
     * Test grant success cases.
67
     *
68
     * @dataProvider grantSuccessCaseProvider
69
     */
70
    public function testSuccessGrant(
71
        $tokenOptions,
72
        $expectedTokensClass,
73
        array $grantArgs,
74
        AccessTokenInterface $expectedAccessToken
75
    ) {
76
        $eventDispatcher = $this->prophesize(EventDispatcherInterface::class);
77
        $eventDispatcher
78
            ->dispatch(AccessTokenEvents::MAJORA_ACCESS_TOKEN_CREATED, Argument::type(AccessTokenEvent::class))
79
            ->shouldBeCalled()
80
        ;
81
        $applicationLoader = $this->prophesize(ApplicationLoaderInterface::class);
82
        $applicationLoader
83
            ->retrieveByApiKeyAndSecret('mocked_key', 'mocked_secret')
84
            ->willReturn(new Application())
85
            ->shouldBeCalled()
86
        ;
87
        $randomTokenGenerator = $this->prophesize(RandomTokenGenerator::class);
88
        $randomTokenGenerator->generate('access_token')->willReturn('mocked_hash')->shouldBeCalled();
89
        $randomTokenGenerator->generate('refresh_token')->shouldNotBeCalled();
90
91
        $extension = $this->prophesize(GrantExtensionInterface::class);
92
        $extension
93
            ->configureRequestParameters(Argument::type(OptionsResolver::class))
94
            ->shouldBeCalled()
95
        ;
96
        $extension
97
            ->grant(Argument::type(Application::class), Argument::type(LoginAttempt::class))
98
            ->shouldBeCalled()
99
        ;
100
101
        $server = new Server(
102
            $eventDispatcher->reveal(),
103
            $applicationLoader->reveal(),
104
            $randomTokenGenerator->reveal(),
105
            $tokenOptions,
106
            array('mocked_grant_type' => $extension->reveal())
107
        );
108
109
        $accessToken = $server->grant(...$grantArgs);
110
111
        $this->assertInstanceOf($expectedTokensClass, $accessToken);
112
        $this->assertEquals($expectedAccessToken->getExpireIn(), $accessToken->getExpireIn());
113
        $this->assertNull($accessToken->getRefreshToken());
114
    }
115
116
    /**
117
     * Refresh token creation cases providers.
118
     */
119 View Code Duplication
    public function refreshTokenCreationCaseProvider()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
120
    {
121
        return array(
122
            'default_settings' => $defaultCase = array(
123
                array(),
124
                RefreshToken::class,
125
                array(
126
                    array(
127
                        'grant_type' => 'mocked_grant_type',
128
                        'client_api_key' => 'mocked_key',
129
                        'client_secret' => 'mocked_secret',
130
                    ),
131
                    array(),
132
                    array(),
133
                ),
134
                new RefreshToken(
135
                    new Application(),
136
                    new Account(),
137
                    RefreshTokenInterface::DEFAULT_TTL,
138
                    'mocked_refresh_token_hash'
139
                ),
140
            ),
141
            'ttl_settings' => array_replace_recursive($defaultCase, array(
142
                array('refresh_token_ttl' => 654321),
143
                RefreshToken::class,
144
                array(),
145
                new RefreshToken(new Application(), new Account(), 654321, 'mocked_refresh_token_hash'),
146
            )),
147
            'class_settings' => array_replace_recursive($defaultCase, array(
148
                array('refresh_token_class' => MockedRefreshToken::class),
149
                MockedRefreshToken::class,
150
                array(),
151
                new MockedRefreshToken(
152
                    new Application(),
153
                    new Account(),
154
                    RefreshTokenInterface::DEFAULT_TTL,
155
                    'mocked_refresh_token_hash'
156
                ),
157
            )),
158
        );
159
    }
160
161
    /**
162
     * Tests refresh token creation on access token granting.
163
     *
164
     * @dataProvider refreshTokenCreationCaseProvider
165
     */
166
    public function testRefreshTokenOnGrant(
167
        $tokenOptions,
168
        $expectedTokensClass,
169
        array $grantArgs,
170
        RefreshTokenInterface $expectedRefreshToken
171
    ) {
172
        $applicationLoader = $this->prophesize(ApplicationLoaderInterface::class);
173
        $applicationLoader
174
            ->retrieveByApiKeyAndSecret('mocked_key', 'mocked_secret')
175
            ->willReturn((new Application())->setAllowedGrantTypes(array('refresh_token')))
176
            ->shouldBeCalled()
177
        ;
178
        $randomTokenGenerator = $this->prophesize(RandomTokenGenerator::class);
179
        $randomTokenGenerator->generate('access_token')
180
            ->willReturn('mocked_access_token_hash')
181
            ->shouldBeCalled()
182
        ;
183
        $randomTokenGenerator
184
            ->generate('refresh_token')
185
            ->willReturn('mocked_refresh_token_hash')
186
            ->shouldBeCalled()
187
        ;
188
189
        $server = new Server(
190
            $this->prophesize(EventDispatcherInterface::class)->reveal(),
191
            $applicationLoader->reveal(),
192
            $randomTokenGenerator->reveal(),
193
            $tokenOptions,
194
            array(
195
                'refresh_token' => $this->prophesize(GrantExtensionInterface::class)->reveal(),
196
                'mocked_grant_type' => $this->prophesize(GrantExtensionInterface::class)->reveal(),
197
            )
198
        );
199
200
        $accessToken = $server->grant(...$grantArgs);
201
202
        $this->assertInstanceOf($expectedTokensClass, $refreshToken = $accessToken->getRefreshToken());
203
        $this->assertEquals($expectedRefreshToken->getExpireIn(), $refreshToken->getExpireIn());
204
    }
205
206
    /**
207
     * Provider for error cases.
208
     */
209
    public function errorCaseProvider()
210
    {
211
        return array(
212
            'any_grant_type' => array(
213
                array(
214
                    array(
215
                        'client_api_key' => 'mocked_key',
216
                        'client_secret' => 'mocked_secret',
217
                    ),
218
                    array(),
219
                    array(),
220
                ),
221
                new \InvalidArgumentException('Any grant_type given.'),
222
            ),
223
            'bad_grant_type' => array(
224
                array(
225
                    array(
226
                        'grant_type' => 'bad_grant_type',
227
                        'client_api_key' => 'mocked_key',
228
                        'client_secret' => 'mocked_secret',
229
                    ),
230
                    array(),
231
                    array(),
232
                ),
233
                new \InvalidArgumentException('Given grant_type is invalid.'),
234
            ),
235
            'any_application' => array(
236
                array(
237
                    array(
238
                        'grant_type' => 'mocked_grant_type',
239
                        'client_api_key' => 'bad_api_key',
240
                        'client_secret' => 'bad_secret',
241
                    ),
242
                    array(),
243
                    array(),
244
                ),
245
                new InvalidGrantException(
246
                    new LoginAttempt(array(), array(), array()),
247
                    'Any application found for given api_key / secret.'
248
                ),
249
            ),
250
        );
251
    }
252
253
    /**
254
     * Tests grant() method error cases.
255
     *
256
     * @dataProvider errorCaseProvider
257
     */
258
    public function testGrantErrors(array $grantArgs, \Exception $expectedException)
259
    {
260
        $applicationLoader = $this->prophesize(ApplicationLoaderInterface::class);
261
        $applicationLoader
262
            ->retrieveByApiKeyAndSecret(Argument::type('string'), Argument::type('string'))
263
            ->will(function ($args) {
264
                return $args[0] == 'bad_api_key' && $args[1] == 'bad_secret' ?
265
                    null :
266
                    new Application()
267
                ;
268
            })
269
        ;
270
        $randomTokenGenerator = $this->prophesize(RandomTokenGenerator::class);
271
        $randomTokenGenerator->generate('access_token')
272
            ->willReturn('mocked_access_token_hash')
273
        ;
274
275
        $server = new Server(
276
            $this->prophesize(EventDispatcherInterface::class)->reveal(),
277
            $applicationLoader->reveal(),
278
            $randomTokenGenerator->reveal(),
279
            array(),
280
            array('mocked_grant_type' => $this->prophesize(GrantExtensionInterface::class)->reveal())
281
        );
282
283
        $this->expectException(get_class($expectedException));
284
        $this->expectExceptionMessage($expectedException->getMessage());
285
286
        $server->grant(...$grantArgs);
287
    }
288
}
289
290
class MockedAccessToken extends AccessToken
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
291
{
292
}
293
class MockedRefreshToken extends RefreshToken
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
294
{
295
}
296