diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 516b078..4c9e1d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,17 +7,17 @@ on: branches: [ main ] jobs: - build: + ci: runs-on: ubuntu-latest strategy: matrix: - php-versions: [ '8.1', '8.2', '8.3' ] + php-versions: [ '8.3', '8.4', '8.5' ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: - fetch-depth: 0 # To avoid "Shallow clone detected" error in SonarCloud report + fetch-depth: 0 #~ PHP Setup - name: Setup PHP ${{ matrix.php-versions }} @@ -48,30 +48,18 @@ jobs: #~ CI part - name: Dependencies - run: make deps + run: make php/deps - name: Check Code Style - run: make phpcs + run: make php/check - name: Units Tests - run: make tests + run: make php/tests - name: Fix unit tests report path run: | sed -i 's+'$GITHUB_WORKSPACE'+/github/workspace+g' build/reports/phpunit/clover.xml sed -i 's+'$GITHUB_WORKSPACE'+/github/workspace+g' build/reports/phpunit/unit.xml - - name: PHP min compatibility - run: make php-min-compatibility - - - name: PHP max compatibility - run: make php-max-compatibility - - name: PHP Static Analyze - run: make analyze - - - name: SonarCloud Scan - uses: SonarSource/sonarcloud-github-action@v2.1.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: make php/analyze diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml new file mode 100644 index 0000000..ee46a95 --- /dev/null +++ b/.github/workflows/sonarcloud.yml @@ -0,0 +1,46 @@ +name: SonarQube + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + sonarcloud: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # To avoid "Shallow clone detected" error in SonarCloud report + + #~ PHP Setup + - name: Setup PHP 8.3 # Minimum version + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + + #~ Composer Cache + - name: Get Composer Cache Directory + id: composer-cache + run: | + echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + + - name: Install dependencies + if: steps.composer-cache.outputs.cache-hit != 'true' + run: make install + + - name: Units Tests + run: make php/tests # To generate the coverage report + + - name: SonarQube Scan + uses: SonarSource/sonarqube-scan-action@v7 + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index de5ea3b..d16dbbd 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -4,7 +4,7 @@ //~ Rules ->setRules( [ - '@PER-CS2.0' => true, + '@PER-CS3x0' => true, ] ) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65523b8..ed1bcb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ---- +## [3.0.0] - 2026-01-05 +[3.0.0]: https://github.com/eureka-framework/component-serializer/compare/2.1.0...3.0.0 +### Added +- Add PHP 8.5 support +### Removed +- Drop PHP 8.1 & 8.2 support +### Changed +- Improve code & types +- Fix phpstan errors +- Fix code style +- Update dev dependencies +- Update CI configs + +---- + ## [2.1.0] - 2024-08-22 [2.1.0]: https://github.com/eureka-framework/component-serializer/compare/2.0.0...2.1.0 ### Changed diff --git a/Makefile b/Makefile index d0176ef..199be3e 100644 --- a/Makefile +++ b/Makefile @@ -1,25 +1,12 @@ -.PHONY: validate install update phpcs phpcbf phpmincompatibility phpmaxcompatibility phpstan analyze tests testdox ci clean +.PHONY: validate install update php/deps php/check php/fix php/min-compatibility php/max-compatibility php/phpstan php/analyze php/tests php/test php/testdox ci clean -PHP_MIN_VERSION := "8.1" -PHP_MAX_VERSION := "8.3" +PHP_MIN_VERSION := "8.3" +PHP_MAX_VERSION := "8.5" COMPOSER_BIN := composer - -ifneq (,$(wildcard ./.env)) - include .env - export -endif - define header = @if [ -t 1 ]; then printf "\n\e[37m\e[100m \e[104m $(1) \e[0m\n"; else printf "\n### $(1)\n"; fi endef -#~ Composer dependency -build: generator phpcsf - -generator: - $(call header,"Build new version of client, formatter & VO") - @./bin/script generator --file="./data/openapi.json" --debug - #~ Composer dependency validate: $(call header,Composer Validation) @@ -34,16 +21,12 @@ update: @${COMPOSER_BIN} update @${COMPOSER_BIN} bump --dev-only -outdated: - $(call header,Composer Outdated) - @${COMPOSER_BIN} outdated --direct - composer.lock: install #~ Vendor binaries dependencies -vendor/bin/php-cs-fixer: -vendor/bin/phpstan: -vendor/bin/phpunit: +vendor/bin/php-cs-fixer: composer.lock +vendor/bin/phpstan: composer.lock +vendor/bin/phpunit: composer.lock #~ Report directories dependencies build/reports/phpunit: @@ -53,49 +36,45 @@ build/reports/phpstan: @mkdir -p build/reports/phpstan #~ main commands -deps: composer.json # jenkins + manual +php/deps: composer.json $(call header,Checking Dependencies) - @XDEBUG_MODE=off ./vendor/bin/composer-dependency-analyser --config=./ci/composer-dependency-analyser.php # for shadow & unused required dependencies - @XDEBUG_MODE=off ./vendor/bin/composer-require-checker check # mainly for ext-* missing dependencies + @XDEBUG_MODE=off ./vendor/bin/composer-dependency-analyser --config ./ci/composer-dependency-analyser.php # for shadow, unused required dependencies and ext-* missing dependencies -phpcs: vendor/bin/php-cs-fixer # jenkins + manual +php/check: vendor/bin/php-cs-fixer $(call header,Checking Code Style) - @XDEBUG_MODE=off ./vendor/bin/php-cs-fixer check -v --diff - -phpcsf: vendor/bin/php-cs-fixer # manual + @XDEBUG_MODE=off ./vendor/bin/php-cs-fixer check +php/fix: vendor/bin/php-cs-fixer $(call header,Fixing Code Style) @XDEBUG_MODE=off ./vendor/bin/php-cs-fixer fix -v -php-min-compatibility: vendor/bin/phpstan build/reports/phpstan # jenkins + manual - $(call header,Checking PHP $(PHP_MIN_VERSION) compatibility) - @XDEBUG_MODE=off ./vendor/bin/phpstan analyse --configuration=./ci/php-min-compatibility.neon --error-format=table +php/min-compatibility: vendor/bin/phpstan build/reports/phpstan + $(call header,Checking PHP ${PHP_MIN_VERSION} compatibility) + @XDEBUG_MODE=off ./vendor/bin/phpstan analyse --configuration=./ci/phpmin-compatibility.neon --error-format=table -php-max-compatibility: vendor/bin/phpstan build/reports/phpstan # jenkins + manual - $(call header,Checking PHP $(PHP_MAX_VERSION) compatibility) - @XDEBUG_MODE=off ./vendor/bin/phpstan analyse --configuration=./ci/php-max-compatibility.neon --error-format=table +php/max-compatibility: vendor/bin/phpstan build/reports/phpstan #ci + $(call header,Checking PHP ${PHP_MAX_VERSION} compatibility) + @XDEBUG_MODE=off ./vendor/bin/phpstan analyse --configuration=./ci/phpmax-compatibility.neon --error-format=table -phpstan: vendor/bin/phpstan build/reports/phpstan # jenkins - $(call header,Running Static Analyze) - @XDEBUG_MODE=off ./vendor/bin/phpstan analyse --error-format=checkstyle > ./build/reports/phpstan/phpstan.xml - -analyze: vendor/bin/phpstan build/reports/phpstan # manual +php/analyze: vendor/bin/phpstan build/reports/phpstan #manual & ci $(call header,Running Static Analyze - Pretty tty format) @XDEBUG_MODE=off ./vendor/bin/phpstan analyse --error-format=table -tests: vendor/bin/phpunit build/reports/phpunit # jenkins + manual +php/tests: vendor/bin/phpunit build/reports/phpunit #ci $(call header,Running Unit Tests) - @XDEBUG_MODE=coverage php -dzend_extension=xdebug.so ./vendor/bin/phpunit --testsuite=unit --coverage-clover=./build/reports/phpunit/clover.xml --log-junit=./build/reports/phpunit/unit.xml --coverage-php=./build/reports/phpunit/unit.cov --coverage-html=./build/reports/coverage/ --fail-on-warning + @XDEBUG_MODE=coverage php ./vendor/bin/phpunit --testsuite=unit --coverage-clover=./build/reports/phpunit/clover.xml --log-junit=./build/reports/phpunit/unit.xml --coverage-php=./build/reports/phpunit/unit.cov --coverage-html=./build/reports/coverage/ --fail-on-warning + +php/test: php/tests -integration: vendor/bin/phpunit build/reports/phpunit # manual +php/integration: vendor/bin/phpunit build/reports/phpunit #manual $(call header,Running Integration Tests) @XDEBUG_MODE=coverage php -dzend_extension=xdebug.so ./vendor/bin/phpunit --testsuite=integration --fail-on-warning -testdox: vendor/bin/phpunit # manual +php/testdox: vendor/bin/phpunit #manual $(call header,Running Unit Tests (Pretty format)) @XDEBUG_MODE=coverage php -dzend_extension=xdebug.so ./vendor/bin/phpunit --testsuite=unit --fail-on-warning --testdox -clean: # manual - $(call header,Cleaning previous build) +clean: + $(call header,Cleaning previous build) #manual @if [ "$(shell ls -A ./build)" ]; then rm -rf ./build/*; fi; echo " done" -ci: clean validate deps phpcs tests php-min-compatibility php-max-compatibility analyze +ci: clean validate install php/deps php/check php/tests php/integration php/min-compatibility php/max-compatibility php/analyze diff --git a/README.md b/README.md index 0adf083..6d25147 100644 --- a/README.md +++ b/README.md @@ -217,46 +217,55 @@ NB: For the components, the `composer.lock` file is not committed. ### Testing & CI (Continuous Integration) #### Tests -You can run tests (with coverage) on your side with following command: +You can run unit tests (with coverage) on your side with following command: ```bash -make tests +make php/tests ``` -You can run tests (with coverage) on your side with following command: +You can run integration tests (without coverage) on your side with following command: ```bash -make integration +make php/integration ``` For prettier output (but without coverage), you can use the following command: ```bash -make testdox # run tests without coverage reports but with prettified output +make php/testdox # run tests without coverage reports but with prettified output ``` #### Code Style You also can run code style check with following commands: ```bash -make phpcs +make php/check ``` You also can run code style fixes with following commands: ```bash -make phpcsf +make php/fix +``` + +#### Check for missing explicit dependencies +You can check if any explicit dependency is missing with the following command: +```bash +make php/deps ``` #### Static Analysis To perform a static analyze of your code (with phpstan, lvl 9 at default), you can use the following command: ```bash -make analyze +make php/analyse ``` +To ensure you code still compatible with current supported version at Deezer and futures versions of php, you need to +run the following commands (both are required for full support): + Minimal supported version: ```bash -make php-min-compatibility +make php/min-compatibility ``` Maximal supported version: ```bash -make php-max-compatibility +make php/max-compatibility ``` #### CI Simulation @@ -265,7 +274,6 @@ And the last "helper" commands, you can run before commit and push, is: make ci ``` - ## License -This project is licensed under the MIT License - see the `LICENSE` file for details +This project is currently under The MIT License (MIT). See [LICENCE](LICENSE) file for more information. diff --git a/ci/php-min-compatibility.neon b/ci/phpmax-compatibility.neon similarity index 90% rename from ci/php-min-compatibility.neon rename to ci/phpmax-compatibility.neon index d1a8a4d..162415e 100644 --- a/ci/php-min-compatibility.neon +++ b/ci/phpmax-compatibility.neon @@ -3,7 +3,7 @@ includes: - ./../vendor/phpstan/phpstan-phpunit/rules.neon parameters: - phpVersion: 80100 + phpVersion: 80500 level: 0 paths: - ./../src diff --git a/ci/php-max-compatibility.neon b/ci/phpmin-compatibility.neon similarity index 100% rename from ci/php-max-compatibility.neon rename to ci/phpmin-compatibility.neon diff --git a/composer.json b/composer.json index df9a073..1892e9e 100644 --- a/composer.json +++ b/composer.json @@ -29,17 +29,17 @@ }, "require": { - "php": "8.1.*||8.2.*||8.3.*||8.4.*", + "php": ">=8.3", "ext-json": "*" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.62.0", - "maglnet/composer-require-checker": "^4.7.1", - "phpstan/phpstan": "^1.11.11", - "phpstan/phpstan-phpunit": "^1.4.0", - "phpunit/phpcov": "^9.0.2", - "phpunit/phpunit": "^10.5.30", - "shipmonk/composer-dependency-analyser": "^1.7.0" + "friendsofphp/php-cs-fixer": "^3.92.4", + "phpstan/phpstan": "^2.1.33", + "phpstan/phpstan-phpunit": "^2.0.11", + "phpstan/phpstan-strict-rules": "^2.0.7", + "phpunit/phpcov": "^11.0.3", + "phpunit/phpunit": "^12.5.4", + "shipmonk/composer-dependency-analyser": "^1.8.4" } } diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 54d8f6e..b2f73df 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,5 +1,10 @@ +includes: + - ./vendor/phpstan/phpstan-phpunit/extension.neon + - ./vendor/phpstan/phpstan-phpunit/rules.neon + - ./vendor/phpstan/phpstan-strict-rules/rules.neon + parameters: - phpVersion: 80100 # PHP 8.1 - Current minimal version supported + phpVersion: 80300 level: max paths: - ./src @@ -8,10 +13,20 @@ parameters: bootstrapFiles: - ./vendor/autoload.php + treatPhpDocTypesAsCertain: false + ignoreErrors: - - path: './tests/unit/SerializerTest.php' - message: '`Parameter #2 \$class of method (.+)JsonSerializer::unserialize\(\) expects class-string, string given.`' - - path: './src/JsonSerializer.php' - message: '`Method (.+)JsonSerializer::isHydratableArgument\(\) has parameter .+ with generic class ReflectionClass but does not specify its types: T`' - - path: './src/JsonSerializer.php' + - message: '`Dead catch - ReflectionException is never thrown in the try block.`' + path: './src/JsonSerializer.php' + count: 2 + + #~ Both bottom errors are due to contexts objects using `JsonSerializableTrait`. They are false positives. + - + identifier: function.impossibleType + path: 'src/JsonSerializableTrait.php' + count: 2 + - + identifier: function.alreadyNarrowedType + path: 'src/JsonSerializableTrait.php' + count: 1 diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 49e04d0..0f4fcc5 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,10 +1,12 @@ + ./src diff --git a/src/JsonSerializableTrait.php b/src/JsonSerializableTrait.php index 175cc73..b5a93d9 100644 --- a/src/JsonSerializableTrait.php +++ b/src/JsonSerializableTrait.php @@ -19,15 +19,21 @@ trait JsonSerializableTrait { /** - * @return array + * @return array */ public function jsonSerialize(): array { $data = []; - //~ Iterate over object properties or collection when objet is iterable - /** @var \Iterator|array $this */ - foreach ($this as $property => $value) { + if (\is_iterable($this)) { + //~ Iterate over collection when objet is iterable + $object = \iterator_to_array($this); + } else { + //~ Iterate over object properties when not iterable + $object = \get_object_vars($this); + } + + foreach ($object as $property => $value) { $data[$property] = ($value instanceof \JsonSerializable) ? $value->jsonSerialize() : $value; } diff --git a/src/JsonSerializer.php b/src/JsonSerializer.php index 123d64a..b88c6eb 100644 --- a/src/JsonSerializer.php +++ b/src/JsonSerializer.php @@ -19,7 +19,7 @@ * Exception code range: 10000-10100 * @author Romain Cottard */ -final class JsonSerializer +final class JsonSerializer implements JsonSerializerInterface { /** * @param \JsonSerializable $object @@ -29,7 +29,7 @@ final class JsonSerializer public function serialize(\JsonSerializable $object): string { try { - return json_encode($object, JSON_THROW_ON_ERROR); + return \json_encode($object, JSON_THROW_ON_ERROR); } catch (\JsonException $exception) { throw new SerializerException( '[CLI-10200] Cannot serialize data (json_encode failed)!', @@ -40,8 +40,9 @@ public function serialize(\JsonSerializable $object): string } /** - * @phpstan-param class-string $class - * @phpstan-return object + * @template T of object + * @param class-string $class + * @return T * @throws SerializerException */ public function unserialize(string $json, string $class, bool $skippableParameters = false): object @@ -61,8 +62,10 @@ public function unserialize(string $json, string $class, bool $skippableParamete } /** - * @phpstan-param class-string $class - * @phpstan-param array $data + * @template T of object + * @param class-string $class + * @param array $data + * @return T * @throws SerializerException */ private function hydrate(string $class, array $data, bool $skippableParameters): object @@ -78,7 +81,7 @@ private function hydrate(string $class, array $data, bool $skippableParameters): } if ($reflection->getConstructor() === null) { - return new $class(); + return new $class(); // @codeCoverageIgnore } $parameters = $reflection->getConstructor()->getParameters(); @@ -129,15 +132,16 @@ private function getArgumentValueFromType( try { $reflectionClass = new \ReflectionClass($parameterTypeName); + // @codeCoverageIgnoreStart } catch (\ReflectionException $exception) { throw new SerializerException( "[CLI-10204] Given class does not exists! (class: '$parameterName')", 10204, $exception, ); + // @codeCoverageIgnoreEnd } - /** @var mixed $argumentValue */ $argumentValue = $data[$parameterName]; if ($this->isHydratableArgument($reflectionClass, $argumentValue)) { $argumentValue = $this->hydrate($reflectionClass->getName(), $argumentValue, $skippableParameters); @@ -151,28 +155,30 @@ private function getArgumentValueFromType( */ private function hasValidNamedData(string $parameterName, array $data): bool { - return array_key_exists($parameterName, $data); + return \array_key_exists($parameterName, $data); } private function hasValidArrayData(\ReflectionParameter $parameter, int $nbParameters): bool { + /** @var \ReflectionNamedType|\ReflectionUnionType|\ReflectionIntersectionType|null $reflectionType */ $reflectionType = $parameter->getType(); if ($reflectionType === null || $nbParameters !== 1) { return false; } - /** @var \ReflectionNamedType[] $types */ - $types = $reflectionType instanceof \ReflectionUnionType ? $reflectionType->getTypes() : [$reflectionType]; - - return \in_array( - 'array', - \array_map(fn(\ReflectionNamedType $t): string => $t->getName(), $types), + $types = $reflectionType instanceof \ReflectionNamedType ? [$reflectionType] : $reflectionType->getTypes(); + $typeHints = \array_map( + fn(\ReflectionType $t): string => $t instanceof \ReflectionNamedType ? $t->getName() : (string) $t, + $types, ); + + return \in_array('array', $typeHints, true); } /** - * @param \ReflectionClass $parameterReflectionClass + * @template T of object + * @param \ReflectionClass $parameterReflectionClass * @param mixed|array $data * @return bool * @phpstan-assert-if-true array $data @@ -180,7 +186,7 @@ private function hasValidArrayData(\ReflectionParameter $parameter, int $nbParam private function isHydratableArgument(\ReflectionClass $parameterReflectionClass, mixed $data): bool { return ( - \in_array(\JsonSerializable::class, $parameterReflectionClass->getInterfaceNames()) + \in_array(\JsonSerializable::class, $parameterReflectionClass->getInterfaceNames(), true) && \is_array($data) ); } diff --git a/src/JsonSerializerInterface.php b/src/JsonSerializerInterface.php index d55246a..dca92b8 100644 --- a/src/JsonSerializerInterface.php +++ b/src/JsonSerializerInterface.php @@ -18,7 +18,7 @@ * * @author Romain Cottard */ -interface JsonSerializerInterface extends \JsonSerializable +interface JsonSerializerInterface { /** * @param \JsonSerializable $object @@ -28,9 +28,10 @@ interface JsonSerializerInterface extends \JsonSerializable public function serialize(\JsonSerializable $object): string; /** - * @param string $json - * @return JsonSerializerInterface + * @template T of object + * @param class-string $class + * @return T * @throws SerializerException */ - public static function unserialize(string $json): JsonSerializerInterface; + public function unserialize(string $json, string $class, bool $skippableParameters = false): object; } diff --git a/src/VO/AbstractCollection.php b/src/VO/AbstractCollection.php index d3f0422..6754e76 100644 --- a/src/VO/AbstractCollection.php +++ b/src/VO/AbstractCollection.php @@ -47,7 +47,7 @@ protected function add(object $value): void /** * Return number of item in collection. * - * @return int + * @return int<0,max> */ public function count(): int { @@ -187,6 +187,9 @@ public function jsonSerialize(): array */ private function getNewIndex(): int { - return (!empty($this->collection)) ? \array_keys($this->collection)[\count($this->collection) - 1] : 0; + return $this->collection !== [] + ? \array_keys($this->collection)[\count($this->collection) - 1] + : 0 + ; } } diff --git a/tests/unit/CollectionTest.php b/tests/unit/CollectionTest.php index 2c9433a..4749844 100644 --- a/tests/unit/CollectionTest.php +++ b/tests/unit/CollectionTest.php @@ -29,20 +29,20 @@ public function testICanIterateOnCollectionObject(): void { $collection = $this->getCollection(); foreach ($collection as $index => $item) { - $this->assertSame($collection[$index]->getName(), $item->getName()); + self::assertSame($collection[$index]->getName(), $item->getName()); } } public function testICanCountElementInCollection(): void { - $this->assertCount(3, $this->getCollection()); + self::assertCount(3, $this->getCollection()); } public function testICanPerformIssetOnCollectionIndex(): void { $collection = $this->getCollection(); - $this->assertTrue(isset($collection[1])); + self::assertTrue(isset($collection[1])); } public function testICanUnsetElementFromCollection(): void @@ -50,15 +50,15 @@ public function testICanUnsetElementFromCollection(): void $collection = $this->getCollection(); unset($collection[1]); - $this->assertFalse(isset($collection[1])); + self::assertFalse(isset($collection[1])); } public function testICanAddElementToTheEndOfTheCollection(): void { $collection = $this->getCollection(); - $collection[] = new EntityB(41, 'New Item #1'); - $this->assertTrue(isset($collection[3])); + $collection[] = new EntityB(41, 'New Item #41'); + self::assertTrue(isset($collection[3])); } public function testICanAddElementToTheCollectionAtTheSpecificIndexPosition(): void @@ -66,16 +66,16 @@ public function testICanAddElementToTheCollectionAtTheSpecificIndexPosition(): v //~ Re-add item to the specific position $collection = $this->getCollection(); - $collection[5] = new EntityB(42, 'New Item #2'); - $this->assertTrue(isset($collection[5])); + $collection[5] = new EntityB(42, 'New Item #42'); + self::assertSame('New Item #42', $collection[5]->getName()); } public function testICanOverrideAnElementInCollection(): void { $collection = $this->getCollection(); - $collection[0] = new EntityB(43, 'New Item #3'); - $this->assertSame('New Item #3', $collection[0]->getName()); + $collection[0] = new EntityB(43, 'New Item #43'); + self::assertSame('New Item #43', $collection[0]->getName()); } public function getCollection(): CollectionEntityB diff --git a/tests/unit/SerializerTest.php b/tests/unit/SerializerTest.php index 16b0634..ec2bf28 100644 --- a/tests/unit/SerializerTest.php +++ b/tests/unit/SerializerTest.php @@ -16,6 +16,7 @@ use Eureka\Component\Serializer\Tests\Unit\VO\CollectionEntityB; use Eureka\Component\Serializer\Tests\Unit\VO\EntityA; use Eureka\Component\Serializer\Tests\Unit\VO\EntityB; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; /** @@ -29,9 +30,8 @@ class SerializerTest extends TestCase * @param \JsonSerializable $originalVO * @return void * @throws SerializerException - * - * @dataProvider provideVOForSerializationAndUnSerializationTests */ + #[DataProvider('provideVOForSerializationAndUnserializationTests')] public function testICanSerializeAndDeserializeAValueObject(\JsonSerializable $originalVO): void { //~ Serializer / Unserializer service @@ -40,11 +40,11 @@ public function testICanSerializeAndDeserializeAValueObject(\JsonSerializable $o //~ Serialize VO $json = $serializer->serialize($originalVO); - //~ Unserialize + //~ Unserialize VO $unserializedVO = $serializer->unserialize($json, get_class($originalVO)); //~ Compare data - $this->assertEquals($originalVO, $unserializedVO); + self::assertEquals($originalVO, $unserializedVO); } /** @@ -57,7 +57,7 @@ public function testASerializerExceptionIsThrownWhenTheUnserializedStringHasAnUn $data = ['id' => 1, 'name' => 'name A#1', 'other' => 'any value']; $this->expectException(SerializerException::class); - (new JsonSerializer())->unserialize(json_encode($data, JSON_THROW_ON_ERROR), EntityA::class); + (new JsonSerializer())->unserialize(\json_encode($data, flags: JSON_THROW_ON_ERROR), VO\EntityA::class); } /** @@ -84,7 +84,7 @@ public function jsonSerialize(): string public function testASerializerExceptionIsThrownWhenIUnserializeAnInvalidJson(): void { $this->expectException(SerializerException::class); - (new JsonSerializer())->unserialize('[', EntityA::class); + (new JsonSerializer())->unserialize('[', VO\EntityA::class); } /** @@ -93,9 +93,9 @@ public function testASerializerExceptionIsThrownWhenIUnserializeAnInvalidJson(): */ public function testASerializerExceptionIsThrownWhenIUnserializeDataAndTryToMapToANonExistingClass(): void { + $classString = \DateTimeImmutable::class; $this->expectException(SerializerException::class); - - (new JsonSerializer())->unserialize('[]', 'Test\Hello\Not\Exists'); + (new JsonSerializer())->unserialize('[]', $classString); } /** @@ -112,9 +112,9 @@ public static function provideVOForSerializationAndUnserializationTests(): array ]; return [ - 'Entity A VO' => [new EntityA(42, 'name A', null)], - 'Entity B VO' => [new EntityB(43, 'name B')], - 'Entity A with Collection VO' => [new EntityA(42, 'name A', new CollectionEntityB($collection))], + 'Entity A VO' => [new VO\EntityA(42, 'name A', null)], + 'Entity B VO' => [new VO\EntityB(43, 'name B')], + 'Entity A with Collection VO' => [new VO\EntityA(42, 'name A', new CollectionEntityB($collection))], ]; } } diff --git a/tests/unit/VO/CollectionEntityB.php b/tests/unit/VO/CollectionEntityB.php index d27ea0d..484e58b 100644 --- a/tests/unit/VO/CollectionEntityB.php +++ b/tests/unit/VO/CollectionEntityB.php @@ -21,11 +21,9 @@ * * @extends AbstractCollection */ -class CollectionEntityB extends AbstractCollection +class CollectionEntityB extends AbstractCollection implements \JsonSerializable { /** - * CollectionEntityB constructor. - * * @phpstan-param list $dataEntitiesB */ public function __construct(array $dataEntitiesB)