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\StubRenderer;
8
9class StubRendererTest extends TestCase
10{
11 protected StubRenderer $renderer;
12
13 protected string $stubPath;
14
15 protected function setUp(): void
16 {
17 parent::setUp();
18
19 $this->stubPath = __DIR__.'/../../fixtures/stubs';
20 @mkdir($this->stubPath, 0755, true);
21
22 $this->renderer = new StubRenderer($this->stubPath);
23 }
24
25 protected function tearDown(): void
26 {
27 // Clean up test stubs
28 if (is_dir($this->stubPath)) {
29 foreach (glob($this->stubPath.'/*.stub') as $file) {
30 @unlink($file);
31 }
32 @rmdir($this->stubPath);
33 }
34
35 parent::tearDown();
36 }
37
38 public function test_it_renders_simple_stub(): void
39 {
40 file_put_contents($this->stubPath.'/simple.stub', 'Hello {{ name }}!');
41
42 $result = $this->renderer->render('simple', ['name' => 'World']);
43
44 $this->assertSame('Hello World!', $result);
45 }
46
47 public function test_it_renders_multiple_variables(): void
48 {
49 file_put_contents(
50 $this->stubPath.'/multiple.stub',
51 'namespace {{ namespace }};
52
53class {{ className }}
54{
55}'
56 );
57
58 $result = $this->renderer->render('multiple', [
59 'namespace' => 'App\\Models',
60 'className' => 'Post',
61 ]);
62
63 $this->assertStringContainsString('namespace App\\Models;', $result);
64 $this->assertStringContainsString('class Post', $result);
65 }
66
67 public function test_it_handles_array_values(): void
68 {
69 file_put_contents(
70 $this->stubPath.'/array.stub',
71 'class Test
72{
73{{ properties }}
74}'
75 );
76
77 $result = $this->renderer->render('array', [
78 'properties' => [
79 ' public string $name;',
80 ' public int $age;',
81 ],
82 ]);
83
84 $this->assertStringContainsString('public string $name;', $result);
85 $this->assertStringContainsString('public int $age;', $result);
86 }
87
88 public function test_it_handles_empty_values(): void
89 {
90 file_put_contents($this->stubPath.'/empty.stub', 'Hello{{ suffix }}');
91
92 $result = $this->renderer->render('empty', ['suffix' => '']);
93
94 $this->assertSame('Hello', $result);
95 }
96
97 public function test_it_handles_null_values(): void
98 {
99 file_put_contents($this->stubPath.'/null.stub', 'Hello{{ suffix }}');
100
101 $result = $this->renderer->render('null', ['suffix' => null]);
102
103 $this->assertSame('Hello', $result);
104 }
105
106 public function test_it_removes_unreplaced_variables(): void
107 {
108 file_put_contents($this->stubPath.'/unreplaced.stub', 'Hello {{ name }}{{ extra }}');
109
110 $result = $this->renderer->render('unreplaced', ['name' => 'World']);
111
112 $this->assertSame('Hello World', $result);
113 $this->assertStringNotContainsString('{{ extra }}', $result);
114 }
115
116 public function test_it_caches_stub_contents(): void
117 {
118 file_put_contents($this->stubPath.'/cached.stub', 'Original');
119
120 // First render
121 $result1 = $this->renderer->render('cached', []);
122
123 // Change file content
124 file_put_contents($this->stubPath.'/cached.stub', 'Modified');
125
126 // Second render should still use cached version
127 $result2 = $this->renderer->render('cached', []);
128
129 $this->assertSame('Original', $result1);
130 $this->assertSame('Original', $result2);
131 }
132
133 public function test_it_can_clear_cache(): void
134 {
135 file_put_contents($this->stubPath.'/clearable.stub', 'Original');
136
137 // First render
138 $result1 = $this->renderer->render('clearable', []);
139
140 // Change file and clear cache
141 file_put_contents($this->stubPath.'/clearable.stub', 'Modified');
142 $this->renderer->clearCache();
143
144 // Should load new version
145 $result2 = $this->renderer->render('clearable', []);
146
147 $this->assertSame('Original', $result1);
148 $this->assertSame('Modified', $result2);
149 }
150
151 public function test_it_throws_when_stub_not_found(): void
152 {
153 $this->expectException(GenerationException::class);
154 $this->expectExceptionMessage('Template not found: nonexistent');
155
156 $this->renderer->render('nonexistent', []);
157 }
158
159 public function test_it_can_set_custom_stub_path(): void
160 {
161 $customPath = __DIR__.'/../../fixtures/custom-stubs';
162 @mkdir($customPath, 0755, true);
163 file_put_contents($customPath.'/custom.stub', 'Custom stub');
164
165 $this->renderer->setStubPath($customPath);
166 $result = $this->renderer->render('custom', []);
167
168 $this->assertSame('Custom stub', $result);
169
170 // Cleanup
171 @unlink($customPath.'/custom.stub');
172 @rmdir($customPath);
173 }
174
175 public function test_it_prefers_published_stubs(): void
176 {
177 // This test would require a full Laravel app context
178 // For now, we just test that the method checks for published stubs
179 file_put_contents($this->stubPath.'/package.stub', 'Package version');
180
181 $result = $this->renderer->render('package', []);
182
183 $this->assertSame('Package version', $result);
184 }
185
186 public function test_it_lists_available_stubs(): void
187 {
188 file_put_contents($this->stubPath.'/stub1.stub', 'Stub 1');
189 file_put_contents($this->stubPath.'/stub2.stub', 'Stub 2');
190 file_put_contents($this->stubPath.'/stub3.stub', 'Stub 3');
191
192 $stubs = $this->renderer->getAvailableStubs();
193
194 $this->assertContains('stub1', $stubs);
195 $this->assertContains('stub2', $stubs);
196 $this->assertContains('stub3', $stubs);
197 }
198
199 public function test_it_handles_boolean_values(): void
200 {
201 file_put_contents($this->stubPath.'/boolean.stub', 'Active: {{ active }}');
202
203 $result1 = $this->renderer->render('boolean', ['active' => true]);
204 $result2 = $this->renderer->render('boolean', ['active' => false]);
205
206 $this->assertSame('Active: true', $result1);
207 $this->assertSame('Active: false', $result2);
208 }
209
210 public function test_it_handles_numeric_values(): void
211 {
212 file_put_contents($this->stubPath.'/numeric.stub', 'Count: {{ count }}');
213
214 $result = $this->renderer->render('numeric', ['count' => 42]);
215
216 $this->assertSame('Count: 42', $result);
217 }
218}