From 73814e251ad8b78c41bbb4c929cc9aea17b54d13 Mon Sep 17 00:00:00 2001 From: Fulvio Notarstefano Date: Fri, 28 Jun 2024 20:11:35 +0900 Subject: [PATCH] Ignore throws in function mocks (#245) # Summary I have noticed that in some circumstances the mocks contained in `API/function-mocks.php` could trigger false positives in static analyzers like PhpStan or just the IDE if using WP_Mock within a project. I think by removing the `@throws` solves this, although PhpStan will complain about it _in this_ project. I suppose since these are just internal mocks we can safely ignore. I did try using `@noinspection` tags but PhpStorm wasn't happy (whether specific to unhandled exceptions or not). As for the strict type notations, same reason, externally it will reflect WP behavior (the alternative was to leave non-strict and rely only on phpdoc -- like WP does -- but then PhpStan would complain again... could swap that for a phpstan-ignore again, up to you) ## Closes #248 ## Contributor checklist - [x] I agree to follow this project's [**Code of Conduct**](https://github.com/10up/.github/blob/trunk/CODE_OF_CONDUCT.md). - [x] I have updated the documentation accordingly - [x] I have added tests to cover changes introduced by this pull request - [x] All new and existing tests pass ## Testing ### Reviewer checklist - [x] Code changes review - [ ] Documentation changes review - [x] Unit tests pass - [x] Static analysis passes --- php/WP_Mock/API/function-mocks.php | 96 +++++++++++++++--------------- php/WP_Mock/Functions/Handler.php | 3 +- tests/Integration/WP_MockTest.php | 3 +- 3 files changed, 52 insertions(+), 50 deletions(-) diff --git a/php/WP_Mock/API/function-mocks.php b/php/WP_Mock/API/function-mocks.php index 72ebec0..1e74915 100644 --- a/php/WP_Mock/API/function-mocks.php +++ b/php/WP_Mock/API/function-mocks.php @@ -83,77 +83,77 @@ function apply_filters($tag, $value) if (! function_exists('esc_html')) { /** - * @return string|mixed - * @throws ExpectationFailedException|Exception + * @return string */ - function esc_html() + function esc_html() : string { + /** @phpstan-ignore-next-line to prevent flagging the function as throwing exception in codebases requiring WP_Mock */ return Handler::handlePredefinedReturnFunction(__FUNCTION__, func_get_args()); } } if (! function_exists('esc_attr')) { /** - * @return string|mixed - * @throws ExpectationFailedException|Exception + * @return string */ - function esc_attr() + function esc_attr() : string { + /** @phpstan-ignore-next-line to prevent flagging the function as throwing exception in codebases requiring WP_Mock */ return Handler::handlePredefinedReturnFunction(__FUNCTION__, func_get_args()); } } if (! function_exists('esc_url')) { /** - * @return string|mixed - * @throws ExpectationFailedException|Exception + * @return string */ - function esc_url() + function esc_url() : string { + /** @phpstan-ignore-next-line to prevent flagging the function as throwing exception in codebases requiring WP_Mock */ return Handler::handlePredefinedReturnFunction(__FUNCTION__, func_get_args()); } } if (! function_exists('esc_url_raw')) { /** - * @return string|mixed - * @throws ExpectationFailedException|Exception + * @return string */ - function esc_url_raw() + function esc_url_raw() : string { + /** @phpstan-ignore-next-line to prevent flagging the function as throwing exception in codebases requiring WP_Mock */ return Handler::handlePredefinedReturnFunction(__FUNCTION__, func_get_args()); } } if (! function_exists('esc_js')) { /** - * @return string|mixed - * @throws ExpectationFailedException|Exception + * @return string */ - function esc_js() + function esc_js() : string { + /** @phpstan-ignore-next-line to prevent flagging the function as throwing exception in codebases requiring WP_Mock */ return Handler::handlePredefinedReturnFunction(__FUNCTION__, func_get_args()); } } if (! function_exists('esc_textarea')) { /** - * @return string|mixed - * @throws ExpectationFailedException|Exception + * @return string */ - function esc_textarea() + function esc_textarea() : string { + /** @phpstan-ignore-next-line to prevent flagging the function as throwing exception in codebases requiring WP_Mock */ return Handler::handlePredefinedReturnFunction(__FUNCTION__, func_get_args()); } } if (! function_exists('__')) { /** - * @return string|mixed - * @throws ExpectationFailedException|Exception + * @return string */ - function __() + function __() : string { + /** @phpstan-ignore-next-line to prevent flagging the function as throwing exception in codebases requiring WP_Mock */ return Handler::handlePredefinedReturnFunction(__FUNCTION__, func_get_args()); } } @@ -161,32 +161,32 @@ function __() if (! function_exists('_e')) { /** * @return void - * @throws ExpectationFailedException|Exception */ - function _e(): void + function _e() : void { + /** @phpstan-ignore-next-line to prevent flagging the function as throwing exception in codebases requiring WP_Mock */ Handler::handlePredefinedEchoFunction(__FUNCTION__, func_get_args()); } } if (! function_exists('_x')) { /** - * @return string|mixed - * @throws ExpectationFailedException|Exception + * @return string */ - function _x() + function _x() : string { + /** @phpstan-ignore-next-line to prevent flagging the function as throwing exception in codebases requiring WP_Mock */ return Handler::handlePredefinedReturnFunction(__FUNCTION__, func_get_args()); } } if (! function_exists('esc_html__')) { /** - * @return string|mixed - * @throws ExpectationFailedException|Exception + * @return string */ - function esc_html__() + function esc_html__() : string { + /** @phpstan-ignore-next-line to prevent flagging the function as throwing exception in codebases requiring WP_Mock */ return Handler::handlePredefinedReturnFunction(__FUNCTION__, func_get_args()); } } @@ -194,32 +194,32 @@ function esc_html__() if (! function_exists('esc_html_e')) { /** * @return void - * @throws ExpectationFailedException|Exception */ - function esc_html_e(): void + function esc_html_e() : void { + /** @phpstan-ignore-next-line to prevent flagging the function as throwing exception in codebases requiring WP_Mock */ Handler::handlePredefinedEchoFunction(__FUNCTION__, func_get_args()); } } if (! function_exists('esc_html_x')) { /** - * @return string|mixed - * @throws ExpectationFailedException|Exception + * @return string */ - function esc_html_x() + function esc_html_x() : string { + /** @phpstan-ignore-next-line to prevent flagging the function as throwing exception in codebases requiring WP_Mock */ return Handler::handlePredefinedReturnFunction(__FUNCTION__, func_get_args()); } } if (! function_exists('esc_attr__')) { /** - * @return string|mixed - * @throws ExpectationFailedException|Exception + * @return string */ - function esc_attr__() + function esc_attr__() : string { + /** @phpstan-ignore-next-line to prevent flagging the function as throwing exception in codebases requiring WP_Mock */ return Handler::handlePredefinedReturnFunction(__FUNCTION__, func_get_args()); } } @@ -227,42 +227,44 @@ function esc_attr__() if (! function_exists('esc_attr_e')) { /** * @return void - * @throws ExpectationFailedException|Exception */ - function esc_attr_e(): void + function esc_attr_e() : void { + /** @phpstan-ignore-next-line to prevent flagging the function as throwing exception in codebases requiring WP_Mock */ Handler::handlePredefinedEchoFunction(__FUNCTION__, func_get_args()); } } if (! function_exists('esc_attr_x')) { /** - * @return string|mixed - * @throws ExpectationFailedException + * @return string */ - function esc_attr_x() + function esc_attr_x() : string { + /** @phpstan-ignore-next-line to prevent flagging the function as throwing exception in codebases requiring WP_Mock */ return Handler::handlePredefinedReturnFunction(__FUNCTION__, func_get_args()); } } if (! function_exists('_n')) { /** - * @return string|mixed singular or plural string based on number - * @throws ExpectationFailedException if too few arguments passed + * @return string */ - function _n() + function _n() : string { $args = func_get_args(); if (count($args) >= 3) { /** @phpstan-ignore-next-line */ if (isset($args[0]) && 1 >= intval($args[2])) { - return $args[0]; + /** @phpstan-ignore-next-line */ + return (string) $args[0]; } else { - return $args[1]; + /** @phpstan-ignore-next-line */ + return (string) $args[1]; } } else { + /** @phpstan-ignore-next-line to prevent flagging the function as throwing exception in codebases requiring WP_Mock */ throw new ExpectationFailedException(sprintf('Too few arguments to function %s', __FUNCTION__)); } } diff --git a/php/WP_Mock/Functions/Handler.php b/php/WP_Mock/Functions/Handler.php index bc75987..914c3ac 100644 --- a/php/WP_Mock/Functions/Handler.php +++ b/php/WP_Mock/Functions/Handler.php @@ -104,7 +104,7 @@ public static function handlePredefinedReturnFunction(string $functionName, arra * @param string $functionName function name * @param array $args function arguments * @return void - * @throws Exception|ExpectationFailedException + * @throws ExpectationFailedException */ public static function handlePredefinedEchoFunction(string $functionName, array $args = []): void { @@ -115,6 +115,7 @@ public static function handlePredefinedEchoFunction(string $functionName, array } catch (Exception $exception) { ob_end_clean(); + /** @var ExpectationFailedException $exception */ throw $exception; } diff --git a/tests/Integration/WP_MockTest.php b/tests/Integration/WP_MockTest.php index 04461fb..3af7bb3 100644 --- a/tests/Integration/WP_MockTest.php +++ b/tests/Integration/WP_MockTest.php @@ -130,7 +130,6 @@ public function providerCommonFunctionsDefaultFunctionality(): array * @preserveGlobalState disabled * * @return void - * @throws Exception */ public function testDefaultFailsInStrictMode(): void { @@ -175,7 +174,7 @@ public function testMockingOverridesDefaults(): void */ public function testBotchedMocksStillOverridesDefault(): void { - WP_Mock::userFunction('esc_html'); + WP_Mock::userFunction('esc_html')->andReturn(''); /** @phpstan-ignore-next-line function "exists" */ $this->assertEmpty(esc_html('Input'));