Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/exception/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,9 @@ enum Message: string
/**
* Error when the page is not found.
*
* Format: "Page not found."
* Format: "Page not found in StatelessApplication."
*/
case PAGE_NOT_FOUND = 'Page not found.';
case PAGE_NOT_FOUND = 'Page not found in StatelessApplication.';

/**
* Error when the PSR-7 request adapter is not set.
Expand Down
130 changes: 52 additions & 78 deletions tests/http/stateless/ApplicationErrorHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
use yii\base\{Exception, InvalidConfigException};
use yii\helpers\Json;
use yii\log\{FileTarget, Logger};
use yii\web\NotFoundHttpException;
use yii2\extensions\psrbridge\exception\Message;
use yii2\extensions\psrbridge\http\Response;
use yii2\extensions\psrbridge\tests\provider\StatelessApplicationProvider;
use yii2\extensions\psrbridge\tests\support\FactoryHelper;
Expand Down Expand Up @@ -48,11 +46,6 @@ public function testErrorViewLogic(
): void {
@\runkit_constant_redefine('YII_DEBUG', $debug);

$_SERVER = [
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => $route,
];

$app = $this->statelessApplication(
[
'components' => [
Expand All @@ -61,7 +54,7 @@ public function testErrorViewLogic(
],
);

$response = $app->handle(FactoryHelper::createServerRequestCreator()->createFromGlobals());
$response = $app->handle(FactoryHelper::createRequest('GET', $route));

self::assertSame(
$expectedStatusCode,
Expand Down Expand Up @@ -173,11 +166,6 @@ public function testFiltersSensitiveServerVariablesInFallbackExceptionMessage():
*/
public function testLogExceptionIsCalledWhenHandlingException(): void
{
$_SERVER = [
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => 'site/trigger-exception',
];

$app = $this->statelessApplication(
[
'flushLogger' => false,
Expand All @@ -196,7 +184,7 @@ public function testLogExceptionIsCalledWhenHandlingException(): void
],
);

$response = $app->handle(FactoryHelper::createServerRequestCreator()->createFromGlobals());
$response = $app->handle(FactoryHelper::createRequest('GET', '/site/trigger-exception'));

self::assertSame(
500,
Expand Down Expand Up @@ -238,7 +226,7 @@ public function testLogExceptionIsCalledWhenHandlingException(): void
self::assertTrue(
$exceptionLogFound,
"Logger should contain an error log entry with category '{$expectedCategory}' and message " .
"'Exception error message.' when 'logException()' is called during exception handling.",
"'Exception error message'.",
);
self::assertFalse(
$app->flushLogger,
Expand All @@ -256,11 +244,6 @@ public function testRenderExceptionPassesExceptionParameterToTemplateView(): voi

$initialBufferLevel = ob_get_level();

$_SERVER = [
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => 'site/trigger-exception',
];

$warningsCaptured = [];

set_error_handler(
Expand All @@ -287,7 +270,7 @@ static function ($errno, $errstr, $errfile, $errline) use (&$warningsCaptured):
],
);

$response = $app->handle(FactoryHelper::createServerRequestCreator()->createFromGlobals());
$response = $app->handle(FactoryHelper::createRequest('GET', '/site/trigger-exception'));

self::assertSame(
500,
Expand All @@ -307,33 +290,30 @@ static function ($errno, $errstr, $errfile, $errline) use (&$warningsCaptured):

self::assertEmpty(
$undefinedExceptionWarnings,
"Should be no 'Undefined variable' warnings, confirming that exception parameter is defined in the " .
'view context when rendering exception.',
"Should be no 'Undefined variable' warnings.",
);

$responseBody = $response->getBody()->getContents();

self::assertStringContainsString(
Exception::class,
$responseBody,
"Response body should contain exception class when exception parameter is passed to 'renderFile()'.",
'Response body should contain exception class.',
);
self::assertStringContainsString(
'Stack trace:',
$responseBody,
"Response body should contain 'Stack trace:' section, confirming exception object is available to template.",
"Response body should contain 'Stack trace:' section.",
);
self::assertStringContainsString(
'Exception error message.',
$responseBody,
"Response body should contain the exact exception message 'Exception error message.', confirming " .
'the exception object was properly passed to the view.',
"Response body should contain the exact exception message 'Exception error message.'.",
);
self::assertStringContainsString(
'SiteController.php',
$responseBody,
"Response body should contain reference to 'SiteController.php' where the exception was throw, " .
'confirming full exception details are available in the view.',
"Response body should contain reference to 'SiteController.php'.",
);
} finally {
restore_error_handler();
Expand All @@ -359,11 +339,6 @@ public function testRenderExceptionWithDifferentFormats(
string $route,
array $expectedContent,
): void {
$_SERVER = [
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => $route,
];

$app = $this->statelessApplication(
[
'components' => [
Expand All @@ -373,7 +348,7 @@ public function testRenderExceptionWithDifferentFormats(
],
);

$response = $app->handle(FactoryHelper::createServerRequestCreator()->createFromGlobals());
$response = $app->handle(FactoryHelper::createRequest('GET', $route));

self::assertSame(
$expectedStatusCode,
Expand Down Expand Up @@ -432,22 +407,15 @@ public function testRenderExceptionWithErrorActionReturningResponseObject(): voi
{
@\runkit_constant_redefine('YII_DEBUG', false);

$_SERVER = [
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => 'site/trigger-exception',
];

$app = $this->statelessApplication(
[
'components' => [
'errorHandler' => [
'errorAction' => 'site/error-with-response',
],
'errorHandler' => ['errorAction' => 'site/error-with-response'],
],
],
);

$response = $app->handle(FactoryHelper::createServerRequestCreator()->createFromGlobals());
$response = $app->handle(FactoryHelper::createRequest('GET', '/site/trigger-exception'));

self::assertSame(
500,
Expand All @@ -468,7 +436,7 @@ public function testRenderExceptionWithErrorActionReturningResponseObject(): voi
HTML,
),
self::normalizeLineEndings($response->getBody()->getContents()),
"Response body should contain content from Response object returned by 'errorAction'.",
'Response body should contain content from Response object.',
);

@\runkit_constant_redefine('YII_DEBUG', true);
Expand All @@ -479,11 +447,6 @@ public function testRenderExceptionWithErrorActionReturningResponseObject(): voi
*/
public function testReturnHtmlErrorResponseWhenErrorHandlerActionIsInvalid(): void
{
$_SERVER = [
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => 'site/nonexistent-action',
];

$app = $this->statelessApplication(
[
'components' => [
Expand All @@ -492,7 +455,7 @@ public function testReturnHtmlErrorResponseWhenErrorHandlerActionIsInvalid(): vo
],
);

$response = $app->handle(FactoryHelper::createServerRequestCreator()->createFromGlobals());
$response = $app->handle(FactoryHelper::createRequest('GET', '/site/nonexistent-action'));

self::assertSame(
500,
Expand All @@ -512,8 +475,7 @@ public function testReturnHtmlErrorResponseWhenErrorHandlerActionIsInvalid(): vo
HTML,
),
self::normalizeLineEndings($response->getBody()->getContents()),
"Response body should contain error message about 'An Error occurred while handling another error' and " .
'the InvalidRouteException when errorHandler action is invalid.',
"Response body should contain error message about 'An Error occurred while handling another error'.",
);
}

Expand All @@ -522,14 +484,9 @@ public function testReturnHtmlErrorResponseWhenErrorHandlerActionIsInvalid(): vo
*/
public function testThrowableOccursDuringRequestHandling(): void
{
$_SERVER = [
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => 'nonexistent/invalidaction',
];

$app = $this->statelessApplication();

$response = $app->handle(FactoryHelper::createServerRequestCreator()->createFromGlobals());
$response = $app->handle(FactoryHelper::createRequest('GET', '/nonexistent/invalidaction'));

self::assertSame(
404,
Expand All @@ -544,8 +501,7 @@ public function testThrowableOccursDuringRequestHandling(): void
self::assertStringContainsString(
'<pre>Not Found: Page not found.</pre>',
$response->getBody()->getContents(),
"Response body should contain error message about 'Not Found: Page not found' when Throwable occurs " .
'during request handling.',
"Response body should contain error message about 'Not Found: Page not found'.",
);
}

Expand All @@ -554,14 +510,9 @@ public function testThrowableOccursDuringRequestHandling(): void
*/
public function testThrowNotFoundHttpExceptionWhenStrictParsingDisabledAndRouteIsMissing(): void
{
$_SERVER = [
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => 'site/profile/123',
];

$app = $this->statelessApplication();

$response = $app->handle(FactoryHelper::createServerRequestCreator()->createFromGlobals());
$response = $app->handle(FactoryHelper::createRequest('GET', '/site/profile/123'));

self::assertSame(
404,
Expand All @@ -576,34 +527,57 @@ public function testThrowNotFoundHttpExceptionWhenStrictParsingDisabledAndRouteI
self::assertStringContainsString(
'<pre>Not Found: Page not found.</pre>',
$response->getBody()->getContents(),
"Response body should contain the default not found message '<pre>Not Found: Page not found.</pre>' " .
'when a NotFoundHttpException is thrown.',
"Response body should contain the default not found message '<pre>Not Found: Page not found.</pre>'.",
);
}

/**
* @throws InvalidConfigException if the configuration is invalid or incomplete.
*/
#[RequiresPhpExtension('runkit7')]
public function testThrowNotFoundHttpExceptionWhenStrictParsingEnabledAndRouteIsMissing(): void
{
$_SERVER = [
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => 'site/profile/123',
];
@\runkit_constant_redefine('YII_ENV_TEST', false);

$initialBufferLevel = ob_get_level();

$app = $this->statelessApplication(
[
'components' => [
'urlManager' => ['enableStrictParsing' => true],
'errorHandler' => ['errorAction' => null],
'response' => ['format' => Response::FORMAT_JSON],
'urlManager' => [
'enableStrictParsing' => true,
'rules' => [],
],
],
],
);

$app->handle(FactoryHelper::createServerRequestCreator()->createFromGlobals());
$response = $app->handle(FactoryHelper::createRequest('GET', '/site/profile/123'));

$this->expectException(NotFoundHttpException::class);
$this->expectExceptionMessage(Message::PAGE_NOT_FOUND->getMessage());
self::assertSame(
404,
$response->getStatusCode(),
"Expected HTTP '404' for route 'site/profile/123'.",
);
self::assertSame(
'application/json; charset=UTF-8',
$response->getHeaderLine('Content-Type'),
"Expected Content-Type 'application/json; charset=UTF-8' for route 'site/profile/123'.",
);
self::assertJsonStringEqualsJsonString(
<<<JSON
{"name":"Not Found","message":"Page not found in StatelessApplication.","code":0,"status":404,"type":"yii\\\\web\\\\NotFoundHttpException"}
JSON,
$response->getBody()->getContents(),
'Response body should contain JSON with NotFoundHttpException details.',
);

while (ob_get_level() < $initialBufferLevel) {
ob_start();
}

$app->request->resolve();
@\runkit_constant_redefine('YII_ENV_TEST', true);
}
}
12 changes: 5 additions & 7 deletions tests/http/stateless/ApplicationRoutingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ public function testHandlePostParameters(): void
{"foo":"bar","a":{"b":"c"}}
JSON,
$response->getBody()->getContents(),
"Response body should match expected JSON string '{\"foo\":\"bar\",\"a\":{\"b\":\"c\"}}' for " .
"'site/post' route.",
"Response body should match expected JSON string '{\"foo\":\"bar\",\"a\":{\"b\":\"c\"}}'.",
);
}

Expand Down Expand Up @@ -80,8 +79,7 @@ public function testHandleQueryParameters(): void
{"foo":"bar","a":{"b":"c"}}
JSON,
$response->getBody()->getContents(),
"Response body should match expected JSON string '{\"foo\":\"bar\",\"a\":{\"b\":\"c\"}}' for " .
"'site/get' route.",
"Response body should match expected JSON string '{\"foo\":\"bar\",\"a\":{\"b\":\"c\"}}'.",
);
}

Expand Down Expand Up @@ -114,7 +112,7 @@ public function testHandleRouteAndQueryParameters(): void
{"test":"foo","q":"1","queryParams":{"test":"foo","q":"1"}}
JSON,
$response->getBody()->getContents(),
"Response body should contain valid JSON with route and query parameters for 'site/query/foo?q=1' route.",
'Response body should contain valid JSON with route and query parameters.',
);
}

Expand Down Expand Up @@ -142,12 +140,12 @@ public function testHandleRouteParameters(): void
self::assertSame(
'{"site/update":"123"}',
$response->getBody()->getContents(),
"Response body should contain valid JSON with the route parameter for 'site/update/123' route.",
'Response body should contain valid JSON with the route parameter.',
);
self::assertSame(
'site/update/123',
$request->getUri()->getPath(),
"Request path should be 'site/update/123' for 'site/update/123' route.",
"Request path should be 'site/update/123'.",
);
}
}
Loading