Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
50 / 50
n/a
0 / 0
CRAP
n/a
0 / 0
1<?php
2
3// ╔════════════════════════════════════════════════════════════╗
4// ║ MIT Licence (#Expat) - https://opensource.org/licenses/MIT ║
5// ║ Copyright 2026 Frederic Poeydomenge <dyno@phexium.com>     ║
6// ╚════════════════════════════════════════════════════════════╝
7
8declare(strict_types=1);
9
10pest()->group('unit');
11
12use AppDemo\Shared\Application\Middleware\RbacPermissionMiddleware;
13use AppDemo\Shared\Domain\UserContext;
14use AppDemo\User\Domain\UserGroup;
15use Nyholm\Psr7\Factory\Psr17Factory;
16use Nyholm\Psr7\Response;
17use Nyholm\Psr7\ServerRequest;
18use Tests\AppDemo\Fake\Application\Service\RbacPermissionService as FakeRbacPermissionService;
19use Tests\AppDemo\Fixture\UserMother;
20use Tests\Phexium\Fake\Plugin\Http\RequestHandler as FakeRequestHandler;
21
22const REQUIRED_PERMISSION = 'some-permission';
23
24beforeEach(function (): void {
25    $this->rbacPermissionService = new FakeRbacPermissionService();
26    $this->responseFactory = new Psr17Factory();
27
28    $this->middleware = new RbacPermissionMiddleware(
29        $this->rbacPermissionService,
30        $this->responseFactory,
31        REQUIRED_PERMISSION
32    );
33});
34
35describe('Authorized access', function (): void {
36    it('proceeds to next handler when user has permission', function (): void {
37        $user = UserMother::user();
38        $userContext = new UserContext($user, $this->rbacPermissionService);
39        $expectedResponse = new Response(200);
40
41        $this->rbacPermissionService->addPermission(UserGroup::User, REQUIRED_PERMISSION);
42
43        $request = new ServerRequest('GET', '/');
44        $request = $request->withAttribute('user_context', $userContext);
45        $handler = new FakeRequestHandler($expectedResponse);
46
47        $response = $this->middleware->process($request, $handler);
48
49        expect($response)->toBe($expectedResponse)
50            ->and($handler->getHandleCallCount())->toBe(1)
51        ;
52    });
53});
54
55describe('Unauthorized access', function (): void {
56    it('returns 403 when user does not have permission', function (): void {
57        $user = UserMother::user();
58        $userContext = new UserContext($user, $this->rbacPermissionService);
59
60        $request = new ServerRequest('GET', '/');
61        $request = $request->withAttribute('user_context', $userContext);
62        $handler = new FakeRequestHandler(new Response(200));
63
64        $response = $this->middleware->process($request, $handler);
65
66        expect($response->getStatusCode())->toBe(RbacPermissionMiddleware::STATUS_FORBIDDEN)
67            ->and((string) $response->getBody())->toBe('Permission denied.')
68            ->and($handler->getHandleCallCount())->toBe(0)
69        ;
70    });
71
72    it('returns 403 when user is not authenticated', function (): void {
73        $userContext = new UserContext(null, $this->rbacPermissionService);
74
75        $request = new ServerRequest('GET', '/');
76        $request = $request->withAttribute('user_context', $userContext);
77        $handler = new FakeRequestHandler(new Response(200));
78
79        $response = $this->middleware->process($request, $handler);
80
81        expect($response->getStatusCode())->toBe(RbacPermissionMiddleware::STATUS_FORBIDDEN)
82            ->and((string) $response->getBody())->toBe('Authentication required.')
83            ->and($handler->getHandleCallCount())->toBe(0)
84        ;
85    });
86});