55namespace yii2 \extensions \phpstan \tests ;
66
77use PHPUnit \Framework \TestCase ;
8+ use RuntimeException ;
89use yii2 \extensions \phpstan \ServiceMap ;
910use yii2 \extensions \phpstan \StubFilesExtension ;
1011
1112use function file_get_contents ;
13+ use function glob ;
14+ use function sys_get_temp_dir ;
15+ use function unlink ;
1216
1317/**
1418 * Unit tests for {@see StubFilesExtension} dynamic stub file generation.
1822 */
1923final class StubFilesExtensionTest extends TestCase
2024{
25+ /**
26+ * Tracked stub file paths generated during tests, cleaned up in tearDown.
27+ *
28+ * @phpstan-var string[]
29+ */
30+ private array $ generatedStubs = [];
31+
2132 public function testGeneratedStubIsCached (): void
2233 {
2334 $ stubFilesExtension = new StubFilesExtension (new ServiceMap ());
@@ -32,8 +43,54 @@ public function testGeneratedStubIsCached(): void
3243 );
3344 }
3445
46+ public function testGetFilesReturnsStubForBaseApplicationType (): void
47+ {
48+ $ this ->cleanGeneratedStubs ();
49+
50+ $ ds = DIRECTORY_SEPARATOR ;
51+ $ configPath = __DIR__ . "{$ ds }config {$ ds }phpstan-base-app-config.php " ;
52+
53+ $ stubFilesExtension = new StubFilesExtension (new ServiceMap ($ configPath ));
54+
55+ $ files = $ stubFilesExtension ->getFiles ();
56+
57+ self ::assertCount (
58+ 1 ,
59+ $ files ,
60+ 'Should return exactly one stub file. ' ,
61+ );
62+
63+ $ stubPath = $ files [0 ] ?? null ;
64+
65+ self ::assertNotNull (
66+ $ stubPath ,
67+ "Stub file path should not be 'null'. " ,
68+ );
69+ self ::assertFileExists (
70+ $ stubPath ,
71+ 'Generated stub file should exist on disk. ' ,
72+ );
73+
74+ $ stubContent = (string ) file_get_contents ($ stubPath );
75+
76+ self ::assertStringContainsString (
77+ '@var \yii\base\Application ' ,
78+ $ stubContent ,
79+ "Stub should declare 'Yii:: \$app' as '\yii\base\Application' for base configuration. " ,
80+ );
81+ self ::assertStringNotContainsString (
82+ 'class Application extends ' ,
83+ $ stubContent ,
84+ 'Stub should not declare a child application class for the base application type. ' ,
85+ );
86+
87+ $ this ->generatedStubs [] = $ stubPath ;
88+ }
89+
3590 public function testGetFilesReturnsStubForConsoleApplicationType (): void
3691 {
92+ $ this ->cleanGeneratedStubs ();
93+
3794 $ ds = DIRECTORY_SEPARATOR ;
3895 $ configPath = __DIR__ . "{$ ds }config {$ ds }phpstan-console-config.php " ;
3996
@@ -62,10 +119,14 @@ public function testGetFilesReturnsStubForConsoleApplicationType(): void
62119 (string ) file_get_contents ($ stubPath ),
63120 "Stub should declare 'Yii:: \$app' as '\yii\console\Application' for console configuration. " ,
64121 );
122+
123+ $ this ->generatedStubs [] = $ stubPath ;
65124 }
66125
67126 public function testGetFilesReturnsStubForCustomApplicationType (): void
68127 {
128+ $ this ->cleanGeneratedStubs ();
129+
69130 $ ds = DIRECTORY_SEPARATOR ;
70131 $ configPath = __DIR__ . "{$ ds }config {$ ds }phpstan-custom-app-config.php " ;
71132
@@ -95,10 +156,14 @@ public function testGetFilesReturnsStubForCustomApplicationType(): void
95156 "Stub should declare 'Yii:: \$app' as '\yii2 \extensions\phpstan \tests\support\stub\ApplicationCustom' "
96157 . ' for custom configuration. ' ,
97158 );
159+
160+ $ this ->generatedStubs [] = $ stubPath ;
98161 }
99162
100163 public function testGetFilesReturnsStubForDefaultApplicationType (): void
101164 {
165+ $ this ->cleanGeneratedStubs ();
166+
102167 $ stubFilesExtension = new StubFilesExtension (new ServiceMap ());
103168
104169 $ files = $ stubFilesExtension ->getFiles ();
@@ -124,10 +189,58 @@ public function testGetFilesReturnsStubForDefaultApplicationType(): void
124189 (string ) file_get_contents ($ stubPath ),
125190 "Stub should default to '\yii\web\Application' when no configuration is provided. " ,
126191 );
192+
193+ $ this ->generatedStubs [] = $ stubPath ;
194+ }
195+
196+ public function testGetFilesReturnsStubForGlobalNamespaceApplicationType (): void
197+ {
198+ $ this ->cleanGeneratedStubs ();
199+
200+ $ ds = DIRECTORY_SEPARATOR ;
201+ $ configPath = __DIR__ . "{$ ds }config {$ ds }phpstan-global-class-app-config.php " ;
202+
203+ $ stubFilesExtension = new StubFilesExtension (new ServiceMap ($ configPath ));
204+
205+ $ files = $ stubFilesExtension ->getFiles ();
206+
207+ self ::assertCount (
208+ 1 ,
209+ $ files ,
210+ 'Should return exactly one stub file. ' ,
211+ );
212+
213+ $ stubPath = $ files [0 ] ?? null ;
214+
215+ self ::assertNotNull (
216+ $ stubPath ,
217+ "Stub file path should not be 'null'. " ,
218+ );
219+ self ::assertFileExists (
220+ $ stubPath ,
221+ 'Generated stub file should exist on disk. ' ,
222+ );
223+
224+ $ stubContent = (string ) file_get_contents ($ stubPath );
225+
226+ self ::assertStringContainsString (
227+ '@var \GlobalApplication ' ,
228+ $ stubContent ,
229+ "Stub should declare 'Yii:: \$app' as '\GlobalApplication' for global namespace configuration. " ,
230+ );
231+ self ::assertStringContainsString (
232+ 'class GlobalApplication extends \yii\base\Application {} ' ,
233+ $ stubContent ,
234+ 'Stub should declare the global namespace application class extending base Application. ' ,
235+ );
236+
237+ $ this ->generatedStubs [] = $ stubPath ;
127238 }
128239
129240 public function testGetFilesReturnsStubForWebApplicationType (): void
130241 {
242+ $ this ->cleanGeneratedStubs ();
243+
131244 $ ds = DIRECTORY_SEPARATOR ;
132245 $ configPath = __DIR__ . "{$ ds }config {$ ds }phpstan-config.php " ;
133246
@@ -156,5 +269,46 @@ public function testGetFilesReturnsStubForWebApplicationType(): void
156269 (string ) file_get_contents ($ stubPath ),
157270 "Stub should declare 'Yii:: \$app' as '\yii\web\Application' for web configuration. " ,
158271 );
272+
273+ $ this ->generatedStubs [] = $ stubPath ;
274+ }
275+
276+ public function testThrowExceptionWhenStubFileCannotBeWritten (): void
277+ {
278+ $ ds = DIRECTORY_SEPARATOR ;
279+ $ nonWritableDir = $ ds . 'nonexistent ' . $ ds . 'directory ' . $ ds . 'path ' ;
280+
281+ $ stubFilesExtension = new StubFilesExtension (new ServiceMap (), $ nonWritableDir );
282+
283+ $ this ->expectException (RuntimeException::class);
284+ $ this ->expectExceptionMessage ('Ensure the temporary directory is writable. ' );
285+
286+ $ stubFilesExtension ->getFiles ();
287+ }
288+
289+ protected function tearDown (): void
290+ {
291+ foreach ($ this ->generatedStubs as $ path ) {
292+ if (file_exists ($ path )) {
293+ unlink ($ path );
294+ }
295+ }
296+
297+ $ this ->generatedStubs = [];
298+ }
299+
300+ /**
301+ * Removes all generated PHPStan stub files from the temporary directory.
302+ */
303+ private function cleanGeneratedStubs (): void
304+ {
305+ $ ds = DIRECTORY_SEPARATOR ;
306+ $ pattern = sys_get_temp_dir () . "{$ ds }yii2-phpstan-stub-*.stub " ;
307+
308+ $ files = glob ($ pattern );
309+
310+ foreach ($ files !== false ? $ files : [] as $ file ) {
311+ unlink ($ file );
312+ }
159313 }
160314}
0 commit comments