Skip to content

Commit e9aefd3

Browse files
committed
Add tests
1 parent 441427b commit e9aefd3

File tree

5 files changed

+392
-1
lines changed

5 files changed

+392
-1
lines changed

src/JsonStream.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ final class JsonStream extends Stream implements JsonStreamInterface
3030
* @param int $encodingOptions Optional JSON encoding flags as defined by {@see json_encode()}. Defaults to 0.
3131
*/
3232
public function __construct(
33-
private mixed $payload,
33+
private mixed $payload = [],
3434
private int $encodingOptions = self::ENCODING_OPTIONS
3535
) {
3636
parent::__construct(fopen('php://temp', 'wb+'));

tests/JsonResponseTest.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace FastForward\Http\Message\Tests;
6+
7+
use FastForward\Http\Message\JsonResponse;
8+
use FastForward\Http\Message\JsonResponseInterface;
9+
use FastForward\Http\Message\JsonStream;
10+
use FastForward\Http\Message\JsonStreamInterface;
11+
use PHPUnit\Framework\Attributes\CoversClass;
12+
use PHPUnit\Framework\Attributes\UsesClass;
13+
use PHPUnit\Framework\TestCase;
14+
15+
#[CoversClass(JsonResponse::class)]
16+
#[UsesClass(JsonStream::class)]
17+
final class JsonResponseTest extends TestCase
18+
{
19+
public function testClassImplementsJsonResponseInterface(): void
20+
{
21+
$this->assertInstanceOf(JsonResponseInterface::class, new JsonResponse());
22+
}
23+
24+
public function testConstructorWillInitializeWithPayload(): void
25+
{
26+
$payload = ['success' => true];
27+
28+
$response = new JsonResponse($payload);
29+
30+
$this->assertSame(['success' => true], $response->getPayload());
31+
$this->assertInstanceOf(JsonStreamInterface::class, $response->getBody());
32+
$this->assertSame('application/json; charset=utf-8', $response->getHeaderLine('Content-Type'));
33+
}
34+
35+
public function testWithPayloadWillReturnNewInstanceWithNewPayload(): void
36+
{
37+
$initialPayload = ['foo' => 'bar'];
38+
$newPayload = ['bar' => 'baz'];
39+
40+
$original = new JsonResponse($initialPayload);
41+
$updated = $original->withPayload($newPayload);
42+
43+
$this->assertSame($initialPayload, $original->getPayload());
44+
$this->assertSame($newPayload, $updated->getPayload());
45+
46+
$this->assertNotSame($original, $updated);
47+
$this->assertInstanceOf(JsonResponse::class, $updated);
48+
}
49+
50+
public function testWithPayloadWillNotMutateOriginalResponse(): void
51+
{
52+
$payload = ['immutable' => true];
53+
54+
$response = new JsonResponse($payload);
55+
$newPayload = ['immutable' => false];
56+
57+
$newResponse = $response->withPayload($newPayload);
58+
59+
$this->assertSame(['immutable' => true], $response->getPayload());
60+
$this->assertSame(['immutable' => false], $newResponse->getPayload());
61+
62+
$this->assertNotSame($response, $newResponse);
63+
}
64+
}

tests/JsonStreamTest.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace FastForward\Http\Message\Tests;
6+
7+
use FastForward\Http\Message\JsonStream;
8+
use JsonException;
9+
use PHPUnit\Framework\Attributes\CoversClass;
10+
use PHPUnit\Framework\TestCase;
11+
12+
#[CoversClass(JsonStream::class)]
13+
final class JsonStreamTest extends TestCase
14+
{
15+
public function testClassImplementsJsonStreamInterface(): void
16+
{
17+
$this->assertInstanceOf(JsonStream::class, new JsonStream());
18+
}
19+
20+
public function testConstructorWillEncodePayloadAndPreserveDecodedValue(): void
21+
{
22+
$payload = ['key' => 'value'];
23+
24+
$stream = new JsonStream($payload);
25+
26+
$this->assertSame($payload, $stream->getPayload());
27+
$this->assertSame(json_encode($payload, JsonStream::ENCODING_OPTIONS), (string) $stream);
28+
}
29+
30+
public function testWithPayloadWillReturnNewInstanceWithNewPayload(): void
31+
{
32+
$initialPayload = ['first' => 1];
33+
$newPayload = ['second' => 2];
34+
35+
$original = new JsonStream($initialPayload);
36+
$updated = $original->withPayload($newPayload);
37+
38+
$this->assertSame($initialPayload, $original->getPayload());
39+
$this->assertSame($newPayload, $updated->getPayload());
40+
$this->assertSame(json_encode($newPayload, JsonStream::ENCODING_OPTIONS), (string) $updated);
41+
$this->assertNotSame($original, $updated);
42+
$this->assertNotSame($original->getPayload(), $updated->getPayload());
43+
$this->assertInstanceOf(JsonStream::class, $updated);
44+
}
45+
46+
public function testConstructorWillThrowExceptionWhenPayloadIsResource(): void
47+
{
48+
$this->expectException(\InvalidArgumentException::class);
49+
$this->expectExceptionMessage('Cannot JSON encode resources');
50+
51+
$resource = fopen('php://temp', 'rb');
52+
new JsonStream($resource);
53+
}
54+
55+
public function testConstructorWillThrowJsonExceptionOnInvalidPayload(): void
56+
{
57+
$this->expectException(JsonException::class);
58+
59+
$data = "\xB1\x31"; // Malformed UTF-8 sequence
60+
new JsonStream($data);
61+
}
62+
63+
public function testWithPayloadWillNotMutateOriginalInstance(): void
64+
{
65+
$payload = ['immutable' => true];
66+
67+
$stream = new JsonStream($payload);
68+
$newPayload = ['immutable' => false];
69+
70+
$newStream = $stream->withPayload($newPayload);
71+
72+
$this->assertSame(['immutable' => true], $stream->getPayload());
73+
$this->assertSame(json_encode(['immutable' => true], JsonStream::ENCODING_OPTIONS), (string) $stream);
74+
75+
$this->assertSame(['immutable' => false], $newStream->getPayload());
76+
$this->assertSame(json_encode(['immutable' => false], JsonStream::ENCODING_OPTIONS), (string) $newStream);
77+
}
78+
}

tests/RequestMethodTest.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\FastForward\Http\Message;
6+
7+
use FastForward\Http\Message\RequestMethod;
8+
use PHPUnit\Framework\Attributes\CoversClass;
9+
use PHPUnit\Framework\Attributes\DataProvider;
10+
use PHPUnit\Framework\TestCase;
11+
12+
#[CoversClass(RequestMethod::class)]
13+
final class RequestMethodTest extends TestCase
14+
{
15+
#[DataProvider('provideSafeMethods')]
16+
public function testIsSafeWillReturnTrue(RequestMethod $method): void
17+
{
18+
$this->assertTrue($method->isSafe());
19+
}
20+
21+
#[DataProvider('provideUnsafeMethods')]
22+
public function testIsSafeWillReturnFalse(RequestMethod $method): void
23+
{
24+
$this->assertFalse($method->isSafe());
25+
}
26+
27+
#[DataProvider('provideIdempotentMethods')]
28+
public function testIsIdempotentWillReturnTrue(RequestMethod $method): void
29+
{
30+
$this->assertTrue($method->isIdempotent());
31+
}
32+
33+
#[DataProvider('provideNonIdempotentMethods')]
34+
public function testIsIdempotentWillReturnFalse(RequestMethod $method): void
35+
{
36+
$this->assertFalse($method->isIdempotent());
37+
}
38+
39+
#[DataProvider('provideCacheableMethods')]
40+
public function testIsCacheableWillReturnTrue(RequestMethod $method): void
41+
{
42+
$this->assertTrue($method->isCacheable());
43+
}
44+
45+
#[DataProvider('provideNonCacheableMethods')]
46+
public function testIsCacheableWillReturnFalse(RequestMethod $method): void
47+
{
48+
$this->assertFalse($method->isCacheable());
49+
}
50+
51+
public static function provideSafeMethods(): array
52+
{
53+
return [
54+
[RequestMethod::Get],
55+
[RequestMethod::Head],
56+
[RequestMethod::Options],
57+
[RequestMethod::Trace],
58+
];
59+
}
60+
61+
public static function provideUnsafeMethods(): array
62+
{
63+
return [
64+
[RequestMethod::Post],
65+
[RequestMethod::Put],
66+
[RequestMethod::Patch],
67+
[RequestMethod::Delete],
68+
[RequestMethod::Purge],
69+
[RequestMethod::Connect],
70+
];
71+
}
72+
73+
public static function provideIdempotentMethods(): array
74+
{
75+
return [
76+
[RequestMethod::Get],
77+
[RequestMethod::Head],
78+
[RequestMethod::Put],
79+
[RequestMethod::Delete],
80+
[RequestMethod::Options],
81+
[RequestMethod::Trace],
82+
];
83+
}
84+
85+
public static function provideNonIdempotentMethods(): array
86+
{
87+
return [
88+
[RequestMethod::Post],
89+
[RequestMethod::Patch],
90+
[RequestMethod::Purge],
91+
[RequestMethod::Connect],
92+
];
93+
}
94+
95+
public static function provideCacheableMethods(): array
96+
{
97+
return [
98+
[RequestMethod::Get],
99+
[RequestMethod::Head],
100+
];
101+
}
102+
103+
public static function provideNonCacheableMethods(): array
104+
{
105+
return [
106+
[RequestMethod::Post],
107+
[RequestMethod::Put],
108+
[RequestMethod::Patch],
109+
[RequestMethod::Delete],
110+
[RequestMethod::Purge],
111+
[RequestMethod::Options],
112+
[RequestMethod::Trace],
113+
[RequestMethod::Connect],
114+
];
115+
}
116+
}

0 commit comments

Comments
 (0)