packages/requirements/tests/Unit/Console/OverviewTest.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\CommandHandler;
13use Requirements\Console\CommandLine;
14use Requirements\Console\Options;
15use Requirements\Console\Overview;
16use Symfony\Component\Console\Input\ArgvInput;
17use Symfony\Component\Console\Output\BufferedOutput;
18use Symfony\Component\Console\Output\OutputInterface;
19
20#[CoversClass(Overview::class)]
21#[UsesClass(CommandHandler::class)]
22#[UsesClass(CommandLine::class)]
23#[UsesClass(Options::class)]
24#[Small]
25final class OverviewTest extends TestCase
26{
27    /**
28     * @param list<string> $arguments
29     */
30    #[DataProvider('providerRequested')]
31    public function testRequestedTellsWhetherTheOverviewIsAskedFor(array $arguments, bool $expected): void
32    {
33        self::assertSame($expected, (new Overview())->requested((new CommandLine())->create(), new ArgvInput(['requirements', ...$arguments])));
34    }
35
36    /**
37     * @return array<string, array{list<string>, bool}>
38     */
39    public static function providerRequested(): array
40    {
41        return [
42            'nothing' => [[], true],
43            'help option' => [['--help'], true],
44            'help shortcut' => [['-h'], true],
45            'help option without decoration' => [['--help', '--no-ansi'], true],
46            'help with a missing configuration' => [['--config', 'missing.yaml', '--help'], true],
47            'help with json' => [['--json', '--help'], true],
48            'help command' => [['help'], true],
49            'help for a command' => [['help', 'coverage'], false],
50            'quiet' => [['--quiet'], true],
51            'command' => [['lint'], false],
52            'command help' => [['coverage', '--help'], false],
53            'command help shortcut' => [['spec', '-h'], false],
54            'list' => [['list'], false],
55            'unknown command' => [['unknown'], false],
56            'version' => [['--version'], false],
57            'version shortcut' => [['-V'], false],
58            'help with version' => [['help', '--version'], false],
59            'unknown option' => [['--unknown'], false],
60        ];
61    }
62
63    public function testRequestedLeavesTheInputUnbound(): void
64    {
65        $input = new ArgvInput(['requirements', 'lint']);
66        (new Overview())->requested((new CommandLine())->create(), $input);
67        self::assertSame([], $input->getArguments());
68    }
69
70    public function testShowDescribesTheApplication(): void
71    {
72        $output = new BufferedOutput();
73        (new Overview())->show((new CommandLine())->create(), $output, []);
74        $text = $output->fetch();
75        self::assertStringContainsString('Usage:', $text);
76        self::assertStringContainsString('Available commands:', $text);
77        self::assertStringContainsString('Show source coverage and enforce total and differential gates.', $text);
78        self::assertStringContainsString('--config', $text);
79        self::assertStringNotContainsString("\x1b", $text);
80    }
81
82    /**
83     * @param list<string> $arguments
84     */
85    #[DataProvider('providerShowDecoration')]
86    public function testShowHonorsTheDecorationOptions(bool $decorated, array $arguments, bool $expected): void
87    {
88        $output = new BufferedOutput(OutputInterface::VERBOSITY_NORMAL, $decorated);
89        (new Overview())->show((new CommandLine())->create(), $output, $arguments);
90        self::assertSame($expected, $output->isDecorated());
91        self::assertSame($expected, str_contains($output->fetch(), "\x1b["));
92    }
93
94    /**
95     * @return array<string, array{bool, list<string>, bool}>
96     */
97    public static function providerShowDecoration(): array
98    {
99        return [
100            'plain stays plain' => [false, [], false],
101            'decorated stays decorated' => [true, [], true],
102            'no ansi' => [true, ['--no-ansi'], false],
103            'ansi' => [false, ['--ansi'], true],
104            'ansi wins over no ansi' => [false, ['--no-ansi', '--ansi'], true],
105        ];
106    }
107
108    /**
109     * @param list<string> $arguments
110     */
111    #[DataProvider('providerShowQuiet')]
112    public function testShowHonorsQuiet(array $arguments): void
113    {
114        $output = new BufferedOutput();
115        (new Overview())->show((new CommandLine())->create(), $output, $arguments);
116        self::assertSame(OutputInterface::VERBOSITY_QUIET, $output->getVerbosity());
117        self::assertSame('', $output->fetch());
118    }
119
120    /**
121     * @return array<string, array{list<string>}>
122     */
123    public static function providerShowQuiet(): array
124    {
125        return [
126            'long' => [['--quiet']],
127            'short' => [['-q']],
128            'with help' => [['--help', '--quiet']],
129        ];
130    }
131}
132