Skip to content

Commit 70a79a9

Browse files
committed
test: harden provider-based business coverage
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
1 parent 6ca28a1 commit 70a79a9

4 files changed

Lines changed: 544 additions & 215 deletions

File tree

tests/Unit/Html/SubsetHtmlParserTest.php

Lines changed: 80 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,78 @@
1010
use DOMDocument;
1111
use LibreSign\XObjectTemplate\Exception\UnsupportedSubsetException;
1212
use LibreSign\XObjectTemplate\Html\SubsetHtmlParser;
13+
use PHPUnit\Framework\Attributes\DataProvider;
1314
use PHPUnit\Framework\TestCase;
1415

1516
final class SubsetHtmlParserTest extends TestCase
1617
{
17-
public function testUnsupportedTagThrowsException(): void
18+
/**
19+
* @return iterable<string, array{0: string, 1: string}>
20+
*/
21+
public static function unsupportedTagProvider(): iterable
22+
{
23+
yield 'table is outside the supported subset' => [
24+
'<table><tr><td>x</td></tr></table>',
25+
'Tag <table> is not supported.',
26+
];
27+
28+
yield 'unordered lists are outside the supported subset' => [
29+
'<ul><li>x</li></ul>',
30+
'Tag <ul> is not supported.',
31+
];
32+
33+
yield 'semantic strong tags are outside the supported subset' => [
34+
'<strong>x</strong>',
35+
'Tag <strong> is not supported.',
36+
];
37+
}
38+
39+
/**
40+
* @return iterable<string, array{0: string, 1: string, 2: string, 3: string, 4: list<string>}>
41+
*/
42+
public static function inheritableStyleProvider(): iterable
43+
{
44+
yield 'layout-only styles stay on parent while text styles inherit' => [
45+
'<div style="width:58%;height:100%;padding:18 24;font-size:20;color:#123456">'
46+
. '<div style="font-weight:700">Title</div>'
47+
. '</div>',
48+
'width:58%;height:100%;padding:18 24;font-size:20;color:#123456',
49+
'font-size:20;color:#123456;font-weight:700',
50+
'font-size:20;color:#123456;font-weight:700',
51+
['width:58%', 'height:100%', 'padding:18 24'],
52+
];
53+
54+
yield 'text alignment white-space and color inherit together' => [
55+
'<div style="text-align:right;white-space:nowrap;color:#222222;font-size:11">'
56+
. '<span>Aligned</span>'
57+
. '</div>',
58+
'text-align:right;white-space:nowrap;color:#222222;font-size:11',
59+
'text-align:right;white-space:nowrap;color:#222222;font-size:11',
60+
'text-align:right;white-space:nowrap;color:#222222;font-size:11',
61+
[],
62+
];
63+
64+
yield 'malformed declarations preserve last inheritable values and colon values' => [
65+
'<div style=" ; COLOR : #fff ; broken ; font-family : Times:Bold ; invalid: ; '
66+
. 'white-space : nowrap ; hyphens : auto ; color : #abc ; line-height : 12 ; ">'
67+
. '<span style="font-weight:bold">Hello</span>'
68+
. '</div>',
69+
'; COLOR : #fff ; broken ; font-family : Times:Bold ; invalid: ; white-space : nowrap ; '
70+
. 'hyphens : auto ; color : #abc ; line-height : 12 ;',
71+
'color:#abc;font-family:Times:Bold;white-space:nowrap;hyphens:auto;line-height:12;font-weight:bold',
72+
'color:#abc;font-family:Times:Bold;white-space:nowrap;hyphens:auto;line-height:12;font-weight:bold',
73+
[],
74+
];
75+
}
76+
77+
#[DataProvider('unsupportedTagProvider')]
78+
public function testUnsupportedTagThrowsException(string $html, string $expectedMessage): void
1879
{
1980
$parser = new SubsetHtmlParser();
2081

2182
$this->expectException(UnsupportedSubsetException::class);
22-
$this->expectExceptionMessage('Tag <table> is not supported.');
23-
$parser->parse('<table><tr><td>x</td></tr></table>');
83+
$this->expectExceptionMessage($expectedMessage);
84+
$parser->parse($html);
2485
}
2586

2687
public function testParseNormalizesAttributesAndTrimsTextNodes(): void
@@ -62,31 +123,26 @@ public function testParseMergesInheritedStylesAndKeepsAllowedTags(): void
62123
self::assertSame('font-size:10; margin:2', $nodes[0]->children[2]->attributes['style']);
63124
}
64125

