Skip to content

Commit aaff341

Browse files
committed
Console: Improve test coverage
- Add `TestCase::assertConsoleMessagesMatch()`
1 parent 2e8dd85 commit aaff341

File tree

2 files changed

+236
-0
lines changed

2 files changed

+236
-0
lines changed

tests/unit/Toolkit/Console/ConsoleTest.php

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@
66
use Salient\Console\Target\AnalogTarget;
77
use Salient\Console\Target\StreamTarget;
88
use Salient\Console\Console as ConsoleService;
9+
use Salient\Core\Exception\Exception;
10+
use Salient\Core\Exception\MultipleErrorException;
911
use Salient\Core\Facade\Console;
1012
use Salient\Testing\Console\MockTarget;
1113
use Salient\Testing\Core\MockPhpStream;
1214
use Salient\Tests\TestCase;
15+
use Salient\Utility\Exception\InvalidArgumentTypeException;
1316
use Salient\Utility\File;
1417
use Salient\Utility\Get;
1518

@@ -447,6 +450,204 @@ public function testCloseAfterLogProgress(): void
447450
$this->assertSameTargetOutput("\e[?7l\e[33m⠋ \e[39mStarting\r\e[K\e[?7h");
448451
}
449452

453+
/**
454+
* @backupGlobals enabled
455+
*/
456+
public function testException(): void
457+
{
458+
$_ENV['DEBUG'] = '0';
459+
$console = $this->Console;
460+
$line = __LINE__ + 1;
461+
$ex1 = new InvalidArgumentTypeException(1, 'class', 'class-string', 71);
462+
$ex2 = new Exception('message2', $ex1);
463+
$ex3 = new MultipleErrorException('message3', 'error1', 'error2');
464+
$ex4 = new ExceptionWithMetadata('message4');
465+
$console->exception($ex2);
466+
$console->exception($ex3, Console::LEVEL_ERROR, null);
467+
$ex3->reportErrors($console);
468+
$console->exception($ex3, Console::LEVEL_ERROR, null);
469+
$console->exception($ex4, Console::LEVEL_WARNING);
470+
$_ENV['DEBUG'] = '1';
471+
$console->exception($ex4, Console::LEVEL_WARNING, null, false);
472+
473+
$this->assertSameConsoleMessages([
474+
[3, sprintf(
475+
"! Exception:\n message2 in %s:%d\n Caused by InvalidArgumentTypeException: Argument #1 (\$class) must be of type class-string, int given in %s:%d",
476+
__FILE__,
477+
$line + 1,
478+
__FILE__,
479+
$line,
480+
)],
481+
[7, sprintf(
482+
": Stack trace:\n %s",
483+
str_replace("\n", "\n ", $ex2->getTraceAsString()),
484+
)],
485+
[3, sprintf(
486+
"! MultipleErrorException:\n message3:\n - error1\n - error2 in %s:%d",
487+
__FILE__,
488+
$line + 2,
489+
)],
490+
[3, 'Error: error1'],
491+
[3, 'Error: error2'],
492+
[3, sprintf(
493+
'! MultipleErrorException: message3 in %s:%d',
494+
__FILE__,
495+
$line + 2,
496+
)],
497+
[4, '^ ExceptionWithMetadata: message4'],
498+
[7, sprintf(
499+
": Stack trace:\n %s",
500+
str_replace("\n", "\n ", $ex4->getTraceAsString()),
501+
)],
502+
[7, ": foo:\n bar"],
503+
[7, ": baz:\n 1"],
504+
[4, sprintf(
505+
'^ ExceptionWithMetadata: message4 in %s:%d',
506+
__FILE__,
507+
$line + 3,
508+
)],
509+
], $this->TtyTarget->getMessages());
510+
$this->assertSame(5, $console->errors());
511+
$this->assertSame(1, $console->warnings());
512+
}
513+
514+
/**
515+
* @dataProvider summaryProvider
516+
*
517+
* @param array<array{Console::LEVEL_*,string,2?:array<string,mixed>}> $expected
518+
*/
519+
public function testSummary(
520+
array $expected,
521+
int $errors,
522+
int $warnings,
523+
string $finishedText = 'Command finished',
524+
string $successText = 'without errors',
525+
bool $withResourceUsage = false,
526+
bool $withoutErrorsAndWarnings = false,
527+
bool $withGenericType = false,
528+
bool $expectedHasPatterns = false
529+
): void {
530+
$console = $this->Console;
531+
for ($i = 0; $i < $errors; $i++) {
532+
$console->count(Console::LEVEL_ERROR);
533+
}
534+
for ($i = 0; $i < $warnings; $i++) {
535+
$console->count(Console::LEVEL_WARNING);
536+
}
537+
$console->summary(
538+
$finishedText,
539+
$successText,
540+
$withResourceUsage,
541+
$withoutErrorsAndWarnings,
542+
$withGenericType,
543+
);
544+
545+
if ($expectedHasPatterns) {
546+
$this->assertConsoleMessagesMatch($expected, $this->TtyTarget->getMessages());
547+
} else {
548+
$this->assertSameConsoleMessages($expected, $this->TtyTarget->getMessages());
549+
}
550+
}
551+
552+
/**
553+
* @return array<array{array<array{Console::LEVEL_*,string,2?:array<string,mixed>}>,int,int,3?:string,4?:string,5?:bool,6?:bool,7?:bool,8?:bool}>
554+
*/
555+
public static function summaryProvider(): array
556+
{
557+
return [
558+
[
559+
[[6, '✔ Command finished without errors']],
560+
0,
561+
0,
562+
],
563+
[
564+
[[3, '✘ Command finished with 1 error']],
565+
1,
566+
0,
567+
],
568+
[
569+
[[3, '✘ Command finished with 2 errors and 1 warning']],
570+
2,
571+
1,
572+
],
573+
[
574+
[[4, '✘ Command finished with 0 errors and 2 warnings']],
575+
0,
576+
2,
577+
],
578+
[
579+
[[6, '✔ Done successfully']],
580+
0,
581+
0,
582+
'Done',
583+
'successfully',
584+
false,
585+
true,
586+
],
587+
[
588+
[[6, '» Done']],
589+
1,
590+
0,
591+
'Done',
592+
'successfully',
593+
false,
594+
true,
595+
],
596+
[
597+
[[6, '» Done successfully']],
598+
0,
599+
0,
600+
'Done',
601+
'successfully',
602+
false,
603+
false,
604+
true,
605+
],
606+
[
607+
[[6, '» Done with 1 error']],
608+
1,
609+
0,
610+
'Done',
611+
'successfully',
612+
false,
613+
false,
614+
true,
615+
],
616+
[
617+
[[6, '» Done with 0 errors and 2 warnings']],
618+
0,
619+
2,
620+
'Done',
621+
'successfully',
622+
false,
623+
false,
624+
true,
625+
],
626+
[
627+
[[6, '/^✔ Done successfully in (0|[1-9][0-9]*+)\.[0-9]{3}s \((0|[1-9][0-9]*+)\.[0-9]{3}(B|[KMGTPEZY]iB) memory used\)$/D']],
628+
0,
629+
0,
630+
'Done',
631+
'successfully',
632+
true,
633+
false,
634+
false,
635+
true,
636+
],
637+
[
638+
[[3, '/^✘ Done with 1 error in (0|[1-9][0-9]*+)\.[0-9]{3}s \((0|[1-9][0-9]*+)\.[0-9]{3}(B|[KMGTPEZY]iB) memory used\)$/D']],
639+
1,
640+
0,
641+
'Done',
642+
'successfully',
643+
true,
644+
false,
645+
false,
646+
true,
647+
],
648+
];
649+
}
650+
450651
/**
451652
* @return array{int<0,max>,float|null}
452653
*/
@@ -504,3 +705,14 @@ protected function applyStream($stream): void
504705
$this->IsTty = true;
505706
}
506707
}
708+
709+
class ExceptionWithMetadata extends Exception
710+
{
711+
public function getMetadata(): array
712+
{
713+
return [
714+
'foo' => 'bar',
715+
'baz' => 1,
716+
];
717+
}
718+
}

