├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── bin ├── phpunit └── symfony-grumphp ├── composer.json ├── src ├── Command │ ├── AbstractCommand.php │ ├── InstallCommand.php │ └── UninstallCommand.php └── dist │ ├── .php_cs │ ├── grumphp.yml │ ├── phpstan.neon │ └── phpunit.xml.dist └── tests ├── Command ├── InstallCommandTest.php └── UninstallCommandTest.php └── bootstrap.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | composer.lock 3 | .idea 4 | .php_cs.cache 5 | grumphp.yml 6 | grumphp.yml.scbak 7 | php_cs.php 8 | php_cs.php.scbak 9 | phpstan.neon 10 | phpstan.neon.scbak 11 | phpunit.xml.dist 12 | phpunit.xml.dist.scbak 13 | config/cli-config.php 14 | coverage.sh 15 | !src/dist/coverage.sh 16 | build/logs/clover.xml 17 | bin/.phpunit 18 | build/* 19 | .phpunit.cache 20 | .php_cs 21 | *.scbak 22 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - 7.3 4 | - 7.4 5 | - 8.0 6 | 7 | env: 8 | matrix: 9 | - 10 | cache: 11 | directories: 12 | - "$HOME/.composer/cache" 13 | 14 | before_install: 15 | - alias composer=composer\ --no-interaction && composer selfupdate 16 | 17 | install: 18 | - travis_retry composer update --no-progress --profile --no-scripts --no-suggest && composer install 19 | 20 | script: 21 | - bin/symfony-grumphp install -q 22 | - vendor/bin/grumphp run --testsuite=no-coverage 23 | - bin/symfony-grumphp install -q 24 | - bin/symfony-grumphp uninstall -q 25 | 26 | after_success: 27 | - bin/symfony-grumphp install -q 28 | - vendor/bin/php-coveralls -v 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Marcin Harasim 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Symfony + GrumPHP 2 | 3 | `symfony-grumphp` is configured GrumPHP with bunch of tools for static code analysis mainly based on [PSRs](https://www.php-fig.org/psr/) and [Symfony Coding Standards](https://symfony.com/doc/current/contributing/code/standards.html) for Symfony Framework projects. 4 | 5 | [![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/sci3ma/symfony-grumphp?style=flat-square)](https://github.com/sci3ma/symfony-grumphp) 6 | [![GitHub](https://img.shields.io/github/license/sci3ma/symfony-grumphp?style=flat-square)](https://github.com/sci3ma/symfony-grumphp/blob/master/LICENSE) 7 | [![Packagist (custom server)](https://img.shields.io/packagist/dt/sci3ma/symfony-grumphp?style=flat-square)](https://packagist.org/packages/sci3ma/symfony-grumphp/stats) 8 | [![GitHub last commit](https://img.shields.io/github/last-commit/sci3ma/symfony-grumphp?style=flat-square&logo=github)](https://github.com/sci3ma/symfony-grumphp/commits/master) 9 | [![Travis (.org)](https://img.shields.io/travis/sci3ma/symfony-grumphp?style=flat-square&logo=travis-ci)](https://travis-ci.com/sci3ma/symfony-grumphp) 10 | [![Coveralls github](https://img.shields.io/coveralls/github/sci3ma/symfony-grumphp?logo=coveralls&style=flat-square)](https://coveralls.io/github/sci3ma/symfony-grumphp) 11 | 12 | ## Included tools 13 | * [GrumPHP](https://github.com/phpro/grumphp): `phpro/grumphp` 14 | * [PhpCpd](https://github.com/sebastianbergmann/phpcpd): `sebastian/phpcpd` 15 | * [PHP-CS-FIXER](https://github.com/FriendsOfPHP/PHP-CS-Fixer): `friendsofphp/php-cs-fixer` 16 | * [PHPLint](https://github.com/php-parallel-lint/PHP-Parallel-Lint): `php-parallel-lint/php-parallel-lint` 17 | * [PhpMd](https://github.com/phpmd/phpmd): `phpmd/phpmd` 18 | * [PHPStan](https://github.com/phpstan/phpstan): `phpstan/phpstan` 19 | * [Doctrine extension](https://github.com/phpstan/phpstan-doctrine): `phpstan/phpstan-doctrine` 20 | * [PHPUnit extension](https://github.com/phpstan/phpstan-phpunit): `phpstan/phpstan-phpunit` 21 | * [Symfony Framework extension](https://github.com/phpstan/phpstan-symfony): `phpstan/phpstan-symfony` 22 | * [TheCodingMachine's additional rules](https://github.com/thecodingmachine/phpstan-strict-rules): `thecodingmachine/phpstan-strict-rules` 23 | * [PHPUnit Bridge](https://github.com/symfony/phpunit-bridge): `symfony/phpunit-bridge` 24 | * With Clover Coverage and percentage code coverage check 25 | * [Enlightn Security Checker](https://github.com/enlightn/security-checker): `enlightn/security-checker` 26 | 27 | ## Requirements 28 | PHP needs to be a minimum version of PHP 7.3. 29 | Symfony Framework needs to be a minimum version of Symfony Framework 4.0 or 5.0. 30 | 31 | ## Installation 32 | To install `symfony-grumphp`, [install Composer](https://getcomposer.org/download/), execute the following command: 33 | ``` 34 | composer require --dev sci3ma/symfony-grumphp 35 | ``` 36 | and create (or update) configuration files: 37 | ``` 38 | ./vendor/bin/symfony-grumphp install 39 | ``` 40 | 41 | ## Configuration 42 | You can, and perhaps you should, check and customize all configured tasks in `grumphp.yml` file in project root folder. 43 | 44 | GrumPHP should be enabled by default but you can also enable GrumPHP yourself: 45 | ``` 46 | ./vendor/bin/grumphp git:init 47 | ``` 48 | or disable GrumPHP: 49 | ``` 50 | ./vendor/bin/grumphp git:deinit 51 | ``` 52 | You can find more GrumPHP configuration [here](https://github.com/phpro/grumphp/blob/master/doc/commands.md#installation). 53 | 54 | ##### Test code with the database 55 | If you need to test code that interact with the database you need to instal [`dama/doctrine-test-bundle`](https://github.com/dmaicher/doctrine-test-bundle): 56 | ``` 57 | composer require --dev dama/doctrine-test-bundle 58 | ``` 59 | and uncomment extension `` in `phpunit.xml.dist`. 60 | Read more about [how to Test Code that Interacts with the Database](https://symfony.com/doc/current/testing/database.html) 61 | 62 | ## Uninstall 63 | If you want to uninstall this library remove configuration files first: 64 | ``` 65 | ./vendor/bin/symfony-grumphp uninstall 66 | ``` 67 | then remove package: 68 | ``` 69 | composer remove sci3ma/symfony-grumphp 70 | ``` 71 | 72 | ## Force run 73 | You can run tests/checks our code without commit manually: 74 | ``` 75 | ./vendor/bin/grumphp run 76 | ``` 77 | 78 | -------------------------------------------------------------------------------- /bin/phpunit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | add(new InstallCommand()); 35 | $application->add(new UninstallCommand()); 36 | 37 | try { 38 | $application->run(); 39 | } catch (\Exception $exception) { 40 | fwrite(STDERR, $exception->getMessage() . PHP_EOL); 41 | exit(1); 42 | } 43 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sci3ma/symfony-grumphp", 3 | "description": "Configured GrumPHP with bunch of tools for static code analysis Symfony Framework", 4 | "keywords": ["php", "symfony", "grumphp", "phpcs", "phpmd", "phpstan", "phpunit", "code quality", "standards"], 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Marcin Harasim", 9 | "email": "marcin.harasim@gmail.com" 10 | } 11 | ], 12 | "type": "library", 13 | "require": { 14 | "php": "^7.3|^8.0", 15 | "composer/composer": "^2.0", 16 | "enlightn/security-checker": "^1.5", 17 | "friendsofphp/php-cs-fixer": "^2.18", 18 | "php-parallel-lint/php-parallel-lint": "^1.2", 19 | "phpmd/phpmd": "^2.9", 20 | "phpro/grumphp": "^1.3", 21 | "phpstan/phpstan": "^0.11.2|^0.12.26", 22 | "phpstan/phpstan-doctrine": "^0.11.1|^0.12.0", 23 | "phpstan/phpstan-phpunit": "^0.11.0|^0.12.0", 24 | "phpstan/phpstan-symfony": "^0.11.1|^0.12.0", 25 | "psr/event-dispatcher": "^1.0", 26 | "sebastian/phpcpd": "^6.0", 27 | "symfony/console": "^4.0|^5.0", 28 | "symfony/filesystem": "^4.0|^5.0", 29 | "symfony/phpunit-bridge": "^4.0|^5.0", 30 | "thecodingmachine/phpstan-strict-rules": "^0.11.2|^0.12.0" 31 | }, 32 | "require-dev": { 33 | "php-coveralls/php-coveralls": "^2.4" 34 | }, 35 | "autoload": { 36 | "psr-4": { 37 | "MH\\SymfonyGrumPHP\\": "src/", 38 | "MH\\SymfonyGrumPHP\\Tests\\": "tests/" 39 | } 40 | }, 41 | "support": { 42 | "issues": "https://github.com/sci3ma/symfony-grumphp/issues" 43 | }, 44 | "homepage": "https://github.com/sci3ma/symfony-grumphp", 45 | "config": { 46 | "sort-packages": true 47 | }, 48 | "bin": ["bin/symfony-grumphp"] 49 | } 50 | -------------------------------------------------------------------------------- /src/Command/AbstractCommand.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | abstract class AbstractCommand extends Command 13 | { 14 | /** 15 | * @const array CONF_FILES 16 | */ 17 | protected const CONF_FILES = [ 18 | 'grumphp.yml', 19 | '.php_cs', 20 | 'phpstan.neon', 21 | 'phpunit.xml.dist', 22 | ]; 23 | 24 | /** 25 | * @param string $file 26 | * 27 | * @return string 28 | */ 29 | protected static function normalizeSourceFile(string $file): string 30 | { 31 | return sprintf(str_replace('/', DIRECTORY_SEPARATOR, '%s/../dist/%s'), __DIR__, $file); 32 | } 33 | 34 | /** 35 | * @param string $file 36 | * 37 | * @return string 38 | */ 39 | protected static function normalizeDestinationFile(string $file): string 40 | { 41 | return sprintf(str_replace('/', DIRECTORY_SEPARATOR, '%s/%s'), getcwd(), $file); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Command/InstallCommand.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | final class InstallCommand extends AbstractCommand 16 | { 17 | /** 18 | * {@inheritdoc} 19 | */ 20 | protected static $defaultName = 'install'; 21 | 22 | /** 23 | * {@inheritdoc} 24 | */ 25 | protected function configure(): void 26 | { 27 | $this 28 | ->setDescription('Create configuration files of SymfonyGrumPHP') 29 | ->setHelp('The install command moves preconfigured files to root folder of a project.'); 30 | } 31 | 32 | /** 33 | * {@inheritdoc} 34 | */ 35 | protected function execute(InputInterface $input, OutputInterface $output) 36 | { 37 | $helper = $this->getHelper('question'); 38 | 39 | $filesystem = new Filesystem(); 40 | foreach (self::CONF_FILES as $file) { 41 | $sourceFile = self::normalizeSourceFile($file); 42 | $destinationFile = self::normalizeDestinationFile($file); 43 | 44 | if ($filesystem->exists($destinationFile)) { 45 | $questionOverride = new ConfirmationQuestion( 46 | sprintf('File [%s] exists. Do you want override file? (yes/no) [yes]: ', $file) 47 | ); 48 | 49 | if ($helper->ask($input, $output, $questionOverride)) { 50 | $filesystem->rename($destinationFile, sprintf('%s.scbak', $destinationFile), true); 51 | } 52 | } 53 | 54 | $filesystem->copy($sourceFile, $destinationFile); 55 | 56 | if ('phpstan.neon' === $file) { 57 | $this->modifyNeonFile($destinationFile); 58 | } 59 | 60 | $output->writeln(sprintf('File [%s] has been created.', $file)); 61 | } 62 | 63 | return 0; 64 | } 65 | 66 | /** 67 | * @param string $destinationFile 68 | */ 69 | private function modifyNeonFile(string $destinationFile): void 70 | { 71 | $symfonyKernel = 'Symfony\Component\HttpKernel\Kernel'; 72 | if (class_exists($symfonyKernel)) { 73 | $containerXmlPath = '%rootDir%/../../../var/cache/dev/srcDevDebugProjectContainer.xml'; 74 | 75 | if (version_compare($symfonyKernel::VERSION, '4.2.0', '>=')) { 76 | $containerXmlPath = '%rootDir%/../../../var/cache/dev/srcApp_KernelDevDebugContainer.xml'; 77 | } 78 | 79 | if (version_compare($symfonyKernel::VERSION, '5.0.0', '>=')) { 80 | $containerXmlPath = '%rootDir%/../../../var/cache/dev/App_KernelDevDebugContainer.xml'; 81 | } 82 | 83 | file_put_contents($destinationFile, sprintf(' symfony:%s', PHP_EOL), FILE_APPEND); 84 | file_put_contents($destinationFile, sprintf(' container_xml_path: %s', $containerXmlPath), FILE_APPEND); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/Command/UninstallCommand.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | final class UninstallCommand extends AbstractCommand 16 | { 17 | /** 18 | * {@inheritdoc} 19 | */ 20 | protected static $defaultName = 'uninstall'; 21 | 22 | /** 23 | * {@inheritdoc} 24 | */ 25 | protected function configure(): void 26 | { 27 | $this 28 | ->setDescription('Remove configuration files of SymfonyGrumPHP') 29 | ->setHelp('The uninstall command removes preconfigured files from root folder of a project.'); 30 | } 31 | 32 | /** 33 | * {@inheritdoc} 34 | */ 35 | protected function execute(InputInterface $input, OutputInterface $output) 36 | { 37 | $helper = $this->getHelper('question'); 38 | $question = new ConfirmationQuestion('Do you want to remove configuration files? (yes/no) [yes]: '); 39 | if ($helper->ask($input, $output, $question)) { 40 | $filesystem = new Filesystem(); 41 | foreach (self::CONF_FILES as $file) { 42 | $destinationFile = self::normalizeDestinationFile($file); 43 | $filesystem->remove($destinationFile); 44 | $filesystem->remove(sprintf('%s.scbak', $file)); 45 | $output->writeln(sprintf('Files [%s, %s.scbak] have been deleted.', $file, $file)); 46 | } 47 | } 48 | 49 | return 0; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/dist/.php_cs: -------------------------------------------------------------------------------- 1 | exclude(['var', 'public', 'vendor']) 6 | ->in(__DIR__); 7 | 8 | return PhpCsFixer\Config::create() 9 | ->setFinder($finder); 10 | // @codeCoverageIgnoreEnd 11 | -------------------------------------------------------------------------------- /src/dist/grumphp.yml: -------------------------------------------------------------------------------- 1 | # https://github.com/phpro/grumphp 2 | grumphp: 3 | stop_on_failure: false 4 | process_timeout: 120 5 | parallel: 6 | enabled: true 7 | max_workers: 20 8 | # https://github.com/phpro/grumphp/blob/master/doc/tasks.md 9 | tasks: 10 | clover_coverage: 11 | clover_file: ./build/logs/clover.xml 12 | level: 70 13 | metadata: 14 | priority: 1 15 | git_blacklist: 16 | keywords: 17 | - "die\\(" 18 | - "var_dump\\(" 19 | - "exit;" 20 | - "echo " 21 | - "dump\\(" 22 | - "dd\\(" 23 | regexp_type: G 24 | whitelist_patterns: 25 | - /^public\/(.*)/ 26 | - /^vendor\/(.*)/ 27 | metadata: 28 | priority: 999 29 | phpcpd: 30 | directory: ['.'] 31 | exclude: ['vendor', 'public', 'var', 'config', 'bin', 'translations', 'src/Presentation/Translations', 'src/Migrations', 'src/Infrastructure/Migrations', 'tests', 'src/DataFixtures', 'migrations'] 32 | fuzzy: false 33 | min_lines: 5 34 | min_tokens: 50 35 | metadata: 36 | priority: 999 37 | phpcsfixer: 38 | rules: 39 | - '@PhpCsFixer' 40 | - -multiline_whitespace_before_semicolons 41 | - -php_unit_internal_class 42 | - -php_unit_test_class_requires_covers 43 | - -no_superfluous_phpdoc_tags 44 | - '@DoctrineAnnotation' 45 | verbose: true 46 | diff: true 47 | config: .php_cs 48 | metadata: 49 | priority: 999 50 | phplint: 51 | triggered_by: ['php', 'phtml', 'php3', 'php4', 'php5'] 52 | metadata: 53 | priority: 999 54 | phpmd: 55 | exclude: ['tests', 'config', 'var', 'src/Migrations', 'src/Infrastructure/Migrations', 'migrations'] 56 | ruleset: ['cleancode', 'codesize', 'controversial', 'design', 'unusedcode'] 57 | metadata: 58 | priority: 999 59 | phpstan: 60 | configuration: phpstan.neon 61 | level: 7 62 | memory_limit: '-1' 63 | metadata: 64 | priority: 999 65 | phpunitbridge: 66 | config_file: phpunit.xml.dist 67 | testsuite: Application 68 | always_execute: true 69 | metadata: 70 | priority: 999 71 | securitychecker_enlightn: 72 | lockfile: composer.lock 73 | run_always: false 74 | metadata: 75 | priority: 999 76 | shell: 77 | scripts: 78 | - ['-c', './vendor/bin/simple-phpunit --coverage-clover ./build/logs/clover.xml'] 79 | metadata: 80 | priority: 2 81 | # https://github.com/phpro/grumphp/blob/master/doc/testsuites.md 82 | testsuites: 83 | security: 84 | tasks: 85 | - securitychecker_enlightn 86 | phpunitbridge: 87 | tasks: 88 | - phpunitbridge 89 | phpcsmd: 90 | tasks: 91 | - phpcsfixer 92 | - phpmd 93 | no-phpunitbridge: 94 | tasks: 95 | - git_blacklist 96 | - phpcpd 97 | - phpcsfixer 98 | - phplint 99 | - phpmd 100 | - phpstan 101 | - securitychecker_enlightn 102 | phpcsfixer: 103 | tasks: 104 | - phpcsfixer 105 | phpstan: 106 | tasks: 107 | - phpstan 108 | coverage: 109 | tasks: 110 | - shell 111 | - clover_coverage 112 | no-coverage: 113 | tasks: 114 | - git_blacklist 115 | - phpcpd 116 | - phpcsfixer 117 | - phplint 118 | - phpmd 119 | - phpstan 120 | - phpunitbridge 121 | - securitychecker_enlightn 122 | -------------------------------------------------------------------------------- /src/dist/phpstan.neon: -------------------------------------------------------------------------------- 1 | includes: 2 | - vendor/phpstan/phpstan-doctrine/extension.neon 3 | - vendor/phpstan/phpstan-doctrine/rules.neon 4 | - vendor/phpstan/phpstan-phpunit/extension.neon 5 | - vendor/phpstan/phpstan-phpunit/rules.neon 6 | - vendor/phpstan/phpstan-symfony/extension.neon 7 | - vendor/thecodingmachine/phpstan-strict-rules/phpstan-strict-rules.neon 8 | 9 | parameters: 10 | checkGenericClassInNonGenericObjectType: false 11 | inferPrivatePropertyTypeFromConstructor: true 12 | checkMissingIterableValueType: false 13 | excludes_analyse: 14 | - %rootDir%/../../../bin/* 15 | - %rootDir%/../../../var/* 16 | - %rootDir%/../../../public/* 17 | - %rootDir%/../../../config/* 18 | - %rootDir%/../../../vendor/* 19 | - %rootDir%/../../../tests/* 20 | - %rootDir%/../../../php_cs.php 21 | ignoreErrors: 22 | - '#PHPDoc tag @return with type object is not subtype of native type#' 23 | - '#Method .* should return .* but returns object#' 24 | - '#Method .* should return .* but returns .*ObjectRepository#' 25 | - '#PHPDoc tag @return with type .*ObjectRepository is not subtype of native type .*Repository#' 26 | - '#PHPDoc tag @throws with type .* is not subtype of Throwable#' 27 | - '#call_user_func_array expects callable\(\)#' 28 | - '#expects App\\Entity\\User, Symfony\\Component\\Security\\Core\\User\\UserInterface given.#' 29 | - '#ftp_fput expects resource#' 30 | - '#Call to an undefined method Doctrine\\ORM\\Event\\LifecycleEventArgs::getNewValue\(\)#' 31 | - '#Call to an undefined method Doctrine\\ORM\\Event\\LifecycleEventArgs::getOldValue\(\)#' 32 | - '#Property .*\\Entity\\.* has no typehint specified.#' 33 | - '#Call to an undefined method Doctrine\\Persistence\\ObjectRepositor.*#' 34 | - '#Method App\\.*Repository\(\).*should return App\\Repository\\.*Repository but returns Doctrine\\ORM\\EntityRepository.*#' 35 | - '#Symfony\\Component\\Security\\Core\\User\\UserInterface is not subtype of#' 36 | - '#Call to an undefined method Knp\\Bundle\\PaginatorBundle\\Pagination\\SlidingPaginationInterface.*#' 37 | - '#Call to an undefined method DateTimeInterface::add\(\)#' 38 | - '#string\|Stringable\|Symfony\\Component\\Security\\Core\\User\\UserInterface#' 39 | - '#Variable .* in PHPDoc tag @var does not exist#' 40 | -------------------------------------------------------------------------------- /src/dist/phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | tests/ 24 | 25 | 26 | 27 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 43 | 44 | . 45 | 46 | 47 | 48 | ./tests 49 | ./vendor 50 | ./public 51 | ./config 52 | ./var 53 | ./bin 54 | ./migrations 55 | ./src/Infrastructure/Migrations 56 | ./src/Migrations 57 | ./src/DataFixtures 58 | ./src/Entity 59 | ./src/Domain/Entity 60 | ./src/DTO 61 | ./src/Kernel.php 62 | ./src/dist 63 | ./php_cs.php 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /tests/Command/InstallCommandTest.php: -------------------------------------------------------------------------------- 1 | assertSame('install', $command->getName()); 19 | } 20 | 21 | public function testExecute() 22 | { 23 | $application = new Application(); 24 | $application->add(new InstallCommand()); 25 | 26 | $command = $application->find('install'); 27 | $commandTester = new CommandTester($command); 28 | $commandTester->setInputs(['yes', 'yes', 'yes', 'yes', 'yes']); 29 | $commandTester->execute(['command' => $command->getName()]); 30 | 31 | $this->assertSame(0, $commandTester->getStatusCode()); 32 | 33 | $expectedOutput = 34 | 'File [grumphp.yml] exists. Do you want override file? (yes/no) [yes]: File [grumphp.yml] has been created. 35 | File [.php_cs] exists. Do you want override file? (yes/no) [yes]: File [.php_cs] has been created. 36 | File [phpstan.neon] exists. Do you want override file? (yes/no) [yes]: File [phpstan.neon] has been created. 37 | File [phpunit.xml.dist] exists. Do you want override file? (yes/no) [yes]: File [phpunit.xml.dist] has been created. 38 | '; 39 | $this->assertSame($expectedOutput, $commandTester->getDisplay()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/Command/UninstallCommandTest.php: -------------------------------------------------------------------------------- 1 | assertSame('uninstall', $command->getName()); 20 | } 21 | 22 | public function testExecute() 23 | { 24 | $application = new Application(); 25 | $application->add(new UninstallCommand()); 26 | 27 | $command = $application->find('uninstall'); 28 | $commandTester = new CommandTester($command); 29 | $commandTester->setInputs(['yes', 'yes', 'yes', 'yes', 'yes']); 30 | $commandTester->execute(['command' => $command->getName()]); 31 | 32 | $this->assertSame(0, $commandTester->getStatusCode()); 33 | 34 | $expectedOutput = 35 | 'Do you want to remove configuration files? (yes/no) [yes]: Files [grumphp.yml, grumphp.yml.scbak] have been deleted. 36 | Files [.php_cs, .php_cs.scbak] have been deleted. 37 | Files [phpstan.neon, phpstan.neon.scbak] have been deleted. 38 | Files [phpunit.xml.dist, phpunit.xml.dist.scbak] have been deleted. 39 | '; 40 | $this->assertSame($expectedOutput, $commandTester->getDisplay()); 41 | 42 | // revert removed files 43 | $application->add(new InstallCommand()); 44 | 45 | $command = $application->find('install'); 46 | $commandTester = new CommandTester($command); 47 | $commandTester->setInputs(['yes', 'yes', 'yes', 'yes', 'yes']); 48 | $commandTester->execute(['command' => $command->getName()]); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 |