packages/deriver/tests/Unit/Deriver/Providers/DeclarationProviderTest.php

1<?php
2
3declare (strict_types=1);
4
5namespace Tests\Unit\Deriver\Providers;
6
7use Deriver\Deriver\Evaluator\Call\Provider\DispatchDecision;
8use Deriver\Deriver\Evaluator\Call\Provider\DispatchProvider;
9use Deriver\Deriver\Evaluator\Call\Provider\DispatchRequest;
10use Deriver\Deriver\Evaluator\Call\Provider\DispatchTarget;
11use Deriver\Deriver\Evaluator\Request\EntryPoint;
12use Deriver\Deriver\Evaluator\Term;
13use Deriver\Deriver\Evaluator\TermKind;
14use Deriver\Deriver\Providers\DeclarationProvider;
15use Deriver\Deriver\Providers\EntryPointProvider;
16use Deriver\Deriver\Providers\EnvironmentProvider;
17use Deriver\Deriver\Sources\Path;
18use Deriver\Deriver\Sources\Source;
19use Deriver\Deriver\Sources\Sources;
20use Override;
21use PHPUnit\Framework\Attributes\CoversClass;
22use PHPUnit\Framework\Attributes\Small;
23use PHPUnit\Framework\Attributes\UsesClass;
24use PHPUnit\Framework\TestCase;
25
26/**
27 * @covers \Deriver\Deriver\Providers\DeclarationProvider
28 */
29#[CoversClass(DeclarationProvider::class)]
30#[UsesClass(Sources::class)]
31#[UsesClass(Path::class)]
32#[UsesClass(Source::class)]
33#[Small]
34final class DeclarationProviderTest extends TestCase
35{
36    public function testDeclarationsAreDataAvailableToTheSourceIndex(): void
37    {
38        $input = (new class () implements DeclarationProvider, DispatchProvider, EnvironmentProvider, EntryPointProvider {
39            /**
40             * @return string Provider identity
41             */
42            #[Override]
43            public function id(): string
44            {
45                return 'example.container';
46            }
47            /**
48             * @return string Captured export version
49             */
50            #[Override]
51            public function version(): string
52            {
53                return '1';
54            }
55            /**
56             * @return Sources Explicit generated declaration and semantics
57             */
58            #[Override]
59            public function declarations(): Sources
60            {
61                return new Sources([new Source('generated/service.php', '<?php class GeneratedService{public function label(){return "service";}}')]);
62            }
63            /**
64             * @param DispatchRequest $request Evaluated call metadata
65             * @return DispatchDecision Exported binding, with explicit completeness
66             */
67            #[Override]
68            public function resolve(DispatchRequest $request): DispatchDecision
69            {
70                if ($request->method !== 'label' || ($request->receiver->attributes['type'] ?? '') !== 'Contract') {
71                    return new DispatchDecision();
72                }
73                return new DispatchDecision([new DispatchTarget('GeneratedService::label', new Term(TermKind::Object, 'container:shared-service', attributes: ['class' => 'GeneratedService']))], true, ['container:export-complete']);
74            }
75            /**
76             * @return array<string, Term> Captured settings
77             */
78            #[Override]
79            public function environment(): array
80            {
81                return ['APP_NAME' => Term::constant('captured')];
82            }
83            /**
84             * @return list<EntryPoint> Declared lifecycle entries
85             */
86            #[Override]
87            public function entries(): array
88            {
89                return [new EntryPoint('entry')];
90            }
91        })->declarations();
92        self::assertSame('generated/service.php', $input[0]->path);
93        self::assertStringContainsString('class GeneratedService', $input[0]->contents);
94    }
95}
96