|
| 1 | +<?php |
| 2 | + |
| 3 | +/** |
| 4 | + * JUnit specification: |
| 5 | + * - https://github.com/junit-team/junit5/blob/main/platform-tests/src/test/resources/jenkins-junit.xsda |
| 6 | + */ |
| 7 | +declare (strict_types=1); |
| 8 | +namespace Rector\ChangesReporting\Output; |
| 9 | + |
| 10 | +use DOMDocument; |
| 11 | +use DOMElement; |
| 12 | +use Rector\ChangesReporting\Contract\Output\OutputFormatterInterface; |
| 13 | +use Rector\ValueObject\Configuration; |
| 14 | +use Rector\ValueObject\ProcessResult; |
| 15 | +use RectorPrefix202502\Symfony\Component\Console\Style\SymfonyStyle; |
| 16 | +final class JUnitOutputFormatter implements OutputFormatterInterface |
| 17 | +{ |
| 18 | + /** |
| 19 | + * @readonly |
| 20 | + */ |
| 21 | + private SymfonyStyle $symfonyStyle; |
| 22 | + public const NAME = 'junit'; |
| 23 | + private const XML_ATTRIBUTE_FILE = 'file'; |
| 24 | + private const XML_ATTRIBUTE_NAME = 'name'; |
| 25 | + private const XML_ATTRIBUTE_TYPE = 'type'; |
| 26 | + private const XML_ELEMENT_TESTSUITES = 'testsuites'; |
| 27 | + private const XML_ELEMENT_TESTSUITE = 'testsuite'; |
| 28 | + private const XML_ELEMENT_TESTCASE = 'testcase'; |
| 29 | + private const XML_ELEMENT_ERROR = 'error'; |
| 30 | + public function __construct(SymfonyStyle $symfonyStyle) |
| 31 | + { |
| 32 | + $this->symfonyStyle = $symfonyStyle; |
| 33 | + } |
| 34 | + public function getName() : string |
| 35 | + { |
| 36 | + return self::NAME; |
| 37 | + } |
| 38 | + public function report(ProcessResult $processResult, Configuration $configuration) : void |
| 39 | + { |
| 40 | + if (!\extension_loaded('dom')) { |
| 41 | + $this->symfonyStyle->warning('The "dom" extension is not loaded. The rector could not generate a response in the JUnit format'); |
| 42 | + return; |
| 43 | + } |
| 44 | + $domDocument = new DOMDocument('1.0', 'UTF-8'); |
| 45 | + $xmlTestSuite = $domDocument->createElement(self::XML_ELEMENT_TESTSUITE); |
| 46 | + $xmlTestSuite->setAttribute(self::XML_ATTRIBUTE_NAME, 'rector'); |
| 47 | + $xmlTestSuites = $domDocument->createElement(self::XML_ELEMENT_TESTSUITES); |
| 48 | + $xmlTestSuites->appendChild($xmlTestSuite); |
| 49 | + $domDocument->appendChild($xmlTestSuites); |
| 50 | + $this->appendSystemErrors($processResult, $configuration, $domDocument, $xmlTestSuite); |
| 51 | + $this->appendFileDiffs($processResult, $configuration, $domDocument, $xmlTestSuite); |
| 52 | + echo $domDocument->saveXML() . \PHP_EOL; |
| 53 | + } |
| 54 | + private function appendSystemErrors(ProcessResult $processResult, Configuration $configuration, DOMDocument $domDocument, DOMElement $xmlTestSuite) : void |
| 55 | + { |
| 56 | + if (\count($processResult->getSystemErrors()) === 0) { |
| 57 | + return; |
| 58 | + } |
| 59 | + foreach ($processResult->getSystemErrors() as $error) { |
| 60 | + $filePath = $configuration->isReportingWithRealPath() ? $error->getAbsoluteFilePath() ?? '' : $error->getRelativeFilePath() ?? ''; |
| 61 | + $xmlError = $domDocument->createElement(self::XML_ELEMENT_ERROR, $error->getMessage()); |
| 62 | + $xmlError->setAttribute(self::XML_ATTRIBUTE_TYPE, 'Error'); |
| 63 | + $xmlTestCase = $domDocument->createElement(self::XML_ELEMENT_TESTCASE); |
| 64 | + $xmlTestCase->setAttribute(self::XML_ATTRIBUTE_FILE, $filePath); |
| 65 | + $xmlTestCase->setAttribute(self::XML_ATTRIBUTE_NAME, $filePath . ':' . $error->getLine()); |
| 66 | + $xmlTestCase->appendChild($xmlError); |
| 67 | + $xmlTestSuite->appendChild($xmlTestCase); |
| 68 | + } |
| 69 | + } |
| 70 | + private function appendFileDiffs(ProcessResult $processResult, Configuration $configuration, DOMDocument $domDocument, DOMElement $xmlTestSuite) : void |
| 71 | + { |
| 72 | + if (\count($processResult->getFileDiffs()) === 0) { |
| 73 | + return; |
| 74 | + } |
| 75 | + $fileDiffs = $processResult->getFileDiffs(); |
| 76 | + \ksort($fileDiffs); |
| 77 | + foreach ($fileDiffs as $fileDiff) { |
| 78 | + $filePath = $configuration->isReportingWithRealPath() ? $fileDiff->getAbsoluteFilePath() ?? '' : $fileDiff->getRelativeFilePath() ?? ''; |
| 79 | + $rectorClasses = \implode(' / ', $fileDiff->getRectorShortClasses()); |
| 80 | + $xmlError = $domDocument->createElement(self::XML_ELEMENT_ERROR, $fileDiff->getDiff()); |
| 81 | + $xmlError->setAttribute(self::XML_ATTRIBUTE_TYPE, $rectorClasses); |
| 82 | + $xmlTestCase = $domDocument->createElement(self::XML_ELEMENT_TESTCASE); |
| 83 | + $xmlTestCase->setAttribute(self::XML_ATTRIBUTE_FILE, $filePath); |
| 84 | + $xmlTestCase->setAttribute(self::XML_ATTRIBUTE_NAME, $filePath . ':' . $fileDiff->getFirstLineNumber()); |
| 85 | + $xmlTestCase->appendChild($xmlError); |
| 86 | + $xmlTestSuite->appendChild($xmlTestCase); |
| 87 | + } |
| 88 | + } |
| 89 | +} |
0 commit comments