diff --git a/.markdownlint-cli2.yaml b/.markdownlint-cli2.yaml
index 80c4690430..511a12dd47 100644
--- a/.markdownlint-cli2.yaml
+++ b/.markdownlint-cli2.yaml
@@ -19,6 +19,7 @@ showFound: true
ignores:
- "node_modules/"
- "vendor/"
+ - "tests/Core/Generators/Expectations/"
# Disable inline config comments.
noInlineConfig: true
diff --git a/src/Generators/HTML.php b/src/Generators/HTML.php
index 2a4a8076da..cab4abfd91 100644
--- a/src/Generators/HTML.php
+++ b/src/Generators/HTML.php
@@ -133,7 +133,7 @@ protected function printHeader()
echo ''.PHP_EOL;
echo '
'.PHP_EOL;
echo " $standard Coding Standards".PHP_EOL;
- echo ' '.self::STYLESHEET.PHP_EOL;
+ echo ' '.str_replace("\n", PHP_EOL, self::STYLESHEET).PHP_EOL;
echo ' '.PHP_EOL;
echo ' '.PHP_EOL;
echo " $standard Coding Standards
".PHP_EOL;
@@ -226,6 +226,9 @@ protected function printTextBlock(DOMNode $node)
$content = trim($node->nodeValue);
$content = htmlspecialchars($content);
+ // Use the correct line endings based on the OS.
+ $content = str_replace("\n", PHP_EOL, $content);
+
// Allow em tags only.
$content = str_replace('<em>', '', $content);
$content = str_replace('</em>', '', $content);
diff --git a/src/Generators/Markdown.php b/src/Generators/Markdown.php
index a9839a81a4..40fccd222a 100644
--- a/src/Generators/Markdown.php
+++ b/src/Generators/Markdown.php
@@ -111,6 +111,9 @@ protected function printTextBlock(DOMNode $node)
$content = trim($node->nodeValue);
$content = htmlspecialchars($content);
+ // Use the correct line endings based on the OS.
+ $content = str_replace("\n", PHP_EOL, $content);
+
$content = str_replace('<em>', '*', $content);
$content = str_replace('</em>', '*', $content);
@@ -132,13 +135,13 @@ protected function printCodeComparisonBlock(DOMNode $node)
$firstTitle = $codeBlocks->item(0)->getAttribute('title');
$first = trim($codeBlocks->item(0)->nodeValue);
- $first = str_replace("\n", "\n ", $first);
+ $first = str_replace("\n", PHP_EOL.' ', $first);
$first = str_replace('', '', $first);
$first = str_replace('', '', $first);
$secondTitle = $codeBlocks->item(1)->getAttribute('title');
$second = trim($codeBlocks->item(1)->nodeValue);
- $second = str_replace("\n", "\n ", $second);
+ $second = str_replace("\n", PHP_EOL.' ', $second);
$second = str_replace('', '', $second);
$second = str_replace('', '', $second);
diff --git a/tests/Core/Generators/Expectations/ExpectedOutputEmpty.txt b/tests/Core/Generators/Expectations/ExpectedOutputEmpty.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/Core/Generators/Expectations/ExpectedOutputNoDocs.html b/tests/Core/Generators/Expectations/ExpectedOutputNoDocs.html
new file mode 100644
index 0000000000..060de7aa63
--- /dev/null
+++ b/tests/Core/Generators/Expectations/ExpectedOutputNoDocs.html
@@ -0,0 +1,78 @@
+
+
+ GeneratorTest Coding Standards
+
+
+
+ GeneratorTest Coding Standards
+ Table of Contents
+
+
+
+
diff --git a/tests/Core/Generators/Expectations/ExpectedOutputNoDocs.md b/tests/Core/Generators/Expectations/ExpectedOutputNoDocs.md
new file mode 100644
index 0000000000..ece2692187
--- /dev/null
+++ b/tests/Core/Generators/Expectations/ExpectedOutputNoDocs.md
@@ -0,0 +1,2 @@
+# GeneratorTest Coding Standard
+Documentation generated on *REDACTED* by [PHP_CodeSniffer *VERSION*](https://github.com/PHPCSStandards/PHP_CodeSniffer)
diff --git a/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.html b/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.html
new file mode 100644
index 0000000000..772d3861ec
--- /dev/null
+++ b/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.html
@@ -0,0 +1,82 @@
+
+
+ GeneratorTest Coding Standards
+
+
+
+ GeneratorTest Coding Standards
+ Table of Contents
+
+
+ One Standard Block, No Code
+ Documentation contains one standard block and no code comparison.
+
+
+
diff --git a/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.md b/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.md
new file mode 100644
index 0000000000..f8deb0ce20
--- /dev/null
+++ b/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.md
@@ -0,0 +1,5 @@
+# GeneratorTest Coding Standard
+
+## One Standard Block, No Code
+Documentation contains one standard block and no code comparison.
+Documentation generated on *REDACTED* by [PHP_CodeSniffer *VERSION*](https://github.com/PHPCSStandards/PHP_CodeSniffer)
diff --git a/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.txt b/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.txt
new file mode 100644
index 0000000000..75bbdcb003
--- /dev/null
+++ b/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.txt
@@ -0,0 +1,7 @@
+
+--------------------------------------------------------------
+| GENERATORTEST CODING STANDARD: ONE STANDARD BLOCK, NO CODE |
+--------------------------------------------------------------
+
+Documentation contains one standard block and no code comparison.
+
diff --git a/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.html b/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.html
new file mode 100644
index 0000000000..b17d05212a
--- /dev/null
+++ b/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.html
@@ -0,0 +1,178 @@
+
+
+ GeneratorTest Coding Standards
+
+
+
+ GeneratorTest Coding Standards
+ Table of Contents
+
+
+ No Content
+
+ One Standard Block, Code Comparison
+ Documentation contains one standard block and one code comparison.
+
+
+ Valid: Lorem ipsum dolor sit amet. |
+ Invalid: Maecenas non rutrum dolor. |
+
+
+ class Code {} |
+ class Comparison {} |
+
+
+
+ One Standard Block, No Code
+ Documentation contains one standard block and no code comparison.
+
+ One Standard Block, Two Code Comparisons
+ Documentation contains one standard block and two code comparisons.
+
+
+ Valid: Etiam commodo magna at vestibulum blandit. |
+ Invalid: Vivamus lacinia ante velit. |
+
+
+ class Code {} |
+ class Comparison {} |
+
+
+
+
+ Valid: Pellentesque nisi neque. |
+ Invalid: Mauris dictum metus quis maximus pharetra. |
+
+
+ $one = 10; |
+ $a = 10; |
+
+
+
+ Two Standard Blocks, No Code
+ This is standard block one.
+ This is standard block two.
+
+ Two Standard Blocks, One Code Comparison
+ This is standard block one.
+
+
+ Valid: Vestibulum et orci condimentum. |
+ Invalid: Donec in nisl ut tortor convallis interdum. |
+
+
+ class Code {} |
+ class Comparison {} |
+
+
+ This is standard block two.
+
+ Two Standard Blocks, Three Code Comparisons
+ This is standard block one.
+
+
+ Valid: Vestibulum et orci condimentum. |
+ Invalid: Donec in nisl ut tortor convallis interdum. |
+
+
+ class Code {} |
+ class Comparison {} |
+
+
+ This is standard block two.
+
+
+ Valid: Pellentesque nisi neque. |
+ Invalid: Mauris dictum metus quis maximus pharetra. |
+
+
+ $one = 10; |
+ $a = 10; |
+
+
+
+
+ Valid: Quisque sagittis nisi vitae. |
+ Invalid: Morbi ac libero vitae lorem. |
+
+
+ echo $foo; |
+ print $foo; |
+
+
+
+
+
diff --git a/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.md b/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.md
new file mode 100644
index 0000000000..9b80a5e063
--- /dev/null
+++ b/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.md
@@ -0,0 +1,151 @@
+# GeneratorTest Coding Standard
+
+## No Content
+
+## One Standard Block, Code Comparison
+Documentation contains one standard block and one code comparison.
+
+
+ Valid: Lorem ipsum dolor sit amet. |
+ Invalid: Maecenas non rutrum dolor. |
+
+
+
+
+ class Code {}
+
+ |
+
+
+ class Comparison {}
+
+ |
+
+
+
+## One Standard Block, No Code
+Documentation contains one standard block and no code comparison.
+
+## One Standard Block, Two Code Comparisons
+Documentation contains one standard block and two code comparisons.
+
+
+ Valid: Etiam commodo magna at vestibulum blandit. |
+ Invalid: Vivamus lacinia ante velit. |
+
+
+
+
+ class Code {}
+
+ |
+
+
+ class Comparison {}
+
+ |
+
+
+
+
+ Valid: Pellentesque nisi neque. |
+ Invalid: Mauris dictum metus quis maximus pharetra. |
+
+
+
+
+ $one = 10;
+
+ |
+
+
+ $a = 10;
+
+ |
+
+
+
+## Two Standard Blocks, No Code
+This is standard block one.
+This is standard block two.
+
+## Two Standard Blocks, One Code Comparison
+This is standard block one.
+
+
+ Valid: Vestibulum et orci condimentum. |
+ Invalid: Donec in nisl ut tortor convallis interdum. |
+
+
+
+
+ class Code {}
+
+ |
+
+
+ class Comparison {}
+
+ |
+
+
+This is standard block two.
+
+## Two Standard Blocks, Three Code Comparisons
+This is standard block one.
+
+
+ Valid: Vestibulum et orci condimentum. |
+ Invalid: Donec in nisl ut tortor convallis interdum. |
+
+
+
+
+ class Code {}
+
+ |
+
+
+ class Comparison {}
+
+ |
+
+
+This is standard block two.
+
+
+ Valid: Pellentesque nisi neque. |
+ Invalid: Mauris dictum metus quis maximus pharetra. |
+
+
+
+
+ $one = 10;
+
+ |
+
+
+ $a = 10;
+
+ |
+
+
+
+
+ Valid: Quisque sagittis nisi vitae. |
+ Invalid: Morbi ac libero vitae lorem. |
+
+
+
+
+ echo $foo;
+
+ |
+
+
+ print $foo;
+
+ |
+
+
+Documentation generated on *REDACTED* by [PHP_CodeSniffer *VERSION*](https://github.com/PHPCSStandards/PHP_CodeSniffer)
diff --git a/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.txt b/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.txt
new file mode 100644
index 0000000000..44b402955a
--- /dev/null
+++ b/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.txt
@@ -0,0 +1,100 @@
+
+---------------------------------------------
+| GENERATORTEST CODING STANDARD: NO CONTENT |
+---------------------------------------------
+
+
+----------------------------------------------------------------------
+| GENERATORTEST CODING STANDARD: ONE STANDARD BLOCK, CODE COMPARISON |
+----------------------------------------------------------------------
+
+Documentation contains one standard block and one code comparison.
+
+----------------------------------------- CODE COMPARISON ------------------------------------------
+| Valid: Lorem ipsum dolor sit amet. | Invalid: Maecenas non rutrum dolor. |
+----------------------------------------------------------------------------------------------------
+| class Code {} | class Comparison {} |
+----------------------------------------------------------------------------------------------------
+
+
+--------------------------------------------------------------
+| GENERATORTEST CODING STANDARD: ONE STANDARD BLOCK, NO CODE |
+--------------------------------------------------------------
+
+Documentation contains one standard block and no code comparison.
+
+
+---------------------------------------------------------------------------
+| GENERATORTEST CODING STANDARD: ONE STANDARD BLOCK, TWO CODE COMPARISONS |
+---------------------------------------------------------------------------
+
+Documentation contains one standard block and two code comparisons.
+
+----------------------------------------- CODE COMPARISON ------------------------------------------
+| Valid: Etiam commodo magna at vestibulum | Invalid: Vivamus lacinia ante velit. |
+| blandit. | |
+----------------------------------------------------------------------------------------------------
+| class Code {} | class Comparison {} |
+----------------------------------------------------------------------------------------------------
+
+----------------------------------------- CODE COMPARISON ------------------------------------------
+| Valid: Pellentesque nisi neque. | Invalid: Mauris dictum metus quis maximus |
+| | pharetra. |
+----------------------------------------------------------------------------------------------------
+| $one = 10; | $a = 10; |
+----------------------------------------------------------------------------------------------------
+
+
+---------------------------------------------------------------
+| GENERATORTEST CODING STANDARD: TWO STANDARD BLOCKS, NO CODE |
+---------------------------------------------------------------
+
+This is standard block one.
+
+This is standard block two.
+
+
+---------------------------------------------------------------------------
+| GENERATORTEST CODING STANDARD: TWO STANDARD BLOCKS, ONE CODE COMPARISON |
+---------------------------------------------------------------------------
+
+This is standard block one.
+
+----------------------------------------- CODE COMPARISON ------------------------------------------
+| Valid: Vestibulum et orci condimentum. | Invalid: Donec in nisl ut tortor convallis |
+| | interdum. |
+----------------------------------------------------------------------------------------------------
+| class Code {} | class Comparison {} |
+----------------------------------------------------------------------------------------------------
+
+This is standard block two.
+
+
+------------------------------------------------------------------------------
+| GENERATORTEST CODING STANDARD: TWO STANDARD BLOCKS, THREE CODE COMPARISONS |
+------------------------------------------------------------------------------
+
+This is standard block one.
+
+----------------------------------------- CODE COMPARISON ------------------------------------------
+| Valid: Vestibulum et orci condimentum. | Invalid: Donec in nisl ut tortor convallis |
+| | interdum. |
+----------------------------------------------------------------------------------------------------
+| class Code {} | class Comparison {} |
+----------------------------------------------------------------------------------------------------
+
+This is standard block two.
+
+----------------------------------------- CODE COMPARISON ------------------------------------------
+| Valid: Pellentesque nisi neque. | Invalid: Mauris dictum metus quis maximus |
+| | pharetra. |
+----------------------------------------------------------------------------------------------------
+| $one = 10; | $a = 10; |
+----------------------------------------------------------------------------------------------------
+
+----------------------------------------- CODE COMPARISON ------------------------------------------
+| Valid: Quisque sagittis nisi vitae. | Invalid: Morbi ac libero vitae lorem. |
+----------------------------------------------------------------------------------------------------
+| echo $foo; | print $foo; |
+----------------------------------------------------------------------------------------------------
+
diff --git a/tests/Core/Generators/Fixtures/HTMLDouble.php b/tests/Core/Generators/Fixtures/HTMLDouble.php
new file mode 100644
index 0000000000..cb327efe42
--- /dev/null
+++ b/tests/Core/Generators/Fixtures/HTMLDouble.php
@@ -0,0 +1,46 @@
+
+ * @copyright 2024 Juliette Reinders Folmer. All rights reserved.
+ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
+ */
+
+namespace PHP_CodeSniffer\Tests\Core\Generators\Fixtures;
+
+use PHP_CodeSniffer\Generators\HTML;
+
+class HTMLDouble extends HTML
+{
+
+ /**
+ * Print the footer of the HTML page without the date or version nr to make the expectation fixtures stable.
+ *
+ * @return void
+ */
+ protected function printFooter()
+ {
+ // Turn off errors so we don't get timezone warnings if people
+ // don't have their timezone set.
+ $errorLevel = error_reporting(0);
+ echo ' '.PHP_EOL;
+ error_reporting($errorLevel);
+
+ echo ' '.PHP_EOL;
+ echo ''.PHP_EOL;
+ }
+
+ /**
+ * Print the _real_ footer of the HTML page.
+ *
+ * @return void
+ */
+ public function printRealFooter()
+ {
+ parent::printFooter();
+ }
+}
diff --git a/tests/Core/Generators/Fixtures/MarkdownDouble.php b/tests/Core/Generators/Fixtures/MarkdownDouble.php
new file mode 100644
index 0000000000..2b03c277bb
--- /dev/null
+++ b/tests/Core/Generators/Fixtures/MarkdownDouble.php
@@ -0,0 +1,40 @@
+
+ * @copyright 2024 Juliette Reinders Folmer. All rights reserved.
+ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
+ */
+
+namespace PHP_CodeSniffer\Tests\Core\Generators\Fixtures;
+
+use PHP_CodeSniffer\Generators\Markdown;
+
+class MarkdownDouble extends Markdown
+{
+
+ /**
+ * Print the markdown footer without the date or version nr to make the expectation fixtures stable.
+ *
+ * @return void
+ */
+ protected function printFooter()
+ {
+ // Turn off errors so we don't get timezone warnings if people
+ // don't have their timezone set.
+ error_reporting(0);
+ echo 'Documentation generated on *REDACTED*';
+ echo ' by [PHP_CodeSniffer *VERSION*](https://github.com/PHPCSStandards/PHP_CodeSniffer)'.PHP_EOL;
+ }
+
+ /**
+ * Print the _real_ footer of the markdown page.
+ *
+ * @return void
+ */
+ public function printRealFooter()
+ {
+ parent::printFooter();
+ }
+}
diff --git a/tests/Core/Generators/Fixtures/MockGenerator.php b/tests/Core/Generators/Fixtures/MockGenerator.php
new file mode 100644
index 0000000000..43534180a6
--- /dev/null
+++ b/tests/Core/Generators/Fixtures/MockGenerator.php
@@ -0,0 +1,29 @@
+
+ * @copyright 2024 Juliette Reinders Folmer. All rights reserved.
+ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
+ */
+
+namespace PHP_CodeSniffer\Tests\Core\Generators\Fixtures;
+
+use DOMNode;
+use PHP_CodeSniffer\Generators\Generator;
+
+class MockGenerator extends Generator
+{
+
+ /**
+ * Process the documentation for a single sniff.
+ *
+ * @param \DOMNode $doc The DOMNode object for the sniff.
+ *
+ * @return void
+ */
+ protected function processSniff(DOMNode $doc)
+ {
+ echo $this->getTitle($doc), PHP_EOL;
+ }
+}
diff --git a/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/NoContentStandard.xml b/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/NoContentStandard.xml
new file mode 100644
index 0000000000..83afee8e83
--- /dev/null
+++ b/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/NoContentStandard.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/NoDocumentationElementStandard.xml b/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/NoDocumentationElementStandard.xml
new file mode 100644
index 0000000000..ca8290f1b4
--- /dev/null
+++ b/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/NoDocumentationElementStandard.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockCodeComparisonStandard.xml b/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockCodeComparisonStandard.xml
new file mode 100644
index 0000000000..c3ce35cd71
--- /dev/null
+++ b/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockCodeComparisonStandard.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+ class Code {}
+ ]]>
+
+
+ class Comparison {}
+ ]]>
+
+
+
diff --git a/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockNoCodeStandard.xml b/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockNoCodeStandard.xml
new file mode 100644
index 0000000000..fc014949e7
--- /dev/null
+++ b/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockNoCodeStandard.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockTwoCodeComparisonsStandard.xml b/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockTwoCodeComparisonsStandard.xml
new file mode 100644
index 0000000000..19559e6720
--- /dev/null
+++ b/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockTwoCodeComparisonsStandard.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+ class Code {}
+ ]]>
+
+
+ class Comparison {}
+ ]]>
+
+
+
+
+ $one = 10;
+ ]]>
+
+
+ $a = 10;
+ ]]>
+
+
+
diff --git a/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksNoCodeStandard.xml b/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksNoCodeStandard.xml
new file mode 100644
index 0000000000..f5f621ecdc
--- /dev/null
+++ b/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksNoCodeStandard.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksOneCodeComparisonStandard.xml b/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksOneCodeComparisonStandard.xml
new file mode 100644
index 0000000000..a5b3a3216e
--- /dev/null
+++ b/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksOneCodeComparisonStandard.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ Code {}
+ ]]>
+
+
+ Comparison {}
+ ]]>
+
+
+
+
+
+
diff --git a/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksThreeCodeComparisonsStandard.xml b/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksThreeCodeComparisonsStandard.xml
new file mode 100644
index 0000000000..540ac7eaf7
--- /dev/null
+++ b/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksThreeCodeComparisonsStandard.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+ class Code {}
+ ]]>
+
+
+ class Comparison {}
+ ]]>
+
+
+
+
+
+
+
+ $one = 10;
+ ]]>
+
+
+ $a = 10;
+ ]]>
+
+
+
+
+ echo $foo;
+ ]]>
+
+
+ print $foo;
+ ]]>
+
+
+
diff --git a/tests/Core/Generators/Fixtures/StandardWithDocs/Sniffs/DummySniff.php b/tests/Core/Generators/Fixtures/StandardWithDocs/Sniffs/DummySniff.php
new file mode 100644
index 0000000000..1a2546b111
--- /dev/null
+++ b/tests/Core/Generators/Fixtures/StandardWithDocs/Sniffs/DummySniff.php
@@ -0,0 +1,25 @@
+
+
+
+
diff --git a/tests/Core/Generators/GeneratorTest.php b/tests/Core/Generators/GeneratorTest.php
new file mode 100644
index 0000000000..fd4cdff333
--- /dev/null
+++ b/tests/Core/Generators/GeneratorTest.php
@@ -0,0 +1,222 @@
+
+ * @copyright 2024 Juliette Reinders Folmer. All rights reserved.
+ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
+ */
+
+namespace PHP_CodeSniffer\Tests\Core\Generators;
+
+use PHP_CodeSniffer\Ruleset;
+use PHP_CodeSniffer\Runner;
+use PHP_CodeSniffer\Tests\ConfigDouble;
+use PHP_CodeSniffer\Tests\Core\Generators\Fixtures\MockGenerator;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * Tests the functionality in the abstract Generator class.
+ *
+ * @covers \PHP_CodeSniffer\Generators\Generator
+ */
+final class GeneratorTest extends TestCase
+{
+
+
+ /**
+ * Test the list of available documentation for a standard is generated correctly.
+ *
+ * @param string $standard The standard to use for the test.
+ * @param array $expected The expected list of found docs.
+ *
+ * @dataProvider dataConstructor
+ *
+ * @return void
+ */
+ public function testConstructor($standard, array $expected)
+ {
+ // Set up the ruleset.
+ $config = new ConfigDouble(["--standard=$standard"]);
+ $ruleset = new Ruleset($config);
+
+ $generator = new MockGenerator($ruleset);
+ $this->assertSame($expected, $generator->docFiles);
+
+ }//end testConstructor()
+
+
+ /**
+ * Data provider.
+ *
+ * @return array>>
+ */
+ public static function dataConstructor()
+ {
+ $pathToDocsInFixture = __DIR__.DIRECTORY_SEPARATOR.'Fixtures';
+ $pathToDocsInFixture .= DIRECTORY_SEPARATOR.'StandardWithDocs';
+ $pathToDocsInFixture .= DIRECTORY_SEPARATOR.'Docs'.DIRECTORY_SEPARATOR;
+
+ return [
+ 'Standard without docs' => [
+ 'standard' => __DIR__.'/NoDocsTest.xml',
+ 'expected' => [],
+ ],
+ 'Standard with an invalid doc file' => [
+ 'standard' => __DIR__.'/NoValidDocsTest.xml',
+ 'expected' => [
+ $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'NoDocumentationElementStandard.xml',
+ ],
+ ],
+ 'Standard with one doc file' => [
+ 'standard' => __DIR__.'/OneDocTest.xml',
+ 'expected' => [
+ $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'OneStandardBlockNoCodeStandard.xml',
+ ],
+ ],
+ 'Standard with multiple doc files' => [
+ 'standard' => __DIR__.'/StructureDocsTest.xml',
+ 'expected' => [
+ $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'NoContentStandard.xml',
+ $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'OneStandardBlockCodeComparisonStandard.xml',
+ $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'OneStandardBlockNoCodeStandard.xml',
+ $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'OneStandardBlockTwoCodeComparisonsStandard.xml',
+ $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'TwoStandardBlocksNoCodeStandard.xml',
+ $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'TwoStandardBlocksOneCodeComparisonStandard.xml',
+ $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'TwoStandardBlocksThreeCodeComparisonsStandard.xml',
+ ],
+ ],
+ ];
+
+ }//end dataConstructor()
+
+
+ /**
+ * Verify that an XML doc which isn't valid documentation yields a TypeError to warn devs.
+ *
+ * This should not be hidden via defensive coding!
+ *
+ * @return void
+ */
+ public function testGeneratingInvalidDocsResultsInTypeError()
+ {
+ // Set up the ruleset.
+ $standard = __DIR__.'/NoValidDocsTest.xml';
+ $config = new ConfigDouble(["--standard=$standard"]);
+ $ruleset = new Ruleset($config);
+
+ $this->expectException('TypeError');
+ $this->expectExceptionMessage('processSniff(): Argument #1 ($doc) must be of type DOMNode, null given');
+
+ $generator = new MockGenerator($ruleset);
+ $generator->generate();
+
+ }//end testGeneratingInvalidDocsResultsInTypeError()
+
+
+ /**
+ * Verify the wiring for the generate() function.
+ *
+ * @param string $standard The standard to use for the test.
+ * @param string $expected The expected function output.
+ *
+ * @dataProvider dataGeneratingDocs
+ *
+ * @return void
+ */
+ public function testGeneratingDocs($standard, $expected)
+ {
+ // Set up the ruleset.
+ $config = new ConfigDouble(["--standard=$standard"]);
+ $ruleset = new Ruleset($config);
+
+ // Make the test OS independent.
+ $expected = str_replace("\n", PHP_EOL, $expected);
+ $this->expectOutputString($expected);
+
+ $generator = new MockGenerator($ruleset);
+ $generator->generate();
+
+ }//end testGeneratingDocs()
+
+
+ /**
+ * Data provider.
+ *
+ * @return array>
+ */
+ public static function dataGeneratingDocs()
+ {
+ $multidocExpected = "No Content\n";
+ $multidocExpected .= "One Standard Block, Code Comparison\n";
+ $multidocExpected .= "One Standard Block, No Code\n";
+ $multidocExpected .= "One Standard Block, Two Code Comparisons\n";
+ $multidocExpected .= "Two Standard Blocks, No Code\n";
+ $multidocExpected .= "Two Standard Blocks, One Code Comparison\n";
+ $multidocExpected .= "Two Standard Blocks, Three Code Comparisons\n";
+
+ return [
+ 'Standard without docs' => [
+ 'standard' => __DIR__.'/NoDocsTest.xml',
+ 'expected' => '',
+ ],
+ 'Standard with one doc file' => [
+ 'standard' => __DIR__.'/OneDocTest.xml',
+ 'expected' => "One Standard Block, No Code\n",
+ ],
+ 'Standard with multiple doc files' => [
+ 'standard' => __DIR__.'/StructureDocsTest.xml',
+ 'expected' => $multidocExpected,
+ ],
+ ];
+
+ }//end dataGeneratingDocs()
+
+
+ /**
+ * Test that the documentation for each standard passed on the command-line is shown separately.
+ *
+ * @covers \PHP_CodeSniffer\Runner::runPHPCS
+ *
+ * @return void
+ */
+ public function testGeneratorWillShowEachStandardSeparately()
+ {
+ $standard = __DIR__.'/OneDocTest.xml';
+ $_SERVER['argv'] = [
+ 'phpcs',
+ '--generator=Text',
+ "--standard=$standard,PSR1",
+ '--report-width=80',
+ ];
+
+ $regex = '`^
+ \R* # Optional blank line at the start.
+ (?:
+ (?P-+\R) # Line with dashes.
+ \|[ ]GENERATORTEST[ ]CODING[ ]STANDARD:[ ][^\|]+\|\R # Doc title line with prefix expected for first standard.
+ (?P>delimiter) # Line with dashes.
+ .+?\R{2} # Standard description.
+ ) # Only expect this group once.
+ (?:
+ (?P>delimiter) # Line with dashes.
+ \|[ ]PSR1[ ]CODING[ ]STANDARD:[ ][^\|]+\|\R # Doc title line with prefix expected for second standard.
+ (?P>delimiter) # Line with dashes.
+ .+?\R+ # Standard description.
+ (?:
+ -+[ ]CODE[ ]COMPARISON[ ]-+\R # Code Comparison starter line with dashes.
+ (?:.+?(?P>delimiter)\R){2} # Arbitrary text followed by a delimiter line.
+ )* # Code comparison is optional and can exist multiple times.
+ \R+
+ ){3,} # This complete group should occur at least six times.
+ `sx';
+
+ $this->expectOutputRegex($regex);
+
+ $runner = new Runner();
+ $runner->runPHPCS();
+
+ }//end testGeneratorWillShowEachStandardSeparately()
+
+
+}//end class
diff --git a/tests/Core/Generators/HTMLTest.php b/tests/Core/Generators/HTMLTest.php
new file mode 100644
index 0000000000..3106b5029c
--- /dev/null
+++ b/tests/Core/Generators/HTMLTest.php
@@ -0,0 +1,104 @@
+
+ * @copyright 2024 Juliette Reinders Folmer. All rights reserved.
+ * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
+ */
+
+namespace PHP_CodeSniffer\Tests\Core\Generators;
+
+use PHP_CodeSniffer\Ruleset;
+use PHP_CodeSniffer\Tests\ConfigDouble;
+use PHP_CodeSniffer\Tests\Core\Generators\Fixtures\HTMLDouble;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * Test the HTML documentation generation.
+ *
+ * @covers \PHP_CodeSniffer\Generators\HTML
+ */
+final class HTMLTest extends TestCase
+{
+
+
+ /**
+ * Test the generated docs.
+ *
+ * @param string $standard The standard to use for the test.
+ * @param string $pathToExpected Path to a file containing the expected function output.
+ *
+ * @dataProvider dataDocs
+ *
+ * @return void
+ */
+ public function testDocs($standard, $pathToExpected)
+ {
+ // Set up the ruleset.
+ $config = new ConfigDouble(["--standard=$standard"]);
+ $ruleset = new Ruleset($config);
+
+ $expected = file_get_contents($pathToExpected);
+ $this->assertNotFalse($expected, 'Output expectation file could not be found');
+
+ // Make the test OS independent.
+ $expected = str_replace("\n", PHP_EOL, $expected);
+ $this->expectOutputString($expected);
+
+ $generator = new HTMLDouble($ruleset);
+ $generator->generate();
+
+ }//end testDocs()
+
+
+ /**
+ * Data provider.
+ *
+ * @return array>
+ */
+ public static function dataDocs()
+ {
+ return [
+ 'Standard without docs' => [
+ 'standard' => __DIR__.'/NoDocsTest.xml',
+ 'pathToExpected' => __DIR__.'/Expectations/ExpectedOutputNoDocs.html',
+ ],
+ 'Standard with one doc file' => [
+ 'standard' => __DIR__.'/OneDocTest.xml',
+ 'pathToExpected' => __DIR__.'/Expectations/ExpectedOutputOneDoc.html',
+ ],
+ 'Standard with multiple doc files' => [
+ 'standard' => __DIR__.'/StructureDocsTest.xml',
+ 'pathToExpected' => __DIR__.'/Expectations/ExpectedOutputStructureDocs.html',
+ ],
+ ];
+
+ }//end dataDocs()
+
+
+ /**
+ * Test the generated footer.
+ *
+ * @return void
+ */
+ public function testFooter()
+ {
+ // Set up the ruleset.
+ $standard = __DIR__.'/OneDocTest.xml';
+ $config = new ConfigDouble(["--standard=$standard"]);
+ $ruleset = new Ruleset($config);
+
+ $regex = '`^ ';
+ $regex .= 'Documentation generated on [A-Z][a-z]{2}, [0-9]{2} [A-Z][a-z]{2} 20[0-9]{2} [0-2][0-9](?::[0-5][0-9]){2} [+-][0-9]{4}';
+ $regex .= ' by
PHP_CodeSniffer [3-9]\.[0-9]+.[0-9]+';
+ $regex .= '
\R