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