Skip to content

Commit d8c6903

Browse files
committed
Added tests. Fixed issues from test.
1 parent c7e86ea commit d8c6903

10 files changed

Lines changed: 596 additions & 183 deletions

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
},
1515
"require-dev": {
1616
"laminas/laminas-coding-standard": "^3.1",
17-
"phpunit/phpunit": "^12.5",
17+
"phpunit/phpunit": "^12.5.22",
1818
"psalm/plugin-phpunit": "^0.19.5",
19-
"vimeo/psalm": "^6.14"
19+
"vimeo/psalm": "^6.16"
2020
},
2121
"autoload": {
2222
"psr-4": {

composer.lock

Lines changed: 172 additions & 167 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

psalm.baseline.xml

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<files psalm-version="6.14.3@d0b040a91f280f071c1abcb1b77ce3822058725a">
2+
<files psalm-version="6.16.1@f1f5de594dc76faf8784e02d3dc4716c91c6f6ac">
33
<file src="src/ApiProblem.php">
44
<MixedAssignment>
55
<code><![CDATA[$prop]]></code>
@@ -10,10 +10,6 @@
1010
<PossiblyInvalidPropertyAssignmentValue>
1111
<code><![CDATA[$additional]]></code>
1212
</PossiblyInvalidPropertyAssignmentValue>
13-
<PossiblyUnusedMethod>
14-
<code><![CDATA[__get]]></code>
15-
<code><![CDATA[setDetailIncludesStackTrace]]></code>
16-
</PossiblyUnusedMethod>
1713
</file>
1814
<file src="src/ApiProblemResponse.php">
1915
<FalsableReturnStatement>
@@ -25,8 +21,10 @@
2521
<PossiblyFalseArgument>
2622
<code><![CDATA[$json]]></code>
2723
</PossiblyFalseArgument>
28-
<UnusedClass>
29-
<code><![CDATA[ApiProblemResponse]]></code>
30-
</UnusedClass>
24+
</file>
25+
<file src="test/ApiProblemTest.php">
26+
<UnusedVariable>
27+
<code><![CDATA[$a]]></code>
28+
</UnusedVariable>
3129
</file>
3230
</files>

src/ApiProblem.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,9 +271,6 @@ protected function getTitle(): ?string
271271
return get_class($this->detail);
272272
}
273273

274-
if (null === $this->title) {
275-
return 'Unknown';
276-
}
277274
return 'Unknown';
278275
}
279276

src/ApiProblemResponse.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use const JSON_HEX_APOS;
1919
use const JSON_HEX_QUOT;
2020
use const JSON_HEX_TAG;
21+
use const JSON_PARTIAL_OUTPUT_ON_ERROR;
2122
use const JSON_THROW_ON_ERROR;
2223
use const JSON_UNESCAPED_SLASHES;
2324

@@ -32,7 +33,8 @@ final class ApiProblemResponse extends Response
3233
| JSON_HEX_APOS
3334
| JSON_HEX_AMP
3435
| JSON_HEX_QUOT
35-
| JSON_UNESCAPED_SLASHES;
36+
| JSON_UNESCAPED_SLASHES
37+
| JSON_PARTIAL_OUTPUT_ON_ERROR;
3638

3739
public function __construct(ApiProblem $apiProblem)
3840
{

src/Exception/DomainException.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Lmc\Api\Problem\Exception;
6+
7+
use Override;
8+
use Traversable;
9+
10+
final class DomainException extends \DomainException implements ExceptionInterface, ProblemExceptionInterface
11+
{
12+
protected ?string $type = null;
13+
14+
protected array $details = [];
15+
16+
protected ?string $title = null;
17+
18+
public function setAdditionalDetails(array $details): self
19+
{
20+
$this->details = $details;
21+
return $this;
22+
}
23+
24+
public function setType(string $uri): self
25+
{
26+
$this->type = $uri;
27+
return $this;
28+
}
29+
30+
public function setTitle(string $title): self
31+
{
32+
$this->title = $title;
33+
return $this;
34+
}
35+
36+
#[Override]
37+
public function getAdditionalDetails(): Traversable|array|null
38+
{
39+
return $this->details;
40+
}
41+
42+
#[Override]
43+
public function getType(): ?string
44+
{
45+
return $this->type;
46+
}
47+
48+
#[Override]
49+
public function getTitle(): ?string
50+
{
51+
return $this->title;
52+
}
53+
}

src/Exception/ProblemExceptionInterface.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ interface ProblemExceptionInterface
1313
{
1414
public function getAdditionalDetails(): Traversable|array|null;
1515

16-
public function getType(): string;
16+
public function getType(): ?string;
1717

18-
public function getTitle(): string;
18+
public function getTitle(): ?string;
1919
}

test/ApiProblemResponseTest.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 LmcTest\Api\Problem;
6+
7+
use Lmc\Api\Problem\ApiProblem;
8+
use Lmc\Api\Problem\ApiProblemResponse;
9+
use Lmc\Api\Problem\Exception;
10+
use PHPUnit\Framework\TestCase;
11+
12+
use function fopen;
13+
use function json_decode;
14+
use function strtolower;
15+
16+
final class ApiProblemResponseTest extends TestCase
17+
{
18+
public function testApiProblemResponseSetsStatusCodeAndReasonPhrase(): void
19+
{
20+
$response = new ApiProblemResponse(new ApiProblem(400, 'Random error'));
21+
$this->assertEquals(400, $response->getStatusCode());
22+
$this->assertIsString($response->getReasonPhrase());
23+
$this->assertNotEmpty($response->getReasonPhrase());
24+
$this->assertEquals('bad request', strtolower($response->getReasonPhrase()));
25+
}
26+
27+
public function testApiProblemResponseSetsStatusCodeAndReasonPhraseUsingException(): void
28+
{
29+
$exception = new Exception\DomainException('Random error', 400);
30+
$response = new ApiProblemResponse(new ApiProblem(400, $exception));
31+
$this->assertEquals(400, $response->getStatusCode());
32+
$this->assertIsString($response->getReasonPhrase());
33+
$this->assertNotEmpty($response->getReasonPhrase());
34+
$this->assertEquals('bad request', strtolower($response->getReasonPhrase()));
35+
}
36+
37+
public function testApiProblemResponseBodyIsSerializedApiProblem(): void
38+
{
39+
$additional = [
40+
'foo' => fopen('php://memory', 'r'),
41+
];
42+
43+
$expected = [
44+
'foo' => null,
45+
'type' => 'http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html',
46+
'title' => 'Bad Request',
47+
'status' => 400,
48+
'detail' => 'Random error',
49+
];
50+
51+
$apiProblem = new ApiProblem(400, 'Random error', null, null, $additional);
52+
$response = new ApiProblemResponse($apiProblem);
53+
$this->assertEquals($expected, json_decode($response->getBody()->getContents(), true));
54+
}
55+
56+
public function testApiProblemResponseSetsContentTypeHeader(): void
57+
{
58+
$response = new ApiProblemResponse(new ApiProblem(400, 'Random error'));
59+
$headers = $response->getHeaders();
60+
$this->assertArrayHasKey('content-type', $headers);
61+
$header = $headers['content-type'][0];
62+
$this->assertEquals(ApiProblem::CONTENT_TYPE, $header);
63+
}
64+
}

0 commit comments

Comments
 (0)