* @copyright 2002-2026 Nicola Asuni - Tecnick.com LTD * @license https://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE) * @link https://github.com/tecnickcom/tc-lib-pdf * * This file is part of tc-lib-pdf software library. */ namespace Test; use Com\Tecnick\Pdf\CSS\ImportanceNormalizer; use PHPUnit\Framework\Attributes\DataProvider; /** * Test ImportanceNormalizer CSS declaration normalization */ class ImportanceNormalizerTest extends TestUtil { public function testGetAffectedLonghandsExpandsNestedBorderAliases(): void { $affected = ImportanceNormalizer::getAffectedLonghands('border'); $this->assertContains('border-width', $affected); $this->assertContains('border-style', $affected); $this->assertContains('border-color', $affected); $this->assertContains('border-top-width', $affected); $this->assertContains('border-right-style', $affected); $this->assertContains('border-bottom-color', $affected); $this->assertContains('border-left-width', $affected); } public function testNormalizePreservesRegularDeclarations(): void { $input = 'color: red; font-size: 12px;'; $result = ImportanceNormalizer::normalize($input); $this->assertStringContainsString('color:red;', \str_replace(' ', '', $result)); $this->assertStringContainsString('font-size:12px;', \str_replace(' ', '', $result)); $this->assertStringNotContainsString('!important', $result); } public function testNormalizePreservesImportantFlag(): void { $input = 'color: red !important; font-size: 12px;'; $result = ImportanceNormalizer::normalize($input); $this->assertStringContainsString('color:red!important;', \str_replace(' ', '', $result)); $this->assertStringNotContainsString('font-size:12px!important;', \str_replace(' ', '', $result)); } public function testNormalizeBorderShorthandWithoutImportant(): void { $input = 'border: 1px solid red;'; $result = ImportanceNormalizer::normalize($input); // Should contain the shorthand property $this->assertStringContainsString('border:', $result); $this->assertStringNotContainsString('!important', $result); } public function testNormalizeBorderShorthandWithImportant(): void { $input = 'border: 1px solid red !important;'; $result = ImportanceNormalizer::normalize($input); // The shorthand should have !important $this->assertStringContainsString('border:', $result); $this->assertStringContainsString('!important', $result); } public function testNormalizeMixedShorthandAndLonghands(): void { $input = 'margin: 10px !important; margin-top: 20px;'; $result = ImportanceNormalizer::normalize($input); // Should contain both margin shorthand and the longhand $this->assertStringContainsString('margin:', $result); $this->assertStringContainsString('margin-top:', $result); // Shorthand !important should be preserved $this->assertStringContainsString('!important', $result); } public function testNormalizePaddingShorthandWithImportant(): void { $input = 'padding: 5px 10px !important;'; $result = ImportanceNormalizer::normalize($input); $this->assertStringContainsString('padding:', $result); $this->assertStringContainsString('!important', $result); } public function testNormalizeEmptyString(): void { $result = ImportanceNormalizer::normalize(''); $this->assertSame('', $result); } public function testNormalizeHandlesWhitespaceAroundImportant(): void { $input = 'color: blue ! important;'; $result = ImportanceNormalizer::normalize($input); $this->assertStringContainsString('!important', $result); } public function testNormalizeMultipleImportantDeclarations(): void { $input = 'color: red !important; background: blue !important; font-size: 14px;'; $result = ImportanceNormalizer::normalize($input); $normalized = \str_replace(' ', '', $result); $this->assertStringContainsString('color:red!important;', $normalized); $this->assertStringContainsString('background:blue!important;', $normalized); $this->assertStringNotContainsString('font-size:14px!important;', $normalized); } public function testNormalizeHandlesTrailingSemicolon(): void { $input = 'color: red;'; $result = ImportanceNormalizer::normalize($input); $this->assertStringEndsWith(';', $result); } public function testNormalizeCaseInsensitive(): void { $input = 'COLOR: red !IMPORTANT;'; $result = ImportanceNormalizer::normalize($input); // Property should be lowercased $this->assertStringContainsString('color:', $result); // !important flag should be present (case-insensitive) $this->assertStringContainsString('!important', $result); } public function testNormalizeSkipsMalformedDeclarationSegments(): void { $input = 'broken; :12px; color: red;'; $result = ImportanceNormalizer::normalize($input); $normalized = \str_replace(' ', '', $result); $this->assertSame('color:red;', $normalized); } public function testNormalizePromotesExistingLonghandWhenShorthandImportantAppearsLater(): void { $input = 'margin-top: 2px; margin: 10px !important;'; $result = ImportanceNormalizer::normalize($input); $normalized = \str_replace(' ', '', $result); $this->assertStringContainsString('margin-top:2px!important;', $normalized); $this->assertStringContainsString('margin:10px!important;', $normalized); } #[DataProvider('realWorldDeclarationsProvider')] public function testNormalizeRealWorldDeclarations(string $input, string $expectedProperty): void { $result = ImportanceNormalizer::normalize($input); $this->assertStringContainsString($expectedProperty, $result); } /** @return array */ public static function realWorldDeclarationsProvider(): array { return [ 'button_styling' => [ 'padding: 10px 20px !important; color: white; background: blue;', 'padding:', ], 'text_emphasis' => [ 'font-weight: bold !important; font-size: 14px;', 'font-weight:', ], 'border_reset' => [ 'border: none !important; margin: 0;', 'border:', ], ]; } }