Skip to content

Commit 22d2b3c

Browse files
committed
Kill mutants :)
1 parent eab116c commit 22d2b3c

File tree

6 files changed

+91
-19
lines changed

6 files changed

+91
-19
lines changed

src/Id.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@ private function ensureNotEmpty(string $id): void {
3333
private function ensureFollowsHtml5Rules(string $id): void {
3434
// https://www.w3.org/TR/html5-author/global-attributes.html#the-id-attribute
3535
// https://www.w3.org/TR/2012/WD-html5-20121025/single-page.html#space-character
36-
$invalid = "\u{0020}" . // SPACE
37-
"\u{0009}" . // TAB
38-
"\u{000A}" . // LF
39-
"\u{000C}" . //"FF"
40-
"\u{000D}"; // "CR"
36+
$invalid = [
37+
"\u{0020}", // SPACE
38+
"\u{0009}", // TAB
39+
"\u{000A}", // LF
40+
"\u{000C}", //"FF"
41+
"\u{000D}" // "CR"
42+
];
4143

42-
if (preg_match('/^[' . $invalid . ']+$/u', $id)) {
44+
if (preg_match('/^[' . implode('', $invalid) . ']+$/u', $id)) {
4345
throw new InvalidArgumentException(
4446
'ID must not contain space type character (https://www.w3.org/TR/html5-author/global-attributes.html#the-id-attribute)'
4547
);

src/document/DocumentCollection.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,25 @@
1010
namespace Templado\Engine;
1111

1212
use ArrayIterator;
13+
use Countable;
1314
use IteratorAggregate;
15+
use function sizeof;
1416

1517
/** @template-implements IteratorAggregate<int,Document> */
16-
class DocumentCollection implements IteratorAggregate {
18+
class DocumentCollection implements Countable, IteratorAggregate {
1719
/** @psalm-type list<int,Document> */
1820
private array $documents = [];
1921

2022
public function __construct(Document ...$documents) {
2123
$this->documents = $documents;
2224
}
2325

26+
public function count(): int {
27+
return sizeof($this->documents);
28+
}
29+
2430
public function add(Document ...$documents): void {
25-
$this->documents += $documents;
31+
array_push($this->documents, ...$documents);
2632
}
2733
public function getIterator(): ArrayIterator {
2834
return new ArrayIterator($this->documents);

tests/IdTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public function testCanBeConvertedToString(): void {
1616
}
1717

1818
#[DataProvider('invalidIdProvider')]
19-
public function testThrowsExceptionForInvalidInput(string $input): void{
19+
public function testThrowsExceptionForInvalidInput(string $input): void {
2020
$this->expectException(InvalidArgumentException::class);
2121

2222
(new Id($input));

tests/document/DocumentCollectionTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ public function testCanAddDocument(): void {
3737

3838
$collection = new DocumentCollection();
3939
$collection->add($document);
40+
$collection->add($document);
4041

4142
$this->assertContains($document, $collection);
43+
$this->assertCount(2, $collection);
4244
}
4345

4446
}

tests/document/DocumentTest.php

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php declare(strict_types=1);
22
/*
3-
* This file is part of Document\Engine.
3+
* This file is part of Templado\Engine.
44
*
55
* Copyright (c) Arne Blankerts <[email protected]> and contributors
66
*
@@ -9,6 +9,8 @@
99
*/
1010
namespace Templado\Engine;
1111

12+
use function libxml_get_errors;
13+
use ArrayIterator;
1214
use DOMDocument;
1315
use PHPUnit\Framework\Attributes\CoversClass;
1416
use PHPUnit\Framework\Attributes\UsesClass;
@@ -39,6 +41,18 @@ public function testCanBeConstructedFromString(): void {
3941
);
4042
}
4143

44+
public function testExistingLibxmlErrorStateGetsClearedOnConstruct(): void {
45+
libxml_use_internal_errors(true);
46+
$dummy = new DOMDocument();
47+
$dummy->loadXML('parsing-this-will-cause-libxml-errors');
48+
libxml_use_internal_errors(false);
49+
50+
$this->assertInstanceOf(
51+
Document::class,
52+
Document::fromString('<?xml version="1.0" ?><root />')
53+
);
54+
}
55+
4256
public function testCanBeConstructedFromStringWithId(): void {
4357
$id = new Id('abc');
4458
$instance = Document::fromString('<?xml version="1.0" ?><root />', $id);
@@ -51,25 +65,44 @@ public function testCanBeConstructedFromStringWithId(): void {
5165
}
5266

5367
public function testCanBeSerializedBackToStringWithoutSerializer(): void {
54-
$xml = "<?xml version=\"1.0\"?>\n<root/>\n";
68+
$xml = "<?xml version=\"1.0\"?>\n<root/>\n";
5569
$instance = Document::fromString($xml);
5670
$this->assertEquals($xml, $instance->asString());
5771
}
5872

5973
public function testTryingToParseInvalidMarkupStringThrowsException(): void {
60-
$this->expectException(ParsingException::class);
61-
Document::fromString('<?xml version="1.0" ?><root>');
74+
$caught = null;
75+
try {
76+
Document::fromString('<?xml version="1.0" ?><root>');
77+
} catch (\Throwable $t) {
78+
$caught = $t;
79+
}
80+
81+
$this->assertInstanceOf(ParsingException::class, $caught);
82+
$this->assertEmpty(libxml_get_errors());
6283
}
6384

6485
public function testSelectionOfSingleNodeCanBeExtracted(): void {
6586
$id = new Id('test');
66-
$result = (Document::fromString('<?xml version="1.0" ?><root><child /></root>'))->extract(
87+
$result = (Document::fromString('<?xml version="1.0" ?><root><child><p>text</p></child></root>'))->extract(
6788
new XPathSelector('//child'),
6889
$id
6990
);
7091

7192
$this->assertInstanceOf(Document::class, $result);
7293
$this->assertEquals($id, $result->id());
94+
95+
$result->asString(new class($this) implements Serializer {
96+
public function __construct(
97+
private TestCase $testCase
98+
) {
99+
}
100+
public function serialize(DOMDocument $document): string {
101+
$this->testCase->assertEquals('child', $document->documentElement->nodeName);
102+
$this->testCase->assertTrue($document->documentElement->hasChildNodes());
103+
return '';
104+
}
105+
});
73106
}
74107

75108
public function testExtractingEmptySelectionThrowsException(): void {
@@ -80,21 +113,20 @@ public function testExtractingEmptySelectionThrowsException(): void {
80113
}
81114

82115
public function testSelectionOfMultiNodesCanBeExtracted(): void {
83-
$result = (Document::fromString('<?xml version="1.0" ?><root><child /><child /></root>'))->extract(
116+
$result = (Document::fromString('<?xml version="1.0" ?><root><child><p>text</p></child><child /></root>'))->extract(
84117
new XPathSelector('//child')
85118
);
86119

87120
$this->assertInstanceOf(Document::class, $result);
88121

89122
$result->asString(new class($this) implements Serializer {
90-
91123
public function __construct(
92124
private TestCase $testCase
93-
){
94-
125+
) {
95126
}
96127
public function serialize(DOMDocument $document): string {
97128
$this->testCase->assertCount(2, $document->getElementsByTagName('child'));
129+
$this->testCase->assertTrue($document->documentElement->firstElementChild->hasChildNodes());
98130

99131
return '';
100132
}
@@ -126,7 +158,7 @@ public function testTransformationCanBeApplied(): void {
126158
$dom->loadXML('<?xml version="1.0" ?><root><child /></root>');
127159

128160
$selection = $this->createMock(Selection::class);
129-
$selection->method('getIterator')->willReturn(new \ArrayIterator([$dom->documentElement->firstChild]));
161+
$selection->method('getIterator')->willReturn(new ArrayIterator([$dom->documentElement->firstChild]));
130162

131163
$selector = $this->createMock(Selector::class);
132164
$selector->method('select')->willReturn($selection);
@@ -228,4 +260,33 @@ public function testTryingToMergeDocumentCollectionWithDocumentWithoutIdThrowsEx
228260
$target->merge($list);
229261
}
230262

263+
public function testBlankWhitespaceGetsRemoved(): void {
264+
$document = Document::fromString(
265+
implode("\n",[
266+
'<?xml version="1.0" ?>',
267+
'<root>',
268+
' <p>text</p>',
269+
'</root>'
270+
])
271+
);
272+
273+
$document->asString(new class($this) implements Serializer {
274+
public function __construct(
275+
private TestCase $testCase
276+
) {
277+
}
278+
public function serialize(DOMDocument $document): string {
279+
$this->testCase->assertCount(1, $document->documentElement->childNodes);
280+
return '';
281+
}
282+
});
283+
}
284+
285+
public function testNonFatalWarningsFromParsingAreCaught(): void {
286+
$this->expectException(ParsingException::class);
287+
$xml = '<?xml version="1.0" encoding="UTF-8"?>'
288+
.'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
289+
.'<body>&nbsp;</body>';
290+
(Document::fromString($xml));
291+
}
231292
}

tests/document/ParsingExceptionTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ public function testLibXMLErrorsCanBeRetrieved(): void {
1010
(new \DOMDocument())->loadXML('<?xml version="1.0" ?><parseerror>');
1111
$exception = new ParsingException(...libxml_get_errors());
1212
$this->assertCount(1, $exception->errors());
13+
$this->assertEquals('Error(s) during parse', $exception->getMessage());
1314
}
1415
}

0 commit comments

Comments
 (0)