From 7fc12613a849afc978e9bf0a6fb1b32eb68c9d56 Mon Sep 17 00:00:00 2001 From: Nuno Maduro Date: Sat, 18 Feb 2023 14:39:44 +0000 Subject: [PATCH] feat: kernel dump --- resources/views/components/badge.php | 17 ++++ src/Bootstrappers/BootKernelDump.php | 37 ++++++++ src/Bootstrappers/BootSubscribers.php | 1 + src/Kernel.php | 7 ++ src/KernelDump.php | 91 +++++++++++++++++++ src/Plugins/Help.php | 28 +++--- src/Plugins/Parallel.php | 1 - src/Subscribers/EnsureKernelDumpIsFlushed.php | 28 ++++++ tests/.snapshots/Failure.php.inc | 4 +- tests/.snapshots/help-command.txt | 11 +-- 10 files changed, 201 insertions(+), 24 deletions(-) create mode 100644 resources/views/components/badge.php create mode 100644 src/Bootstrappers/BootKernelDump.php create mode 100644 src/KernelDump.php create mode 100644 src/Subscribers/EnsureKernelDumpIsFlushed.php diff --git a/resources/views/components/badge.php b/resources/views/components/badge.php new file mode 100644 index 00000000..df99a599 --- /dev/null +++ b/resources/views/components/badge.php @@ -0,0 +1,17 @@ + ['blue', 'INFO'], + 'ERROR' => ['red', 'ERROR'], +}; + +?> + +
+ + + + +
diff --git a/src/Bootstrappers/BootKernelDump.php b/src/Bootstrappers/BootKernelDump.php new file mode 100644 index 00000000..8e7a34ee --- /dev/null +++ b/src/Bootstrappers/BootKernelDump.php @@ -0,0 +1,37 @@ +add(KernelDump::class, $kernelDump = new KernelDump( + $this->output, + )); + + $kernelDump->enable(); + } +} diff --git a/src/Bootstrappers/BootSubscribers.php b/src/Bootstrappers/BootSubscribers.php index b3f14659..43ee7db1 100644 --- a/src/Bootstrappers/BootSubscribers.php +++ b/src/Bootstrappers/BootSubscribers.php @@ -24,6 +24,7 @@ final class BootSubscribers implements Bootstrapper Subscribers\EnsureConfigurationIsValid::class, Subscribers\EnsureConfigurationIsAvailable::class, Subscribers\EnsureTeamCityEnabled::class, + Subscribers\EnsureKernelDumpIsFlushed::class, ]; /** diff --git a/src/Kernel.php b/src/Kernel.php index e9740eb3..debf1097 100644 --- a/src/Kernel.php +++ b/src/Kernel.php @@ -31,6 +31,7 @@ final class Kernel Bootstrappers\BootSubscribers::class, Bootstrappers\BootFiles::class, Bootstrappers\BootView::class, + Bootstrappers\BootKernelDump::class, ]; /** @@ -106,6 +107,12 @@ final class Kernel */ public function shutdown(): void { + $preBufferOutput = Container::getInstance()->get(KernelDump::class); + + assert($preBufferOutput instanceof KernelDump); + + $preBufferOutput->shutdown(); + CallsShutdown::execute(); } } diff --git a/src/KernelDump.php b/src/KernelDump.php new file mode 100644 index 00000000..14c1ea38 --- /dev/null +++ b/src/KernelDump.php @@ -0,0 +1,91 @@ +buffer .= $message; + + return ''; + }); + } + + /** + * Disable the output buffering. + */ + public function disable(): void + { + ob_clean(); + + if ($this->buffer !== '') { + $this->flush('INFO'); + } + } + + /** + * Shutdown the output buffering. + */ + public function shutdown(): void + { + ob_clean(); + + if ($this->buffer !== '') { + $this->flush('ERROR'); + } + } + + /** + * Flushes the buffer. + */ + private function flush(string $type): void + { + View::renderUsing($this->output); + + if ($this->isOpeningHeadline($this->buffer)) { + $this->buffer = implode(PHP_EOL, array_slice(explode(PHP_EOL, $this->buffer), 2)); + } + + $this->buffer = trim($this->buffer); + $this->buffer = rtrim($this->buffer, '.').'.'; + + View::render('components.badge', [ + 'type' => $type, + 'content' => $this->buffer, + ]); + + $this->buffer = ''; + } + + /** + * Checks if the given output contains an opening headline. + */ + private function isOpeningHeadline(string $output): bool + { + return str_contains($output, 'by Sebastian Bergmann and contributors.'); + } +} diff --git a/src/Plugins/Help.php b/src/Plugins/Help.php index ea8a08ea..2d21ebb6 100644 --- a/src/Plugins/Help.php +++ b/src/Plugins/Help.php @@ -101,15 +101,15 @@ final class Help implements HandlesArguments ]] + $content['Configuration']; $content['Selection'] = [ - [ - 'arg' => '--todos', - 'desc' => 'Output to standard output the list of todos', - ], - [ - 'arg' => '--retry', - 'desc' => 'Run non-passing tests first and stop execution upon first error or failure', - ], - ] + $content['Selection']; + [ + 'arg' => '--todos', + 'desc' => 'Output to standard output the list of todos', + ], + [ + 'arg' => '--retry', + 'desc' => 'Run non-passing tests first and stop execution upon first error or failure', + ], + ] + $content['Selection']; $content['Code Coverage'] = [ [ @@ -123,11 +123,11 @@ final class Help implements HandlesArguments ] + $content['Code Coverage']; $content['Profiling'] = [ - [ - 'arg' => '--profile ', - 'desc' => 'Output to standard output the top ten slowest tests', - ], - ]; + [ + 'arg' => '--profile ', + 'desc' => 'Output to standard output the top ten slowest tests', + ], + ]; unset($content['Miscellaneous']); diff --git a/src/Plugins/Parallel.php b/src/Plugins/Parallel.php index 92c2e1c5..b85227d1 100644 --- a/src/Plugins/Parallel.php +++ b/src/Plugins/Parallel.php @@ -5,7 +5,6 @@ declare(strict_types=1); namespace Pest\Plugins; use ParaTest\ParaTestCommand; -use Pest\Contracts\Plugins\AddsOutput; use Pest\Contracts\Plugins\HandlesArguments; use Pest\Plugins\Actions\CallsAddsOutput; use Pest\Plugins\Concerns\HandleArguments; diff --git a/src/Subscribers/EnsureKernelDumpIsFlushed.php b/src/Subscribers/EnsureKernelDumpIsFlushed.php new file mode 100644 index 00000000..debcc99c --- /dev/null +++ b/src/Subscribers/EnsureKernelDumpIsFlushed.php @@ -0,0 +1,28 @@ +get(KernelDump::class); + + assert($kernelDump instanceof KernelDump); + + $kernelDump->disable(); + } +} diff --git a/tests/.snapshots/Failure.php.inc b/tests/.snapshots/Failure.php.inc index 09ca928d..727211aa 100644 --- a/tests/.snapshots/Failure.php.inc +++ b/tests/.snapshots/Failure.php.inc @@ -1,6 +1,6 @@ ##teamcity[testSuiteStarted name='Tests/tests/Failure' locationHint='file://tests/.tests/Failure.php' flowId='1234'] ##teamcity[testStarted name='it can fail with comparison' locationHint='pest_qn://tests/.tests/Failure.php::it can fail with comparison' flowId='1234'] -##teamcity[testFailed name='it can fail with comparison' message='Failed asserting that true matches expected false.' details='at src/Mixins/Expectation.php:342|nat src/Support/ExpectationPipeline.php:75|nat src/Support/ExpectationPipeline.php:79|nat src/Expectation.php:300|nat tests/.tests/Failure.php:6|nat src/Factories/TestCaseMethodFactory.php:100|nat src/Concerns/Testable.php:262|nat src/Support/ExceptionTrace.php:28|nat src/Concerns/Testable.php:262|nat src/Concerns/Testable.php:217|nat src/Kernel.php:89' type='comparisonFailure' actual='true' expected='false' flowId='1234'] +##teamcity[testFailed name='it can fail with comparison' message='Failed asserting that true matches expected false.' details='at src/Mixins/Expectation.php:342|nat src/Support/ExpectationPipeline.php:75|nat src/Support/ExpectationPipeline.php:79|nat src/Expectation.php:300|nat tests/.tests/Failure.php:6|nat src/Factories/TestCaseMethodFactory.php:100|nat src/Concerns/Testable.php:262|nat src/Support/ExceptionTrace.php:28|nat src/Concerns/Testable.php:262|nat src/Concerns/Testable.php:217|nat src/Kernel.php:91' type='comparisonFailure' actual='true' expected='false' flowId='1234'] ##teamcity[testFinished name='it can fail with comparison' duration='100000' flowId='1234'] ##teamcity[testStarted name='it can be ignored because of no assertions' locationHint='pest_qn://tests/.tests/Failure.php::it can be ignored because of no assertions' flowId='1234'] ##teamcity[testIgnored name='it can be ignored because of no assertions' message='This test did not perform any assertions' details='' flowId='1234'] @@ -9,7 +9,7 @@ ##teamcity[testIgnored name='it can be ignored because it is skipped' message='This test was ignored.' details='' flowId='1234'] ##teamcity[testFinished name='it can be ignored because it is skipped' duration='100000' flowId='1234'] ##teamcity[testStarted name='it can fail' locationHint='pest_qn://tests/.tests/Failure.php::it can fail' flowId='1234'] -##teamcity[testFailed name='it can fail' message='oh noo' details='at tests/.tests/Failure.php:18|nat src/Factories/TestCaseMethodFactory.php:100|nat src/Concerns/Testable.php:262|nat src/Support/ExceptionTrace.php:28|nat src/Concerns/Testable.php:262|nat src/Concerns/Testable.php:217|nat src/Kernel.php:89' flowId='1234'] +##teamcity[testFailed name='it can fail' message='oh noo' details='at tests/.tests/Failure.php:18|nat src/Factories/TestCaseMethodFactory.php:100|nat src/Concerns/Testable.php:262|nat src/Support/ExceptionTrace.php:28|nat src/Concerns/Testable.php:262|nat src/Concerns/Testable.php:217|nat src/Kernel.php:91' flowId='1234'] ##teamcity[testFinished name='it can fail' duration='100000' flowId='1234'] ##teamcity[testStarted name='it is not done yet' locationHint='pest_qn://tests/.tests/Failure.php::it is not done yet' flowId='1234'] ##teamcity[testIgnored name='it is not done yet' message='This test was ignored.' details='' flowId='1234'] diff --git a/tests/.snapshots/help-command.txt b/tests/.snapshots/help-command.txt index 4327381e..ccdd5b57 100644 --- a/tests/.snapshots/help-command.txt +++ b/tests/.snapshots/help-command.txt @@ -15,8 +15,8 @@ --migrate-configuration ....... Migrate configuration file to current format SELECTION OPTIONS: - --list-suites ................................... List available test suites - --testsuite ............... Only run tests from the specified test suite(s) + --todos ........................ Output to standard output the list of todos + --retry Run non-passing tests first and stop execution upon first error or failure --exclude-testsuite ........ Exclude tests from the specified test suite(s) --list-groups ................................... List available test groups --group ........................ Only run tests from the specified group(s) @@ -95,9 +95,6 @@ --disable-coverage-ignore Disable attributes and annotations for ignoring code coverage --no-coverage ........................... Ignore code coverage configuration - MISCELLANEOUS OPTIONS: - -h|--help .................................... Prints this usage information - --version ..................................... Prints the version and exits - --atleast-version ....... Checks that version is greater than min and exits - --check-version ................ Check whether PHPUnit is the latest version + PROFILING OPTIONS: + --profile .............. Output to standard output the top ten slowest tests