Passed
Pull Request — master (#71)
by Matthieu
05:19
created

testMiddlewareWithoutUserId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 17
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 27
rs 9.7
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AtlassianConnectBundle\Tests\Service;
6
7
use AtlassianConnectBundle\Entity\TenantInterface;
8
use AtlassianConnectBundle\Service\GuzzleJWTMiddleware;
9
use Firebase\JWT\JWT;
10
use GuzzleHttp\Client;
11
use GuzzleHttp\ClientInterface;
12
use GuzzleHttp\Handler\MockHandler;
13
use GuzzleHttp\HandlerStack;
14
use GuzzleHttp\Psr7\Response;
15
use GuzzleHttp\Psr7\Uri;
16
use PHPUnit\Framework\TestCase;
17
use Psr\Http\Message\RequestInterface;
18
19
/**
20
 * @covers \AtlassianConnectBundle\Service\GuzzleJWTMiddleware
21
 * @covers \AtlassianConnectBundle\Service\JWTGenerator
22
 * @covers \AtlassianConnectBundle\Service\QSHGenerator
23
 */
24
final class GuzzleJWTMiddlewareTest extends TestCase
25
{
26
    public function testMiddlewareWithoutUserId(): void
27
    {
28
        $middleware = GuzzleJWTMiddleware::middleware($this->createMock(ClientInterface::class));
29
30
        $request = $this->createMock(RequestInterface::class);
31
32
        $request
33
            ->method('getUri')
34
            ->willReturn(new Uri('https://atlassian.io/api/test'));
35
36
        $request->method('getMethod')
37
            ->willReturn('GET');
38
39
        $request->expects($this->once())
40
            ->method('withHeader')
41
            ->with('Authorization', $this->callback(function (string $jwt): bool {
42
                $this->assertSame('JWT', explode(' ', $jwt)[0]);
43
                $jwt = JWT::decode(explode(' ', $jwt)[1], 'shared-secret', ['HS256']);
44
                $this->assertSame('addon-key', $jwt->iss);
45
46
                return true;
47
            }))
48
            ->willReturn($request);
49
50
        $invokable = $middleware(function (RequestInterface $request, array $options) { });
51
52
        $invokable($request, ['tenant' => $this->getTenant(), 'user_id' => null]);
53
    }
54
55
    public function testUserTokenMiddleware(): void
56
    {
57
        $mock = new MockHandler([
58
            new Response(200, [], json_encode(['access_token' => 'token'])),
59
        ]);
60
        $client = new Client(['handler' => HandlerStack::create($mock)]);
61
62
        $middleware = GuzzleJWTMiddleware::middleware($client);
63
64
        $request = $this->createMock(RequestInterface::class);
65
66
        $request
67
            ->method('getUri')
68
            ->willReturn(new Uri('https://atlassian.io/api/test'));
69
70
        $request->method('getMethod')
71
            ->willReturn('GET');
72
73
        $request->expects($this->exactly(2))
74
            ->method('withHeader')
75
            ->withConsecutive(['Accept', 'application/json'], ['Authorization', 'Bearer token'])
76
            ->willReturn($request);
77
78
        $invokable = $middleware(function (RequestInterface $request, array $options) { });
79
80
        $invokable($request, ['tenant' => $this->getTenant(), 'user_id' => 'abc']);
81
    }
82
83
    public function testTenantDoesNotExist(): void
84
    {
85
        $this->expectException(\RuntimeException::class);
86
        $this->expectExceptionMessage('Tenant not provided!');
87
88
        $middleware = GuzzleJWTMiddleware::middleware($this->createMock(ClientInterface::class));
89
        $invokable = $middleware(function (RequestInterface $request, array $options) { });
90
91
        $invokable($this->createMock(RequestInterface::class), []);
92
    }
93
94
    public function testUserProvidedButNotAnOauthApp(): void
95
    {
96
        $this->expectException(\RuntimeException::class);
97
        $this->expectExceptionMessage('Tenant is not set up as oath application. Install the app with "ACT_AS_USER" scope.');
98
99
        $middleware = GuzzleJWTMiddleware::middleware($this->createMock(ClientInterface::class));
100
        $invokable = $middleware(function (RequestInterface $request, array $options) { });
101
102
        $tenant = $this->createMock(TenantInterface::class);
103
        $tenant->method('getOauthClientId')->willReturn(null);
104
105
        $invokable($this->createMock(RequestInterface::class), ['tenant' => $tenant, 'user_id' => 'abc']);
106
    }
107
108
    private function getTenant(): TenantInterface
109
    {
110
        $tenant = $this->createMock(TenantInterface::class);
111
        $tenant->method('getBaseUrl')
112
            ->willReturn('https://app.atlassian.com');
113
114
        $tenant->method('getAddonKey')
115
            ->willReturn('addon-key');
116
117
        $tenant
118
            ->method('getSharedSecret')
119
            ->willReturn('shared-secret');
120
121
        $tenant
122
            ->method('getOauthClientId')
123
            ->willReturn('oath');
124
125
        return $tenant;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $tenant returns the type PHPUnit\Framework\MockObject\MockObject which is incompatible with the type-hinted return AtlassianConnectBundle\Entity\TenantInterface.
Loading history...
126
    }
127
}
128