packages/requirements/tests/Unit/Test/RunnerConfigTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Test;
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\Input\Fields;
13use Requirements\Input\InvalidInputException;
14use Requirements\Test\RunnerConfig;
15
16#[CoversClass(RunnerConfig::class)]
17#[UsesClass(Fields::class)]
18#[Small]
19final class RunnerConfigTest extends TestCase
20{
21    public function testFromReadsEveryField(): void
22    {
23        $config = RunnerConfig::from(['extension' => 'behat', 'command' => ['php', 'vendor/bin/behat'], 'cwd' => 'tests', 'timeout' => 5], '/project');
24        self::assertSame('behat', $config->extension);
25        self::assertSame(['php', 'vendor/bin/behat'], $config->command);
26        self::assertSame('/project/tests', $config->directory);
27        self::assertSame(5.0, $config->timeout);
28    }
29
30    public function testFromDefaultsToTheConfigurationDirectoryAndSixtySeconds(): void
31    {
32        $config = RunnerConfig::from(['extension' => 'phpunit', 'command' => ['php', 'vendor/bin/phpunit']], '/project');
33        self::assertSame('/project/.', $config->directory);
34        self::assertSame(60.0, $config->timeout);
35    }
36
37    public function testFromTreatsANullTimeoutAsAbsent(): void
38    {
39        self::assertSame(60.0, RunnerConfig::from(['extension' => 'phpunit', 'command' => ['phpunit'], 'timeout' => null], '/project')->timeout);
40    }
41
42    public function testFromKeepsAnAbsoluteWorkingDirectory(): void
43    {
44        self::assertSame('/srv/app', RunnerConfig::from(['extension' => 'phpunit', 'command' => ['phpunit'], 'cwd' => '/srv/app'], '/project')->directory);
45    }
46
47    public function testFromAcceptsAFractionalTimeout(): void
48    {
49        self::assertSame(0.5, RunnerConfig::from(['extension' => 'phpunit', 'command' => ['phpunit'], 'timeout' => 0.5], '/project')->timeout);
50    }
51
52    public function testFromKeepsRepeatedCommandArguments(): void
53    {
54        self::assertSame(['php', '-d', 'a=1', '-d', 'b=1'], RunnerConfig::from(['extension' => 'phpunit', 'command' => ['php', '-d', 'a=1', '-d', 'b=1']], '/project')->command);
55    }
56
57    public function testTimeoutDefaultsToSixtySecondsWhenConstructed(): void
58    {
59        $config = new RunnerConfig('phpunit', ['php', 'vendor/bin/phpunit'], '/project');
60        self::assertSame(60.0, $config->timeout);
61    }
62
63    #[DataProvider('providerFromRejectsInvalidEntries')]
64    public function testFromRejectsInvalidEntries(mixed $value, string $message): void
65    {
66        $this->expectException(InvalidInputException::class);
67        $this->expectExceptionMessage($message);
68        RunnerConfig::from($value, '/project');
69    }
70
71    /**
72     * @return array<string, array{mixed, string}>
73     */
74    public static function providerFromRejectsInvalidEntries(): array
75    {
76        $runner = ['extension' => 'phpunit', 'command' => ['phpunit']];
77        $command = 'Runners require a nonempty command and positive timeout.';
78        return [
79            'not a mapping' => ['phpunit', 'runner must be a mapping.'],
80            'unknown field' => [[...$runner, 'env' => []], "runner: unknown field 'env'."],
81            'missing command' => [['extension' => 'phpunit'], $command],
82            'empty command' => [[...$runner, 'command' => []], $command],
83            'command string' => [[...$runner, 'command' => 'phpunit'], 'runner.command must be a list.'],
84            'blank command entry' => [[...$runner, 'command' => ['php', ' ']], 'runner.command must contain nonempty strings.'],
85            'zero timeout' => [[...$runner, 'timeout' => 0], $command],
86            'negative timeout' => [[...$runner, 'timeout' => -1.5], $command],
87            'string timeout' => [[...$runner, 'timeout' => '5'], $command],
88            'infinite timeout' => [[...$runner, 'timeout' => INF], $command],
89            'missing extension' => [['command' => ['phpunit']], 'extension must be a nonempty string.'],
90            'blank cwd' => [[...$runner, 'cwd' => ''], 'cwd must be a nonempty string.'],
91        ];
92    }
93}
94