Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
101 / 101
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\Domain\UserContext;
13use AppDemo\User\Domain\UserGroup;
14use Phexium\Domain\Id\IdInterface;
15use Tests\AppDemo\Fake\Application\Service\RbacPermissionService as FakeRbacPermissionService;
16use Tests\AppDemo\Fixture\UserMother;
17
18beforeEach(function (): void {
19    $this->rbacService = new FakeRbacPermissionService();
20});
21
22describe('User identity', function (): void {
23    it('returns user when authenticated', function (): void {
24        $user = UserMother::admin();
25        $userContext = new UserContext($user, $this->rbacService);
26
27        expect($userContext->getUser())->toBe($user);
28    });
29
30    it('returns null when user is not authenticated', function (): void {
31        $userContext = new UserContext(null, $this->rbacService);
32
33        expect($userContext->getUser())->toBeNull();
34    });
35
36    it('returns user ID when authenticated', function (): void {
37        $user = UserMother::admin(123);
38        $userContext = new UserContext($user, $this->rbacService);
39
40        $userId = $userContext->getUserId();
41        expect($userId)->toBeInstanceOf(IdInterface::class)
42            ->and($userId->getValue())->toBe(123)
43        ;
44    });
45
46    it('returns null user ID when user is not authenticated', function (): void {
47        $userContext = new UserContext(null, $this->rbacService);
48
49        expect($userContext->getUserId())->toBeNull();
50    });
51
52    it('returns true when user is authenticated', function (): void {
53        $user = UserMother::user();
54        $userContext = new UserContext($user, $this->rbacService);
55
56        expect($userContext->isAuthenticated())->toBeTrue();
57    });
58
59    it('returns false when user is not authenticated', function (): void {
60        $userContext = new UserContext(null, $this->rbacService);
61
62        expect($userContext->isAuthenticated())->toBeFalse();
63    });
64});
65
66describe('Single permission', function (): void {
67    it('returns true when authenticated user has the requested permission', function (): void {
68        $user = UserMother::admin();
69
70        $this->rbacService->addPermission(UserGroup::Admin, 'book.create');
71
72        $userContext = new UserContext($user, $this->rbacService);
73
74        expect($userContext->can('book.create'))->toBeTrue();
75    });
76
77    it('returns false when authenticated user does not have the requested permission', function (): void {
78        $user = UserMother::user();
79
80        $userContext = new UserContext($user, $this->rbacService);
81
82        expect($userContext->can('book.delete'))->toBeFalse();
83    });
84
85    it('returns false when user is not authenticated', function (): void {
86        $userContext = new UserContext(null, $this->rbacService);
87
88        expect($userContext->can('book.create'))->toBeFalse();
89    });
90
91    it('returns all permissions when user is authenticated', function (): void {
92        $user = UserMother::admin();
93        $expectedPermissions = ['book.create', 'book.update', 'book.delete'];
94
95        $this->rbacService->setPermissions(UserGroup::Admin, $expectedPermissions);
96
97        $userContext = new UserContext($user, $this->rbacService);
98
99        expect($userContext->getPermissions())->toBe($expectedPermissions);
100    });
101
102    it('returns empty array when user is not authenticated', function (): void {
103        $userContext = new UserContext(null, $this->rbacService);
104
105        expect($userContext->getPermissions())->toBe([]);
106    });
107});
108
109describe('Multiple permissions', function (): void {
110    it('returns true when authenticated user has at least one of the requested permissions', function (): void {
111        $user = UserMother::admin();
112        $permissions = ['book.create', 'book.update', 'book.delete'];
113
114        $this->rbacService->addPermission(UserGroup::Admin, 'book.create');
115
116        $userContext = new UserContext($user, $this->rbacService);
117
118        expect($userContext->canAny($permissions))->toBeTrue();
119    });
120
121    it('returns false when authenticated user has none of the requested permissions', function (): void {
122        $user = UserMother::user();
123        $permissions = ['book.delete', 'user.delete'];
124
125        $userContext = new UserContext($user, $this->rbacService);
126
127        expect($userContext->canAny($permissions))->toBeFalse();
128    });
129
130    it('returns false when checking any permissions and user is not authenticated', function (): void {
131        $userContext = new UserContext(null, $this->rbacService);
132
133        expect($userContext->canAny(['book.create', 'book.update']))->toBeFalse();
134    });
135
136    it('returns true when authenticated user has all requested permissions', function (): void {
137        $user = UserMother::admin();
138        $permissions = ['book.create', 'book.update'];
139
140        $this->rbacService->setPermissions(UserGroup::Admin, $permissions);
141
142        $userContext = new UserContext($user, $this->rbacService);
143
144        expect($userContext->canAll($permissions))->toBeTrue();
145    });
146
147    it('returns false when authenticated user is missing at least one permission', function (): void {
148        $user = UserMother::user();
149        $permissions = ['book.create', 'book.delete'];
150
151        $this->rbacService->addPermission(UserGroup::User, 'book.create');
152
153        $userContext = new UserContext($user, $this->rbacService);
154
155        expect($userContext->canAll($permissions))->toBeFalse();
156    });
157
158    it('returns false when checking all permissions and user is not authenticated', function (): void {
159        $userContext = new UserContext(null, $this->rbacService);
160
161        expect($userContext->canAll(['book.create', 'book.update']))->toBeFalse();
162    });
163});