toBeInstanceOf(\App\Framework\QrCode\ValueObjects\QrCodeMatrix::class) ->and($matrix->getSize())->toBeGreaterThan(0) ->and($matrix->getVersion()->getVersionNumber())->toBe(1); }); test('can generate QR code with auto-size config', function () { $shortData = 'Test'; $longData = str_repeat('A', 30); $matrix1 = QrCodeGenerator::generate($shortData); $matrix2 = QrCodeGenerator::generate($longData); expect($matrix1->getVersion()->getVersionNumber())->toBe(1) ->and($matrix2->getVersion()->getVersionNumber())->toBeGreaterThanOrEqual(2); }); test('can generate QR code with explicit version', function () { $data = 'Test'; $config = QrCodeConfig::withVersion(2); $matrix = QrCodeGenerator::generate($data, $config); expect($matrix->getVersion()->getVersionNumber())->toBe(2) ->and($matrix->getSize())->toBe(25); // Version 2 = 25x25 }); test('generates proper matrix size for different versions', function () { $data = 'Test'; $matrix1 = QrCodeGenerator::generate($data, QrCodeConfig::withVersion(1)); $matrix2 = QrCodeGenerator::generate($data, QrCodeConfig::withVersion(2)); $matrix3 = QrCodeGenerator::generate($data, QrCodeConfig::withVersion(3)); expect($matrix1->getSize())->toBe(21) // Version 1: 21x21 ->and($matrix2->getSize())->toBe(25) // Version 2: 25x25 ->and($matrix3->getSize())->toBe(29); // Version 3: 29x29 }); test('matrix contains finder patterns', function () { $data = 'Test'; $matrix = QrCodeGenerator::generate($data); // Check top-left finder pattern (corner module should be dark) expect($matrix->getModuleAt(0, 0)->isDark())->toBeTrue() ->and($matrix->getModuleAt(6, 6)->isDark())->toBeTrue(); }); test('matrix contains timing patterns', function () { $data = 'Test'; $matrix = QrCodeGenerator::generate($data); // Row 6 should have alternating modules (timing pattern) expect($matrix->getModuleAt(6, 8)->isDark())->toBeTrue() ->and($matrix->getModuleAt(6, 9)->isLight())->toBeTrue() ->and($matrix->getModuleAt(6, 10)->isDark())->toBeTrue(); }); test('throws exception when data too long for version', function () { $data = str_repeat('A', 100); // Too long for version 1-3 QrCodeGenerator::generate($data); })->throws(\App\Framework\Exception\FrameworkException::class); test('matrix has correct dark module count', function () { $data = 'Test'; $matrix = QrCodeGenerator::generate($data); $darkCount = $matrix->countDarkModules(); // Matrix should have some dark modules (at least finder patterns) expect($darkCount)->toBeGreaterThan(50) // Finder patterns alone = ~63 modules ->and($darkCount)->toBeLessThan($matrix->getSize() * $matrix->getSize()); }); test('can generate ASCII representation', function () { $data = 'A'; $matrix = QrCodeGenerator::generate($data); $ascii = $matrix->toAsciiArt(); expect($ascii)->toBeString() ->and($ascii)->toContain('█') // Should contain dark modules ->and($ascii)->toContain('░'); // Should contain light modules }); test('can generate binary representation', function () { $data = 'A'; $matrix = QrCodeGenerator::generate($data); $binary = $matrix->toBinaryString(); expect($binary)->toBeString() ->and($binary)->toContain('1') // Should contain 1s (dark) ->and($binary)->toContain('0'); // Should contain 0s (light) }); test('generates deterministic output for same input', function () { $data = 'Test123'; $matrix1 = QrCodeGenerator::generate($data); $matrix2 = QrCodeGenerator::generate($data); expect($matrix1->toBinaryString())->toBe($matrix2->toBinaryString()); }); test('supports different data types', function () { // Numeric-like data (but still byte mode in Phase 1) $numeric = '1234567890'; $matrix1 = QrCodeGenerator::generate($numeric); // Alphanumeric-like data $alphanumeric = 'HELLO WORLD 123'; $matrix2 = QrCodeGenerator::generate($alphanumeric); // Special characters $special = 'test@example.com'; $matrix3 = QrCodeGenerator::generate($special); // UTF-8 $utf8 = 'Hëllö Wörld'; $matrix4 = QrCodeGenerator::generate($utf8); expect($matrix1)->toBeInstanceOf(\App\Framework\QrCode\ValueObjects\QrCodeMatrix::class) ->and($matrix2)->toBeInstanceOf(\App\Framework\QrCode\ValueObjects\QrCodeMatrix::class) ->and($matrix3)->toBeInstanceOf(\App\Framework\QrCode\ValueObjects\QrCodeMatrix::class) ->and($matrix4)->toBeInstanceOf(\App\Framework\QrCode\ValueObjects\QrCodeMatrix::class); });