diff --git a/.github/workflows/integrate.yaml b/.github/workflows/integrate.yaml
index 6129f6dc..667bd150 100644
--- a/.github/workflows/integrate.yaml
+++ b/.github/workflows/integrate.yaml
@@ -311,3 +311,6 @@ jobs:
- name: "Run unit tests with phpunit/phpunit"
run: "vendor/bin/phpunit --colors=always --configuration=test/Unit/phpunit.xml"
+
+ - name: "Run end-to-end tests with phpunit/phpunit"
+ run: "vendor/bin/phpunit --colors=always --configuration=test/EndToEnd/phpunit.xml"
diff --git a/Makefile b/Makefile
index 81a9c8ff..39dab100 100644
--- a/Makefile
+++ b/Makefile
@@ -32,9 +32,10 @@ static-code-analysis-baseline: vendor ## Generates a baseline for static code an
vendor/bin/psalm --config=psalm.xml --set-baseline=psalm-baseline.xml
.PHONY: tests
-tests: vendor ## Runs unit tests with phpunit/phpunit
+tests: vendor ## Runs unit and end-to-end tests with phpunit/phpunit
mkdir -p .build/phpunit
vendor/bin/phpunit --configuration=test/Unit/phpunit.xml
+ vendor/bin/phpunit --configuration=test/EndToEnd/phpunit.xml
vendor: composer.json composer.lock
composer validate --strict
diff --git a/composer.json b/composer.json
index 96fe374b..b1e99d55 100644
--- a/composer.json
+++ b/composer.json
@@ -26,6 +26,7 @@
"phpunit/phpunit": "^9.5.27",
"psalm/plugin-phpunit": "~0.18.4",
"symfony/filesystem": "^5.0.0 || ^6.0.0",
+ "symfony/process": "^5.0.0 || ^6.0.0",
"vimeo/psalm": "^5.4.0"
},
"autoload": {
diff --git a/composer.lock b/composer.lock
index 9c48498c..02fa2dd0 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": "a600ca8c849c1dfc15689ffe5585bcae",
+ "content-hash": "2a2e8f16725addadee5948e16fa1c631",
"packages": [
{
"name": "composer/pcre",
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index 38372f47..1cfb4970 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -10,6 +10,11 @@
$rules
+
+
+ Console\Command\FixCommandExitStatusCalculator::EXIT_STATUS_FLAG_HAS_INVALID_CONFIG
+
+
new FixerFactory()
diff --git a/test/EndToEnd/RuleSet/AbstractRuleSetTestCase.php b/test/EndToEnd/RuleSet/AbstractRuleSetTestCase.php
new file mode 100644
index 00000000..3467b953
--- /dev/null
+++ b/test/EndToEnd/RuleSet/AbstractRuleSetTestCase.php
@@ -0,0 +1,151 @@
+mkdir(self::temporaryDirectory());
+
+ self::fileSystem()->dumpFile(
+ self::configPath(),
+ self::configContents(),
+ );
+ }
+
+ final protected function tearDown(): void
+ {
+ self::fileSystem()->remove(self::temporaryDirectory());
+ }
+
+ final public function testConfigurationIsConsideredValid(): void
+ {
+ $process = new Process\Process([
+ 'vendor/bin/php-cs-fixer',
+ 'fix',
+ \sprintf(
+ '--config=%s',
+ self::configPath(),
+ ),
+ '--dry-run',
+ ]);
+
+ $process->run();
+
+ $exitCode = $process->getExitCode();
+
+ self::assertNotNull($exitCode);
+ self::assertSame(0, Console\Command\FixCommandExitStatusCalculator::EXIT_STATUS_FLAG_HAS_INVALID_CONFIG & $exitCode, \sprintf(
+ 'Failed asserting that the configuration in "%s" is considered valid by friendsofphp/php-cs-fixer.',
+ self::className(),
+ ));
+ }
+
+ private static function fileSystem(): Filesystem\Filesystem
+ {
+ return new Filesystem\Filesystem();
+ }
+
+ private static function configPath(): string
+ {
+ return \sprintf(
+ '%s/.php-cs-fixer.php',
+ self::temporaryDirectory(),
+ );
+ }
+
+ private static function configContents(): string
+ {
+ return \sprintf(
+ <<<'PHP'
+getFinder()
+ ->exclude([
+ '.build/',
+ '.github/',
+ '.notes/',
+ ])
+ ->ignoreDotFiles(false)
+ ->in('%s')
+ ->name('.php-cs-fixer.php');
+
+$config->setUsingCache(false);
+
+return $config;
+PHP
+ ,
+ self::className(),
+ self::projectDirectory(),
+ );
+ }
+
+ /**
+ * @psalm-return class-string
+ *
+ * @throws \RuntimeException
+ */
+ private static function className(): string
+ {
+ $className = \preg_replace(
+ '/Test$/',
+ '',
+ \str_replace(
+ '\Test\EndToEnd',
+ '',
+ static::class,
+ ),
+ );
+
+ if (!\is_string($className)) {
+ throw new \RuntimeException(\sprintf(
+ 'Failed resolving class name from test class name "%s".',
+ static::class,
+ ));
+ }
+
+ if (!\class_exists($className)) {
+ throw new \RuntimeException(\sprintf(
+ 'Class name "%s" resolved from test class name "%s" does not reference a class that exists.',
+ $className,
+ static::class,
+ ));
+ }
+
+ return $className;
+ }
+
+ private static function projectDirectory(): string
+ {
+ return __DIR__ . '/../../..';
+ }
+
+ private static function temporaryDirectory(): string
+ {
+ return __DIR__ . '/../../../.build/test';
+ }
+}
diff --git a/test/EndToEnd/RuleSet/Php80Test.php b/test/EndToEnd/RuleSet/Php80Test.php
new file mode 100644
index 00000000..071562ed
--- /dev/null
+++ b/test/EndToEnd/RuleSet/Php80Test.php
@@ -0,0 +1,25 @@
+
+
+
+ .
+
+
+