packages/requirements/tests/Unit/Source/ResourceLocationTest.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\TestCase;
11use Requirements\Source\ResourceLocation;
12use RuntimeException;
13
14#[CoversClass(ResourceLocation::class)]
15#[Small]
16final class ResourceLocationTest extends TestCase
17{
18 #[DataProvider('providerResolve')]
19 public function testResolve(string $uri, string $expected): void
20 {
21 self::assertSame($expected, (new ResourceLocation())->resolve($uri, '/project/config'));
22 }
23
24 /**
25 * @return array<string, array{string, string}>
26 */
27 public static function providerResolve(): array
28 {
29 return [
30 'relative path' => ['docs/manual.html', '/project/config/docs/manual.html'],
31 'parent path' => ['../manual.html', '/project/config/../manual.html'],
32 'absolute path' => ['/srv/manual.html', '/srv/manual.html'],
33 'https' => ['https://example.org/manual.html', 'https://example.org/manual.html'],
34 'http' => ['http://example.org/manual.html', 'http://example.org/manual.html'],
35 ];
36 }
37
38 #[DataProvider('providerResolveOtherScheme')]
39 public function testResolveRejectsOtherSchemes(string $uri): void
40 {
41 $this->expectException(RuntimeException::class);
42 $this->expectExceptionMessage('Built-in sources accept HTTP(S) URLs or local paths only.');
43 (new ResourceLocation())->resolve($uri, '/project/config');
44 }
45
46 /**
47 * @return array<string, array{string}>
48 */
49 public static function providerResolveOtherScheme(): array
50 {
51 return [
52 'file' => ['file:///etc/passwd'],
53 'ftp' => ['ftp://example.org/manual.html'],
54 'scheme inside an absolute path' => ['/srv/ftp://manual.html'],
55 'http later in the uri' => ['php://filter/http://example.org'],
56 'uppercase https' => ['HTTPS://example.org/manual.html'],
57 ];
58 }
59}
60