65-
public function testParseOnlyInheritsTextualStylesToDescendants(): void
126+
#[DataProvider('inheritableStyleProvider')]
127+
public function testParseOnlyInheritsTextualStylesToDescendants(
128+
string $html,
129+
string $expectedRootStyle,
130+
string $expectedChildStyle,
131+
string $expectedTextStyle,
132+
array $excludedFragments,
133+
): void
66134
{
67135
$parser = new SubsetHtmlParser();
68136

69-
$nodes = $parser->parse(
70-
'<div style="width:58%;height:100%;padding:18 24;font-size:20;color:#123456">'
71-
. '<div style="font-weight:700">Title</div>'
72-
. '</div>',
73-
);
137+
$nodes = $parser->parse($html);
74138

75-
self::assertSame(
76-
'width:58%;height:100%;padding:18 24;font-size:20;color:#123456',
77-
$nodes[0]->attributes['style'],
78-
);
79-
self::assertSame(
80-
'font-size:20;color:#123456;font-weight:700',
81-
$nodes[0]->children[0]->attributes['style'],
82-
);
83-
self::assertSame(
84-
'font-size:20;color:#123456;font-weight:700',
85-
$nodes[0]->children[0]->children[0]->attributes['style'],
86-
);
87-
self::assertStringNotContainsString('width:58%', $nodes[0]->children[0]->attributes['style']);
88-
self::assertStringNotContainsString('height:100%', $nodes[0]->children[0]->attributes['style']);
89-
self::assertStringNotContainsString('padding:18 24', $nodes[0]->children[0]->attributes['style']);
139+
self::assertSame($expectedRootStyle, $nodes[0]->attributes['style']);
140+
self::assertSame($expectedChildStyle, $nodes[0]->children[0]->attributes['style']);
141+
self::assertSame($expectedTextStyle, $nodes[0]->children[0]->children[0]->attributes['style']);
142+
143+
foreach ($excludedFragments as $excludedFragment) {
144+
self::assertStringNotContainsString($excludedFragment, $nodes[0]->children[0]->attributes['style']);
145+
}
90146
}
91147

92148
public function testParseNormalizesTagAndAttributeNamesAndKeepsAllAttributes(): void
@@ -178,32 +234,6 @@ public function testParseKeepsAllTopLevelNodesInOrder(): void
178234
$this->assertSame('Second', $nodes[1]->children[0]->text);
179235
}
180236

181-
public function testParseFiltersInheritedStylesAfterMalformedDeclarationsAndPreservesColonValues(): void
182-
{
183-
$parser = new SubsetHtmlParser();
184-
185-
$nodes = $parser->parse(
186-
'<div style=" ; COLOR : #fff ; broken ; font-family : Times:Bold ; invalid: ; '
187-
. 'white-space : nowrap ; hyphens : auto ; color : #abc ; line-height : 12 ; ">'
188-
. '<span style="font-weight:bold">Hello</span>'
189-
. '</div>',
190-
);
191-
192-
$this->assertSame(
193-
'; COLOR : #fff ; broken ; font-family : Times:Bold ; invalid: ; white-space : nowrap ; '
194-
. 'hyphens : auto ; color : #abc ; line-height : 12 ;',
195-
$nodes[0]->attributes['style'],
196-
);
197-
$this->assertSame(
198-
'color:#abc;font-family:Times:Bold;white-space:nowrap;hyphens:auto;line-height:12;font-weight:bold',
199-
$nodes[0]->children[0]->attributes['style'],
200-
);
201-
$this->assertSame(
202-
'color:#abc;font-family:Times:Bold;white-space:nowrap;hyphens:auto;line-height:12;font-weight:bold',
203-
$nodes[0]->children[0]->children[0]->attributes['style'],
204-
);
205-
}
206-
207237
public function testParseClearsPreExistingLibxmlErrorBuffer(): void
208238
{
209239
$parser = new SubsetHtmlParser();

0 commit comments

Comments
 (0)