Parse and validate AT Protocol Lexicons with DTO generation for Laravel
1<?php
2
3namespace SocialDept\AtpSchema\Tests\Unit\Support;
4
5use Orchestra\Testbench\TestCase;
6use SocialDept\AtpSchema\Support\ExtensionManager;
7
8class ExtensionManagerTest extends TestCase
9{
10 protected ExtensionManager $manager;
11
12 protected function setUp(): void
13 {
14 parent::setUp();
15
16 $this->manager = new ExtensionManager();
17 }
18
19 public function test_it_registers_hook(): void
20 {
21 $this->manager->hook('test', fn () => 'result');
22
23 $this->assertTrue($this->manager->has('test'));
24 }
25
26 public function test_it_executes_hook(): void
27 {
28 $this->manager->hook('test', fn () => 'result1');
29 $this->manager->hook('test', fn () => 'result2');
30
31 $results = $this->manager->execute('test');
32
33 $this->assertEquals(['result1', 'result2'], $results);
34 }
35
36 public function test_it_executes_hook_with_arguments(): void
37 {
38 $this->manager->hook('test', fn ($a, $b) => $a + $b);
39
40 $results = $this->manager->execute('test', 5, 3);
41
42 $this->assertEquals([8], $results);
43 }
44
45 public function test_it_returns_empty_array_for_nonexistent_hook(): void
46 {
47 $results = $this->manager->execute('nonexistent');
48
49 $this->assertEquals([], $results);
50 }
51
52 public function test_it_executes_until_first_non_null(): void
53 {
54 $this->manager->hook('test', fn () => null);
55 $this->manager->hook('test', fn () => 'found');
56 $this->manager->hook('test', fn () => 'not reached');
57
58 $result = $this->manager->executeUntil('test');
59
60 $this->assertEquals('found', $result);
61 }
62
63 public function test_it_returns_null_when_all_hooks_return_null(): void
64 {
65 $this->manager->hook('test', fn () => null);
66 $this->manager->hook('test', fn () => null);
67
68 $result = $this->manager->executeUntil('test');
69
70 $this->assertNull($result);
71 }
72
73 public function test_it_returns_null_for_nonexistent_hook_until(): void
74 {
75 $result = $this->manager->executeUntil('nonexistent');
76
77 $this->assertNull($result);
78 }
79
80 public function test_it_filters_value_through_hooks(): void
81 {
82 $this->manager->hook('test', fn ($value) => $value * 2);
83 $this->manager->hook('test', fn ($value) => $value + 10);
84
85 $result = $this->manager->filter('test', 5);
86
87 $this->assertEquals(20, $result); // (5 * 2) + 10
88 }
89
90 public function test_it_returns_original_value_when_no_hooks(): void
91 {
92 $result = $this->manager->filter('nonexistent', 'original');
93
94 $this->assertEquals('original', $result);
95 }
96
97 public function test_it_filters_with_additional_arguments(): void
98 {
99 $this->manager->hook('test', fn ($value, $multiplier) => $value * $multiplier);
100
101 $result = $this->manager->filter('test', 5, 3);
102
103 $this->assertEquals(15, $result);
104 }
105
106 public function test_it_checks_if_has_hook(): void
107 {
108 $this->assertFalse($this->manager->has('test'));
109
110 $this->manager->hook('test', fn () => 'result');
111
112 $this->assertTrue($this->manager->has('test'));
113 }
114
115 public function test_it_gets_hook_callbacks(): void
116 {
117 $callback1 = fn () => 'result1';
118 $callback2 = fn () => 'result2';
119
120 $this->manager->hook('test', $callback1);
121 $this->manager->hook('test', $callback2);
122
123 $callbacks = $this->manager->get('test');
124
125 $this->assertCount(2, $callbacks);
126 $this->assertSame($callback1, $callbacks[0]);
127 $this->assertSame($callback2, $callbacks[1]);
128 }
129
130 public function test_it_returns_empty_array_for_nonexistent_hook_get(): void
131 {
132 $callbacks = $this->manager->get('nonexistent');
133
134 $this->assertEquals([], $callbacks);
135 }
136
137 public function test_it_removes_hook(): void
138 {
139 $this->manager->hook('test', fn () => 'result');
140
141 $this->assertTrue($this->manager->has('test'));
142
143 $this->manager->remove('test');
144
145 $this->assertFalse($this->manager->has('test'));
146 }
147
148 public function test_it_clears_all_hooks(): void
149 {
150 $this->manager->hook('test1', fn () => 'result1');
151 $this->manager->hook('test2', fn () => 'result2');
152
153 $this->assertTrue($this->manager->has('test1'));
154 $this->assertTrue($this->manager->has('test2'));
155
156 $this->manager->clear();
157
158 $this->assertFalse($this->manager->has('test1'));
159 $this->assertFalse($this->manager->has('test2'));
160 }
161
162 public function test_it_counts_callbacks(): void
163 {
164 $this->assertEquals(0, $this->manager->count('test'));
165
166 $this->manager->hook('test', fn () => 'result1');
167
168 $this->assertEquals(1, $this->manager->count('test'));
169
170 $this->manager->hook('test', fn () => 'result2');
171
172 $this->assertEquals(2, $this->manager->count('test'));
173 }
174
175 public function test_it_gets_hook_names(): void
176 {
177 $this->manager->hook('test1', fn () => 'result1');
178 $this->manager->hook('test2', fn () => 'result2');
179 $this->manager->hook('test3', fn () => 'result3');
180
181 $names = $this->manager->names();
182
183 $this->assertEquals(['test1', 'test2', 'test3'], $names);
184 }
185
186 public function test_it_returns_empty_array_when_no_hooks(): void
187 {
188 $names = $this->manager->names();
189
190 $this->assertEquals([], $names);
191 }
192
193 public function test_it_chains_hook_calls(): void
194 {
195 $result = $this->manager
196 ->hook('test1', fn () => 'result1')
197 ->hook('test2', fn () => 'result2');
198
199 $this->assertSame($this->manager, $result);
200 $this->assertTrue($this->manager->has('test1'));
201 $this->assertTrue($this->manager->has('test2'));
202 }
203
204 public function test_it_chains_remove_calls(): void
205 {
206 $this->manager->hook('test', fn () => 'result');
207
208 $result = $this->manager->remove('test');
209
210 $this->assertSame($this->manager, $result);
211 }
212
213 public function test_it_chains_clear_calls(): void
214 {
215 $result = $this->manager->clear();
216
217 $this->assertSame($this->manager, $result);
218 }
219
220 public function test_it_handles_multiple_callbacks_for_same_hook(): void
221 {
222 $executed = [];
223
224 $this->manager->hook('test', function () use (&$executed) {
225 $executed[] = 'first';
226 });
227
228 $this->manager->hook('test', function () use (&$executed) {
229 $executed[] = 'second';
230 });
231
232 $this->manager->hook('test', function () use (&$executed) {
233 $executed[] = 'third';
234 });
235
236 $this->manager->execute('test');
237
238 $this->assertEquals(['first', 'second', 'third'], $executed);
239 }
240
241 public function test_it_handles_complex_filter_chain(): void
242 {
243 $this->manager->hook('transform', fn ($value) => strtoupper($value));
244 $this->manager->hook('transform', fn ($value) => str_replace(' ', '_', $value));
245 $this->manager->hook('transform', fn ($value) => $value.'_SUFFIX');
246
247 $result = $this->manager->filter('transform', 'hello world');
248
249 $this->assertEquals('HELLO_WORLD_SUFFIX', $result);
250 }
251
252 public function test_it_handles_execute_until_with_arguments(): void
253 {
254 $this->manager->hook('search', fn ($needle, $haystack) => in_array($needle, $haystack) ? $needle : null);
255
256 $result = $this->manager->executeUntil('search', 'b', ['a', 'b', 'c']);
257
258 $this->assertEquals('b', $result);
259 }
260
261 public function test_it_removes_nonexistent_hook_safely(): void
262 {
263 $result = $this->manager->remove('nonexistent');
264
265 $this->assertSame($this->manager, $result);
266 }
267}