diff --git a/tests/IntegrationTest/RegisterExternalStandardsTest.php b/tests/IntegrationTest/RegisterExternalStandardsTest.php
index e2841dd6..63b5e62b 100644
--- a/tests/IntegrationTest/RegisterExternalStandardsTest.php
+++ b/tests/IntegrationTest/RegisterExternalStandardsTest.php
@@ -27,6 +27,22 @@ final class RegisterExternalStandardsTest extends TestCase
),
);
+ private $configOneStandardMultiRuleset = array(
+ 'name' => 'phpcs-composer-installer/register-external-stnds-multistnd',
+ 'require-dev' => array(
+ 'squizlabs/php_codesniffer' => null,
+ 'phpcs-composer-installer/multistandard' => '*',
+ ),
+ );
+
+ private $configOneStandardInSrcSubdir = array(
+ 'name' => 'phpcs-composer-installer/register-external-stnds-in-src-subdir',
+ 'require-dev' => array(
+ 'squizlabs/php_codesniffer' => null,
+ 'phpcs-composer-installer/dummy-src' => '*',
+ ),
+ );
+
/**
* Set up test environment before each test.
*/
@@ -188,4 +204,141 @@ public function dataRegisterOneStandard()
$versions = PHPCSVersions::get(2, true, true);
return PHPCSVersions::toDataprovider($versions);
}
+
+ /**
+ * Test registering one external standard with multiple rulesets.
+ *
+ * @dataProvider dataRegisterOneStandardMultipleRulesets
+ *
+ * @param string $phpcsVersion PHPCS version to use in this test.
+ * This version is randomly selected from the PHPCS versions compatible
+ * with the PHP version used in the test.
+ *
+ * @return void
+ */
+ public function testRegisterOneStandardWithMultipleRulesets($phpcsVersion)
+ {
+ $config = $this->configOneStandardMultiRuleset;
+ $config['require-dev']['squizlabs/php_codesniffer'] = $phpcsVersion;
+
+ $this->writeComposerJsonFile($config, static::$tempLocalPath);
+
+ // Install the dependencies and verify that the plugin has run.
+ $expectedStdOut = $this->willPluginOutputShow() ? 'PHP CodeSniffer Config installed_paths set to ' : null;
+ $this->assertExecute(
+ sprintf('composer install -v --no-ansi --working-dir=%s', escapeshellarg(static::$tempLocalPath)),
+ 0, // Expected exit code.
+ $expectedStdOut, // Expectation for stdout.
+ null, // No stderr expectation.
+ 'Failed to install dependencies.'
+ );
+
+ // Verify that only the one path is registered.
+ $result = $this->executeCliCommand('"vendor/bin/phpcs" --config-show', static::$tempLocalPath);
+ $this->assertSame(0, $result['exitcode'], 'Exitcode for "phpcs --config-show" did not match 0');
+
+ $expected = array(
+ '/phpcs-composer-installer/multistandard',
+ );
+
+ $this->assertSame(
+ $expected,
+ $this->configShowToPathsArray($result['stdout']),
+ 'Paths as updated by the plugin does not contain the expected path'
+ );
+
+ // Verify that PHPCS sees all three external standards.
+ $result = $this->executeCliCommand('"vendor/bin/phpcs" -i', static::$tempLocalPath);
+ $this->assertSame(0, $result['exitcode'], 'Exitcode for "phpcs -i" did not match 0');
+
+ $expected = PHPCSVersions::getStandards($phpcsVersion);
+ $expected[] = 'MyFirstStandard';
+ $expected[] = 'MySecondStandard';
+ $expected[] = 'My-Third-Standard';
+ sort($expected, \SORT_NATURAL);
+
+ $this->assertSame(
+ $expected,
+ $this->standardsPhraseToArray($result['stdout']),
+ 'Installed standards do not match the expected standards.'
+ );
+ }
+
+ /**
+ * Data provider.
+ *
+ * @return array
+ */
+ public function dataRegisterOneStandardMultipleRulesets()
+ {
+ // Test against the highest and lowest supported PHPCS version of each major + PHPCS 4.x dev.
+ $versions = PHPCSVersions::getHighLowEachMajor(false, true);
+ return PHPCSVersions::toDataprovider($versions);
+ }
+
+ /**
+ * Test registering an external standard which has the ruleset in a subdirectory nested in `src`.
+ *
+ * @dataProvider dataRandomPHPCSVersion
+ *
+ * @param string $phpcsVersion PHPCS version to use in this test.
+ *
+ * @return void
+ */
+ public function testRegisterOneStandardInSrcSubdir($phpcsVersion)
+ {
+ $config = $this->configOneStandardInSrcSubdir;
+ $config['require-dev']['squizlabs/php_codesniffer'] = $phpcsVersion;
+
+ $this->writeComposerJsonFile($config, static::$tempGlobalPath);
+
+ // Install the dependencies and verify that the plugin has run.
+ $this->assertExecute(
+ 'composer global install -v --no-ansi',
+ 0, // Expected exit code.
+ 'PHP CodeSniffer Config installed_paths set to ', // Expectation for stdout.
+ null, // No stderr expectation.
+ 'Failed to install dependencies.'
+ );
+
+ // Verify that the path for the directory above the ruleset is registered.
+ $result = $this->executeCliCommand('"vendor/bin/phpcs" --config-show', static::$tempGlobalPath);
+ $this->assertSame(0, $result['exitcode'], 'Exitcode for "phpcs --config-show" did not match 0');
+
+ $expected = array(
+ '/phpcs-composer-installer/dummy-src/src',
+ );
+
+ $this->assertSame(
+ $expected,
+ $this->configShowToPathsArray($result['stdout']),
+ 'Paths as updated by the plugin does not contain the expected path'
+ );
+
+ // Verify that PHPCS sees the external standard.
+ $result = $this->executeCliCommand('"vendor/bin/phpcs" -i', static::$tempGlobalPath);
+ $this->assertSame(0, $result['exitcode'], 'Exitcode for "phpcs -i" did not match 0');
+
+ $expected = PHPCSVersions::getStandards($phpcsVersion);
+ $expected[] = 'DummySrcSubDir';
+ sort($expected, \SORT_NATURAL);
+
+ $this->assertSame(
+ $expected,
+ $this->standardsPhraseToArray($result['stdout']),
+ 'Installed standards do not match the expected standards.'
+ );
+ }
+
+ /**
+ * Data provider.
+ *
+ * @return array
+ */
+ public function dataRandomPHPCSVersion()
+ {
+ // Test against one random PHPCS version.
+ $versions = array(PHPCSVersions::getRandom(true, true));
+ return PHPCSVersions::toDataprovider($versions);
+ }
}
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 57b00c04..540e9112 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -579,4 +579,47 @@ protected function standardsPhraseToArray($phrase)
return $standards;
}
+
+ /**
+ * Retrieve a list of the paths registered with PHPCS based on the output of `phpcs --config-show`.
+ *
+ * @param string $configShow The `stdout` output of `phpcs --config-show`.
+ *
+ * @return array Numerically indexed array of paths, stripped of absolute/relative path differences,
+ * natural sort applied.
+ *
+ * @throws RuntimeException When the passed argument is not a string.
+ */
+ protected function configShowToPathsArray($configShow)
+ {
+ if (is_string($configShow) === false) {
+ throw new RuntimeException('The config-show input must be a string.');
+ }
+
+ if (preg_match('`installed_paths:\s+([^\n\r]+)\s+`', $configShow, $matches) !== 1) {
+ return array();
+ }
+
+ $pathsAsArray = explode(',', $matches[1]);
+ $pathsAsArray = array_map(
+ function ($value) {
+ $search = array(
+ '`^[^\r\n]+/vendor/`',
+ '`^\.\./\.\./`',
+ );
+
+ $replaced = preg_replace($search, '/', $value);
+ if ($replaced === null) {
+ return $value;
+ }
+
+ return trim($replaced); // Trim off whitespace just to be on the safe side.
+ },
+ $pathsAsArray
+ );
+
+ sort($pathsAsArray, \SORT_NATURAL);
+
+ return $pathsAsArray;
+ }
}
diff --git a/tests/fixtures/README.md b/tests/fixtures/README.md
index 6a470872..92944a9c 100644
--- a/tests/fixtures/README.md
+++ b/tests/fixtures/README.md
@@ -40,3 +40,25 @@ An external PHPCS standard with the `ruleset.xml` file in a subdirectory ("norma
| **Includes sniff(s):** | :heavy_checkmark: One sniff - `DummySubDir.Demo.Demo` - which is PHPCS cross-version compatible. |
| **Requires the plugin:** | :x: |
+### Package name: `phpcs-composer-installer/multistandard`
+
+**Description:**
+An external PHPCS standard with multiple rulesets, each in a subdirectory ("normal" standard setup).
+
+| Characteristics | Notes |
+|--------------------------|------------------------------------------------------------|
+| **Standard(s):** | `MyFirstStandard`, `MySecondStandard`, `My-Third-Standard` |
+| **Includes sniff(s):** | :x: |
+| **Requires the plugin:** | :heavy_checkmark: |
+
+### Package name: `phpcs-composer-installer/dummy-src`
+
+**Description:**
+An external PHPCS standard with the `ruleset.xml` file in a deeper nested subdirectory.
+
+| Characteristics | Notes |
+|--------------------------|-------------------|
+| **Standard(s):** | `DummySrcSubDir` |
+| **Includes sniff(s):** | :x: |
+| **Requires the plugin:** | :heavy_checkmark: |
+
diff --git a/tests/fixtures/dummy-src/composer.json b/tests/fixtures/dummy-src/composer.json
new file mode 100644
index 00000000..9ded9e25
--- /dev/null
+++ b/tests/fixtures/dummy-src/composer.json
@@ -0,0 +1,16 @@
+{
+ "name" : "phpcs-composer-installer/dummy-src",
+ "description" : "Dummy PHPCS standard with deeper nested subdirectory ruleset for use in the tests.",
+ "type" : "phpcodesniffer-standard",
+ "license" : "MIT",
+ "require" : {
+ "php" : ">=5.4",
+ "squizlabs/php_codesniffer" : "*",
+ "dealerdirect/phpcodesniffer-composer-installer" : "*"
+ },
+ "config": {
+ "allow-plugins": {
+ "dealerdirect/phpcodesniffer-composer-installer": true
+ }
+ }
+}
diff --git a/tests/fixtures/dummy-src/src/DummySrcSubDir/ruleset.xml b/tests/fixtures/dummy-src/src/DummySrcSubDir/ruleset.xml
new file mode 100644
index 00000000..3e434f11
--- /dev/null
+++ b/tests/fixtures/dummy-src/src/DummySrcSubDir/ruleset.xml
@@ -0,0 +1,5 @@
+
+
+
+ Dummy PHPCS standard for testing.
+
diff --git a/tests/fixtures/multistandard/My-Third-Standard/ruleset.xml b/tests/fixtures/multistandard/My-Third-Standard/ruleset.xml
new file mode 100644
index 00000000..ca6a9818
--- /dev/null
+++ b/tests/fixtures/multistandard/My-Third-Standard/ruleset.xml
@@ -0,0 +1,5 @@
+
+
+
+ Dummy PHPCS standard for testing.
+
diff --git a/tests/fixtures/multistandard/MyFirstStandard/ruleset.xml b/tests/fixtures/multistandard/MyFirstStandard/ruleset.xml
new file mode 100644
index 00000000..424ac051
--- /dev/null
+++ b/tests/fixtures/multistandard/MyFirstStandard/ruleset.xml
@@ -0,0 +1,5 @@
+
+
+
+ Dummy PHPCS standard for testing.
+
diff --git a/tests/fixtures/multistandard/MySecondStandard/ruleset.xml b/tests/fixtures/multistandard/MySecondStandard/ruleset.xml
new file mode 100644
index 00000000..462d4141
--- /dev/null
+++ b/tests/fixtures/multistandard/MySecondStandard/ruleset.xml
@@ -0,0 +1,5 @@
+
+
+
+ Dummy PHPCS standard for testing.
+
diff --git a/tests/fixtures/multistandard/composer.json b/tests/fixtures/multistandard/composer.json
new file mode 100644
index 00000000..f56d04c3
--- /dev/null
+++ b/tests/fixtures/multistandard/composer.json
@@ -0,0 +1,16 @@
+{
+ "name" : "phpcs-composer-installer/multistandard",
+ "description" : "Dummy PHPCS standard with multiple rulesets each in a subdirectory for use in the tests.",
+ "type" : "phpcodesniffer-standard",
+ "license" : "MIT",
+ "require" : {
+ "php" : ">=5.4",
+ "squizlabs/php_codesniffer" : "*",
+ "dealerdirect/phpcodesniffer-composer-installer" : "*"
+ },
+ "config": {
+ "allow-plugins": {
+ "dealerdirect/phpcodesniffer-composer-installer": true
+ }
+ }
+}