PHP Classes

File: tests/ParametersTest.php

Recommend this page to a friend!
  Classes of Rodolfo Berrios Arce   Parameter   tests/ParametersTest.php   Download  
File: tests/ParametersTest.php
Role: Class source
Content type: text/plain
Description: Class source
Class: Parameter
Validate function parameters with PHP attributes
Author: By
Last change:
Date: 20 days ago
Size: 15,253 bytes
 

Contents

Class file image Download
<?php /* * This file is part of Chevere. * * (c) Rodolfo Berrios <[email protected]> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare(strict_types=1); namespace Chevere\Tests; use BadMethodCallException; use Chevere\Parameter\ArrayParameter; use Chevere\Parameter\BoolParameter; use Chevere\Parameter\FloatParameter; use Chevere\Parameter\Interfaces\ParameterInterface; use Chevere\Parameter\IntParameter; use Chevere\Parameter\IterableParameter; use Chevere\Parameter\NullParameter; use Chevere\Parameter\ObjectParameter; use Chevere\Parameter\Parameters; use Chevere\Parameter\StringParameter; use Chevere\Parameter\UnionParameter; use Chevere\Tests\src\VariadicParameters; use InvalidArgumentException; use OutOfBoundsException; use OverflowException; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use ReflectionMethod; use function Chevere\Parameter\int; use function Chevere\Parameter\reflectionToParameters; use function Chevere\Parameter\string; final class ParametersTest extends TestCase { public function testConstructEmpty(): void { $name = 'name'; $parameters = new Parameters(); $this->assertCount(0, $parameters); $this->assertCount(0, $parameters->optionalKeys()); $this->assertCount(0, $parameters->requiredKeys()); $this->assertFalse($parameters->has($name)); $this->assertFalse($parameters->isVariadic()); $this->expectException(OutOfBoundsException::class); $parameters->get($name); } public function testAssertEmpty(): void { $name = 'name'; $parameters = new Parameters(); $this->expectException(OutOfBoundsException::class); $parameters->assertHas($name); } public function testConstruct(): void { $name = 'name'; $parameter = new StringParameter(); $parameters = new Parameters(...[ $name => $parameter, ]); $this->assertCount(1, $parameters); $this->assertCount(0, $parameters->optionalKeys()); $this->assertCount(1, $parameters->requiredKeys()); $parameters->assertHas($name); $this->assertTrue($parameters->has($name)); $this->assertTrue($parameters->requiredKeys()->contains($name)); $this->assertSame($parameter, $parameters->get($name)); $this->expectException(OverflowException::class); $parameters->withRequired( $name, $parameter, ); } public function testConstructPositional(): void { $foo = string(); $bar = int(); $parameters = new Parameters($foo, $bar); $this->assertCount(2, $parameters); $this->assertTrue($parameters->has('0')); $this->assertTrue($parameters->has('1')); $this->assertSame($foo, $parameters->get('0')); $this->assertSame($bar, $parameters->get('1')); } public function testRequiredMissing(): void { $parameters = new Parameters(); $this->assertFalse($parameters->has('foo')); $this->expectException(OutOfBoundsException::class); $this->expectExceptionMessage('Key `foo` not found'); $parameters->required('foo'); } public function testOptionalMissing(): void { $parameters = new Parameters(); $this->assertFalse($parameters->has('foo')); $this->expectException(OutOfBoundsException::class); $this->expectExceptionMessage('Key `foo` not found'); $parameters->optional('foo'); } public function testRequiredCasting(): void { $parameter = string(); $parameters = new Parameters(foo: $parameter); $this->assertTrue($parameters->has('foo')); $this->assertSame($parameter, $parameters->required('foo')->string()); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Parameter `foo` is required'); $parameters->optional('foo'); } public function testRequiredCastingPositional(): void { $parameter = string(); $parameters = new Parameters($parameter); $this->assertTrue($parameters->has('0')); $this->assertSame($parameter, $parameters->required('0')->string()); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Parameter `0` is required'); $parameters->optional('0'); } public function testOptionalCasting(): void { $parameter = string(); $parameters = (new Parameters()) ->withOptional('foo', $parameter); $this->assertSame($parameter, $parameters->optional('foo')->string()); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Parameter `foo` is optional'); $parameters->required('foo'); } public function testWithRequiredOverflow(): void { $name = 'name'; $parameter = new StringParameter(); $parameters = new Parameters( ...[ $name => $parameter, ] ); $this->assertCount(1, $parameters); $this->assertCount(0, $parameters->optionalKeys()); $this->assertCount(1, $parameters->requiredKeys()); $parameters->assertHas($name); $this->assertTrue($parameters->has($name)); $this->assertTrue($parameters->requiredKeys()->contains($name)); $this->assertSame($parameter, $parameters->get($name)); $parametersWith = $parameters->withRequired('test', $parameter); $this->assertNotSame($parameters, $parametersWith); $this->expectException(OverflowException::class); $parameters->withRequired( $name, $parameter, ); } public function testWithout(): void { $parameters = (new Parameters()) ->withRequired('a', string()) ->withRequired('b', string()) ->withRequired('c', string()) ->withOptional('x', string()) ->withOptional('y', string()) ->withOptional('z', string()); $parametersWith = $parameters->without('a', 'y'); $this->assertNotSame($parameters, $parametersWith); $this->assertCount(4, $parametersWith); $this->assertSame(['b', 'c'], $parametersWith->requiredKeys()->toArray()); $this->assertSame(['x', 'z'], $parametersWith->optionalKeys()->toArray()); } public function testWithRequiredOptional(): void { $name = 'name'; $parameter = new StringParameter(); $parameters = new Parameters(); $this->assertSame(false, $parameters->isVariadic()); $parametersWith = $parameters->withOptional($name, $parameter); $this->assertNotSame($parameters, $parametersWith); $this->assertCount(1, $parametersWith); $this->assertCount(1, $parametersWith->optionalKeys()); $this->assertCount(0, $parametersWith->requiredKeys()); $this->assertTrue($parametersWith->has($name)); $this->assertTrue($parametersWith->optionalKeys()->contains($name)); $this->assertFalse($parametersWith->requiredKeys()->contains($name)); $this->assertSame($parameter, $parametersWith->get($name)); $this->expectException(OverflowException::class); $parametersWith->withOptional($name, $parameter); } public function testWithVariadicParameters(): void { $reflector = new ReflectionMethod(VariadicParameters::class, 'main'); $parameters = reflectionToParameters($reflector); $this->assertTrue($parameters->isVariadic()); $return = $parameters( _task: 'test', _priority: 2, _maxRetries: 3, foo: 'bar', bar: 'baz', ); $this->assertSame( [ '_task' => 'test', '_priority' => 2, '_maxRetries' => 3, 'foo' => 'bar', 'bar' => 'baz', ], $return->toArray() ); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage( <<<PLAIN [foo...argument]: Argument must be of type Stringable|string, true given PLAIN ); $this->expectExceptionMessage( <<<PLAIN [bar...argument]: Argument must be of type Stringable|string, int given PLAIN ); $parameters( _task: 'test', _priority: 0, _maxRetries: 0, foo: true, bar: 123, ); } public static function dataProviderGetCast(): array { return [ [new StringParameter(), 'string'], [new IntParameter(), 'int'], [new FloatParameter(), 'float'], [new BoolParameter(), 'bool'], [new ArrayParameter(), 'array'], [new ObjectParameter(), 'object'], [new NullParameter(), 'null', 'int'], ]; } #[DataProvider('dataProviderGetCast')] public function testGetCast( ParameterInterface $parameter, string $type, string $error = 'null' ): void { $name = 'test'; $parameters = new Parameters(...[ $name => $parameter, ]); $this->assertSame( $parameter, $parameters->required($name)->{$type}() ); $this->expectException(\TypeError::class); $parameters->required($name)->{$error}(); } public function testGetUnion(): void { $name = 'test'; $type1 = new StringParameter(); $type2 = new IntParameter(); $parameters = new Parameters($type1, $type2); $parameter = new UnionParameter($parameters); $parameters = new Parameters(...[ $name => $parameter, ]); $this->assertSame( $parameter, $parameters->required($name)->union() ); $this->expectException(\TypeError::class); $parameters->required($name)->null(); } public function testGetIterable(): void { $name = 'test'; $parameter = new IterableParameter( value: string(), key: int(), ); $parameters = new Parameters(...[ $name => $parameter, ]); $this->assertSame( $parameter, $parameters->required($name)->iterable() ); $this->expectException(\TypeError::class); $parameters->required($name)->null(); } public function testWithOptionalMinimum(): void { $parameters = (new Parameters())->withOptional('a', string()); $parametersWith = $parameters->withOptionalMinimum(1); $this->assertNotSame($parameters, $parametersWith); $this->assertSame(1, $parametersWith->optionalMinimum()); } public function testWithOptionalMinimumBadMethodCall(): void { $parameters = new Parameters(); $this->expectException(BadMethodCallException::class); $parameters->withOptionalMinimum(1); } public function testWithOptionalMinimumInvalidArgument(): void { $parameters = (new Parameters())->withOptional('foo', string()); $this->expectException(InvalidArgumentException::class); $parameters->withOptionalMinimum(2); } public function testWithOptionalMinimumInvalidArgumentNumber(): void { $parameters = (new Parameters())->withOptional('foo', string()); $this->expectException(InvalidArgumentException::class); $parameters->withOptionalMinimum(-1); } public function testWithOptionalMinimumWithout(): void { $parameters = (new Parameters()) ->withOptional('foo', string()) ->withOptional('bar', string()); $parametersWith = $parameters->withOptionalMinimum(1); $parametersWith = $parametersWith->without('foo'); $parametersWith = $parametersWith->withOptionalMinimum(0); $this->expectNotToPerformAssertions(); $parametersWith->without('bar'); } public function testWithOptionalMinimumWithoutInvalidArgument(): void { $parameters = (new Parameters())->withOptional('foo', string()); $parametersWith = $parameters->withOptionalMinimum(1); $this->expectException(InvalidArgumentException::class); $parametersWith->without('foo'); } public function testWithMakeOptional(): void { $parameters = new Parameters( foo: string(), bar: int() ); $parametersWith = $parameters->withMakeOptional('foo'); $this->assertNotSame($parameters, $parametersWith); $this->assertCount(2, $parametersWith); $this->assertCount(1, $parametersWith->optionalKeys()); $this->assertCount(1, $parametersWith->requiredKeys()); $this->assertTrue($parametersWith->optionalKeys()->contains('foo')); $this->assertTrue($parametersWith->requiredKeys()->contains('bar')); $this->expectException(InvalidArgumentException::class); $parametersWith->withMakeOptional('foo'); } public function testWithMakeRequired(): void { $parameters = (new Parameters()) ->withOptional('foo', string()) ->withOptional('bar', int()); $parametersWith = $parameters->withMakeRequired('bar'); $this->assertNotSame($parameters, $parametersWith); $this->assertCount(2, $parametersWith); $this->assertCount(1, $parametersWith->optionalKeys()); $this->assertCount(1, $parametersWith->requiredKeys()); $this->assertTrue($parametersWith->optionalKeys()->contains('foo')); $this->assertTrue($parametersWith->requiredKeys()->contains('bar')); $this->expectException(InvalidArgumentException::class); $parametersWith->withMakeRequired('bar'); } public function testWithMerge(): void { $foo = string(); $bar = int(); $parametersFoo = new Parameters(foo: $foo); $parametersBar = (new Parameters())->withOptional('bar', $bar); $parameters = (new Parameters(foo: $foo))->withOptional('bar', $bar); $fooWithMerge = $parametersFoo->withMerge($parametersBar); $this->assertNotSame($parametersFoo, $fooWithMerge); $this->assertEquals($parameters, $fooWithMerge); $this->assertSame(['foo'], $fooWithMerge->requiredKeys()->toArray()); $this->assertSame(['bar'], $fooWithMerge->optionalKeys()->toArray()); $barWithMerge = $parametersBar->withMerge($parametersFoo); $this->assertSame(['foo'], $barWithMerge->requiredKeys()->toArray()); $this->assertSame(['bar'], $barWithMerge->optionalKeys()->toArray()); } public function withIsVariadic(): void { $parameters = new Parameters(); $with = $parameters->withIsVariadic(true); $this->assertNotEquals($with, $parameters); $this->assertTrue($with->isVariadic()); } }