tests/unit/Toolkit/TestCase.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,30 @@ public static function assertSameConsoleMessages(
7878
self::assertEquals($expected, $actual, $message);
7979
}
8080

81+
/**
82+
* Assert that console messages matching the given regular expressions are
83+
* written
84+
*
85+
* @param array<array{Console::LEVEL_*,string,2?:array<string,mixed>}> $expected
86+
* @param array<array{Console::LEVEL_*,string,2?:array<string,mixed>}> $actual
87+
*/
88+
public static function assertConsoleMessagesMatch(
89+
array $expected,
90+
array $actual,
91+
string $message = ''
92+
): void {
93+
foreach ($expected as $i => $expectedMessage) {
94+
self::assertMatchesRegularExpression($expectedMessage[1], $actual[$i][1], $message);
95+
$_expected[$i][0] = $expectedMessage[0];
96+
$_actual[$i][0] = $actual[$i][0];
97+
if (isset($expectedMessage[2])) {
98+
$_expected[$i][2] = $expectedMessage[2];
99+
$_actual[$i][2] = $actual[$i][2] ?? null;
100+
}
101+
}
102+
self::assertEquals($_expected ?? [], $_actual ?? [], $message);
103+
}
104+
81105
/**
82106
* Expect an exception if a given value is a string
83107
*

0 commit comments

Comments
 (0)