Parse and validate AT Protocol Lexicons with DTO generation for Laravel
1<?php
2
3namespace SocialDept\AtpSchema\Tests\Unit\Generator;
4
5use Orchestra\Testbench\TestCase;
6use SocialDept\AtpSchema\Exceptions\GenerationException;
7use SocialDept\AtpSchema\Generator\TemplateRenderer;
8
9class TemplateRendererTest extends TestCase
10{
11 protected TemplateRenderer $renderer;
12
13 protected function setUp(): void
14 {
15 parent::setUp();
16
17 $this->renderer = new TemplateRenderer();
18 }
19
20 public function test_it_renders_template_with_simple_variables(): void
21 {
22 $template = 'Hello, {{name}}!';
23 $this->renderer->registerTemplate('greeting', $template);
24
25 $result = $this->renderer->render('greeting', ['name' => 'World']);
26
27 $this->assertSame('Hello, World!', $result);
28 }
29
30 public function test_it_renders_record_template(): void
31 {
32 $result = $this->renderer->render('record', [
33 'namespace' => 'App\\Lexicon\\App\\Bsky\\Feed',
34 'className' => 'Post',
35 'nsid' => 'app.bsky.feed.post',
36 'description' => 'A post record',
37 'properties' => [
38 [
39 'name' => 'text',
40 'type' => 'string',
41 'phpType' => 'string',
42 'required' => true,
43 'description' => 'Post text content',
44 ],
45 ],
46 ]);
47
48 $this->assertStringContainsString('namespace App\\Lexicon\\App\\Bsky\\Feed', $result);
49 $this->assertStringContainsString('class Post', $result);
50 $this->assertStringContainsString('public readonly string $text', $result);
51 $this->assertStringContainsString('Post text content', $result);
52 }
53
54 public function test_it_renders_object_template(): void
55 {
56 $result = $this->renderer->render('object', [
57 'namespace' => 'App\\Lexicon\\App\\Bsky\\Feed',
58 'className' => 'ReplyRef',
59 'description' => 'A reply reference',
60 'properties' => [
61 [
62 'name' => 'parent',
63 'type' => 'string',
64 'phpType' => 'string',
65 'required' => true,
66 'description' => null,
67 ],
68 ],
69 ]);
70
71 $this->assertStringContainsString('namespace App\\Lexicon\\App\\Bsky\\Feed', $result);
72 $this->assertStringContainsString('class ReplyRef', $result);
73 $this->assertStringContainsString('public readonly string $parent', $result);
74 }
75
76 public function test_it_handles_nullable_properties(): void
77 {
78 $result = $this->renderer->render('record', [
79 'namespace' => 'App\\Lexicon\\Test',
80 'className' => 'Test',
81 'nsid' => 'test.example.test',
82 'description' => 'Test',
83 'properties' => [
84 [
85 'name' => 'optional',
86 'type' => 'string',
87 'phpType' => 'string',
88 'required' => false,
89 'description' => null,
90 ],
91 ],
92 ]);
93
94 $this->assertStringContainsString('?string $optional', $result);
95 }
96
97 public function test_it_registers_custom_template(): void
98 {
99 $this->renderer->registerTemplate('custom', 'Custom: {{value}}');
100
101 $result = $this->renderer->render('custom', ['value' => 'Test']);
102
103 $this->assertSame('Custom: Test', $result);
104 }
105
106 public function test_it_throws_on_unknown_template(): void
107 {
108 $this->expectException(GenerationException::class);
109 $this->expectExceptionMessage('Template not found: nonexistent');
110
111 $this->renderer->render('nonexistent', []);
112 }
113
114 public function test_it_renders_multiple_properties(): void
115 {
116 $result = $this->renderer->render('record', [
117 'namespace' => 'App\\Lexicon\\Test',
118 'className' => 'Test',
119 'nsid' => 'test.example.test',
120 'description' => 'Test',
121 'properties' => [
122 [
123 'name' => 'field1',
124 'type' => 'string',
125 'phpType' => 'string',
126 'required' => true,
127 'description' => 'First field',
128 ],
129 [
130 'name' => 'field2',
131 'type' => 'integer',
132 'phpType' => 'int',
133 'required' => false,
134 'description' => 'Second field',
135 ],
136 ],
137 ]);
138
139 $this->assertStringContainsString('public readonly string $field1', $result);
140 $this->assertStringContainsString('public readonly ?int $field2', $result);
141 $this->assertStringContainsString('First field', $result);
142 $this->assertStringContainsString('Second field', $result);
143 }
144}