Skip to content

Commit

Permalink
Print failure/error/warning/skipped/incomplete messages in HTML reports
Browse files Browse the repository at this point in the history
  • Loading branch information
Naktibalda committed Oct 28, 2022
1 parent 700288e commit 0b946e6
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 21 deletions.
118 changes: 97 additions & 21 deletions src/Codeception/Reporter/HtmlReporter.php
Expand Up @@ -20,6 +20,8 @@
use SebastianBergmann\Timer\Timer;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

use function trigger_error;

class HtmlReporter implements EventSubscriberInterface
{
use StaticEventsTrait;
Expand All @@ -45,8 +47,6 @@ class HtmlReporter implements EventSubscriberInterface

protected string $templatePath;

protected array $failures = [];

private string $reportFile;

private Timer $timer;
Expand Down Expand Up @@ -88,41 +88,52 @@ public function beforeSuite(SuiteEvent $event): void

public function testSuccess(TestEvent $event): void
{
$this->printTestResult($event->getTest(), $event->getTime(), 'scenarioSuccess');
$this->printTestEvent($event, 'scenarioSuccess');
}

public function testError(FailEvent $event): void
{
$this->printTestResult($event->getTest(), $event->getTime(), 'scenarioFailed');
$this->printTestEvent($event, 'scenarioFailed');
}

public function testFailure(FailEvent $event): void
{
$this->printTestResult($event->getTest(), $event->getTime(), 'scenarioFailed');
$this->printTestEvent($event, 'scenarioFailed');
}

public function testWarning(FailEvent $event): void
{
$this->printTestResult($event->getTest(), $event->getTime(), 'scenarioSuccess');
$this->printTestEvent($event, 'scenarioSuccess');
}

public function testSkipped(FailEvent $event): void
{
$this->printTestResult($event->getTest(), $event->getTime(), 'scenarioSkipped');
$this->printTestEvent($event, 'scenarioSkipped');
}

public function testIncomplete(FailEvent $event): void
{
$this->printTestResult($event->getTest(), $event->getTime(), 'scenarioIncomplete');
$this->printTestEvent($event, 'scenarioIncomplete');
}

public function testUseless(FailEvent $event): void
{
$this->printTestResult($event->getTest(), $event->getTime(), 'scenarioUseless');
$this->printTestEvent($event, 'scenarioUseless');
}

public function printTestResult(Test $test, float $time, string $scenarioStatus): void
public function printTestEvent(TestEvent $event, string $scenarioStatus): void
{
$failure = '';

$test = $event->getTest();
if ($event instanceof FailEvent) {
$failTemplate = new Template(
$this->templatePath . 'fail.html'
);
$failTemplate->setVar(['fail' => nl2br($event->getFail()->getMessage())]);
$failure = $failTemplate->render() . PHP_EOL;
}

$steps = [];

if ($test instanceof ScenarioDriven) {
Expand Down Expand Up @@ -154,23 +165,88 @@ public function printTestResult(Test $test, float $time, string $scenarioStatus)
}
}

$png = '';
$html = '';
if ($test instanceof TestInterface) {
$reports = $test->getMetadata()->getReports();
if (isset($reports['png'])) {
$localPath = PathResolver::getRelativeDir($reports['png'], codecept_output_dir());
$png = "<tr><td class='error'><div class='screenshot'><img src='$localPath' alt='failure screenshot'></div></td></tr>";
}
if (isset($reports['html'])) {
$localPath = PathResolver::getRelativeDir($reports['html'], codecept_output_dir());
$html = "<tr><td class='error'>See <a href='$localPath' target='_blank'>HTML snapshot</a> of a failed page</td></tr>";
}
}

$toggle = $stepsBuffer ? '<span class="toggle">+</span>' : '';

$testString = htmlspecialchars(ucfirst(Descriptor::getTestAsString($test)), ENT_QUOTES | ENT_SUBSTITUTE);
$testString = preg_replace('~^([\s\w\\\]+):\s~', '<span class="quiet">$1 &raquo;</span> ', $testString);

$scenarioTemplate = new Template(
$this->templatePath . 'scenario.html'
);
$scenarioTemplate->setVar(
[
'id' => ++$this->id,
'name' => $testString,
'scenarioStatus' => $scenarioStatus,
'steps' => $stepsBuffer,
'toggle' => $toggle,
'failure' => $failure,
'png' => $png,
'html' => $html,
'time' => round($event->getTime(), 2),
]
);

$failures = '';
$name = Descriptor::getTestSignatureUnique($test);
if (isset($this->failures[$name])) {
$failTemplate = new Template(
$this->templatePath . 'fail.html'
);
foreach ($this->failures[$name] as $failure) {
$failTemplate->setVar(['fail' => nl2br($failure)]);
$failures .= $failTemplate->render() . PHP_EOL;
$this->scenarios .= $scenarioTemplate->render();
}

public function printTestResult(Test $test, float $time, string $scenarioStatus): void
{
//keep this method for backwards compatibility, remove in Codeception 6.0
trigger_error(
__METHOD__ . ' is deprecated, please use printTestEvent instead',
E_USER_DEPRECATED,
);

$steps = [];

if ($test instanceof ScenarioDriven) {
$steps = $test->getScenario()->getSteps();
}

$stepsBuffer = '';
$subStepsRendered = [];

foreach ($steps as $step) {
$metaStep = $step->getMetaStep();
if ($metaStep) {
$key = $this->getMetaStepKey($metaStep);
$subStepsRendered[$key][] = $this->renderStep($step);
}
}

foreach ($steps as $step) {
$metaStep = $step->getMetaStep();
if ($metaStep) {
$key = $this->getMetaStepKey($metaStep);
if (! empty($subStepsRendered[$key])) {
$subStepsBuffer = implode('', $subStepsRendered[$key]);
unset($subStepsRendered[$key]);
$stepsBuffer .= $this->renderSubsteps($step->getMetaStep(), $subStepsBuffer);
}
} else {
$stepsBuffer .= $this->renderStep($step);
}
$this->failures[$name] = [];
}

$scenarioTemplate = new Template(
$this->templatePath . 'scenario.html'
);

$png = '';
$html = '';
if ($test instanceof TestInterface) {
Expand All @@ -197,7 +273,7 @@ public function printTestResult(Test $test, float $time, string $scenarioStatus)
'scenarioStatus' => $scenarioStatus,
'steps' => $stepsBuffer,
'toggle' => $toggle,
'failure' => $failures,
'failure' => '',
'png' => $png,
'html' => $html,
'time' => round($time, 2)
Expand Down
1 change: 1 addition & 0 deletions tests/cli/RunCest.php
Expand Up @@ -779,6 +779,7 @@ public function runHtmlWithPhpBrowserCheckReport(CliGuy $I)
$I->seeInShellOutput('Response: ' . $expectedReportAbsFilename);
$I->seeFileFound('report.html', $expectedRelReportPath);
$I->seeInThisFile("See <a href='" . $expectedReportFilename . "' target='_blank'>HTML snapshot</a> of a failed page");
$I->seeInThisFile('Failed asserting that on page /');
}

private function htmlReportRegexCheckProvider(): array
Expand Down

0 comments on commit 0b946e6

Please sign in to comment.