packages/requirements/tests/Unit/Source/UnitTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Source;
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\Model\Source;
13use Requirements\Source\Unit;
14
15#[CoversClass(Unit::class)]
16#[UsesClass(Source::class)]
17#[Small]
18final class UnitTest extends TestCase
19{
20    public function testKeyHashesTheUriFormatAndLocation(): void
21    {
22        $unit = new Unit('line:1', 'Names start with a letter.');
23
24        self::assertSame(hash('sha256', "notes.txt\0text\0line:1"), $unit->key(new Source('notes', 'notes.txt', 'text', 'lines:1')));
25    }
26
27    public function testKeyIgnoresTheIdSelectorAndText(): void
28    {
29        $key = (new Unit('line:1', 'First.'))->key(new Source('notes', 'notes.txt', 'text', 'lines:1'));
30
31        self::assertSame($key, (new Unit('line:1', 'Second.'))->key(new Source('other', 'notes.txt', 'text', 'lines:1-9')));
32    }
33
34    #[DataProvider('providerKeyDistinguishes')]
35    public function testKeyDistinguishesUnits(string $uri, string $format, string $location): void
36    {
37        $key = (new Unit('line:1', 'Text.'))->key(new Source('notes', 'notes.txt', 'text', 'lines:1'));
38
39        self::assertNotSame($key, (new Unit($location, 'Text.'))->key(new Source('notes', $uri, $format, 'lines:1')));
40    }
41
42    /**
43     * @return array<string, array{string, string, string}>
44     */
45    public static function providerKeyDistinguishes(): array
46    {
47        return [
48            'uri' => ['other.txt', 'text', 'line:1'],
49            'format' => ['notes.txt', 'markdown', 'line:1'],
50            'location' => ['notes.txt', 'text', 'line:2'],
51            'boundary' => ['notes.txtte', 'xt', 'line:1'],
52        ];
53    }
54
55    #[DataProvider('providerNormalize')]
56    public function testNormalize(string $text, string $expected): void
57    {
58        self::assertSame($expected, Unit::normalize($text));
59    }
60
61    /**
62     * @return array<string, array{string, string}>
63     */
64    public static function providerNormalize(): array
65    {
66        return [
67            'collapsed whitespace' => ["  Names\n\tstart  with a letter. ", 'Names start with a letter.'],
68            'no-break space' => ["Names\u{00a0}\u{00a0}start.", 'Names start.'],
69            'carriage return' => ["Names\r\nstart.", 'Names start.'],
70            'blank' => [" \n\t ", ''],
71            'unicode kept' => ['日本語 text', '日本語 text'],
72            'invalid UTF-8 only trimmed' => ["  \xFF  text ", "\xFF  text"],
73        ];
74    }
75}
76