diff --git a/.gitignore b/.gitignore index 8dd7d04..24e4831 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /vendor/ composer.lock +.phpunit.cache .phpunit.result.cache .idea infection.log diff --git a/composer.json b/composer.json index d83d442..f98eb41 100644 --- a/composer.json +++ b/composer.json @@ -24,11 +24,12 @@ }, "require-dev": { "ext-json": "*", - "jasny/php-code-quality": "~3.0.0", + "mikey179/vfsstream": "^1.6.11", "phpstan/phpstan": "~1.12.0", - "phpunit/phpunit": "^9.6", + "phpunit/phpunit": "^11.0", "nyholm/psr7": "^1.1", - "relay/relay": "^2.0" + "relay/relay": "^2.0", + "squizlabs/php_codesniffer": "^3.10" }, "suggest": { "ext-zend-opcache": "May prevent filesystem reads" @@ -40,6 +41,7 @@ }, "autoload-dev": { "psr-4": { + "Jasny\\SwitchRoute\\Tests\\Utils\\": "tests/Utils/", "Jasny\\SwitchRoute\\Tests\\": "tests/unit/", "Jasny\\SwitchRoute\\FunctionalTests\\": "tests/functional/" } @@ -47,7 +49,7 @@ "scripts": { "test": [ "phpstan analyse", - "phpunit --testdox --colors=always", + "XDEBUG_MODE=coverage phpunit --testdox --colors=always --coverage-text", "phpcs -p src" ] }, diff --git a/phpcs.xml b/phpcs.xml index 5897613..877a071 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -1,12 +1,6 @@ - - The Jasny coding standard. - - - - - - - + + PSR-12 coding standard + diff --git a/phpstan.neon b/phpstan.neon index 9b13aac..4392422 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -2,5 +2,4 @@ parameters: level: 3 paths: - src -includes: - - vendor/phpstan/phpstan-strict-rules/rules.neon + diff --git a/phpunit.xml.dist b/phpunit.xml.dist index cbe1f43..ea7bd36 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,27 +1,17 @@ - - - - - tests/unit - - - tests/functional - - - - - src - - - - - + + + + tests/unit + + + tests/functional + + + + + + src + + - diff --git a/src/Generator.php b/src/Generator.php index fc18918..0d6f9fd 100644 --- a/src/Generator.php +++ b/src/Generator.php @@ -53,31 +53,38 @@ public function generate(string $name, string $file, callable $getRoutes, bool $ throw new \LogicException("Expected code as string, got " . gettype($code)); } - if (!is_dir(dirname($file))) { - $this->tryFs('mkdir', dirname($file), self::DIR_MODE, true); + $dir = dirname($file); + + if (!file_exists($dir)) { + $this->tryFs(fn () => mkdir($dir, self::DIR_MODE, true)); + } elseif (!is_dir($dir)) { + throw new \RuntimeException("'$dir' exists and is not a directory"); } - $this->tryFs('file_put_contents', $file, $code); + $this->tryFs(fn () => file_put_contents($file, $code)); } /** * Try a file system function and throw a \RuntimeException on failure. * * @param callable $fn - * @param mixed ...$args * @return mixed */ - protected function tryFs(callable $fn, ...$args) + protected function tryFs(callable $fn) { $level = error_reporting(); - error_reporting($level ^ (E_WARNING | E_USER_WARNING | E_NOTICE | E_USER_NOTICE)); + error_reporting($level ^ ~(E_WARNING | E_USER_WARNING | E_NOTICE | E_USER_NOTICE)); error_clear_last(); + $ret = null; + try { - $ret = $fn(...$args); + $ret = $fn(); } finally { - error_reporting($level); + if ($ret !== false) { + error_reporting($level); + } } if ($ret === false) { diff --git a/src/Generator/GenerateFunction.php b/src/Generator/GenerateFunction.php index eb9ebe7..cda196f 100644 --- a/src/Generator/GenerateFunction.php +++ b/src/Generator/GenerateFunction.php @@ -116,7 +116,7 @@ protected function generateRoute(string $key, array $route, array $vars, ?callab $invocation = $this->invoker->generateInvocation($route, $genArg, $new); } catch (ReflectionException $exception) { - throw new InvalidRouteException("Invalid route for '$key'. ". $exception->getMessage(), 0, $exception); + throw new InvalidRouteException("Invalid route for '$key'. " . $exception->getMessage(), 0, $exception); } return "return $invocation;"; diff --git a/src/Generator/GenerateInvokeMiddleware.php b/src/Generator/GenerateInvokeMiddleware.php index 4abe257..89942a9 100644 --- a/src/Generator/GenerateInvokeMiddleware.php +++ b/src/Generator/GenerateInvokeMiddleware.php @@ -195,7 +195,7 @@ function ($name, $type, $default) { ); } catch (ReflectionException $exception) { $key = preg_replace('/{.*?}/', '*', $key); - throw new InvalidRouteException("Invalid route for '$key'. ". $exception->getMessage(), 0, $exception); + throw new InvalidRouteException("Invalid route for '$key'. " . $exception->getMessage(), 0, $exception); } return "return $invocation;"; diff --git a/tests/Utils/CallbackMockTrait.php b/tests/Utils/CallbackMockTrait.php new file mode 100644 index 0000000..ec63fb1 --- /dev/null +++ b/tests/Utils/CallbackMockTrait.php @@ -0,0 +1,84 @@ + + * $callback = $this->createCallbackMock($this->once(), ['abc'], 10); + * + * + * OR + * + * + * $callback = $this->createCallbackMock( + * $this->once(), + * function(InvocationMocker $invoke) { + * $invoke->with('abc')->willReturn(10); + * } + * ); + * + * + * @param InvocationOrder $matcher + * @param \Closure|array|null $assert + * @param mixed $return + * @return MockObject|callable + */ + protected function createCallbackMock($matcher, $assert = null, $return = null): MockObject + { + if (isset($assert) && !is_array($assert) && !$assert instanceof \Closure) { + $type = (is_object($assert) ? get_class($assert) . ' ' : '') . gettype($assert); + throw new \InvalidArgumentException("Expected an array or Closure, got a $type"); + } + + $callback = $this->getMockBuilder(DummyCallback::class) + ->setMockClassName('CallbackMock_' . \substr(\md5((string) \mt_rand()), 0, 8)) + ->getMock(); + $invoke = $callback->expects($matcher)->method('__invoke'); + + if ($assert instanceof \Closure) { + $assert($invoke); + } elseif (is_array($assert)) { + $invoke->with(...$assert)->willReturn($return); + } + + return $callback; + } +} + +/** + * @internal + * @codeCoverageIgnore + */ +class DummyCallback +{ + /** + * Invoke object. + * + * @return mixed + */ + public function __invoke() + { + return null; + } +} diff --git a/tests/Utils/Consecutive.php b/tests/Utils/Consecutive.php new file mode 100644 index 0000000..5b9b1bb --- /dev/null +++ b/tests/Utils/Consecutive.php @@ -0,0 +1,69 @@ +with(...Consecutive::create(...$withCodes)) + */ + +declare(strict_types=1); + +namespace Jasny\SwitchRoute\Tests\Utils; + +use PHPUnit\Framework\Assert; +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\Constraint\IsEqual; +use RuntimeException; + +class Consecutive +{ + public static function create(...$parameterGroups): array + { + $result = []; + $parametersCount = null; + $groups = []; + $values = []; + + foreach ($parameterGroups as $index => $parameters) { + // initial + $parametersCount ??= count($parameters); + + // compare + if ($parametersCount !== count($parameters)) { + throw new RuntimeException('Parameters count max much in all groups'); + } + + // prepare parameters + foreach ($parameters as $parameter) { + if (!$parameter instanceof Constraint) { + $parameter = new IsEqual($parameter); + } + + $groups[$index][] = $parameter; + } + } + + // collect values + foreach ($groups as $parameters) { + foreach ($parameters as $index => $parameter) { + $values[$index][] = $parameter; + } + } + + // build callback + for ($index = 0; $index < $parametersCount; ++$index) { + $result[$index] = Assert::callback(static function ($value) use ($values, $index) { + static $map = null; + $map ??= $values[$index]; + + $expectedArg = array_shift($map); + if ($expectedArg === null) { + throw new RuntimeException('No more expected calls'); + } + $expectedArg->evaluate($value); + + return true; + }); + } + + return $result; + } +} diff --git a/tests/functional/FunctionTest.php b/tests/functional/FunctionTest.php index 7381695..5962265 100644 --- a/tests/functional/FunctionTest.php +++ b/tests/functional/FunctionTest.php @@ -8,16 +8,13 @@ use Jasny\SwitchRoute\Invoker; use org\bovigo\vfs\vfsStream; use org\bovigo\vfs\vfsStreamDirectory; +use PHPUnit\Framework\Attributes\CoversNothing; +use PHPUnit\Framework\Attributes\DataProvider; -/** - * @coversNothing - */ +#[CoversNothing] class FunctionTest extends TestCase { - /** - * @var vfsStreamDirectory - */ - protected static $root; + protected static ?vfsStreamDirectory $root; public static function setUpBeforeClass(): void { @@ -46,9 +43,7 @@ public static function tearDownAfterClass(): void self::$root = null; } - /** - * @dataProvider provider - */ + #[DataProvider('provider')] public function test(string $method, string $path, $expected) { $fn = \Closure::fromCallable(__NAMESPACE__ . '\\route'); diff --git a/tests/functional/MiddlewareTest.php b/tests/functional/MiddlewareTest.php index 2fd8374..2db8318 100644 --- a/tests/functional/MiddlewareTest.php +++ b/tests/functional/MiddlewareTest.php @@ -11,45 +11,24 @@ use Nyholm\Psr7\Factory\Psr17Factory as HttpFactory; use org\bovigo\vfs\vfsStream; use org\bovigo\vfs\vfsStreamDirectory; +use PHPUnit\Framework\Attributes\CoversNothing; +use PHPUnit\Framework\Attributes\DataProvider; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; use Relay\Relay; -/** - * @coversNothing - */ +#[CoversNothing] class MiddlewareTest extends TestCase { - /** - * @var vfsStreamDirectory - */ - protected static $root; + protected static ?vfsStreamDirectory $root; - /** - * @var string - */ - protected static $namespace; + protected static string $namespace; + protected static string $file; - /** - * @var string - */ - protected static $file; - - /** - * @var MiddlewareInterface - */ - protected $routeMiddleware; - - /** - * @var NotFoundMiddleware - */ - protected $notFoundMiddleware; - - /** - * @var MiddlewareInterface - */ - protected $invokeMiddleware; + protected MiddlewareInterface $routeMiddleware; + protected NotFoundMiddleware $notFoundMiddleware; + protected MiddlewareInterface $invokeMiddleware; public static function setUpBeforeClass(): void @@ -114,9 +93,7 @@ public function setUp(): void $this->invokeMiddleware = new $invokeMiddlewareClass($instantiate); } - /** - * @dataProvider provider - */ + #[DataProvider('provider')] public function test(string $method, string $path, $expected, $expectedStatus = 200) { $relay = new Relay([$this->routeMiddleware, $this->notFoundMiddleware, $this->invokeMiddleware]); diff --git a/tests/functional/TestCase.php b/tests/functional/TestCase.php index 72d5891..490030c 100644 --- a/tests/functional/TestCase.php +++ b/tests/functional/TestCase.php @@ -8,12 +8,12 @@ abstract class TestCase extends Base { - protected $users = [ + protected static array $users = [ 1 => ['id' => 1, 'name' => 'joe', 'email' => 'joe@example.com'], 2 => ['id' => 2, 'name' => 'jane', 'email' => 'jane@example.com'], ]; - protected $photos = [ + protected static array $photos = [ 1 => [ ['id' => 11, 'name' => 'sunrise'], ['id' => 12, 'name' => 'sunset'], @@ -45,21 +45,21 @@ public static function getRoutes(): array ]; } - public function provider() + public static function provider(): array { return [ 'GET /' => ['GET', '/', "Some information"], - 'GET /users' => ['GET', '/users', array_values($this->users)], + 'GET /users' => ['GET', '/users', array_values(self::$users)], 'POST /users' => ['POST', '/users', "added user"], - 'GET /users/1' => ['GET', '/users/1', $this->users[1]], - 'GET /users/2' => ['GET', '/users/2', $this->users[2]], + 'GET /users/1' => ['GET', '/users/1', self::$users[1]], + 'GET /users/2' => ['GET', '/users/2', self::$users[2]], 'POST /users/1' => ['POST', '/users/1', "updated user '1'"], 'PUT /users/1' => ['PUT', '/users/1', "updated user '1'"], 'DELETE /users/1' => ['DELETE', '/users/2', "deleted user '2'"], - 'GET /users/1/photos' => ['GET', '/users/1/photos', $this->photos[1]], - 'GET /users/2/photos' => ['GET', '/users/2/photos', $this->photos[2]], + 'GET /users/1/photos' => ['GET', '/users/1/photos', self::$photos[1]], + 'GET /users/2/photos' => ['GET', '/users/2/photos', self::$photos[2]], 'POST /users/1/photos' => ['POST', '/users/1/photos', "added photos for user 1"], 'POST /export' => ['POST', '/export', ['data', 'export']], @@ -69,9 +69,9 @@ public function provider() 'PATCH /users/1 (405)' => ['PATCH', '/users/1', "405 Method Not Allowed (GET, POST, PUT, DELETE)", 405], // Test with trailing slash - 'GET /users/' => ['GET', '/users/', array_values($this->users)], - 'GET /users/2/' => ['GET', '/users/2/', $this->users[2]], - 'GET /users/2/photos/' => ['GET', '/users/2/photos/', $this->photos[2]], + 'GET /users/' => ['GET', '/users/', array_values(self::$users)], + 'GET /users/2/' => ['GET', '/users/2/', self::$users[2]], + 'GET /users/2/photos/' => ['GET', '/users/2/photos/', self::$photos[2]], ]; } } diff --git a/tests/unit/EndpointTest.php b/tests/unit/EndpointTest.php index abec98b..7552599 100644 --- a/tests/unit/EndpointTest.php +++ b/tests/unit/EndpointTest.php @@ -4,15 +4,14 @@ namespace Jasny\SwitchRoute\Tests; -use Exception; use Jasny\SwitchRoute\Endpoint; use Jasny\SwitchRoute\InvalidRouteException; use OutOfBoundsException; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; -/** - * @covers \Jasny\SwitchRoute\Endpoint - */ +#[CoversClass(Endpoint::class)] class EndpointTest extends TestCase { public function testGetPath() @@ -22,7 +21,7 @@ public function testGetPath() $this->assertEquals('/users/*', $endpoint->getPath()); } - public function methodProvider() + public static function methodProvider() { return [ 'upper case' => ['GET', 'POST', 'PATCH'], @@ -31,9 +30,7 @@ public function methodProvider() ]; } - /** - * @dataProvider methodProvider - */ + #[DataProvider('methodProvider')] public function testWithRoute($method) { $endpoint = new Endpoint('/users/*'); @@ -49,9 +46,7 @@ public function testWithRoute($method) $this->assertEquals([], $endpoint->getRoutes()); } - /** - * @dataProvider methodProvider - */ + #[DataProvider('methodProvider')] public function testWithRouteWithDuplicateMethod($method) { $this->expectException(InvalidRouteException::class); @@ -90,9 +85,7 @@ public function testGetRoutes() $this->assertEquals($expected, $endpoint->getRoutes()); } - /** - * @dataProvider methodProvider - */ + #[DataProvider('methodProvider')] public function testGetVars($get, $post, $patch) { $endpoint = (new Endpoint('/users/*/*')) diff --git a/tests/unit/ExtendTest.php b/tests/unit/ExtendTest.php index 512d5e2..90516d3 100644 --- a/tests/unit/ExtendTest.php +++ b/tests/unit/ExtendTest.php @@ -50,7 +50,7 @@ public function testExtendedGenerator() $this->assertFalse($scriptExists); /** tryFs */ - $tryFsResult = $extendedGenerator->callTryFs('disk_free_space', '.'); + $tryFsResult = $extendedGenerator->callTryFs(fn () => disk_free_space('.')); $this->assertIsFloat($tryFsResult); } @@ -261,9 +261,9 @@ public function callScriptExists(string $file): bool return $this->scriptExists($file); } - public function callTryFs(callable $fn, ...$args) + public function callTryFs(callable $fn) { - return $this->tryFs($fn, ...$args); + return $this->tryFs($fn); } }; } diff --git a/tests/unit/Generator/GenerateFunctionTest.php b/tests/unit/Generator/GenerateFunctionTest.php index d597470..83819bd 100644 --- a/tests/unit/Generator/GenerateFunctionTest.php +++ b/tests/unit/Generator/GenerateFunctionTest.php @@ -6,17 +6,18 @@ use Closure; use Jasny\SwitchRoute\Endpoint; +use Jasny\SwitchRoute\Generator\AbstractGenerate; +use Jasny\SwitchRoute\Tests\Utils\Consecutive; use Jasny\SwitchRoute\Generator\GenerateFunction; use Jasny\SwitchRoute\InvalidRouteException; use Jasny\SwitchRoute\Invoker; use Jasny\SwitchRoute\Tests\RoutesTrait; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use ReflectionException; -/** - * @covers \Jasny\SwitchRoute\Generator\GenerateFunction - * @covers \Jasny\SwitchRoute\Generator\AbstractGenerate - */ +#[CoversClass(GenerateFunction::class)] +#[CoversClass(AbstractGenerate::class)] class GenerateFunctionTest extends TestCase { use RoutesTrait; @@ -24,7 +25,6 @@ class GenerateFunctionTest extends TestCase protected function getRouteArgs() { $routes = $this->getRoutes(); - $notFound = null; $routeArgs = []; $isClosure = $this->isInstanceOf(Closure::class); @@ -53,7 +53,7 @@ public function testGenerate() $invoker = $this->createMock(Invoker::class); $invoker->expects($this->exactly(count($routeArgs)))->method('generateInvocation') - ->withConsecutive(...$routeArgs) + ->with(...Consecutive::create(...$routeArgs)) ->willReturnCallback(function ($route, callable $genArg) { ['controller' => $controller, 'action' => $action] = $route + ['controller' => null, 'action' => null]; $arg = $action !== 'NotFoundAction' ? $genArg('id', '', null) : $genArg('allowedMethods', '', []); diff --git a/tests/unit/Generator/GenerateInvokeMiddlewareTest.php b/tests/unit/Generator/GenerateInvokeMiddlewareTest.php index e827b9c..941dd59 100644 --- a/tests/unit/Generator/GenerateInvokeMiddlewareTest.php +++ b/tests/unit/Generator/GenerateInvokeMiddlewareTest.php @@ -10,15 +10,16 @@ use Jasny\SwitchRoute\InvalidRouteException; use Jasny\SwitchRoute\Invoker; use Jasny\SwitchRoute\Tests\RoutesTrait; +use Jasny\SwitchRoute\Tests\Utils\Consecutive; use Nyholm\Psr7\ServerRequest; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; use ReflectionException; -/** - * @covers \Jasny\SwitchRoute\Generator\GenerateInvokeMiddleware - * @covers \Jasny\SwitchRoute\Generator\AbstractGenerate - */ +#[CoversClass(\Jasny\SwitchRoute\Generator\GenerateInvokeMiddleware::class)] +#[CoversClass(\Jasny\SwitchRoute\Generator\AbstractGenerate::class)] class GenerateInvokeMiddlewareTest extends TestCase { use RoutesTrait; @@ -41,7 +42,7 @@ protected function getRouteArgs() return $routeArgs; } - public function serverRequestProvider() + public static function serverRequestProvider() { return [ ServerRequestInterface::class => [ServerRequestInterface::class], @@ -49,9 +50,7 @@ public function serverRequestProvider() ]; } - /** - * @dataProvider serverRequestProvider - */ + #[DataProvider('serverRequestProvider')] public function testGenerate(string $serverRequestClass) { $routes = $this->getRoutes(); @@ -60,7 +59,7 @@ public function testGenerate(string $serverRequestClass) $invoker = $this->createMock(Invoker::class); $invoker->expects($this->exactly(count($routeArgs)))->method('generateInvocation') - ->withConsecutive(...$routeArgs) + ->with(...Consecutive::create(...$routeArgs)) ->willReturnCallback(function ($route, callable $genArg) use ($serverRequestClass) { ['controller' => $controller, 'action' => $action] = $route; $request = $genArg('request', $serverRequestClass, null); diff --git a/tests/unit/Generator/GenerateRouteMiddlewareTest.php b/tests/unit/Generator/GenerateRouteMiddlewareTest.php index 0c49eb8..c573ad2 100644 --- a/tests/unit/Generator/GenerateRouteMiddlewareTest.php +++ b/tests/unit/Generator/GenerateRouteMiddlewareTest.php @@ -5,14 +5,14 @@ namespace Jasny\SwitchRoute\Tests\Generator; use Jasny\SwitchRoute\Endpoint; +use Jasny\SwitchRoute\Generator\AbstractGenerate; use Jasny\SwitchRoute\Generator\GenerateRouteMiddleware; use Jasny\SwitchRoute\Tests\RoutesTrait; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; -/** - * @covers \Jasny\SwitchRoute\Generator\GenerateRouteMiddleware - * @covers \Jasny\SwitchRoute\Generator\AbstractGenerate - */ +#[CoversClass(GenerateRouteMiddleware::class)] +#[CoversClass(AbstractGenerate::class)] class GenerateRouteMiddlewareTest extends TestCase { use RoutesTrait; diff --git a/tests/unit/GeneratorTest.php b/tests/unit/GeneratorTest.php index c6b38f4..f095ccb 100644 --- a/tests/unit/GeneratorTest.php +++ b/tests/unit/GeneratorTest.php @@ -6,16 +6,15 @@ use Jasny\SwitchRoute\Generator; use Jasny\SwitchRoute\InvalidRouteException; -use Jasny\PHPUnit\CallbackMockTrait; +use Jasny\SwitchRoute\Tests\Utils\CallbackMockTrait; use LogicException; use org\bovigo\vfs\vfsStream; use org\bovigo\vfs\vfsStreamDirectory; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use RuntimeException; -/** - * @covers \Jasny\SwitchRoute\Generator - */ +#[CoversClass(Generator::class)] class GeneratorTest extends TestCase { use CallbackMockTrait; @@ -125,7 +124,7 @@ public function testGenerateWithUnexpectedReturnValue() public function testGenerateCreateDirFailure() { $this->expectException(RuntimeException::class); - $this->expectExceptionMessage("mkdir(): Path vfs://tmp/generated exists"); + $this->expectExceptionMessage("'vfs://tmp/generated' exists and is not a directory"); vfsStream::create([ 'generated' => 'test' diff --git a/tests/unit/InvokerTest.php b/tests/unit/InvokerTest.php index 3356e15..cccca7a 100644 --- a/tests/unit/InvokerTest.php +++ b/tests/unit/InvokerTest.php @@ -7,8 +7,11 @@ use BadMethodCallException; use Jasny\ReflectionFactory\ReflectionFactory; use Jasny\SwitchRoute\Invoker; -use Jasny\PHPUnit\CallbackMockTrait; +use Jasny\SwitchRoute\Tests\Utils\CallbackMockTrait; +use Jasny\SwitchRoute\Tests\Utils\Consecutive; use LogicException; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\Builder\InvocationMocker; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -18,9 +21,7 @@ use ReflectionParameter; use ReflectionType; -/** - * @covers \Jasny\SwitchRoute\Invoker - */ +#[CoversClass(Invoker::class)] class InvokerTest extends TestCase { use CallbackMockTrait; @@ -48,7 +49,7 @@ protected function createReflectionFactoryMock($invokable, $isStatic, $parameter } - public function invokableProvider() + public static function invokableProvider() { return [ "FooController::toDoAction" => [ @@ -72,9 +73,7 @@ public function invokableProvider() ]; } - /** - * @dataProvider invokableProvider - */ + #[DataProvider('invokableProvider')] public function testGenerate($controller, $action, $invokable, $expected) { $reflectionFactory = $this->createReflectionFactoryMock($invokable, false, []); @@ -86,9 +85,7 @@ public function testGenerate($controller, $action, $invokable, $expected) $this->assertEquals(sprintf($expected, ''), $code); } - /** - * @dataProvider invokableProvider - */ + #[DataProvider('invokableProvider')] public function testGenerateWithoutNullKeys($controller, $action, $invokable, $expected) { $reflectionFactory = $this->createReflectionFactoryMock($invokable, false, []); @@ -100,9 +97,7 @@ public function testGenerateWithoutNullKeys($controller, $action, $invokable, $e $this->assertEquals(sprintf($expected, ''), $code); } - /** - * @dataProvider invokableProvider - */ + #[DataProvider('invokableProvider')] public function testGenerateWithArguments($controller, $action, $invokable, $expected) { $expectedCode = sprintf($expected, "\$var['id'] ?? NULL, \$var['some'] ?? NULL, \$var['good'] ?? 'ok'"); @@ -127,7 +122,7 @@ public function testGenerateWithArguments($controller, $action, $invokable, $exp $genArg = $this->createCallbackMock($this->exactly(3), function (InvocationMocker $invoke) { $invoke - ->withConsecutive(['id', null, null], ['some', null, null], ['good', 'string', 'ok']) + ->with(...Consecutive::create(['id', null, null], ['some', null, null], ['good', 'string', 'ok'])) ->willReturnOnConsecutiveCalls("\$var['id'] ?? NULL", "\$var['some'] ?? NULL", "\$var['good'] ?? 'ok'"); }); @@ -152,9 +147,7 @@ public function testGenerateOfStaticMethod() $this->assertEquals("\FooController::barAction(\$var['id'] ?? NULL)", $code); } - /** - * @dataProvider invokableProvider - */ + #[DataProvider('invokableProvider')] public function testGenerateWithNamespace($controller, $action, $invokable, $expected) { $invokable[0] = 'App\\Generated\\' . $invokable[0]; @@ -218,7 +211,7 @@ public function testGenerateWithMethodString() $this->assertEquals("(new \\App\\Foo)->toDo(\$var['id'] ?? NULL)", $code); } - public function invalidInvokerProvider() + public static function invalidInvokerProvider() { $closure = function () { }; @@ -234,9 +227,7 @@ public function invalidInvokerProvider() ]; } - /** - * @dataProvider invalidInvokerProvider - */ + #[DataProvider('invalidInvokerProvider')] public function testGenerateWithInvalidInvoker($invoker, $type) { $this->expectException(LogicException::class); @@ -289,9 +280,7 @@ public function testGenerateDefault() $this->assertEquals($expected, $invoker->generateDefault()); } - /** - * @dataProvider invokableProvider - */ + #[DataProvider('invokableProvider')] public function testCreateInvokable($controller, $action, $expected) { $invokable = Invoker::createInvokable($controller, $action); diff --git a/tests/unit/NoInvokerTest.php b/tests/unit/NoInvokerTest.php index eb9ee9d..6300986 100644 --- a/tests/unit/NoInvokerTest.php +++ b/tests/unit/NoInvokerTest.php @@ -5,13 +5,11 @@ namespace Jasny\SwitchRoute\Tests; use Jasny\SwitchRoute\NoInvoker; -use Jasny\PHPUnit\CallbackMockTrait; +use Jasny\SwitchRoute\Tests\Utils\CallbackMockTrait; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; -/** - * @covers \Jasny\SwitchRoute\NoInvoker - */ -class NoInvokerTest extends TestCase +#[CoversClass(NoInvoker::class)] class NoInvokerTest extends TestCase { use CallbackMockTrait; diff --git a/tests/unit/NotFoundMiddlewareTest.php b/tests/unit/NotFoundMiddlewareTest.php index b9df88b..57094ce 100644 --- a/tests/unit/NotFoundMiddlewareTest.php +++ b/tests/unit/NotFoundMiddlewareTest.php @@ -6,6 +6,8 @@ use Jasny\SwitchRoute\NotFoundException; use Jasny\SwitchRoute\NotFoundMiddleware; +use Jasny\SwitchRoute\Tests\Utils\Consecutive; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ResponseFactoryInterface; use Psr\Http\Message\ResponseInterface; @@ -13,9 +15,7 @@ use Psr\Http\Message\StreamInterface; use Psr\Http\Server\RequestHandlerInterface; -/** - * @covers \Jasny\SwitchRoute\NotFoundMiddleware - */ +#[CoversClass(NotFoundMiddleware::class)] class NotFoundMiddlewareTest extends TestCase { public function testFound() @@ -80,10 +80,7 @@ public function testMethodNotAllowed() $responseBody = $this->createMock(StreamInterface::class); $response = $this->createMock(ResponseInterface::class); $response->expects($this->exactly(2))->method('withHeader') - ->withConsecutive( - ['Content-Type', 'text/plain'], - ['Allow', 'GET, POST'] - ) + ->with(...Consecutive::create(['Content-Type', 'text/plain'], ['Allow', 'GET, POST'])) ->willReturnSelf(); $response->expects($this->once())->method('getBody')->willReturn($responseBody); $responseBody->expects($this->once())->method('write')->with('Method Not Allowed');