diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e230c9ba..b611f472 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -7,6 +7,7 @@ docs/ @JoshuaEstes /src/SonsOfPHP/Bard @JoshuaEstes # Each component/contract needs a Team +/src/SonsOfPHP/**/Assert @JoshuaEstes /src/SonsOfPHP/**/Cache @JoshuaEstes /src/SonsOfPHP/**/Clock @JoshuaEstes /src/SonsOfPHP/**/Container @JoshuaEstes diff --git a/.github/labeler.yml b/.github/labeler.yml index f2caedf9..d369c5f3 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -2,6 +2,10 @@ Bard: - docs/bard/* - src/SonsOfPHP/Bard/* +Assert: + - docs/components/assert/* + - src/SonsOfPHP/**/Assert/* + Cache: - docs/components/cache/* - src/SonsOfPHP/**/Cache/* diff --git a/CHANGELOG.md b/CHANGELOG.md index 2601ee5a..f6427a80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ To get the diff between two versions, go to https://github.com/SonsOfPHP/sonsofp ## [Unreleased] +* [PR #222](https://github.com/SonsOfPHP/sonsofphp/pull/222) [Assert] New Component * [PR #221](https://github.com/SonsOfPHP/sonsofphp/pull/221) [StateMachine] New Contract and Component * [PR #220](https://github.com/SonsOfPHP/sonsofphp/pull/220) [Filesystem] Adds bridges for AWS and LiipImagineBundle * [PR #214](https://github.com/SonsOfPHP/sonsofphp/pull/214) [Logger] Bug fixes and updates diff --git a/bard.json b/bard.json index 57abc536..52498537 100644 --- a/bard.json +++ b/bard.json @@ -5,6 +5,10 @@ "path": "src/SonsOfPHP/Bard", "repository": "git@github.com:SonsOfPHP/bard.git" }, + { + "path": "src/SonsOfPHP/Component/Assert", + "repository": "git@github.com:SonsOfPHP/assert.git" + }, { "path": "src/SonsOfPHP/Component/StateMachine", "repository": "git@github.com:SonsOfPHP/state-machine.git" diff --git a/composer.json b/composer.json index cc5c4446..a459bf7b 100644 --- a/composer.json +++ b/composer.json @@ -87,8 +87,7 @@ "psr/http-server-handler": "^1.0", "psr/http-server-middleware": "^1.0", "aws/aws-sdk-php": "^3.0", - "liip/imagine-bundle": "^2.0", - "sonsofphp/state-machine-contract": "0.3.x-dev" + "liip/imagine-bundle": "^2.0" }, "replace": { "sonsofphp/bard": "self.version", @@ -135,11 +134,13 @@ "sonsofphp/filesystem-aws": "self.version", "sonsofphp/filesystem-liip-imagine": "self.version", "sonsofphp/state-machine": "self.version", - "sonsofphp/state-machine-contract": "self.version" + "sonsofphp/state-machine-contract": "self.version", + "sonsofphp/assert": "self.version" }, "autoload": { "psr-4": { "SonsOfPHP\\Bard\\": "src/SonsOfPHP/Bard/src", + "SonsOfPHP\\Component\\Assert\\": "src/SonsOfPHP/Component/Assert", "SonsOfPHP\\Component\\StateMachine\\": "src/SonsOfPHP/Component/StateMachine", "SonsOfPHP\\Contract\\StateMachine\\": "src/SonsOfPHP/Contract/StateMachine", "SonsOfPHP\\Contract\\Mailer\\": "src/SonsOfPHP/Contract/Mailer", @@ -186,6 +187,7 @@ }, "exclude-from-classmap": [ "src/SonsOfPHP/Bard/Tests", + "src/SonsOfPHP/Component/Assert/Tests", "src/SonsOfPHP/Component/StateMachine/Tests", "src/SonsOfPHP/Component/Mailer/Tests", "src/SonsOfPHP/Component/Cache/Tests", @@ -238,4 +240,4 @@ "SonsOfPHP\\Bridge\\Symfony\\Cqrs\\Tests\\": "src/SonsOfPHP/Bridge/Symfony/Cqrs/Tests" } } -} \ No newline at end of file +} diff --git a/docs/components/assert/index.md b/docs/components/assert/index.md new file mode 100644 index 00000000..6e918948 --- /dev/null +++ b/docs/components/assert/index.md @@ -0,0 +1,9 @@ +--- +title: Assert +--- + +## Installation + +```shell +composer require sonsofphp/assert +``` diff --git a/phpunit.xml.dist b/phpunit.xml.dist index c1abb041..db12a572 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -105,7 +105,7 @@ - + diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 5cfe54a6..df13d13d 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -131,6 +131,22 @@ + + + get('ContentType')]]> + + + + + + + + + + + + + @@ -186,6 +202,40 @@ + + + filesystem->mimeType($path); + $extension = $this->extensionGuesser->getExtensions($mimeType)[0] ?? null; + + return new Binary( + $this->filesystem->read($path), + $mimeType, + $extension, + ); + } catch(FilesystemExceptionInterface $exception) { + throw new NotLoadableException(sprintf('Source image "%s" not found.', $path), 0, $exception); + }]]> + + + + + + + + + + + + + + + + + + + + @@ -379,6 +429,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -710,11 +791,6 @@ - - - - - @@ -733,6 +809,11 @@ + + + + + @@ -1145,6 +1226,15 @@ + + mimeType($path, $context); + } catch (FilesystemExceptionInterface) { + }]]> + + + + @@ -1155,15 +1245,14 @@ + + - - - @@ -1180,16 +1269,6 @@ - - - - - - - - - - adapter->get($path, $context)]]> @@ -2048,6 +2127,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2180,6 +2334,7 @@ + @@ -2195,7 +2350,12 @@ + + + + + @@ -2217,11 +2377,10 @@ + - - @@ -2378,4 +2537,25 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/SonsOfPHP/Component/Assert/.gitattributes b/src/SonsOfPHP/Component/Assert/.gitattributes new file mode 100644 index 00000000..84c7add0 --- /dev/null +++ b/src/SonsOfPHP/Component/Assert/.gitattributes @@ -0,0 +1,4 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore diff --git a/src/SonsOfPHP/Component/Assert/.gitignore b/src/SonsOfPHP/Component/Assert/.gitignore new file mode 100644 index 00000000..5414c2c6 --- /dev/null +++ b/src/SonsOfPHP/Component/Assert/.gitignore @@ -0,0 +1,3 @@ +composer.lock +phpunit.xml +vendor/ diff --git a/src/SonsOfPHP/Component/Assert/Assert.php b/src/SonsOfPHP/Component/Assert/Assert.php new file mode 100644 index 00000000..3cf81aa0 --- /dev/null +++ b/src/SonsOfPHP/Component/Assert/Assert.php @@ -0,0 +1,344 @@ + + */ +class Assert +{ + public const INVALID_ARRAY = 1; + public const INVALID_BOOLEAN = 2; + public const INVALID_CALLABLE = 3; + public const INVALID_COUNTABLE = 4; + public const INVALID_DOUBLE = 5; + public const INVALID_FLOAT = 6; + public const INVALID_INTEGER = 7; + public const INVALID_ITERABLE = 8; + public const INVALID_NULL = 9; + public const INVALID_NUMERIC = 10; + public const INVALID_OBJECT = 11; + public const INVALID_RESOURCE = 12; + public const INVALID_SCALAR = 13; + public const INVALID_STRING = 14; + + protected static string $exceptionClass = InvalidArgumentException::class; + protected static bool $throwException = true; + + public static function getExceptionClass(): string + { + return static::$exceptionClass; + } + + public static function setExceptionClass(string $class): void + { + static::$exceptionClass = $class; + } + + /** + * Disable throwing exceptions + */ + public static function disable(): void + { + static::$throwException = false; + } + + /** + * Enable throwing exceptions + */ + public static function enable(): void + { + static::$throwException = true; + } + + public static function string(mixed $value, ?string $message = null): bool + { + if (is_string($value)) { + return true; + } + + return static::throwException( + static::generateMessage($message ?? 'Expected "string" got "%s"', $value), + self::INVALID_STRING + ); + } + + public static function int(mixed $value, ?string $message = null): bool + { + if (is_int($value)) { + return true; + } + + return static::throwException( + static::generateMessage($message ?? 'Expected "int" got "%s"', $value), + self::INVALID_INTEGER + ); + } + + public static function float(mixed $value, ?string $message = null): bool + { + if (is_float($value)) { + return true; + } + + return static::throwException( + static::generateMessage($message ?? 'Expected "float" got "%s"', $value), + self::INVALID_FLOAT + ); + } + + public static function numeric(mixed $value, ?string $message = null): bool + { + if (is_numeric($value)) { + return true; + } + + return static::throwException( + static::generateMessage($message ?? 'Expected "numeric" got "%s"', $value), + self::INVALID_NUMERIC + ); + } + + public static function bool(mixed $value, ?string $message = null): bool + { + if (is_bool($value)) { + return true; + } + + return static::throwException( + static::generateMessage($message ?? 'Expected "boolean" got "%s"', $value), + self::INVALID_BOOLEAN + ); + } + + public static function scalar(mixed $value, ?string $message = null): bool + { + if (is_scalar($value)) { + return true; + } + + return static::throwException( + static::generateMessage($message ?? 'Expected "scalar" got "%s"', $value), + self::INVALID_SCALAR + ); + } + + public static function object(mixed $value, ?string $message = null): bool + { + if (is_object($value)) { + return true; + } + + return static::throwException( + static::generateMessage($message ?? 'Expected "object" got "%s"', $value), + self::INVALID_OBJECT + ); + } + + public static function callable(mixed $value, ?string $message = null): bool + { + if (is_callable($value)) { + return true; + } + + return static::throwException( + static::generateMessage($message ?? 'Expected "callable" got "%s"', $value), + self::INVALID_CALLABLE + ); + } + + public static function array(mixed $value, ?string $message = null): bool + { + if (is_array($value)) { + return true; + } + + return static::throwException( + static::generateMessage($message ?? 'Expected "array" got "%s"', $value), + self::INVALID_ARRAY + ); + } + + public static function resource(mixed $value, ?string $message = null): bool + { + if (is_resource($value)) { + return true; + } + + return static::throwException( + static::generateMessage($message ?? 'Expected "resource" got "%s"', $value), + self::INVALID_ARRAY + ); + } + + public static function empty(mixed $value, ?string $message = null): bool + { + if (empty($value)) { + return true; + } + + return static::throwException( + static::generateMessage($message ?? 'Expected "empty" got "%s"', $value) + ); + } + + public static function null(mixed $value, ?string $message = null): bool + { + if (null === $value) { + return true; + } + + return static::throwException( + static::generateMessage($message ?? 'Expected "null" got "%s"', $value), + self::INVALID_NULL + ); + } + + public static function true(mixed $value, ?string $message = null): bool + { + if (true === $value) { + return true; + } + + return static::throwException( + static::generateMessage($message ?? 'Expected "true" got "%s"', $value), + self::INVALID_BOOLEAN + ); + } + + public static function false(mixed $value, ?string $message = null): bool + { + if (false === $value) { + return true; + } + + return static::throwException( + static::generateMessage($message ?? 'Expected "false" got "%s"', $value), + self::INVALID_BOOLEAN + ); + } + + public static function eq(mixed $value, mixed $value2, ?string $message = null): bool + { + if ($value == $value2) { + return true; + } + + return static::throwException( + static::generateMessage($message ?? 'Expected "%s" == "%s"', $value, $value2) + ); + } + + public static function same(mixed $value, mixed $value2, ?string $message = null): bool + { + if ($value === $value2) { + return true; + } + + return static::throwException( + static::generateMessage($message ?? 'Expected "%s" == "%s"', $value, $value2) + ); + } + + protected static function createException(?string $message = null, int $code = 0): Exception + { + $class = static::$exceptionClass; + + return new $class($message ?? '', $code); + } + + protected static function throwException(?string $message = null, int $code = 0): false + { + if (static::$throwException) { + throw static::createException($message ?? '', $code); + } + + return false; + } + + protected static function valueToString(mixed $value): string + { + $type = gettype($value); + $debugType = get_debug_type($value); + + return match ($type) { + 'boolean' => $value ? 'true' : 'false', + 'integer' => sprintf('%d', $value), + 'double' => sprintf('%f', $value), + 'string' => $value, + 'NULL' => 'null', + 'resource' => $debugType, + 'object' => match ($debugType) { + 'DateTimeImmutable', + 'DateTime' => sprintf('%s: %s', $value::class, $value->format('c')), + default => $value instanceof Stringable ? (string) $value : $debugType, + }, + default => $debugType, + }; + } + + protected static function generateMessage(string $message, ...$values): string + { + foreach ($values as $key => $value) { + $values[$key] = static::valueToString($value); + } + + return sprintf($message, ...$values); + } + + /** + * Usage: + * nullOr{method}(mixed $value, string $message) + * all{method}(array $values, string $message) + * not{method}(mixed $value, string $message) + */ + public static function __callStatic(string $method, array $args) + { + if (str_starts_with($method, 'nullOr')) { + if (null !== $args[0]) { + $method = lcfirst(substr($method, 6)); + call_user_func_array([static::class, $method], $args); + } + + return true; + } + + if (str_starts_with($method, 'all')) { + $method = lcfirst(substr($method, 3)); + $values = array_shift($args); + foreach ($values as $value) { + call_user_func_array([static::class, $method], array_merge([$value], $args)); + } + + return true; + } + + if (str_starts_with($method, 'not')) { + $method = lcfirst(substr($method, 3)); + + try { + $ret = call_user_func_array([static::class, $method], $args); + } catch (InvalidArgumentException) { + return true; + } + + return static::throwException( + static::generateMessage('not "%s" got "%s"', $method, ...$args) + ); + } + + throw new BadMethodCallException(sprintf('Unknown method "%s"', $method)); + } + + /** @codeCoverageIgnore */ + private function __construct() {} + + /** @codeCoverageIgnore */ + private function __clone() {} +} diff --git a/src/SonsOfPHP/Component/Assert/InvalidArgumentException.php b/src/SonsOfPHP/Component/Assert/InvalidArgumentException.php new file mode 100644 index 00000000..7982bb06 --- /dev/null +++ b/src/SonsOfPHP/Component/Assert/InvalidArgumentException.php @@ -0,0 +1,10 @@ + + */ +class InvalidArgumentException extends \InvalidArgumentException {} diff --git a/src/SonsOfPHP/Component/Assert/LICENSE b/src/SonsOfPHP/Component/Assert/LICENSE new file mode 100644 index 00000000..39238382 --- /dev/null +++ b/src/SonsOfPHP/Component/Assert/LICENSE @@ -0,0 +1,19 @@ +Copyright 2022 to Present Joshua Estes + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/SonsOfPHP/Component/Assert/README.md b/src/SonsOfPHP/Component/Assert/README.md new file mode 100644 index 00000000..60889b73 --- /dev/null +++ b/src/SonsOfPHP/Component/Assert/README.md @@ -0,0 +1,36 @@ +Sons of PHP - Assert +==================== + +## Installation + +```shell +composer require sonsofphp/assert +``` + +## Usage + +```php +assertTrue(Assert::string($value)); + } + + public function testItHasTheCorrectDefaultExceptionClass(): void + { + $this->assertSame(InvalidArgumentException::class, Assert::getExceptionClass()); + } + + public function testItsExceptionClassIsMutable(): void + { + Assert::setExceptionClass('Exception'); + $this->assertSame(Exception::class, Assert::getExceptionClass()); + } + + #[DataProvider('valueToStringProvider')] + public function testItCanConvertValueToString(mixed $expected, mixed $value): void + { + $method = new ReflectionMethod(Assert::class, 'valueToString'); + $this->assertSame($expected, $method->invoke(null, $value)); + } + + #[DataProvider('validIntProvider')] + #[DataProvider('validFloatProvider')] + public function testItCanIdentifyNotString(mixed $value): void + { + $this->assertTrue(Assert::notString($value)); + } + + public function testItWillThrowExceptionForNotStringWhenStringPassedIn(): void + { + $this->expectException(InvalidArgumentException::class); + Assert::notString('Sons of PHP'); + } + + public function testItCanIdentifyNullOrString(): void + { + $this->assertTrue(Assert::nullOrString(null)); + $this->assertTrue(Assert::nullOrString('Sons of PHP')); + } + + public function testItWillThrowExceptionForNullOrStringWhenNotNullOrString(): void + { + $this->expectException(InvalidArgumentException::class); + Assert::nullOrString(42); + } + + public function testItCanIdentifyAllString(): void + { + $this->assertTrue(Assert::allString(['Sons', 'of', 'PHP'])); + } + + public function testItWillThrowExceptionForAllStringWhenNotAllStrings(): void + { + $this->expectException(InvalidArgumentException::class); + Assert::allString(['duck', 'duck', 'goose', 42]); + } + + public function testItWillThrowBadMethodCallExceptionWhenStaticMethodIsInvalid(): void + { + $this->expectException(BadMethodCallException::class); + Assert::badMethod(); + } + + public function testItWillThrowBadMethodCallExceptionWhenStaticMethodIsInvalidButStartsWithKeyword(): void + { + $this->expectException(BadMethodCallException::class); + Assert::notAMethod(); + } + + public function testItWillNotThrowExceptionWhenDisabled(): void + { + Assert::disable(); + $this->assertFalse(Assert::string(42)); + + Assert::enable(); + $this->expectException(InvalidArgumentException::class); + Assert::string(42); + } + + #[DataProvider('validIntProvider')] + #[DataProvider('validFloatProvider')] + #[DataProvider('validBoolProvider')] + #[DataProvider('validObjectProvider')] + #[DataProvider('validCallableProvider')] + #[DataProvider('validArrayProvider')] + public function testItWillThrowExceptionForStringWithInvalidString(mixed $value): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionCode(Assert::INVALID_STRING); + Assert::string($value); + } + + #[DataProvider('validIntProvider')] + public function testItCanIdentifyInt(mixed $value): void + { + $this->assertTrue(Assert::int($value)); + } + + #[DataProvider('validStringProvider')] + #[DataProvider('validFloatProvider')] + public function testItWillThrowExceptionForIntWithInvalidInt(mixed $value): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionCode(Assert::INVALID_INTEGER); + Assert::int($value); + } + + #[DataProvider('validFloatProvider')] + public function testItCanIdentifyFloat(mixed $value): void + { + $this->assertTrue(Assert::float($value)); + } + + #[DataProvider('validStringProvider')] + public function testItWillThrowExceptionForFloatWithFloat(mixed $value): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionCode(Assert::INVALID_FLOAT); + Assert::float($value); + } + + #[DataProvider('validNumericProvider')] + public function testItCanIdentifyNumeric(mixed $value): void + { + $this->assertTrue(Assert::numeric($value)); + } + + #[DataProvider('validArrayProvider')] + public function testItWillThrowExceptionForNumericWithNumeric(mixed $value): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionCode(Assert::INVALID_NUMERIC); + Assert::numeric($value); + } + + #[DataProvider('validBoolProvider')] + public function testItCanIdentifyBool(mixed $value): void + { + $this->assertTrue(Assert::bool($value)); + } + + #[DataProvider('validArrayProvider')] + public function testItWillThrowExceptionForBoolWithBool(mixed $value): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionCode(Assert::INVALID_BOOLEAN); + Assert::bool($value); + } + + #[DataProvider('validScalarProvider')] + public function testItCanIdentifyScalar(mixed $value): void + { + $this->assertTrue(Assert::scalar($value)); + } + + #[DataProvider('validArrayProvider')] + #[DataProvider('validObjectProvider')] + public function testItWillThrowExceptionForScalarWithScalar(mixed $value): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionCode(Assert::INVALID_SCALAR); + Assert::scalar($value); + } + + #[DataProvider('validObjectProvider')] + public function testItCanIdentifyObject(mixed $value): void + { + $this->assertTrue(Assert::object($value)); + } + + #[DataProvider('validArrayProvider')] + public function testItWillThrowExceptionForObjectWithObject(mixed $value): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionCode(Assert::INVALID_OBJECT); + Assert::object($value); + } + + #[DataProvider('validCallableProvider')] + public function testItCanIdentifyCallable(mixed $value): void + { + $this->assertTrue(Assert::callable($value)); + } + + #[DataProvider('validArrayProvider')] + public function testItWillThrowExceptionForCallableWithCallable(mixed $value): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionCode(Assert::INVALID_CALLABLE); + Assert::callable($value); + } + + #[DataProvider('validArrayProvider')] + public function testItCanIdentifyArray(mixed $value): void + { + $this->assertTrue(Assert::array($value)); + } + + #[DataProvider('validStringProvider')] + public function testItWillThrowExceptionForArrayWithArray(mixed $value): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionCode(Assert::INVALID_ARRAY); + Assert::array($value); + } + + #[DataProvider('validEmptyProvider')] + public function testItCanIdentifyEmpty(mixed $value): void + { + $this->assertTrue(Assert::empty($value)); + } + + #[DataProvider('validStringProvider')] + public function testItWillThrowExceptionForEmptyWithEmpty(mixed $value): void + { + $this->expectException(InvalidArgumentException::class); + Assert::empty($value); + } + + #[DataProvider('validNullProvider')] + public function testItCanIdentifyNull(mixed $value): void + { + $this->assertTrue(Assert::null($value)); + } + + #[DataProvider('validStringProvider')] + public function testItWillThrowExceptionForNullWithNull(mixed $value): void + { + $this->expectException(InvalidArgumentException::class); + Assert::null($value); + } + + #[DataProvider('validTrueProvider')] + public function testItCanIdentifyTrue(mixed $value): void + { + $this->assertTrue(Assert::true($value)); + } + + #[DataProvider('validStringProvider')] + public function testItWillThrowExceptionForTrueWithTrue(mixed $value): void + { + $this->expectException(InvalidArgumentException::class); + Assert::true($value); + } + + #[DataProvider('validFalseProvider')] + public function testItCanIdentifyFalse(mixed $value): void + { + $this->assertTrue(Assert::false($value)); + } + + #[DataProvider('validStringProvider')] + public function testItWillThrowExceptionForFalseWithFalse(mixed $value): void + { + $this->expectException(InvalidArgumentException::class); + Assert::false($value); + } + + #[DataProvider('validEqProvider')] + public function testItCanIdentifyEq(mixed $value, mixed $value2): void + { + $this->assertTrue(Assert::eq($value, $value2)); + } + + #[DataProvider('invalidEqProvider')] + public function testItWillThrowExceptionForEqWithEq(mixed $value, mixed $value2): void + { + $this->expectException(InvalidArgumentException::class); + Assert::eq($value, $value2); + } + + #[DataProvider('validSameProvider')] + public function testItCanIdentifySame(mixed $value, mixed $value2): void + { + $this->assertTrue(Assert::same($value, $value2)); + } + + #[DataProvider('invalidEqProvider')] + public function testItWillThrowExceptionForSameWithSame(mixed $value, mixed $value2): void + { + $this->expectException(InvalidArgumentException::class); + Assert::same($value, $value2); + } + + #[DataProvider('validResourceProvider')] + public function testItCanIdentifyResource(mixed $value): void + { + $this->assertTrue(Assert::resource($value)); + } + + #[DataProvider('validStringProvider')] + public function testItWillThrowExceptionForResourceWithResource(mixed $value): void + { + $this->expectException(InvalidArgumentException::class); + Assert::resource($value); + } +} diff --git a/src/SonsOfPHP/Component/Assert/composer.json b/src/SonsOfPHP/Component/Assert/composer.json new file mode 100644 index 00000000..174e1024 --- /dev/null +++ b/src/SonsOfPHP/Component/Assert/composer.json @@ -0,0 +1,50 @@ +{ + "name": "sonsofphp/assert", + "type": "library", + "description": "", + "keywords": [ + "assert" + ], + "homepage": "https://github.com/SonsOfPHP/assert", + "license": "MIT", + "authors": [ + { + "name": "Joshua Estes", + "email": "joshua@sonsofphp.com" + } + ], + "support": { + "issues": "https://github.com/SonsOfPHP/sonsofphp/issues", + "forum": "https://github.com/orgs/SonsOfPHP/discussions", + "docs": "https://docs.sonsofphp.com" + }, + "autoload": { + "psr-4": { + "SonsOfPHP\\Component\\Assert\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "prefer-stable": true, + "require": { + "php": ">=8.2" + }, + "extra": { + "sort-packages": true, + "branch-alias": { + "dev-main": "0.3.x-dev" + } + }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/JoshuaEstes" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/packagist-sonsofphp-sonsofphp" + } + ] +} \ No newline at end of file