Test for Logger Service
This commit is contained in:
parent
70ef717506
commit
14366b5ed4
|
|
@ -0,0 +1,295 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Tests\Service;
|
||||||
|
|
||||||
|
use App\Service\LoggerService;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\RequestStack;
|
||||||
|
|
||||||
|
class LoggerServiceTest extends TestCase
|
||||||
|
{
|
||||||
|
private LoggerService $service;
|
||||||
|
|
||||||
|
// Mocks for all the channels
|
||||||
|
private MockObject|LoggerInterface $userManagementLogger;
|
||||||
|
private MockObject|LoggerInterface $organizationManagementLogger;
|
||||||
|
private MockObject|LoggerInterface $accessControlLogger;
|
||||||
|
private MockObject|LoggerInterface $emailNotificationLogger;
|
||||||
|
private MockObject|LoggerInterface $adminActionsLogger;
|
||||||
|
private MockObject|LoggerInterface $securityLogger;
|
||||||
|
private MockObject|LoggerInterface $errorLogger;
|
||||||
|
private MockObject|LoggerInterface $awsLogger;
|
||||||
|
private MockObject|RequestStack $requestStack;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
// Create mocks for all dependencies
|
||||||
|
$this->userManagementLogger = $this->createMock(LoggerInterface::class);
|
||||||
|
$this->organizationManagementLogger = $this->createMock(LoggerInterface::class);
|
||||||
|
$this->accessControlLogger = $this->createMock(LoggerInterface::class);
|
||||||
|
$this->emailNotificationLogger = $this->createMock(LoggerInterface::class);
|
||||||
|
$this->adminActionsLogger = $this->createMock(LoggerInterface::class);
|
||||||
|
$this->securityLogger = $this->createMock(LoggerInterface::class);
|
||||||
|
$this->errorLogger = $this->createMock(LoggerInterface::class);
|
||||||
|
$this->awsLogger = $this->createMock(LoggerInterface::class);
|
||||||
|
$this->requestStack = $this->createMock(RequestStack::class);
|
||||||
|
|
||||||
|
$this->service = new LoggerService(
|
||||||
|
$this->userManagementLogger,
|
||||||
|
$this->organizationManagementLogger,
|
||||||
|
$this->accessControlLogger,
|
||||||
|
$this->emailNotificationLogger,
|
||||||
|
$this->adminActionsLogger,
|
||||||
|
$this->securityLogger,
|
||||||
|
$this->errorLogger,
|
||||||
|
$this->awsLogger,
|
||||||
|
$this->requestStack
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to simulate a request with a specific IP.
|
||||||
|
*/
|
||||||
|
private function mockRequestIp(?string $ip): void
|
||||||
|
{
|
||||||
|
if ($ip === null) {
|
||||||
|
$this->requestStack->method('getCurrentRequest')->willReturn(null);
|
||||||
|
} else {
|
||||||
|
$request = $this->createMock(Request::class);
|
||||||
|
$request->method('getClientIp')->willReturn($ip);
|
||||||
|
$this->requestStack->method('getCurrentRequest')->willReturn($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper assertion to check context contains basic fields + specific data.
|
||||||
|
*/
|
||||||
|
private function assertContextContains(array $expectedSubset): \PHPUnit\Framework\Constraint\Callback
|
||||||
|
{
|
||||||
|
return $this->callback(function (array $context) use ($expectedSubset) {
|
||||||
|
// Check Timestamp exists (we can't check exact value easily)
|
||||||
|
if (!isset($context['timestamp'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check IP exists
|
||||||
|
if (!isset($context['ip'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check specific keys
|
||||||
|
foreach ($expectedSubset as $key => $value) {
|
||||||
|
if (!array_key_exists($key, $context) || $context[$key] !== $value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// TESTS FOR USER MANAGEMENT LOGS
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
public function testLogUserCreated(): void
|
||||||
|
{
|
||||||
|
$this->mockRequestIp('127.0.0.1');
|
||||||
|
|
||||||
|
$this->userManagementLogger->expects($this->once())
|
||||||
|
->method('notice')
|
||||||
|
->with(
|
||||||
|
"New user created: 10",
|
||||||
|
$this->assertContextContains([
|
||||||
|
'target_user_id' => 10,
|
||||||
|
'acting_user_id' => 99,
|
||||||
|
'ip' => '127.0.0.1'
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->service->logUserCreated(10, 99);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLogCGUAcceptanceLogsToTwoChannels(): void
|
||||||
|
{
|
||||||
|
$this->mockRequestIp('192.168.1.1');
|
||||||
|
$userId = 55;
|
||||||
|
|
||||||
|
// Expect call on User Logger
|
||||||
|
$this->userManagementLogger->expects($this->once())
|
||||||
|
->method('info')
|
||||||
|
->with("User accepted CGU", $this->assertContextContains(['user_id' => $userId]));
|
||||||
|
|
||||||
|
// Expect call on Security Logger
|
||||||
|
$this->securityLogger->expects($this->once())
|
||||||
|
->method('info')
|
||||||
|
->with("User accepted CGU", $this->assertContextContains(['user_id' => $userId]));
|
||||||
|
|
||||||
|
$this->service->logCGUAcceptance($userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// TESTS FOR ORGANIZATION LOGS
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
public function testLogUserOrganizationLinkCreated(): void
|
||||||
|
{
|
||||||
|
$this->mockRequestIp('10.0.0.1');
|
||||||
|
|
||||||
|
$this->organizationManagementLogger->expects($this->once())
|
||||||
|
->method('notice')
|
||||||
|
->with(
|
||||||
|
'User-Organization link created',
|
||||||
|
$this->assertContextContains([
|
||||||
|
'target_user_id' => 1,
|
||||||
|
'organization_id' => 2,
|
||||||
|
'acting_user_id' => 3,
|
||||||
|
'uo_id' => 4
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->service->logUserOrganizationLinkCreated(1, 2, 3, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// TESTS FOR ERROR LOGS
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
public function testLogError(): void
|
||||||
|
{
|
||||||
|
$this->mockRequestIp('127.0.0.1');
|
||||||
|
|
||||||
|
$this->errorLogger->expects($this->once())
|
||||||
|
->method('error')
|
||||||
|
->with(
|
||||||
|
'Something failed',
|
||||||
|
$this->assertContextContains(['details' => 'foo'])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->service->logError('Something failed', ['details' => 'foo']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLogEntityNotFoundHandlesGlobals(): void
|
||||||
|
{
|
||||||
|
$this->mockRequestIp('127.0.0.1');
|
||||||
|
|
||||||
|
// Simulate global server variable for REQUEST_URI
|
||||||
|
$_SERVER['REQUEST_URI'] = '/some/path';
|
||||||
|
|
||||||
|
$this->errorLogger->expects($this->once())
|
||||||
|
->method('error')
|
||||||
|
->with(
|
||||||
|
'Entity not found',
|
||||||
|
$this->assertContextContains([
|
||||||
|
'entity_type' => 'User',
|
||||||
|
'id' => 123,
|
||||||
|
'page_accessed' => '/some/path'
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->service->logEntityNotFound('User', ['id' => 123], 1);
|
||||||
|
|
||||||
|
// Cleanup global
|
||||||
|
unset($_SERVER['REQUEST_URI']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// TESTS FOR SECURITY LOGS
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
public function testLogAccessDenied(): void
|
||||||
|
{
|
||||||
|
$this->mockRequestIp('10.10.10.10');
|
||||||
|
|
||||||
|
$this->securityLogger->expects($this->once())
|
||||||
|
->method('warning')
|
||||||
|
->with(
|
||||||
|
'Access denied',
|
||||||
|
$this->assertContextContains(['acting_user_id' => 5])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->service->logAccessDenied(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLogTokenRevocation(): void
|
||||||
|
{
|
||||||
|
$this->mockRequestIp(null); // Test with NO REQUEST (e.g. CLI)
|
||||||
|
|
||||||
|
$this->securityLogger->expects($this->once())
|
||||||
|
->method('warning')
|
||||||
|
->with(
|
||||||
|
'Token revoked',
|
||||||
|
$this->callback(function($context) {
|
||||||
|
return $context['ip'] === 'unknown' && $context['reason'] === 'expired';
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->service->logTokenRevocation('Token revoked', ['reason' => 'expired']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// TESTS FOR ADMIN ACTIONS
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
public function testLogSuperAdmin(): void
|
||||||
|
{
|
||||||
|
$this->mockRequestIp('1.2.3.4');
|
||||||
|
|
||||||
|
$this->adminActionsLogger->expects($this->once())
|
||||||
|
->method('notice')
|
||||||
|
->with(
|
||||||
|
'Global reset',
|
||||||
|
$this->assertContextContains([
|
||||||
|
'target_user_id' => 10,
|
||||||
|
'acting_user_id' => 1,
|
||||||
|
'organization_id' => null
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->service->logSuperAdmin(10, 1, 'Global reset');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// TESTS FOR AWS LOGS
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
public function testLogAWSAction(): void
|
||||||
|
{
|
||||||
|
$this->mockRequestIp('8.8.8.8');
|
||||||
|
|
||||||
|
$this->awsLogger->expects($this->once())
|
||||||
|
->method('info')
|
||||||
|
->with(
|
||||||
|
'AWS action performed: Upload',
|
||||||
|
$this->assertContextContains(['bucket' => 'my-bucket'])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->service->logAWSAction('Upload', ['bucket' => 'my-bucket']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// TESTS FOR ACCESS CONTROL
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
public function testLogRoleEntityAssignment(): void
|
||||||
|
{
|
||||||
|
$this->mockRequestIp('127.0.0.1');
|
||||||
|
|
||||||
|
$this->accessControlLogger->expects($this->once())
|
||||||
|
->method('info')
|
||||||
|
->with(
|
||||||
|
'Role Assigned',
|
||||||
|
$this->assertContextContains([
|
||||||
|
'target_user_id' => 2,
|
||||||
|
'organization_id' => 3,
|
||||||
|
'role_id' => 4,
|
||||||
|
'acting_user_id' => 1
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->service->logRoleEntityAssignment(2, 3, 4, 1, 'Role Assigned');
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue