packages/sql-catalog/tests/Unit/Facade/ConfigurationSchemaTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Facade;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\DataProvider;
9use PHPUnit\Framework\Attributes\UsesClass;
10use PHPUnit\Framework\TestCase;
11use SqlCatalog\Facade\ConfigurationSchema;
12use SqlCatalog\Facade\InvalidConfigurationException;
13use stdClass;
14
15#[CoversClass(ConfigurationSchema::class)]
16#[UsesClass(InvalidConfigurationException::class)]
17final class ConfigurationSchemaTest extends TestCase
18{
19    public function testOptionsPreservesListsAndResolvesOnlyFilesystemPaths(): void
20    {
21        $options = ConfigurationSchema::options((object) ['paths' => ['src'], 'exclude' => ['*.tmp', 'vendor'], 'root' => '/project', 'kind' => ['select'], 'function-models' => new stdClass()], '/config');
22        self::assertSame(['paths' => ['/config/src'], 'exclude' => ['*.tmp', 'vendor'], 'root' => ['/project'], 'kind' => ['select']], $options);
23        self::assertSame(['extension' => [], 'root' => ['/config']], ConfigurationSchema::options((object) ['extensions' => []], '/config'));
24    }
25
26    #[DataProvider('providerInvalidOptions')]
27    public function testOptionsRejectsInvalidSettings(stdClass $data): void
28    {
29        $this->expectException(InvalidConfigurationException::class);
30        ConfigurationSchema::options($data, '/config');
31    }
32
33    /**
34     * @return list<array{stdClass}>
35     */
36    public static function providerInvalidOptions(): array
37    {
38        return [
39            [(object) ['unknown' => 'value']],
40            [(object) ['reporter' => []]],
41            [(object) ['reporter' => '']],
42            [(object) ['paths' => 'src']],
43            [(object) ['paths' => ['x' => 'src']]],
44            [(object) ['paths' => [1]]],
45            [(object) ['paths' => ['']]],
46        ];
47    }
48
49    public function testModelsReadsAMappingAndAllowsNoRegistrations(): void
50    {
51        self::assertSame([], ConfigurationSchema::models(new stdClass()));
52        self::assertSame([], ConfigurationSchema::models((object) ['function-models' => new stdClass()]));
53        self::assertSame(['array_fill' => 'App\\Model'], ConfigurationSchema::models((object) ['function-models' => (object) ['array_fill' => 'App\\Model']]));
54    }
55
56    #[DataProvider('providerInvalidModels')]
57    public function testModelsRejectsMalformedRegistrations(stdClass $data): void
58    {
59        $this->expectException(InvalidConfigurationException::class);
60        ConfigurationSchema::models($data);
61    }
62
63    /**
64     * @return list<array{stdClass}>
65     */
66    public static function providerInvalidModels(): array
67    {
68        return [
69            [(object) ['function-models' => []]],
70            [(object) ['function-models' => null]],
71            [(object) ['function-models' => (object) ['' => 'Model']]],
72            [(object) ['function-models' => (object) ['foo' => '']]],
73            [(object) ['function-models' => (object) ['foo' => false]]],
74        ];
75    }
76
77    #[DataProvider('providerPaths')]
78    public function testAbsolutePreservesAbsolutePathsAndResolvesRelativePaths(string $path, string $expected): void
79    {
80        self::assertSame($expected, ConfigurationSchema::absolute($path, '/config'));
81    }
82
83    /**
84     * @return list<array{string, string}>
85     */
86    public static function providerPaths(): array
87    {
88        return [['src', '/config/src'], ['/src', '/src'], ['C:/src', 'C:/src'], ['C:\\src', 'C:\\src'], ['\\\\server\\src', '\\\\server\\src']];
89    }
90}
91