renderSvg($matrix); expect($svg)->toBeString() ->and($svg)->toContain('and($svg)->toContain('and($svg)->toContain(''); }); test('can render QR code to inline SVG', function () { $data = 'Test'; $matrix = QrCodeGenerator::generate($data); $renderer = new QrCodeRenderer(); $svg = $renderer->renderInlineSvg($matrix); expect($svg)->toBeString() ->and($svg)->not->toContain('and($svg)->toContain('and($svg)->toContain(''); }); test('renders with default style', function () { $data = 'Test'; $matrix = QrCodeGenerator::generate($data); $renderer = new QrCodeRenderer(); $svg = $renderer->renderSvg($matrix); // Should contain rectangles for modules expect($svg)->toContain('and($svg)->toContain('width=') ->and($svg)->toContain('height='); }); test('renders with custom style', function () { $data = 'Test'; $matrix = QrCodeGenerator::generate($data); $renderer = new QrCodeRenderer(); $style = QrCodeStyle::withColors( SvgColor::fromHex('#0000ff'), // Blue dark modules SvgColor::fromHex('#ffff00') // Yellow light modules ); $svg = $renderer->renderCustom($matrix, $style); expect($svg)->toBeString() ->and($svg)->toContain('renderSvg($matrix, $style); // Compact style has smaller modules (5px) expect($svg)->toContain('and($svg)->toContain('width='); }); test('renders with large style', function () { $data = 'Test'; $matrix = QrCodeGenerator::generate($data); $renderer = new QrCodeRenderer(); $style = QrCodeStyle::large(); $svg = $renderer->renderSvg($matrix, $style); // Large style has bigger modules (20px) expect($svg)->toContain('and($svg)->toContain('width='); }); test('renders with inverted style', function () { $data = 'Test'; $matrix = QrCodeGenerator::generate($data); $renderer = new QrCodeRenderer(); $style = QrCodeStyle::inverted(); $svg = $renderer->renderSvg($matrix, $style); // Should render (white modules on black background) expect($svg)->toContain('toDataUrl($matrix); expect($dataUrl)->toBeString() ->and($dataUrl)->toStartWith('data:image/svg+xml;base64,') ->and(strlen($dataUrl))->toBeGreaterThan(100); }); test('data URL contains valid base64', function () { $data = 'Test'; $matrix = QrCodeGenerator::generate($data); $renderer = new QrCodeRenderer(); $dataUrl = $renderer->toDataUrl($matrix); $base64 = substr($dataUrl, strlen('data:image/svg+xml;base64,')); $decoded = base64_decode($base64, true); expect($decoded)->not->toBeFalse() ->and($decoded)->toContain('renderSvg($matrix); expect($svg)->toContain('QR Code') ->and($svg)->toContain('QR Code Version'); }); test('renders different sizes correctly', function () { $data = 'Test'; $matrix1 = QrCodeGenerator::generate($data, \App\Framework\QrCode\ValueObjects\QrCodeConfig::withVersion(1)); $matrix2 = QrCodeGenerator::generate($data, \App\Framework\QrCode\ValueObjects\QrCodeConfig::withVersion(2)); $renderer = new QrCodeRenderer(); $style = QrCodeStyle::default(); $svg1 = $renderer->renderSvg($matrix1, $style); $svg2 = $renderer->renderSvg($matrix2, $style); // Larger version should have larger SVG expect(strlen($svg2))->toBeGreaterThan(strlen($svg1)); }); test('can render to file', function () { $data = 'Test'; $matrix = QrCodeGenerator::generate($data); $renderer = new QrCodeRenderer(); $filepath = __DIR__ . '/../../../../tests/tmp/test-qrcode.svg'; // Ensure directory exists if (!is_dir(dirname($filepath))) { mkdir(dirname($filepath), 0777, true); } $renderer->renderToFile($matrix, $filepath); expect(file_exists($filepath))->toBeTrue() ->and(filesize($filepath))->toBeGreaterThan(0); // Cleanup if (file_exists($filepath)) { unlink($filepath); } }); test('rendered SVG has correct viewBox', function () { $data = 'Test'; $matrix = QrCodeGenerator::generate($data); $renderer = new QrCodeRenderer(); $svg = $renderer->renderSvg($matrix); // Should contain viewBox attribute expect($svg)->toContain('viewBox='); }); test('renders consistent output for same input', function () { $data = 'Test123'; $matrix = QrCodeGenerator::generate($data); $renderer = new QrCodeRenderer(); $svg1 = $renderer->renderSvg($matrix); $svg2 = $renderer->renderSvg($matrix); expect($svg1)->toBe($svg2); });