diff --git a/changelog.md b/changelog.md index 8cc2646..8e140ea 100644 --- a/changelog.md +++ b/changelog.md @@ -2,22 +2,33 @@ All notable changes to this project will be documented in this file. +## [1.2.3] - 2019-07-09 +### Added +- Following methods are added to trait `ExtraAssertions`: + - `assertReturnsCarbonNow(callable $func, ?string $message = null)` + +### Changed +- method `getLastErrors` is added to `Generator` interface +- error messages are added to `GenerateIDETestContainerCommand` + + ## [1.2.2] - 2019-07-08 ### Changed - fix error in `WrapperDataProcessor` -## [1.2.1] - 2019-07-08 + +## [1.2.1-dep] - 2019-07-08 ### Changed - fix errors in `generate-ide-test-containers` -## [1.2.0] - 2019-07-07 +## [1.2.0-dep] - 2019-07-07 ### Changed - fix errors in `_ide_test_container.php` - `DataLoaderFactory` and `DirectoryDataLoaderFactory` are removed -## [1.1.0] - 2019-07-07 +## [1.1.0-dep] - 2019-07-07 ### Changed - `mikey179/vfsstream` is moved from require-dev to require section of composer.json - trait `ExtraAssertions` does not include `ExtraUtils` anymore @@ -25,7 +36,7 @@ All notable changes to this project will be documented in this file. - all classes are made final, for which this was possible -## [1.0.0] - 2019-06-27 +## [1.0.0-dep] - 2019-06-27 ### Added - trait `ExtraUtils` that contains following service methods: - `invokeMethod(object $object, string $methodName, ?array $parameters = null)` @@ -44,8 +55,9 @@ All notable changes to this project will be documented in this file. - command `generate-ide-test-containers` that generate service file for IDE used to autocomplete -[1.2.2]: https://github.com/raptor-mvk/test-utils/compare/v1.2.1...v1.2.2 -[1.2.1]: https://github.com/raptor-mvk/test-utils/compare/v1.2.0...v1.2.1 -[1.2.0]: https://github.com/raptor-mvk/test-utils/compare/v1.1.0...v1.2.0 -[1.1.0]: https://github.com/raptor-mvk/test-utils/compare/v1.0.0...v1.1.0 -[1.0.0]: https://github.com/raptor-mvk/test-utils/releases/tag/v1.0.0 \ No newline at end of file +[1.2.3]: https://github.com/raptor-mvk/test-utils/compare/v1.2.2...v1.2.3 +[1.2.2]: https://github.com/raptor-mvk/test-utils/compare/v1.2.1-dep...v1.2.2 +[1.2.1-dep]: https://github.com/raptor-mvk/test-utils/compare/v1.2.0-dep...v1.2.1-dep +[1.2.0-dep]: https://github.com/raptor-mvk/test-utils/compare/v1.1.0-dep...v1.2.0-dep +[1.1.0-dep]: https://github.com/raptor-mvk/test-utils/compare/v1.0.0-dep...v1.1.0-dep +[1.0.0-dep]: https://github.com/raptor-mvk/test-utils/releases/tag/v1.0.0-dep \ No newline at end of file diff --git a/composer.json b/composer.json index cbce8f3..4786162 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,7 @@ "php": ">=7.3.0", "symfony/console": "^4.0", "mikey179/vfsstream": "1.6.*", + "nesbot/carbon": "^2.19", "ext-json": "*" }, "require-dev": { diff --git a/composer.lock b/composer.lock index ed40d68..c9da8d7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6cfdc34461961d4de25836f6dfd00e9e", + "content-hash": "438261bdbdfa37c51652ebd3f5b7b1ce", "packages": [ { "name": "mikey179/vfsStream", @@ -52,6 +52,66 @@ "homepage": "http://vfs.bovigo.org/", "time": "2019-04-08T13:54:32+00:00" }, + { + "name": "nesbot/carbon", + "version": "2.20.0", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "bc671b896c276795fad8426b0aa24e8ade0f2498" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/bc671b896c276795fad8426b0aa24e8ade0f2498", + "reference": "bc671b896c276795fad8426b0aa24e8ade0f2498", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.1.8 || ^8.0", + "symfony/translation": "^3.4 || ^4.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.14 || ^3.0", + "kylekatarnls/multi-tester": "^1.1", + "phpmd/phpmd": "^2.6", + "phpstan/phpstan": "^0.11", + "phpunit/phpunit": "^7.5 || ^8.0", + "squizlabs/php_codesniffer": "^3.4" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "http://nesbot.com" + } + ], + "description": "A simple API extension for DateTime.", + "homepage": "http://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "time": "2019-06-25T10:00:57+00:00" + }, { "name": "psr/container", "version": "1.0.0", @@ -350,6 +410,139 @@ "standards" ], "time": "2019-06-13T11:15:36+00:00" + }, + { + "name": "symfony/translation", + "version": "v4.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "934ab1d18545149e012aa898cf02e9f23790f7a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/934ab1d18545149e012aa898cf02e9f23790f7a0", + "reference": "934ab1d18545149e012aa898cf02e9f23790f7a0", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^1.1.2" + }, + "conflict": { + "symfony/config": "<3.4", + "symfony/dependency-injection": "<3.4", + "symfony/yaml": "<3.4" + }, + "provide": { + "symfony/translation-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/http-kernel": "~3.4|~4.0", + "symfony/intl": "~3.4|~4.0", + "symfony/service-contracts": "^1.1.2", + "symfony/var-dumper": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "psr/log-implementation": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Translation Component", + "homepage": "https://symfony.com", + "time": "2019-06-13T11:03:18+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v1.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "cb4b18ad7b92a26e83b65dde940fab78339e6f3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/cb4b18ad7b92a26e83b65dde940fab78339e6f3c", + "reference": "cb4b18ad7b92a26e83b65dde940fab78339e6f3c", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "suggest": { + "symfony/translation-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-06-13T11:15:36+00:00" } ], "packages-dev": [ @@ -995,16 +1188,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "7.0.5", + "version": "7.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "aed67b57d459dcab93e84a5c9703d3deb5025dff" + "reference": "d471d0d2b529a67c6a722dd446c4ec90881ac315" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aed67b57d459dcab93e84a5c9703d3deb5025dff", - "reference": "aed67b57d459dcab93e84a5c9703d3deb5025dff", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d471d0d2b529a67c6a722dd446c4ec90881ac315", + "reference": "d471d0d2b529a67c6a722dd446c4ec90881ac315", "shasum": "" }, "require": { @@ -1013,17 +1206,17 @@ "php": "^7.2", "phpunit/php-file-iterator": "^2.0.2", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.0.1", + "phpunit/php-token-stream": "^3.0.2", "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^4.1", + "sebastian/environment": "^4.2.2", "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1" + "theseer/tokenizer": "^1.1.3" }, "require-dev": { - "phpunit/phpunit": "^8.0" + "phpunit/phpunit": "^8.2.2" }, "suggest": { - "ext-xdebug": "^2.6.1" + "ext-xdebug": "^2.7.2" }, "type": "library", "extra": { @@ -1054,7 +1247,7 @@ "testing", "xunit" ], - "time": "2019-06-06T12:28:18+00:00" + "time": "2019-07-08T05:29:42+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1198,16 +1391,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "3.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18" + "reference": "c4a66b97f040e3e20b3aa2a243230a1c3a9f7c8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c99e3be9d3e85f60646f152f9002d46ed7770d18", - "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c4a66b97f040e3e20b3aa2a243230a1c3a9f7c8c", + "reference": "c4a66b97f040e3e20b3aa2a243230a1c3a9f7c8c", "shasum": "" }, "require": { @@ -1243,20 +1436,20 @@ "keywords": [ "tokenizer" ], - "time": "2018-10-30T05:52:18+00:00" + "time": "2019-07-08T05:24:54+00:00" }, { "name": "phpunit/phpunit", - "version": "8.2.3", + "version": "8.2.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "f67ca36860ebca7224d4573f107f79bd8ed0ba03" + "reference": "25fe0b5031b24722f66a75ad479a074cccc1bb37" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f67ca36860ebca7224d4573f107f79bd8ed0ba03", - "reference": "f67ca36860ebca7224d4573f107f79bd8ed0ba03", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/25fe0b5031b24722f66a75ad479a074cccc1bb37", + "reference": "25fe0b5031b24722f66a75ad479a074cccc1bb37", "shasum": "" }, "require": { @@ -1283,7 +1476,7 @@ "sebastian/global-state": "^3.0.0", "sebastian/object-enumerator": "^3.0.3", "sebastian/resource-operations": "^2.0.1", - "sebastian/type": "^1.1.0", + "sebastian/type": "^1.1.3", "sebastian/version": "^2.0.1" }, "require-dev": { @@ -1326,7 +1519,7 @@ "testing", "xunit" ], - "time": "2019-06-19T12:03:56+00:00" + "time": "2019-07-03T08:30:33+00:00" }, { "name": "roave/security-advisories", @@ -2071,16 +2264,16 @@ }, { "name": "sebastian/type", - "version": "1.1.2", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "251ca774d58181fe1d3eda68843264eaae7e07ef" + "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/251ca774d58181fe1d3eda68843264eaae7e07ef", - "reference": "251ca774d58181fe1d3eda68843264eaae7e07ef", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/3aaaa15fa71d27650d62a948be022fe3b48541a3", + "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3", "shasum": "" }, "require": { @@ -2113,7 +2306,7 @@ ], "description": "Collection of value objects that represent the types of the PHP type system", "homepage": "https://github.com/sebastianbergmann/type", - "time": "2019-06-19T06:39:12+00:00" + "time": "2019-07-02T08:10:15+00:00" }, { "name": "sebastian/version", diff --git a/readme.md b/readme.md index 981d079..8b74620 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -# Raptor Test Utils v1.2.2 +# Raptor Test Utils v1.2.3 (c) Mikhail Kamorin aka raptor_MVK @@ -43,12 +43,15 @@ additional assertions will be available: - `assertArraysAreSameIgnoringOrderRecursive(array $expected, array $actual, ?string $message = null)` checks the assertion that two associative arrays contains same elements ignoring their order at every level. Before checking, arrays are encoded as JSON strings, therefore you cannot use objects or functions as elements of an array. + - `assertReturnsCarbonNow(callable $func, ?string $message = null)` checks the assertion that the given function + returns result of `Carbon::now()`, invoked while running ### Virtual file system Add trait `ExtraUtils` or `ExtraAssertions` to the class that contains tests or to the common base test class. Method `setupVFS` should be used in `setUp` method or in the test method just before using other methods of the trait. -No tearDown actions is needed regarding virtual file system. After that the following additional methods will be available: +No tearDown actions is needed regarding virtual file system. After that the following additional methods will be +available: - `addFileToVFS(string $filename, ?int $permissions = null, ?string $content = null)` adds file with given permissions and content to virtual file system. @@ -95,7 +98,8 @@ keys. Service field `_name` itself is excluded from the objects. Then each array value is wrapped into TestDataContainer object. Values are retrieved from containers using getters. Name of getters follow standard agreements: - if the name of field starts with 'is', then the getter name is field name converted to camel case - - otherwise, if the field is of bool type, then the getter name is field name converted to studly case and prefixed with + - otherwise, if the field is of bool type, then the getter name is field name converted to studly case and prefixed + with 'is' - otherwise, the getter name is field name converted to studly case and prefixed with 'get' diff --git a/src/TestUtils/Command/GenerateIDETestContainerCommand.php b/src/TestUtils/Command/GenerateIDETestContainerCommand.php index b291f84..51750e6 100644 --- a/src/TestUtils/Command/GenerateIDETestContainerCommand.php +++ b/src/TestUtils/Command/GenerateIDETestContainerCommand.php @@ -53,6 +53,21 @@ protected function configure(): void ->addArgument('path', InputArgument::REQUIRED, 'Enter the root folder for JSON test files:'); } + /** + * Outputs error messages from generator. + * + * @param OutputInterface $output + */ + private function outputGeneratorErrors(OutputInterface $output): void + { + $errors = $this->generator->getLastErrors(); + if (!empty($errors)) { + foreach ($errors as $filename => $error) { + $output->write("$filename: $error\n"); + } + } + } + /** @noinspection PhpMissingParentCallCommonInspection __approved__ parent method is overridden */ /** * @param InputInterface $input @@ -63,6 +78,13 @@ protected function execute(InputInterface $input, OutputInterface $output): void { $path = $input->getArgument('path'); $content = $this->generator->generate($path); - file_put_contents("{$this->filePath}/_ide_test_container.php", $content); + $this->outputGeneratorErrors($output); + $filename = "{$this->filePath}/_ide_test_container.php"; + if (file_exists($filename) && !is_writable($filename)) { + $output->write("Could not write to the file _id_test_container.php.\n"); + return; + } + file_put_contents($filename, $content); + $output->write("File _id_test_container.php was successfully generated.\n"); } } diff --git a/src/TestUtils/DataLoader/DirectoryDataLoader.php b/src/TestUtils/DataLoader/DirectoryDataLoader.php index 190551a..4751a7e 100644 --- a/src/TestUtils/DataLoader/DirectoryDataLoader.php +++ b/src/TestUtils/DataLoader/DirectoryDataLoader.php @@ -29,9 +29,9 @@ interface DirectoryDataLoader public function load(string $path, string $filenameRegExp): array; /** - * Returns array of errors that occurred during the last data load. Filenames are array keys. + * Returns array of errors that occurred during the last data load. * - * @return array + * @return array [ filename => errorMessage, ... ] */ public function getLastErrors(): array; } diff --git a/src/TestUtils/DataLoader/RecursiveDirectoryDataLoader.php b/src/TestUtils/DataLoader/RecursiveDirectoryDataLoader.php index 3c3f80c..1c183d2 100644 --- a/src/TestUtils/DataLoader/RecursiveDirectoryDataLoader.php +++ b/src/TestUtils/DataLoader/RecursiveDirectoryDataLoader.php @@ -92,9 +92,9 @@ private function processFile(string $path, string $filename, string $extension): } /** - * Returns array of errors that occurred during the last data load. Filenames are array keys. + * Returns array of errors that occurred during the last data load. * - * @return array + * @return array [ filename => errorMessage, ... ] */ public function getLastErrors(): array { diff --git a/src/TestUtils/ExtraAssertions.php b/src/TestUtils/ExtraAssertions.php index e0c2a35..3086454 100644 --- a/src/TestUtils/ExtraAssertions.php +++ b/src/TestUtils/ExtraAssertions.php @@ -3,7 +3,12 @@ namespace Raptor\TestUtils; +use Carbon\Carbon; use function is_array; +use PHPUnit\Framework\Constraint\GreaterThan; +use PHPUnit\Framework\Constraint\LessThan; +use PHPUnit\Framework\Constraint\LogicalAnd; +use PHPUnit\Framework\Constraint\LogicalNot; /** * Trait with additional assertions. @@ -93,4 +98,22 @@ public static function assertArraysAreSameIgnoringOrderRecursively( $actualString = static::jsonEncodePrettily($actual); static::assertSame($expectedString, $actualString, $message ?? ''); } + + /** + * Asserts that the given function returns result of _Carbon::now()_, invoked while running. + * + * @param callable $func + * @param string|null $message + */ + public static function assertReturnsCarbonNow(callable $func, ?string $message = null): void + { + $timeBefore = Carbon::now()->valueOf(); + $result = $func(); + $actualTime = ($result instanceof Carbon) ? $result->valueOf() : 0; + $timeAfter = Carbon::now()->valueOf(); + $notBeforeConstraint = new LogicalNot(new LessThan($timeBefore)); + $notAfterConstraint = new LogicalNot(new GreaterThan($timeAfter)); + $constraint = LogicalAnd::fromConstraints($notBeforeConstraint, $notAfterConstraint); + static::assertThat($actualTime, $constraint, $message ?? ''); + } } diff --git a/src/TestUtils/Generator/Generator.php b/src/TestUtils/Generator/Generator.php index 8ed346e..59594aa 100644 --- a/src/TestUtils/Generator/Generator.php +++ b/src/TestUtils/Generator/Generator.php @@ -25,4 +25,11 @@ interface Generator * @throws DataDirectoryNotFoundException */ public function generate(string $path): string; + + /** + * Returns array of errors that occurred during the last generation. + * + * @return array [ filename => errorMessage, ... ] + */ + public function getLastErrors(): array; } diff --git a/src/TestUtils/Generator/TestDataContainerGenerator.php b/src/TestUtils/Generator/TestDataContainerGenerator.php index d873d9f..b0ea1b4 100644 --- a/src/TestUtils/Generator/TestDataContainerGenerator.php +++ b/src/TestUtils/Generator/TestDataContainerGenerator.php @@ -3,6 +3,7 @@ namespace Raptor\TestUtils\Generator; +use Memcache; use Raptor\TestUtils\DataLoader\DirectoryDataLoader; use Raptor\TestUtils\DataProcessor\Type\Type; use Raptor\TestUtils\Exceptions\DataDirectoryNotFoundException; @@ -70,4 +71,14 @@ public function generate(string $path): string } return $result; } + + /** + * Returns array of errors that occurred during the last generation. + * + * @return array [ filename => errorMessage, ... ] + */ + public function getLastErrors(): array + { + return $this->directoryDataLoader->getLastErrors(); + } } diff --git a/tests/TestUtils/Command/GenerateIDETestContainerCommandTests.php b/tests/TestUtils/Command/GenerateIDETestContainerCommandTests.php index b9acbed..a42ff79 100644 --- a/tests/TestUtils/Command/GenerateIDETestContainerCommandTests.php +++ b/tests/TestUtils/Command/GenerateIDETestContainerCommandTests.php @@ -17,12 +17,18 @@ final class GenerateIDETestContainerCommandTests extends TestCase { use WithVFS; - public function testCommandGeneratesCorrectFile(): void + /** @noinspection PhpMissingParentCallCommonInspection __approved__ parent method is overridden */ + public function setUp(): void { - $dirname = 'json'; $this->setupVFS(); - $this->prepareVFSDirectoryStructure($dirname); - $fullPath = $this->getFullPath($dirname); + } + + /** + * Checks that command generates correct file. + */ + public function testCommandGeneratesCorrectFile(): void + { + $fullPath = $this->prepareVFSDirectoryStructure('json'); $expectedPath = $this->getFullPath(''); $command = new GenerateIDETestContainerCommand($expectedPath); $commandTester = new CommandTester($command); @@ -33,11 +39,13 @@ public function testCommandGeneratesCorrectFile(): void } /** - * Prepares directory structure in virtual file system. + * Prepares directory structure in virtual file system and returns path to it outside virtual file system. * * @param string $rootDir root directory name + * + * @return string */ - private function prepareVFSDirectoryStructure(string $rootDir): void + private function prepareVFSDirectoryStructure(string $rootDir): string { $fileOneContent = [ ['_name' => 'AAA', 'int' => 3, 'float' => 3.5, 'bool' => true, 'string' => 'bbb', 'array' => [1, 2, 3]], @@ -54,5 +62,80 @@ private function prepareVFSDirectoryStructure(string $rootDir): void ] ]; $this->addStructureToVFS($structure); + return $this->getFullPath($rootDir); + } + + /** + * Checks that command outputs correct message when file is generated without errors. + */ + public function testCommandOutputsCorrectMessageWithoutErrors(): void + { + $fullPath = $this->prepareVFSDirectoryStructure('other_dir'); + $expectedPath = $this->getFullPath(''); + $command = new GenerateIDETestContainerCommand($expectedPath); + $commandTester = new CommandTester($command); + + $commandTester->execute(['path' => $fullPath]); + $output = $commandTester->getDisplay(); + + static::assertSame("File _id_test_container.php was successfully generated.\n", $output); + } + + /** + * Checks that command outputs correct message when file could not be generated. + */ + public function testCommandOutputsCorrectMessageWhenCouldNotWriteToFile(): void + { + $fullPath = $this->prepareVFSDirectoryStructure('any_dir'); + $this->addFileToVFS('_ide_test_container.php', 000); + $expectedPath = $this->getFullPath(''); + $command = new GenerateIDETestContainerCommand($expectedPath); + $commandTester = new CommandTester($command); + + $commandTester->execute(['path' => $fullPath]); + $output = $commandTester->getDisplay(); + + static::assertSame("Could not write to the file _id_test_container.php.\n", $output); + } + + /** + * Checks that command outputs correct message when file is generated with errors. + */ + public function testCommandOutputsCorrectMessageWithErrors(): void + { + $dirname = 'dir_with_errors'; + $fullPath = $this->prepareVFSDirectoryStructureWithErrors($dirname); + $expectedPath = $this->getFullPath(''); + $command = new GenerateIDETestContainerCommand($expectedPath); + $commandTester = new CommandTester($command); + $fileOne = $this->getFullPath("$dirname/file_one.json"); + $fileTwo = $this->getFullPath("$dirname/inside/file_two.json"); + $expectedMessage = "$fileOne: JSON parse error.\n$fileTwo: Expected array, object found at level root.\n" . + "File _id_test_container.php was successfully generated.\n"; + + $commandTester->execute(['path' => $fullPath]); + $output = $commandTester->getDisplay(); + + static::assertSame($expectedMessage, $output); + } + + /** + * Prepares directory structure in virtual file system with errors and returns path to it outside virtual file + * system. + * + * @param string $rootDir root directory name + * + * @return string + */ + private function prepareVFSDirectoryStructureWithErrors(string $rootDir): string + { + $structure = [ + $rootDir => [ + 'file_one.json' => '', + 'inside' => ['file_two.json' => '{"some_field":"some_value"}'] + ] + ]; + $this->addStructureToVFS($structure); + return $this->getFullPath($rootDir); } } diff --git a/tests/TestUtils/DataLoader/ProcessingDataLoaderTests.php b/tests/TestUtils/DataLoader/ProcessingDataLoaderTests.php index e694c87..c11376a 100644 --- a/tests/TestUtils/DataLoader/ProcessingDataLoaderTests.php +++ b/tests/TestUtils/DataLoader/ProcessingDataLoaderTests.php @@ -23,9 +23,9 @@ final class ProcessingDataLoaderTests extends TestCase { use MockeryPHPUnitIntegration, ExtraAssertions, WithVFS; + /** @noinspection PhpMissingParentCallCommonInspection __approved__ parent method is overridden */ protected function setUp(): void { - parent::setUp(); $this->setupVFS(); } diff --git a/tests/TestUtils/DataLoader/RecursiveDirectoryDataLoaderTests.php b/tests/TestUtils/DataLoader/RecursiveDirectoryDataLoaderTests.php index 1e99502..37b7c66 100644 --- a/tests/TestUtils/DataLoader/RecursiveDirectoryDataLoaderTests.php +++ b/tests/TestUtils/DataLoader/RecursiveDirectoryDataLoaderTests.php @@ -24,9 +24,9 @@ final class RecursiveDirectoryDataLoaderTests extends TestCase { use MockeryPHPUnitIntegration, ExtraAssertions, WithVFS; + /** @noinspection PhpMissingParentCallCommonInspection __approved__ parent method is overridden */ protected function setUp(): void { - parent::setUp(); $this->setupVFS(); } diff --git a/tests/TestUtils/ExtraAssertionsTests.php b/tests/TestUtils/ExtraAssertionsTests.php index e75dadd..b1eeb8d 100644 --- a/tests/TestUtils/ExtraAssertionsTests.php +++ b/tests/TestUtils/ExtraAssertionsTests.php @@ -3,6 +3,7 @@ namespace RaptorTests\TestUtils; +use Carbon\Carbon; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\TestCase; use Raptor\TestUtils\ExtraAssertions; @@ -264,4 +265,56 @@ public function rejectableArraysAreSameIgnoringOrderRecursivelyDataProvider(): a { return $this->prepareDifferentArraysTestData(); } + + /** + * Checks that assertion _assertReturnsCarbonNow_ accepts correct function. + */ + public function testAssertReturnsCarbonNowAcceptsCorrectFunction(): void + { + $function = static function() { + return Carbon::now(); + }; + + static::assertReturnsCarbonNow($function); + } + + /** + * Checks that assertion _assertReturnsCarbonNow_ rejects incorrect function. + * + * @param callable $func + * @param string $message + * + * @dataProvider assertReturnsCarbonNowRejectDataProvider + */ + public function testAssertReturnsCarbonNowRejectsIncorrectFunction(callable $func, string $message): void + { + $messageRegExp = "/^$message\n.*$/"; + $this->expectException(ExpectationFailedException::class); + $this->expectExceptionMessageRegExp($messageRegExp); + + static::assertReturnsCarbonNow($func, $message); + } + + /** + * Provides test data for _assertReturnsCarbonNow_ to reject. + * + * @return array [ [ func ], ... ] + */ + public function assertReturnsCarbonNowRejectDataProvider(): array + { + $wrongCarbon = static function() { + return Carbon::now()->addDay(); + }; + $notCarbon = static function() { + return 135; + }; + $nullCarbon = static function() { + return null; + }; + return [ + 'wrong Carbon' => [$wrongCarbon, 'This is wrong Carbon'], + 'not Carbon' => [$notCarbon, 'That is not Carbon'], + 'null Carbon' => [$nullCarbon, 'There is no Carbon'] + ]; + } } diff --git a/tests/TestUtils/TestDataContainerGenerator/TestDataContainerGeneratorTests.php b/tests/TestUtils/TestDataContainerGenerator/TestDataContainerGeneratorTests.php index b1bdaa6..0d1853b 100644 --- a/tests/TestUtils/TestDataContainerGenerator/TestDataContainerGeneratorTests.php +++ b/tests/TestUtils/TestDataContainerGenerator/TestDataContainerGeneratorTests.php @@ -97,4 +97,24 @@ private function prepareDirectoryDataLoaderSecondClassData(): array 'mixed' => new MixedType() ]; } + + /** + * Checks that method _getLastErrors_ returns the result of the directory data loader's _getLastErrors_ method. + */ + public function testGetLastErrorsReturnsResultOfDirectoryDataLoaderGetLastErrors(): void + { + $path = 'some_path'; + $expectedErrors = ['file_one.json' => 'some_error', 'file_two.json' => 'other_error']; + $directoryDataLoader = Mockery::mock(DirectoryDataLoader::class); + $directoryDataLoader->shouldReceive('load') + ->withArgs([$path, '/^.*\.json$/']) + ->andReturn([]); + $directoryDataLoader->shouldReceive('getLastErrors')->andReturn($expectedErrors); + $testDataContainerGenerator = new TestDataContainerGenerator($directoryDataLoader); + + $testDataContainerGenerator->generate($path); + $actualErrors = $testDataContainerGenerator->getLastErrors(); + + static::assertSame($expectedErrors, $actualErrors); + } } diff --git a/tests/TestUtils/WithDataLoaderTests.php b/tests/TestUtils/WithDataLoaderTests.php index b7c4ed9..aa07347 100644 --- a/tests/TestUtils/WithDataLoaderTests.php +++ b/tests/TestUtils/WithDataLoaderTests.php @@ -18,9 +18,9 @@ final class WithDataLoaderTests extends TestCase { use ExtraAssertions, WithVFS, WithDataLoader; + /** @noinspection PhpMissingParentCallCommonInspection __approved__ parent method is overridden */ protected function setUp(): void { - parent::setUp(); $this->setupVFS(); }