connection = $this->createMock(Connection::class); $this->repository = new AuditLogRepository($this->connection); } public function testFindByUserReturnsAuditLogEntries(): void { $userId = Uuid::uuid4(); $tenantId = TenantId::generate(); $rows = [ $this->createRowData(), $this->createRowData(), ]; $queryBuilder = $this->createQueryBuilderMock($rows); $this->connection->method('createQueryBuilder')->willReturn($queryBuilder); $result = $this->repository->findByUser($userId, $tenantId); $this->assertCount(2, $result); $this->assertContainsOnlyInstancesOf(AuditLogEntry::class, $result); } public function testFindByUserAppliesFilters(): void { $userId = Uuid::uuid4(); $tenantId = TenantId::generate(); $from = new DateTimeImmutable('2026-01-01'); $to = new DateTimeImmutable('2026-02-01'); $queryBuilder = $this->createMock(QueryBuilder::class); $queryBuilder->method('select')->willReturnSelf(); $queryBuilder->method('from')->willReturnSelf(); $queryBuilder->method('where')->willReturnSelf(); $queryBuilder->method('orderBy')->willReturnSelf(); // Verify andWhere is called for each filter $queryBuilder->expects($this->atLeast(4)) ->method('andWhere') ->willReturnSelf(); // Verify setParameter is called with expected parameters $capturedParams = []; $queryBuilder->method('setParameter') ->willReturnCallback(static function (string $key, mixed $value) use ($queryBuilder, &$capturedParams) { $capturedParams[$key] = $value; return $queryBuilder; }); // Verify pagination $queryBuilder->expects($this->once()) ->method('setMaxResults') ->with(50) ->willReturnSelf(); $queryBuilder->expects($this->once()) ->method('setFirstResult') ->with(10) ->willReturnSelf(); $result = $this->createMock(Result::class); $result->method('fetchAllAssociative')->willReturn([]); $queryBuilder->method('executeQuery')->willReturn($result); $this->connection->method('createQueryBuilder')->willReturn($queryBuilder); $this->repository->findByUser( $userId, $tenantId, $from, $to, 'ConnexionReussie', 50, 10, ); // Verify the parameters were captured $this->assertArrayHasKey('user_id', $capturedParams); $this->assertArrayHasKey('tenant_id', $capturedParams); $this->assertArrayHasKey('from', $capturedParams); $this->assertArrayHasKey('to', $capturedParams); $this->assertArrayHasKey('event_type', $capturedParams); $this->assertSame('ConnexionReussie', $capturedParams['event_type']); } public function testFindByResourceReturnsResults(): void { $aggregateId = Uuid::uuid4(); $tenantId = TenantId::generate(); $rows = [$this->createRowData()]; $queryBuilder = $this->createQueryBuilderMock($rows); $this->connection->method('createQueryBuilder')->willReturn($queryBuilder); $result = $this->repository->findByResource('Note', $aggregateId, $tenantId); $this->assertCount(1, $result); } public function testFindByCorrelationIdReturnsResults(): void { $correlationId = Uuid::uuid4()->toString(); $tenantId = TenantId::generate(); $rows = [$this->createRowData()]; $queryBuilder = $this->createQueryBuilderMock($rows); $this->connection->method('createQueryBuilder')->willReturn($queryBuilder); $result = $this->repository->findByCorrelationId($correlationId, $tenantId); $this->assertCount(1, $result); } public function testSearchWithAllFilters(): void { $tenantId = TenantId::generate(); $from = new DateTimeImmutable('2026-01-01'); $to = new DateTimeImmutable('2026-02-01'); $rows = [$this->createRowData()]; $queryBuilder = $this->createQueryBuilderMock($rows); $this->connection->method('createQueryBuilder')->willReturn($queryBuilder); $result = $this->repository->search( $tenantId, $from, $to, 'ConnexionReussie', 'User', 100, 0, ); $this->assertCount(1, $result); } public function testEmptyResultReturnsEmptyArray(): void { $userId = Uuid::uuid4(); $tenantId = TenantId::generate(); $queryBuilder = $this->createQueryBuilderMock([]); $this->connection->method('createQueryBuilder')->willReturn($queryBuilder); $result = $this->repository->findByUser($userId, $tenantId); $this->assertSame([], $result); } /** * @return array */ private function createRowData(): array { return [ 'id' => Uuid::uuid4()->toString(), 'aggregate_type' => 'User', 'aggregate_id' => Uuid::uuid4()->toString(), 'event_type' => 'ConnexionReussie', 'payload' => '{"email_hash":"abc123"}', 'metadata' => '{"tenant_id":"tenant-1","user_id":"user-1"}', 'occurred_at' => '2026-02-03T10:30:00+00:00', 'sequence_number' => '1', ]; } /** * @param list> $rows */ private function createQueryBuilderMock(array $rows): QueryBuilder&MockObject { $queryBuilder = $this->createMock(QueryBuilder::class); $queryBuilder->method('select')->willReturnSelf(); $queryBuilder->method('from')->willReturnSelf(); $queryBuilder->method('where')->willReturnSelf(); $queryBuilder->method('andWhere')->willReturnSelf(); $queryBuilder->method('setParameter')->willReturnSelf(); $queryBuilder->method('orderBy')->willReturnSelf(); $queryBuilder->method('setMaxResults')->willReturnSelf(); $queryBuilder->method('setFirstResult')->willReturnSelf(); $result = $this->createMock(Result::class); $result->method('fetchAllAssociative')->willReturn($rows); $queryBuilder->method('executeQuery')->willReturn($result); return $queryBuilder; } }