From 5e8a2e22bfef7446cc6e3c413007bba3df913f48 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 26 Mar 2026 07:59:24 +0000 Subject: [PATCH] Tests: add coverage for untested classes Add tests for PSR7StreamResponse, ImageResponse, FlyFileResponse, ProcessAdapter, StdoutAdapter, and NullComponent. https://claude.ai/code/session_01JpmfUCxQwgqBnP1KzzbGLL --- .../Response/Fly/Adapter/ProcessAdapter.phpt | 43 +++++ .../Response/Fly/Adapter/StdoutAdapter.phpt | 63 +++++++ tests/Cases/Response/Fly/FlyFileResponse.phpt | 104 ++++++++++++ tests/Cases/Response/ImageResponse.phpt | 48 ++++++ tests/Cases/Response/PSR7StreamResponse.phpt | 154 ++++++++++++++++++ tests/Cases/UI/NullComponent.phpt | 22 +++ 6 files changed, 434 insertions(+) create mode 100644 tests/Cases/Response/Fly/Adapter/ProcessAdapter.phpt create mode 100644 tests/Cases/Response/Fly/Adapter/StdoutAdapter.phpt create mode 100644 tests/Cases/Response/Fly/FlyFileResponse.phpt create mode 100644 tests/Cases/Response/ImageResponse.phpt create mode 100644 tests/Cases/Response/PSR7StreamResponse.phpt create mode 100644 tests/Cases/UI/NullComponent.phpt diff --git a/tests/Cases/Response/Fly/Adapter/ProcessAdapter.phpt b/tests/Cases/Response/Fly/Adapter/ProcessAdapter.phpt new file mode 100644 index 0000000..ab04a9b --- /dev/null +++ b/tests/Cases/Response/Fly/Adapter/ProcessAdapter.phpt @@ -0,0 +1,43 @@ +send(new Request(new UrlScript()), new Response()); + $output = ob_get_clean(); + + Assert::same("hello world\n", $output); +}); + +// Test send with custom buffer size +Toolkit::test(function (): void { + $adapter = new ProcessAdapter('echo "buffered"', 'r', 4); + + ob_start(); + $adapter->send(new Request(new UrlScript()), new Response()); + $output = ob_get_clean(); + + Assert::same("buffered\n", $output); +}); + +// Test send with multi-line output +Toolkit::test(function (): void { + $adapter = new ProcessAdapter('printf "line1\nline2\nline3"'); + + ob_start(); + $adapter->send(new Request(new UrlScript()), new Response()); + $output = ob_get_clean(); + + Assert::same("line1\nline2\nline3", $output); +}); diff --git a/tests/Cases/Response/Fly/Adapter/StdoutAdapter.phpt b/tests/Cases/Response/Fly/Adapter/StdoutAdapter.phpt new file mode 100644 index 0000000..3b762d7 --- /dev/null +++ b/tests/Cases/Response/Fly/Adapter/StdoutAdapter.phpt @@ -0,0 +1,63 @@ +receivedBuffer = null; + $state->receivedRequest = null; + $state->receivedResponse = null; + + $adapter = new StdoutAdapter(function (Buffer $buffer, IRequest $request, IResponse $response) use ($state): void { + $state->receivedBuffer = $buffer; + $state->receivedRequest = $request; + $state->receivedResponse = $response; + }); + + $request = new Request(new UrlScript()); + $response = new Response(); + + $adapter->send($request, $response); + + Assert::type(Buffer::class, $state->receivedBuffer); + Assert::same($request, $state->receivedRequest); + Assert::same($response, $state->receivedResponse); +}); + +// Test writing to buffer produces output +Toolkit::test(function (): void { + $adapter = new StdoutAdapter(function (Buffer $buffer): void { + $buffer->write('hello from stdout'); + }); + + ob_start(); + $adapter->send(new Request(new UrlScript()), new Response()); + $output = ob_get_clean(); + + Assert::same('hello from stdout', $output); +}); + +// Test callback without arguments +Toolkit::test(function (): void { + $state = new stdClass(); + $state->executed = false; + + $adapter = new StdoutAdapter(function () use ($state): void { + $state->executed = true; + }); + + $adapter->send(new Request(new UrlScript()), new Response()); + + Assert::true($state->executed); +}); diff --git a/tests/Cases/Response/Fly/FlyFileResponse.phpt b/tests/Cases/Response/Fly/FlyFileResponse.phpt new file mode 100644 index 0000000..2eff979 --- /dev/null +++ b/tests/Cases/Response/Fly/FlyFileResponse.phpt @@ -0,0 +1,104 @@ +contentType = null; + $state->contentDisposition = null; + $state->adapterCalled = false; + + $adapter = new CallbackAdapter(function (IRequest $request, IResponse $response) use ($state): void { + $state->adapterCalled = true; + }); + + $flyFileResponse = new FlyFileResponse($adapter, 'report.pdf'); + + $response = new Response(); + $flyFileResponse->send(new Request(new UrlScript()), $response); + + Assert::true($state->adapterCalled); +}); + +// Test setContentType +Toolkit::test(function (): void { + $state = new stdClass(); + $state->adapterCalled = false; + + $adapter = new CallbackAdapter(function () use ($state): void { + $state->adapterCalled = true; + }); + + $flyFileResponse = new FlyFileResponse($adapter, 'data.csv'); + $flyFileResponse->setContentType('text/csv'); + + $flyFileResponse->send(new Request(new UrlScript()), new Response()); + + Assert::true($state->adapterCalled); +}); + +// Test setFilename changes filename +Toolkit::test(function (): void { + $state = new stdClass(); + $state->adapterCalled = false; + + $adapter = new CallbackAdapter(function () use ($state): void { + $state->adapterCalled = true; + }); + + $flyFileResponse = new FlyFileResponse($adapter, 'original.txt'); + $flyFileResponse->setFilename('renamed.txt'); + + $flyFileResponse->send(new Request(new UrlScript()), new Response()); + + Assert::true($state->adapterCalled); +}); + +// Test setForceDownload false (inline disposition) +Toolkit::test(function (): void { + $state = new stdClass(); + $state->adapterCalled = false; + + $adapter = new CallbackAdapter(function () use ($state): void { + $state->adapterCalled = true; + }); + + $flyFileResponse = new FlyFileResponse($adapter, 'image.png'); + $flyFileResponse->setForceDownload(false); + + $flyFileResponse->send(new Request(new UrlScript()), new Response()); + + Assert::true($state->adapterCalled); +}); + +// Test that adapter receives request and response +Toolkit::test(function (): void { + $state = new stdClass(); + $state->receivedRequest = null; + $state->receivedResponse = null; + + $adapter = new CallbackAdapter(function (IRequest $request, IResponse $response) use ($state): void { + $state->receivedRequest = $request; + $state->receivedResponse = $response; + }); + + $flyFileResponse = new FlyFileResponse($adapter, 'test.txt'); + + $request = new Request(new UrlScript()); + $response = new Response(); + $flyFileResponse->send($request, $response); + + Assert::same($request, $state->receivedRequest); + Assert::same($response, $state->receivedResponse); +}); diff --git a/tests/Cases/Response/ImageResponse.phpt b/tests/Cases/Response/ImageResponse.phpt new file mode 100644 index 0000000..191f7dd --- /dev/null +++ b/tests/Cases/Response/ImageResponse.phpt @@ -0,0 +1,48 @@ +save($filePath); + + $response = new ImageResponse($filePath); + + Assert::type(ImageResponse::class, $response); + + unlink($filePath); +}); + +// Test constructor with custom type and quality +Toolkit::test(function (): void { + $image = Image::fromBlank(1, 1); + $response = new ImageResponse($image, Image::PNG, 9); + + Assert::type(ImageResponse::class, $response); +}); diff --git a/tests/Cases/Response/PSR7StreamResponse.phpt b/tests/Cases/Response/PSR7StreamResponse.phpt new file mode 100644 index 0000000..ea8e1fb --- /dev/null +++ b/tests/Cases/Response/PSR7StreamResponse.phpt @@ -0,0 +1,154 @@ +getContentType()); +}); + +// Test custom content type +Toolkit::test(function (): void { + $stream = createStream('test'); + $response = new PSR7StreamResponse($stream, 'file.pdf', 'application/pdf'); + + Assert::same('application/pdf', $response->getContentType()); +}); + +// Test getters +Toolkit::test(function (): void { + $stream = createStream('test'); + $response = new PSR7StreamResponse($stream, 'document.txt', 'text/plain'); + + Assert::same($stream, $response->getStream()); + Assert::same('document.txt', $response->getName()); + Assert::same('text/plain', $response->getContentType()); +}); + +// Test send outputs stream content +Toolkit::test(function (): void { + $stream = createStream('Hello PSR7 World'); + $response = new PSR7StreamResponse($stream, 'hello.txt', 'text/plain'); + + ob_start(); + $response->send(new Request(new UrlScript()), new Response()); + $output = ob_get_clean(); + + Assert::same('Hello PSR7 World', $output); +}); + +// Test send with empty stream +Toolkit::test(function (): void { + $stream = createStream(''); + $response = new PSR7StreamResponse($stream, 'empty.txt'); + + ob_start(); + $response->send(new Request(new UrlScript()), new Response()); + $output = ob_get_clean(); + + Assert::same('', $output); +}); + +function createStream(string $content): StreamInterface +{ + return new class ($content) implements StreamInterface { + + private string $content; + + private int $position = 0; + + public function __construct(string $content) + { + $this->content = $content; + } + + public function __toString(): string + { + return $this->content; + } + + public function close(): void + { + } + + public function detach() + { + return null; + } + + public function getSize(): ?int + { + return strlen($this->content); + } + + public function tell(): int + { + return $this->position; + } + + public function eof(): bool + { + return $this->position >= strlen($this->content); + } + + public function isSeekable(): bool + { + return true; + } + + public function seek(int $offset, int $whence = SEEK_SET): void + { + $this->position = $offset; + } + + public function rewind(): void + { + $this->position = 0; + } + + public function isWritable(): bool + { + return false; + } + + public function write(string $string): int + { + return 0; + } + + public function isReadable(): bool + { + return true; + } + + public function read(int $length): string + { + $data = substr($this->content, $this->position, $length); + $this->position += strlen($data); + + return $data; + } + + public function getContents(): string + { + return substr($this->content, $this->position); + } + + public function getMetadata(?string $key = null) + { + return $key === null ? [] : null; + } + + }; +} diff --git a/tests/Cases/UI/NullComponent.phpt b/tests/Cases/UI/NullComponent.phpt new file mode 100644 index 0000000..d7f86a8 --- /dev/null +++ b/tests/Cases/UI/NullComponent.phpt @@ -0,0 +1,22 @@ +