Skip to content

Commit

Permalink
Replaces usage of simplexml_load_string with DOMDocument and DOMElement
Browse files Browse the repository at this point in the history
  • Loading branch information
tonysm committed Jul 23, 2021
1 parent ee13952 commit 007eb5d
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 48 deletions.
16 changes: 12 additions & 4 deletions src/Testing/ConvertTestResponseToTurboStreamCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,25 @@

namespace Tonysm\TurboLaravel\Testing;

use DOMDocument;
use Illuminate\Support\Collection;
use Illuminate\Testing\TestResponse;

class ConvertTestResponseToTurboStreamCollection
{
public function __invoke(TestResponse $response): Collection
{
$parsed = simplexml_load_string(<<<XML
<xml>{$response->content()}</xml>
XML);
libxml_use_internal_errors(true);
$document = tap(new DOMDocument())->loadHTML($response->content());
$elements = $document->getElementsByTagName('turbo-stream');

return collect(json_decode(json_encode($parsed), true)['turbo-stream']);
$streams = collect();

/** @var \DOMElement $element */
foreach ($elements as $element) {
$streams->push($element);
}

return $streams;
}
}
60 changes: 16 additions & 44 deletions src/Testing/TurboStreamMatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@
namespace Tonysm\TurboLaravel\Testing;

use Closure;
use Illuminate\Http\Response;
use Illuminate\Support\Arr;
use Illuminate\Testing\TestResponse;
use DOMElement;
use Illuminate\View\ComponentAttributeBag;
use PHPUnit\Framework\Assert;

class TurboStreamMatcher
{
/** @var \DOMElement */
private $turboStream;
private array $wheres = [];
private array $contents = [];

public function __construct($turboStream)
public function __construct(DOMElement $turboStream)
{
$this->turboStream = $turboStream;
}
Expand Down Expand Up @@ -70,9 +70,9 @@ public function attrs(): string
private function matchesProps()
{
foreach ($this->wheres as $prop => $value) {
$actualProp = $this->turboStream['@attributes'][$prop] ?? false;
$propValue = $this->turboStream->getAttribute($prop);

if ($actualProp === false || $actualProp !== $value) {
if (! $propValue || $propValue !== $value) {
return false;
}
}
Expand All @@ -86,55 +86,27 @@ private function matchesContents()
return true;
}

// To assert that the Turbo Stream contains the desired text, we first need to
// rebuild the markup from the response. This is because we had to parse the
// HTML before getting here so we could assert each Turbo Stream separately.

$content = new TestResponse(new Response($this->makeElements($this->turboStream['template'] ?? [])));

foreach ($this->contents as $expectedContent) {
$content->assertSee($expectedContent);
foreach ($this->contents as $content) {
Assert::assertStringContainsString($content, $this->renderElement());
}

return true;
}

private function makeAttributes(array $attributes): string
{
return (new ComponentAttributeBag($attributes))->toHtml();
}

private function makeElements($tags)
private function renderElement(): string
{
if (is_string($tags)) {
return $tags;
}

$content = '';

foreach ($tags as $tag => $contents) {
$attrs = $this->makeAttributes($contents['@attributes'] ?? []);

$strContent = $this->makeElements(is_array($contents) ? Arr::except($contents, '@attributes') : $contents);
$opening = trim(sprintf('%s %s', $tag, $attrs));
$html = '';
$children = $this->turboStream->childNodes;

if ($this->isSelfClosingTag($tag)) {
$content .= "<{$opening} />";
} else {
$content .= "<{$opening}>{$strContent}</{$tag}>";
}
foreach ($children as $child) {
$html .= $child->ownerDocument->saveXML($child);
}

return $content;
return $html;
}

private function isSelfClosingTag(string $tag): bool
private function makeAttributes(array $attributes): string
{
return in_array($tag, [
'input',
'img',
'br',
'source',
]);
return (new ComponentAttributeBag($attributes))->toHtml();
}
}

0 comments on commit 007eb5d

Please sign in to comment.