Skip to content

Commit

Permalink
Added validation exception middleware and validation test [SLE-197]
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelgfeller committed Apr 1, 2024
1 parent 20cfdbb commit 2eb03a8
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 0 deletions.
3 changes: 3 additions & 0 deletions config/middleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
// Has to be after Routing
$app->add(Selective\BasePath\BasePathMiddleware::class);

// Returns a response with validation errors
$app->add(\App\Application\Middleware\ValidationExceptionMiddleware::class);

// Handle and log notices and warnings (throws ErrorException if displayErrorDetails is true)
$app->add(\App\Application\Middleware\NonFatalErrorHandlerMiddleware::class);
// Set error handler to custom DefaultErrorHandler (defined in container.php)
Expand Down
39 changes: 39 additions & 0 deletions src/Application/Middleware/ValidationExceptionMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace App\Application\Middleware;

use App\Application\Responder\JsonEncoder;
use App\Domain\Exception\ValidationException;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

final readonly class ValidationExceptionMiddleware implements MiddlewareInterface
{
public function __construct(
private ResponseFactoryInterface $responseFactory,
private JsonEncoder $jsonEncoder,
) {
}

public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
try {
return $handler->handle($request);
} catch (ValidationException $validationException) {
// Create response (status code and header are added later)
$response = $this->responseFactory->createResponse();

$responseData = [
'status' => 'error',
'message' => $validationException->getMessage(),
// The error format is already transformed to the format that the frontend expects in the exception.
'data' => ['errors' => $validationException->validationErrors],
];

return $this->jsonEncoder->encodeAndAddToResponse($response, $responseData, 422);
}
}
}
38 changes: 38 additions & 0 deletions tests/Integration/User/UserCreateActionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,42 @@ public function testUserCreateAction(): void
// Assert that the user was created in the database
$this->assertTableRow($testUserData, 'user', $testUserData['id']);
}

public function testUserCreateActionInvalid(): void
{
// Set invalid data
$invalidUserData = [
'first_name' => 'J', // min length is 2
'last_name' => 'D', // min length is 2
'email' => 'invalid-email',
];
// Make request
$request = $this->createJsonRequest('POST', $this->urlFor('user-create'), $invalidUserData);
$response = $this->app->handle($request);

// Assert status code
self::assertSame(StatusCodeInterface::STATUS_UNPROCESSABLE_ENTITY, $response->getStatusCode());

// Assert that no database record was created
$this->assertTableRowCount(0, 'user');

// Assert that the response contains the validation error messages
$this->assertJsonData([
'status' => 'error',
'message' => 'Validation error',
'data' => [
'errors' => [
'first_name' => [
0 => 'Minimum length is 2',
],
'last_name' => [
0 => 'Minimum length is 2',
],
'email' => [
0 => 'Invalid email',
],
],
],
], $response);
}
}

0 comments on commit 2eb03a8

Please sign in to comment.