From 5e23347cf7b869a9bedc75d8de302b7d90075be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Sun, 14 Apr 2024 19:34:28 +0200 Subject: [PATCH] test: Tweak the SpecFormatter - Rename it to `SpecPrinter` - Passes the `SpecScenario` object for simplicitation - Add tests --- .../{SpecFormatter.php => SpecPrinter.php} | 37 +- tests/Scoper/Spec/SpecPrinterTest.php | 454 ++++++++++++++++++ tests/Scoper/Spec/SpecScenario.php | 10 +- 3 files changed, 472 insertions(+), 29 deletions(-) rename tests/Scoper/Spec/{SpecFormatter.php => SpecPrinter.php} (90%) create mode 100644 tests/Scoper/Spec/SpecPrinterTest.php diff --git a/tests/Scoper/Spec/SpecFormatter.php b/tests/Scoper/Spec/SpecPrinter.php similarity index 90% rename from tests/Scoper/Spec/SpecFormatter.php rename to tests/Scoper/Spec/SpecPrinter.php index 1e1e218d..1ab39054 100644 --- a/tests/Scoper/Spec/SpecFormatter.php +++ b/tests/Scoper/Spec/SpecPrinter.php @@ -14,12 +14,10 @@ namespace Humbug\PhpScoper\Scoper\Spec; -use Humbug\PhpScoper\Configuration\SymbolsConfiguration; use Humbug\PhpScoper\NotInstantiable; use Humbug\PhpScoper\Symbol\NamespaceRegistry; use Humbug\PhpScoper\Symbol\SymbolRegistry; use Humbug\PhpScoper\Symbol\SymbolsRegistry; -use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; use function array_map; use function count; @@ -34,26 +32,23 @@ /** * @internal */ -#[Group('integration')] -class SpecFormatter extends TestCase +final class SpecPrinter extends TestCase { use NotInstantiable; - /** - * @param string[][] $expectedRegisteredClasses - * @param string[][] $expectedRegisteredFunctions - */ public static function createSpecMessage( - string $file, - string $spec, - string $contents, - SymbolsConfiguration $symbolsConfiguration, + SpecScenario $scenario, SymbolsRegistry $symbolsRegistry, - ?string $expected, - ?string $actual, - array $expectedRegisteredClasses, - array $expectedRegisteredFunctions + ?string $actualCode, ): string { + $file = $scenario->file; + $title = $scenario->title; + $inputCode = $scenario->inputCode; + $symbolsConfiguration = $scenario->symbolsConfiguration; + $expectedCode = $scenario->expectedCode; + $expectedRegisteredClasses = $scenario->expectedRegisteredClasses; + $expectedRegisteredFunctions = $scenario->expectedRegisteredFunctions; + $formattedExposeGlobalClasses = self::convertBoolToString($symbolsConfiguration->shouldExposeGlobalClasses()); $formattedExposeGlobalConstants = self::convertBoolToString($symbolsConfiguration->shouldExposeGlobalConstants()); $formattedExposeGlobalFunctions = self::convertBoolToString($symbolsConfiguration->shouldExposeGlobalFunctions()); @@ -78,7 +73,7 @@ public static function createSpecMessage( $titleSeparator = str_repeat( '=', min( - strlen($spec), + strlen($title), 80, ), ); @@ -87,7 +82,7 @@ public static function createSpecMessage( {$titleSeparator} SPECIFICATION {$titleSeparator} - {$spec} + {$title} {$file} {$titleSeparator} @@ -107,12 +102,12 @@ public static function createSpecMessage( (raw) internal functions: {$formattedInternalFunctions} (raw) internal constants: {$formattedInternalConstants} {$titleSeparator} - {$contents} + {$inputCode} {$titleSeparator} EXPECTED {$titleSeparator} - {$expected} + {$expectedCode} ---------------- recorded functions: {$formattedExpectedRegisteredFunctions} recorded classes: {$formattedExpectedRegisteredClasses} @@ -120,7 +115,7 @@ public static function createSpecMessage( {$titleSeparator} ACTUAL {$titleSeparator} - {$actual} + {$actualCode} ---------------- recorded functions: {$formattedActualRegisteredFunctions} recorded classes: {$formattedActualRegisteredClasses} diff --git a/tests/Scoper/Spec/SpecPrinterTest.php b/tests/Scoper/Spec/SpecPrinterTest.php new file mode 100644 index 00000000..0369e705 --- /dev/null +++ b/tests/Scoper/Spec/SpecPrinterTest.php @@ -0,0 +1,454 @@ +, + * Pádraic Brady + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Humbug\PhpScoper\Scoper\Spec; + +use Humbug\PhpScoper\Configuration\RegexChecker; +use Humbug\PhpScoper\Configuration\SymbolsConfiguration; +use Humbug\PhpScoper\Configuration\SymbolsConfigurationFactory; +use Humbug\PhpScoper\Symbol\SymbolsRegistry; +use PhpParser\Node\Name\FullyQualified; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\TestCase; + +/** + * @internal + */ +#[CoversClass(SpecPrinter::class)] +final class SpecPrinterTest extends TestCase +{ + #[DataProvider('scenarioProvider')] + public function test_it_can_print_a_scenario( + SpecScenario $scenario, + SymbolsRegistry $symbolsRegistry, + ?string $actualCode, + string $expected, + ): void { + $actual = SpecPrinter::createSpecMessage( + $scenario, + $symbolsRegistry, + $actualCode, + ); + + self::assertSame($expected, $actual); + } + + public static function scenarioProvider(): iterable + { + $specCode = <<<'PHP' + echo "Hello world!"; + + PHP; + + $expectedCode = <<<'PHP' + namespace Humbug; + + echo "Hello world!"; + + PHP; + + $actualCode = <<<'PHP' + namespace Prefix; + + echo "Hello world!"; + + PHP; + + yield 'simple scenario' => [ + new SpecScenario( + null, + null, + 'Fixtures/complete-spec-file.php', + '[Example of simple spec file] Spec with the more verbose form', + $specCode, + 'Humbug', + self::createSymbolsConfiguration([]), + $expectedCode, + [], + [], + ), + new SymbolsRegistry(), + $actualCode, + <<<'TEXT' + ============================================================= + SPECIFICATION + ============================================================= + [Example of simple spec file] Spec with the more verbose form + Fixtures/complete-spec-file.php + + ============================================================= + INPUT + expose global classes: true + expose global functions: true + expose global constants: true + + exclude namespaces: [] + expose namespaces: [] + + expose classes: [] + expose functions: [] + expose constants: [] + + (raw) internal classes: [] + (raw) internal functions: [] + (raw) internal constants: [] + ============================================================= + echo "Hello world!"; + + + ============================================================= + EXPECTED + ============================================================= + namespace Humbug; + + echo "Hello world!"; + + ---------------- + recorded functions: [] + recorded classes: [] + + ============================================================= + ACTUAL + ============================================================= + namespace Prefix; + + echo "Hello world!"; + + ---------------- + recorded functions: [] + recorded classes: [] + + ------------------------------------------------------------------------------- + TEXT, + ]; + + yield 'complete scenario without symbols' => [ + new SpecScenario( + 72_000, + 83_000, + 'Fixtures/complete-spec-file.php', + '[Example of simple spec file] Spec with the more verbose form', + $specCode, + 'Humbug', + self::createSymbolsConfiguration([ + 'expose-global-constants' => true, + 'expose-global-classes' => true, + 'expose-global-functions' => true, + 'expose-namespaces' => ['ExposedNamespace'], + 'expose-constants' => ['EXPOSED_CONSTANT'], + 'expose-classes' => ['ExposedClass'], + 'expose-functions' => ['exposed_function'], + 'exclude-namespaces' => ['ExcludedNamespace'], + 'exclude-constants' => ['EXCLUDED_CONSTANT'], + 'exclude-classes' => ['ExcludedClass'], + 'exclude-functions' => ['excluded_function'], + ]), + $expectedCode, + [['Acme\RecordedClass', 'Humbug\Acme\RecordedClass']], + [['Acme\recorded_function', 'Humbug\Acme\recorded_function']], + ), + new SymbolsRegistry(), + $actualCode, + <<<'TEXT' + ============================================================= + SPECIFICATION + ============================================================= + [Example of simple spec file] Spec with the more verbose form + Fixtures/complete-spec-file.php + + ============================================================= + INPUT + expose global classes: true + expose global functions: true + expose global constants: true + + exclude namespaces: [ excludednamespace ] + expose namespaces: [ exposednamespace ] + + expose classes: [ exposedclass ] + expose functions: [ exposed_function ] + expose constants: [ EXPOSED_CONSTANT ] + + (raw) internal classes: [ excludedclass ] + (raw) internal functions: [ excluded_function ] + (raw) internal constants: [ EXCLUDED_CONSTANT ] + ============================================================= + echo "Hello world!"; + + + ============================================================= + EXPECTED + ============================================================= + namespace Humbug; + + echo "Hello world!"; + + ---------------- + recorded functions: [Acme\recorded_function => Humbug\Acme\recorded_function] + recorded classes: [Acme\RecordedClass => Humbug\Acme\RecordedClass] + + ============================================================= + ACTUAL + ============================================================= + namespace Prefix; + + echo "Hello world!"; + + ---------------- + recorded functions: [] + recorded classes: [] + + ------------------------------------------------------------------------------- + TEXT, + ]; + + yield 'complete scenario with multiple items without symbols' => [ + new SpecScenario( + 72_000, + 83_000, + 'Fixtures/complete-spec-file.php', + '[Example of simple spec file] Spec with the more verbose form', + $specCode, + 'Humbug', + self::createSymbolsConfiguration([ + 'expose-global-constants' => true, + 'expose-global-classes' => true, + 'expose-global-functions' => true, + 'expose-namespaces' => ['ExposedNamespace', 'AnotherExposedNamespace'], + 'expose-constants' => ['EXPOSED_CONSTANT', 'ANOTHER_EXPOSED_CONSTANT'], + 'expose-classes' => ['ExposedClass', 'AnotherExposedClass'], + 'expose-functions' => ['exposed_function', 'another_exposed_function'], + 'exclude-namespaces' => ['ExcludedNamespace', 'AnotherExcludedNamespace'], + 'exclude-constants' => ['EXCLUDED_CONSTANT', 'ANOTHER_EXCLUDED_CONSTANT'], + 'exclude-classes' => ['ExcludedClass', 'AnotherExcludedClass'], + 'exclude-functions' => ['excluded_function', 'another_excluded_function'], + ]), + $expectedCode, + [ + ['Acme\RecordedClass', 'Humbug\Acme\RecordedClass'], + ['Acme\AnotherRecordedClass', 'Humbug\Acme\AnotherRecordedClass'], + ], + [ + ['Acme\recorded_function', 'Humbug\Acme\recorded_function'], + ['Acme\another_recorded_function', 'Humbug\Acme\another_recorded_function'], + ], + ), + new SymbolsRegistry(), + $actualCode, + <<<'TEXT' + ============================================================= + SPECIFICATION + ============================================================= + [Example of simple spec file] Spec with the more verbose form + Fixtures/complete-spec-file.php + + ============================================================= + INPUT + expose global classes: true + expose global functions: true + expose global constants: true + + exclude namespaces: [ + - excludednamespace + - anotherexcludednamespace + ] + expose namespaces: [ + - exposednamespace + - anotherexposednamespace + ] + + expose classes: [ + - exposedclass + - anotherexposedclass + ] + expose functions: [ + - exposed_function + - another_exposed_function + ] + expose constants: [ + - EXPOSED_CONSTANT + - ANOTHER_EXPOSED_CONSTANT + ] + + (raw) internal classes: [ + - excludedclass + - anotherexcludedclass + ] + (raw) internal functions: [ + - excluded_function + - another_excluded_function + ] + (raw) internal constants: [ + - EXCLUDED_CONSTANT + - ANOTHER_EXCLUDED_CONSTANT + ] + ============================================================= + echo "Hello world!"; + + + ============================================================= + EXPECTED + ============================================================= + namespace Humbug; + + echo "Hello world!"; + + ---------------- + recorded functions: [ + - Acme\recorded_function => Humbug\Acme\recorded_function + - Acme\another_recorded_function => Humbug\Acme\another_recorded_function + ] + recorded classes: [ + - Acme\RecordedClass => Humbug\Acme\RecordedClass + - Acme\AnotherRecordedClass => Humbug\Acme\AnotherRecordedClass + ] + + ============================================================= + ACTUAL + ============================================================= + namespace Prefix; + + echo "Hello world!"; + + ---------------- + recorded functions: [] + recorded classes: [] + + ------------------------------------------------------------------------------- + TEXT, + ]; + + yield 'simple scenario with recorded symbols' => [ + new SpecScenario( + null, + null, + 'Fixtures/complete-spec-file.php', + '[Example of simple spec file] Spec with the more verbose form', + $specCode, + 'Humbug', + self::createSymbolsConfiguration([]), + $expectedCode, + [], + [], + ), + self::createRegistry( + [ + 'recorded_function' => 'Humbug\recorded_function', + 'another_recorded_function' => 'Humbug\another_recorded_function', + ], + [ + 'RecordedClass' => 'Humbug\RecordedClass', + 'AnotherRecordedClass' => 'Humbug\AnotherRecordedClass', + ], + ), + $actualCode, + <<<'TEXT' + ============================================================= + SPECIFICATION + ============================================================= + [Example of simple spec file] Spec with the more verbose form + Fixtures/complete-spec-file.php + + ============================================================= + INPUT + expose global classes: true + expose global functions: true + expose global constants: true + + exclude namespaces: [] + expose namespaces: [] + + expose classes: [] + expose functions: [] + expose constants: [] + + (raw) internal classes: [] + (raw) internal functions: [] + (raw) internal constants: [] + ============================================================= + echo "Hello world!"; + + + ============================================================= + EXPECTED + ============================================================= + namespace Humbug; + + echo "Hello world!"; + + ---------------- + recorded functions: [] + recorded classes: [] + + ============================================================= + ACTUAL + ============================================================= + namespace Prefix; + + echo "Hello world!"; + + ---------------- + recorded functions: [ + - recorded_function => Humbug\recorded_function + - another_recorded_function => Humbug\another_recorded_function + ] + recorded classes: [ + - RecordedClass => Humbug\RecordedClass + - AnotherRecordedClass => Humbug\AnotherRecordedClass + ] + + ------------------------------------------------------------------------------- + TEXT, + ]; + } + + private static function createSymbolsConfiguration(array $config): SymbolsConfiguration + { + static $factory; + + if (!isset($factory)) { + $factory = new SymbolsConfigurationFactory(new RegexChecker()); + } + + return $factory->createSymbolsConfiguration($config); + } + + /** + * @param array $functions + * @param array $classes + */ + private static function createRegistry( + array $functions, + array $classes, + ): SymbolsRegistry { + $registry = new SymbolsRegistry(); + + foreach ($functions as $original => $alias) { + $registry->recordFunction( + new FullyQualified($original), + new FullyQualified($alias), + ); + } + + foreach ($classes as $original => $alias) { + $registry->recordClass( + new FullyQualified($original), + new FullyQualified($alias), + ); + } + + return $registry; + } +} diff --git a/tests/Scoper/Spec/SpecScenario.php b/tests/Scoper/Spec/SpecScenario.php index af26f81b..76908b35 100644 --- a/tests/Scoper/Spec/SpecScenario.php +++ b/tests/Scoper/Spec/SpecScenario.php @@ -83,16 +83,10 @@ public function assertExpectedResult( SymbolsRegistry $symbolsRegistry, ?string $actualCode, ): void { - $specMessage = SpecFormatter::createSpecMessage( - $this->file, - $this->title, - $this->inputCode, - $this->symbolsConfiguration, + $specMessage = SpecPrinter::createSpecMessage( + $this, $symbolsRegistry, - $this->expectedCode, $actualCode, - $this->expectedRegisteredClasses, - $this->expectedRegisteredFunctions, ); $assert->assertSame($this->expectedCode, $actualCode, $specMessage);