Skip to content

Commit 50fcb80

Browse files
committed
Add unit tests for HTTP exceptions and enhance Swagger UI handler coverage
- Introduced tests for `HttpDuplicateEntryException` and `HttpHandledInvalidArgumentAsSuccessException`, verifying construction, defaults, and log level behavior. - Expanded `SwaggerUIHandler` tests to include content validation and consistent behavior across request methods.
1 parent 3f3a4c8 commit 50fcb80

1 file changed

Lines changed: 80 additions & 1 deletion

File tree

tests/Unit/HttpTest.php

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
namespace Tests\Unit;
44

55
use Laminas\Diactoros\ServerRequest;
6+
use Laminas\Diactoros\Response\HtmlResponse;
7+
use Monolog\Level;
68
use ownHackathon\App\Http\Exception\HttpDuplicateEntryException;
9+
use ownHackathon\App\Http\Exception\HttpHandledInvalidArgumentAsSuccessException;
710
use ownHackathon\App\Http\Exception\HttpInvalidArgumentException;
811
use ownHackathon\App\Http\Exception\HttpUnauthorizedException;
912
use ownHackathon\App\Http\Handler\PingHandler;
@@ -26,6 +29,60 @@
2629
->and((new HttpUnauthorizedException('a', 'b'))->getHttpStatusCode())->toBe(401);
2730
});
2831

32+
test('duplicate entry exception preserves all constructor data and uses conflict status', function (): void {
33+
$previous = new \RuntimeException('database constraint');
34+
$exception = new HttpDuplicateEntryException(
35+
'Duplicate workspace',
36+
'workspace name already in use',
37+
['Workspace:' => 'existing-workspace'],
38+
Level::Error,
39+
$previous,
40+
);
41+
42+
expect($exception->getMessage())->toBe('Duplicate workspace')
43+
->and($exception->getCode())->toBe(409)
44+
->and($exception->getHttpStatusCode())->toBe(409)
45+
->and($exception->getResponseMessage())->toBe('workspace name already in use')
46+
->and($exception->getContext())->toBe(['Workspace:' => 'existing-workspace'])
47+
->and($exception->getLogLevel())->toBe(Level::Error)
48+
->and($exception->getPrevious())->toBe($previous);
49+
});
50+
51+
test('duplicate entry exception applies warning log level and empty context by default', function (): void {
52+
$exception = new HttpDuplicateEntryException('duplicate log', 'duplicate response');
53+
54+
expect($exception->getContext())->toBe([])
55+
->and($exception->getLogLevel())->toBe(Level::Warning)
56+
->and($exception->getPrevious())->toBeNull();
57+
});
58+
59+
test('handled invalid argument exception exposes a successful response status', function (): void {
60+
$previous = new \InvalidArgumentException('invalid input was handled');
61+
$exception = new HttpHandledInvalidArgumentAsSuccessException(
62+
'Invalid account state',
63+
'account already activated',
64+
['account' => 'user@example.test'],
65+
Level::Info,
66+
$previous,
67+
);
68+
69+
expect($exception->getMessage())->toBe('Invalid account state')
70+
->and($exception->getCode())->toBe(200)
71+
->and($exception->getHttpStatusCode())->toBe(200)
72+
->and($exception->getResponseMessage())->toBe('account already activated')
73+
->and($exception->getContext())->toBe(['account' => 'user@example.test'])
74+
->and($exception->getLogLevel())->toBe(Level::Info)
75+
->and($exception->getPrevious())->toBe($previous);
76+
});
77+
78+
test('handled invalid argument exception uses notice log level by default', function (): void {
79+
$exception = new HttpHandledInvalidArgumentAsSuccessException('handled log', 'handled response');
80+
81+
expect($exception->getLogLevel())->toBe(Level::Notice)
82+
->and($exception->getContext())->toBe([])
83+
->and($exception->getPrevious())->toBeNull();
84+
});
85+
2986
test('ping handler returns runtime information', function (): void {
3087
$response = (new PingHandler())->handle(new ServerRequest());
3188
$body = json_decode((string) $response->getBody(), true, 512, JSON_THROW_ON_ERROR);
@@ -59,5 +116,27 @@
59116
define('ROOT_DIR', dirname(__DIR__, 2) . '/');
60117
}
61118
$response = (new SwaggerUIHandler())->handle(new ServerRequest());
62-
expect($response->getStatusCode())->toBe(200)->and($response->getHeaderLine('content-type'))->toContain('text/html');
119+
$body = (string) $response->getBody();
120+
121+
expect($response)->toBeInstanceOf(HtmlResponse::class)
122+
->and($response->getStatusCode())->toBe(200)
123+
->and($response->getHeaderLine('content-type'))->toContain('text/html')
124+
->and($body)->toContain('<title>ownHackathon - SwaggerUI</title>')
125+
->and($body)->toContain('<div id="swagger-ui"></div>')
126+
->and($body)->toContain("url: 'swagger.json'")
127+
->and($body)->toContain('SwaggerUIBundle');
128+
});
129+
130+
test('swagger handler returns the same documentation for any request method', function (): void {
131+
if (!defined('ROOT_DIR')) {
132+
define('ROOT_DIR', dirname(__DIR__, 2) . '/');
133+
}
134+
135+
$handler = new SwaggerUIHandler();
136+
$getResponse = $handler->handle((new ServerRequest())->withMethod('GET'));
137+
$headResponse = $handler->handle((new ServerRequest())->withMethod('HEAD'));
138+
139+
expect((string) $getResponse->getBody())->toBe((string) $headResponse->getBody())
140+
->and($headResponse->getStatusCode())->toBe(200)
141+
->and($headResponse->getHeaderLine('content-type'))->toContain('text/html');
63142
});

0 commit comments

Comments
 (0)