From 76c26991c18595b993c4abb3448baafcccf6b99d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marti=CC=81n=20Go=CC=81mez?= Date: Fri, 20 Feb 2026 16:21:05 +0100 Subject: [PATCH] Improve type safety and null handling - Assert title is not null before string assertions in TestSEO - Add native union type to HTMLParser::grabMultiple() parameter - Replace implicit empty array falsy check with explicit comparison in SimpleSerializer::formatTagCollection() - Skip items with missing keys in ArrayPluck instead of crashing Changelog: fixed --- src/Parser/HTMLParser.php | 7 ++----- src/SnapshotFormatters/SimpleSerializer.php | 10 ++++++++-- src/Support/ArrayPluck.php | 4 ++++ src/TestSEO.php | 8 ++++++-- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/Parser/HTMLParser.php b/src/Parser/HTMLParser.php index bf8eeab..3ce9e82 100644 --- a/src/Parser/HTMLParser.php +++ b/src/Parser/HTMLParser.php @@ -39,16 +39,13 @@ public function grabAttributeFrom(string $xpath, string|array $attributes) return $this->getArgumentsFromNode($nodes->getNode(0), $attributes); } - /** - * @param string|array|null $attribute - */ - public function grabMultiple(string $xpath, $attribute = null): array + public function grabMultiple(string $xpath, string|array|null $attribute = null): array { $result = []; $nodes = $this->crawler->filterXPath($xpath); foreach ($nodes as $node) { - $result[] = $attribute !== null ? $this->getArgumentsFromNode($node, $attribute) : $node->textContent; + $result[] = $attribute !== null ? $this->getArgumentsFromNode($node, $attribute) : $node->textContent; // @phpstan-ignore argument.templateType } return $result; diff --git a/src/SnapshotFormatters/SimpleSerializer.php b/src/SnapshotFormatters/SimpleSerializer.php index de890d8..f086c9b 100644 --- a/src/SnapshotFormatters/SimpleSerializer.php +++ b/src/SnapshotFormatters/SimpleSerializer.php @@ -36,6 +36,12 @@ public function toArray(SEOData $data): array protected function formatTagCollection(TagCollection $collection): ?array { + $tags = $collection->toArray(); + + if ($tags === []) { + return null; + } + return array_map( function ($item) { if (is_array($item)) { @@ -44,8 +50,8 @@ function ($item) { return $this->formatIfUrl($item); }, - $collection->toArray(), - ) ?: null; + $tags, + ); } protected function formatIfUrl(?string $url): ?string diff --git a/src/Support/ArrayPluck.php b/src/Support/ArrayPluck.php index 7f82ea1..6f196ee 100644 --- a/src/Support/ArrayPluck.php +++ b/src/Support/ArrayPluck.php @@ -20,6 +20,10 @@ public function __invoke(string $key, string $value): array $results = []; foreach ($array as $item) { + if (! isset($item[$key], $item[$value])) { + continue; + } + $itemValue = $item[$value]; $itemKey = $item[$key]; diff --git a/src/TestSEO.php b/src/TestSEO.php index e0310a4..b84e2f7 100644 --- a/src/TestSEO.php +++ b/src/TestSEO.php @@ -82,7 +82,9 @@ public function assertTitleIs(string $expected): self public function assertTitleContains(string $expected): self { - Assert::assertStringContainsString($expected, $this->data->title()); + $title = $this->data->title(); + Assert::assertNotNull($title, 'Title tag is missing.'); + Assert::assertStringContainsString($expected, $title); return $this; } @@ -92,7 +94,9 @@ public function assertTitleContains(string $expected): self */ public function assertTitleEndsWith(string $expected): self { - Assert::assertStringEndsWith($expected, $this->data->title()); + $title = $this->data->title(); + Assert::assertNotNull($title, 'Title tag is missing.'); + Assert::assertStringEndsWith($expected, $title); return $this; }