packages/requirements/tests/Unit/Console/CoverageTableTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Console;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\DataProvider;
9use PHPUnit\Framework\Attributes\Small;
10use PHPUnit\Framework\Attributes\UsesClass;
11use PHPUnit\Framework\TestCase;
12use Requirements\Console\CoverageTable;
13use Requirements\Console\Text;
14use Requirements\Input\Fields;
15use Requirements\Input\InvalidInputException;
16use Symfony\Component\Console\Input\ArrayInput;
17use Symfony\Component\Console\Output\BufferedOutput;
18use Symfony\Component\Console\Style\SymfonyStyle;
19
20#[CoversClass(CoverageTable::class)]
21#[UsesClass(Text::class)]
22#[UsesClass(Fields::class)]
23#[Small]
24final class CoverageTableTest extends TestCase
25{
26 public function testRenderShowsOverallSourceAndChangedUnitRows(): void
27 {
28 $output = new BufferedOutput();
29 (new CoverageTable())->render(new SymfonyStyle(new ArrayInput([]), $output), [
30 'overall' => ['total' => 3, 'accounted' => 1, 'supported' => 1, 'unsupported' => 0, 'uncovered' => 2, 'percentage' => 33.333333],
31 'sources' => ['manual' => ['total' => 3, 'accounted' => 1, 'supported' => 1, 'unsupported' => 0, 'uncovered' => 2, 'percentage' => 66.666666]],
32 'diff' => ['total' => 0, 'accounted' => 0, 'supported' => 0, 'unsupported' => 0, 'uncovered' => 0, 'percentage' => null],
33 ]);
34 $text = preg_replace('/ +$/m', '', $output->fetch());
35 self::assertIsString($text);
36 self::assertStringStartsWith(<<<'TABLE'
37 --------------- ------- ----------- ----------- ------------- ----------- ----------
38 Scope Units Accounted Supported Unsupported Uncovered Coverage
39 --------------- ------- ----------- ----------- ------------- ----------- ----------
40 Overall 3 1 1 0 2 33.33%
41 manual 3 1 1 0 2 66.67%
42 Changed units 0 0 0 0 0 n/a
43 --------------- ------- ----------- ----------- ------------- ----------- ----------
44
45TABLE, $text);
46 self::assertStringContainsString('[NOTE] Coverage applies only to the declared source scopes.', $text);
47 }
48
49 public function testRenderOmitsChangedUnitsWithoutASnapshotComparison(): void
50 {
51 $output = new BufferedOutput();
52 (new CoverageTable())->render(new SymfonyStyle(new ArrayInput([]), $output), [
53 'overall' => ['total' => 4, 'accounted' => 2, 'supported' => 1, 'unsupported' => 1, 'uncovered' => 2, 'percentage' => 50],
54 'sources' => ['<info>x</info>' => ['total' => 4, 'accounted' => 2, 'supported' => 1, 'unsupported' => 1, 'uncovered' => 2, 'percentage' => '50'], 'empty' => ['total' => 0, 'accounted' => 0, 'supported' => 0, 'unsupported' => 0, 'uncovered' => 0, 'percentage' => null]],
55 'diff' => null,
56 ]);
57 $text = preg_replace('/ +$/m', '', $output->fetch());
58 self::assertIsString($text);
59 self::assertStringStartsWith(<<<'TABLE'
60 ---------------- ------- ----------- ----------- ------------- ----------- ----------
61 Scope Units Accounted Supported Unsupported Uncovered Coverage
62 ---------------- ------- ----------- ----------- ------------- ----------- ----------
63 Overall 4 2 1 1 2 50.00%
64 <info>x</info> 4 2 1 1 2 n/a
65 empty 0 0 0 0 0 n/a
66 ---------------- ------- ----------- ----------- ------------- ----------- ----------
67
68TABLE, $text);
69 self::assertStringNotContainsString('Changed units', $text);
70 self::assertStringContainsString('Unsupported units', $text);
71 }
72
73 /**
74 * @param array<string, mixed> $report
75 */
76 #[DataProvider('providerRenderRejected')]
77 public function testRenderRejectsScopesThatAreNotMappings(array $report, string $message): void
78 {
79 $this->expectException(InvalidInputException::class);
80 $this->expectExceptionMessage($message);
81 (new CoverageTable())->render(new SymfonyStyle(new ArrayInput([]), new BufferedOutput()), $report);
82 }
83
84 /**
85 * @return array<string, array{array<string, mixed>, string}>
86 */
87 public static function providerRenderRejected(): array
88 {
89 $scope = ['total' => 0, 'accounted' => 0, 'supported' => 0, 'unsupported' => 0, 'uncovered' => 0, 'percentage' => null];
90 return [
91 'sources list' => [['overall' => $scope, 'sources' => 'manual', 'diff' => null], 'sources must be a mapping.'],
92 'overall' => [['overall' => 'all', 'sources' => [], 'diff' => null], 'coverage must be a mapping.'],
93 'source' => [['overall' => $scope, 'sources' => ['manual' => 3], 'diff' => null], 'coverage must be a mapping.'],
94 'diff' => [['overall' => $scope, 'sources' => [], 'diff' => 'none'], 'coverage must be a mapping.'],
95 ];
96 }
97}
98