Files
crm_ecosplay/tests/Service/AnalyticsCryptoServiceTest.php
Serreau Jovann b0731a430c refactor: fix SonarQube code smells and add AnalyticsCryptoService tests
Reduce cognitive complexity and fix code smells across multiple files:
- Extract helper methods in DocuSealService, ForgotPasswordController, WebhookDocuSealController
- Reduce MembresController.persistLocalUser from 8 to 3 parameters using typed array
- Replace chained if/returns with ROLE_ROUTES map in LoginSuccessHandler
- Add 100% test coverage for AnalyticsCryptoService (15 tests)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 19:14:51 +02:00

151 lines
4.8 KiB
PHP

<?php
namespace App\Tests\Service;
use App\Service\AnalyticsCryptoService;
use PHPUnit\Framework\TestCase;
class AnalyticsCryptoServiceTest extends TestCase
{
private AnalyticsCryptoService $service;
protected function setUp(): void
{
$this->service = new AnalyticsCryptoService('test-secret-key');
}
public function testEncryptReturnsBase64String(): void
{
$data = ['page' => '/home', 'visits' => 42];
$encrypted = $this->service->encrypt($data);
$this->assertNotEmpty($encrypted);
$this->assertNotFalse(base64_decode($encrypted, true));
}
public function testEncryptThenDecryptReturnsOriginalData(): void
{
$data = ['page' => '/stats', 'count' => 10, 'nested' => ['a' => 1]];
$encrypted = $this->service->encrypt($data);
$decrypted = $this->service->decrypt($encrypted);
$this->assertSame($data, $decrypted);
}
public function testDecryptInvalidBase64ReturnsNull(): void
{
$this->assertNull($this->service->decrypt('!!!not-base64!!!'));
}
public function testDecryptTooShortPayloadReturnsNull(): void
{
// Less than 28 bytes after decode
$this->assertNull($this->service->decrypt(base64_encode('short')));
}
public function testDecryptCorruptedPayloadReturnsNull(): void
{
$data = ['test' => true];
$encrypted = $this->service->encrypt($data);
// Corrupt the payload by flipping bytes
$raw = base64_decode($encrypted, true);
$corrupted = $raw;
$corrupted[20] = chr(ord($corrupted[20]) ^ 0xFF);
$corrupted[21] = chr(ord($corrupted[21]) ^ 0xFF);
$this->assertNull($this->service->decrypt(base64_encode($corrupted)));
}
public function testDecryptJsFormatWithShortCiphertextReturnsNull(): void
{
// 28 bytes of zeros — neither JS nor PHP format can decrypt
$raw = str_repeat("\x00", 28);
$this->assertNull($this->service->decrypt(base64_encode($raw)));
}
public function testTryDecryptJsFormatWithTooShortInput(): void
{
$method = new \ReflectionMethod(AnalyticsCryptoService::class, 'tryDecryptJsFormat');
$result = $method->invoke($this->service, str_repeat("\x00", 12), 'short');
$this->assertNull($result);
}
public function testDecryptPhpFormatFallback(): void
{
// Build a PHP-format payload: iv (12) + tag (16) + ciphertext
$data = ['fallback' => true];
$json = json_encode($data);
$key = substr(hash('sha256', 'test-secret-key', true), 0, 32);
$iv = random_bytes(12);
$encrypted = openssl_encrypt($json, 'aes-256-gcm', $key, \OPENSSL_RAW_DATA, $iv, $tag, '', 16);
// PHP format: iv + tag + ciphertext
$phpFormat = base64_encode($iv . $tag . $encrypted);
$this->assertSame($data, $this->service->decrypt($phpFormat));
}
public function testGenerateVisitorHashReturnsDeterministicHash(): void
{
$hash1 = $this->service->generateVisitorHash('user-123');
$hash2 = $this->service->generateVisitorHash('user-123');
$this->assertSame($hash1, $hash2);
$this->assertSame(64, \strlen($hash1)); // SHA-256 hex = 64 chars
}
public function testGenerateVisitorHashDiffersForDifferentUids(): void
{
$hash1 = $this->service->generateVisitorHash('user-123');
$hash2 = $this->service->generateVisitorHash('user-456');
$this->assertNotSame($hash1, $hash2);
}
public function testVerifyVisitorHashReturnsTrueForValidHash(): void
{
$uid = 'visitor-abc';
$hash = $this->service->generateVisitorHash($uid);
$this->assertTrue($this->service->verifyVisitorHash($uid, $hash));
}
public function testVerifyVisitorHashReturnsFalseForInvalidHash(): void
{
$this->assertFalse($this->service->verifyVisitorHash('visitor-abc', 'wrong-hash'));
}
public function testGetKeyForJsReturnsBase64EncodedKey(): void
{
$jsKey = $this->service->getKeyForJs();
$this->assertNotEmpty($jsKey);
$decoded = base64_decode($jsKey, true);
$this->assertNotFalse($decoded);
$this->assertSame(32, \strlen($decoded)); // AES-256 key = 32 bytes
}
public function testDifferentSecretsProduceDifferentKeys(): void
{
$service2 = new AnalyticsCryptoService('different-secret');
$this->assertNotSame($this->service->getKeyForJs(), $service2->getKeyForJs());
}
public function testEncryptedByOneServiceCannotBeDecryptedByAnother(): void
{
$service2 = new AnalyticsCryptoService('different-secret');
$data = ['secret' => 'data'];
$encrypted = $this->service->encrypt($data);
$this->assertNull($service2->decrypt($encrypted));
}
}