Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/fix-style.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ jobs:

- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}

- name: Setup PHP
uses: shivammathur/setup-php@v2
Expand Down
17 changes: 12 additions & 5 deletions src/Http/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,28 @@
*/
final class Response implements DroppableInterface
{
use HasMetaData;
use Droppable;
use HasMetaData;

private Crawler $crawler;
private ?Crawler $crawler = null;

public function __construct(
private ResponseInterface $response,
private Request $request,
) {
$this->crawler = new Crawler((string) $response->getBody(), $request->getUri());
}

/**
* @param array<int, mixed> $args
*/
public function __call(string $method, array $args): mixed
{
return $this->crawler->{$method}(...$args);
return $this->getCrawler()->{$method}(...$args);
}

public function getCrawler(): Crawler
{
return $this->crawler ??= new Crawler((string) $this->response->getBody(), (string) $this->request->getUri());
}

public function getRequest(): Request
Expand All @@ -60,7 +67,7 @@ public function getBody(): string
public function withBody(string $body): self
{
$this->response = $this->response->withBody(Utils::streamFor($body));
$this->crawler = new Crawler($body, $this->request->getUri());
$this->crawler = null;

return $this;
}
Expand Down
18 changes: 18 additions & 0 deletions tests/Http/ResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
namespace RoachPHP\Tests\Http;

use GuzzleHttp\Psr7\Stream;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use RoachPHP\Http\Response;
use RoachPHP\Support\DroppableInterface;
use RoachPHP\Testing\Concerns\InteractsWithRequestsAndResponses;
use RoachPHP\Tests\Support\DroppableTestCase;
use Symfony\Component\DomCrawler\Crawler;

/**
* @internal
Expand All @@ -37,6 +39,7 @@ public function testCanAccessDomCrawlerDirectlyFromResponse(): void
self::assertCount(1, $links);
}

#[DataProvider('responseCodeProvider')]
/**
* @dataProvider responseCodeProvider
*/
Expand All @@ -60,6 +63,7 @@ public static function responseCodeProvider(): iterable
];
}

#[DataProvider('responseBodyProvider')]
/**
* @dataProvider responseBodyProvider
*/
Expand All @@ -81,6 +85,7 @@ public static function responseBodyProvider(): iterable

'stream' => [static function (string $body) {
$stream = \fopen('php://memory', 'r+b');
self::assertIsResource($stream);
\fwrite($stream, $body);
\rewind($stream);

Expand All @@ -89,6 +94,7 @@ public static function responseBodyProvider(): iterable

'StreamInterface' => [static function (string $body) {
$stream = \fopen('php://memory', 'r+b');
self::assertIsResource($stream);
\fwrite($stream, $body);
\rewind($stream);

Expand Down Expand Up @@ -125,6 +131,18 @@ public function testUpdatingResponseBodyUpdatesCrawler(): void
self::assertSame('New', $response->filter('p')->text(''));
}

public function testDomCrawlerIsLazyLoadedOnDemand(): void
{
$response = $this->makeResponse(body: '<html lang="en"><body></body></html>');

$crawlerProperty = new \ReflectionProperty(Response::class, 'crawler');

self::assertNull($crawlerProperty->getValue($response));

self::assertSame(0, $response->filter('p')->count());
self::assertInstanceOf(Crawler::class, $crawlerProperty->getValue($response));
}

protected function createDroppable(): DroppableInterface
{
return $this->makeResponse(
Expand Down