66use PHPUnit \Framework \Attributes \PreCondition ;
77use PHPUnit \Framework \Attributes \Test ;
88use Tempest \Core \Commands \InstallCommand ;
9+ use Tempest \Core \InstallerConfig ;
910use Tempest \Support \Filesystem ;
1011use Tempest \Support \Namespace \Psr4Namespace ;
1112use Tempest \Vite \Installer \ViteInstaller ;
1213use Tests \Tempest \Integration \FrameworkIntegrationTestCase ;
14+ use Throwable ;
1315
1416final class ViteInstallerTest extends FrameworkIntegrationTestCase
1517{
@@ -35,7 +37,14 @@ protected function cleanup(): void
3537 #[Test]
3638 public function intalls_vite (): void
3739 {
38- $ this ->console ->call (InstallCommand::class, [ViteInstaller::class, '--tailwindcss=false ' , '--force ' ]);
40+ $ console = $ this ->console ->call (InstallCommand::class, [ViteInstaller::class, '--force ' ]);
41+
42+ if (! Filesystem \is_file (__DIR__ . '/install/vite.config.ts ' )) {
43+ $ this ->dumpInstallerDebug (
44+ installRoot: __DIR__ . '/install ' ,
45+ consoleOutput: $ console ->getBuffer (),
46+ );
47+ }
3948
4049 $ this ->installer ->assertFileExists ('vite.config.ts ' );
4150 $ this ->installer ->assertFileExists ('app/main.entrypoint.ts ' );
@@ -55,4 +64,105 @@ public function intalls_tailwindcss(): void
5564 $ this ->installer ->assertFileContains ('package.json ' , ['"vite" ' , '"vite build" ' ]);
5665 $ this ->installer ->assertFileContains ('vite.config.ts ' , 'vite-plugin-tempest ' );
5766 }
67+
68+ /**
69+ * @param list<string> $consoleOutput
70+ */
71+ private function dumpInstallerDebug (string $ installRoot , array $ consoleOutput ): void
72+ {
73+ $ installerConfig = $ this ->container ->get (InstallerConfig::class);
74+ $ processExecutions = $ this ->process ->executor ?->executions ?? [];
75+ $ viteInstallers = array_values (array_filter (
76+ $ installerConfig ->installers ,
77+ static fn ($ installer ) => in_array (ViteInstaller::class, $ installer ->aliases , true ),
78+ ));
79+ $ viteSourceRoot = dirname ((string ) new \ReflectionClass (ViteInstaller::class)->getFileName ());
80+
81+ $ debug = [
82+ 'os ' => PHP_OS_FAMILY ,
83+ 'php_version ' => PHP_VERSION ,
84+ 'cwd ' => getcwd (),
85+ 'kernel_root ' => $ this ->kernel ->root ,
86+ 'internal_storage ' => $ this ->internalStorage ,
87+ 'install_root ' => $ installRoot ,
88+ 'install_root_exists ' => Filesystem \is_directory ($ installRoot ),
89+ 'install_root_entries ' => $ this ->safeListDirectory ($ installRoot ),
90+ 'install_root_tree ' => $ this ->listDirectoryTree ($ installRoot ),
91+ 'expected_output_file ' => $ installRoot . '/vite.config.ts ' ,
92+ 'expected_output_exists ' => Filesystem \is_file ($ installRoot . '/vite.config.ts ' ),
93+ 'vite_source_root ' => $ viteSourceRoot ,
94+ 'vite_source_vanilla_exists ' => Filesystem \is_file ($ viteSourceRoot . '/vanilla/vite.config.ts ' ),
95+ 'vite_source_tailwind_exists ' => Filesystem \is_file ($ viteSourceRoot . '/tailwindcss/vite.config.ts ' ),
96+ 'installer_count ' => count ($ installerConfig ->installers ),
97+ 'vite_installer_matches ' => array_map (
98+ static fn ($ installer ) => [
99+ 'id ' => $ installer ->id ,
100+ 'aliases ' => $ installer ->aliases ,
101+ ],
102+ $ viteInstallers ,
103+ ),
104+ 'console_output ' => $ consoleOutput ,
105+ 'process_execution_count ' => count ($ processExecutions ),
106+ 'process_commands ' => array_keys ($ processExecutions ),
107+ ];
108+
109+ dd ($ debug );
110+ }
111+
112+ /** @return list<string> */
113+ private function safeListDirectory (string $ path ): array
114+ {
115+ if (! Filesystem \is_directory ($ path )) {
116+ return [];
117+ }
118+
119+ try {
120+ return array_values (Filesystem \list_directory ($ path ));
121+ } catch (Throwable ) {
122+ return [];
123+ }
124+ }
125+
126+ /** @return list<string> */
127+ private function listDirectoryTree (string $ root , int $ maxDepth = 3 , int $ maxItems = 200 ): array
128+ {
129+ if (! is_dir ($ root )) {
130+ return [];
131+ }
132+
133+ $ items = [];
134+ $ rootLength = strlen ($ root ) + 1 ;
135+
136+ try {
137+ $ iterator = new \RecursiveIteratorIterator (
138+ new \RecursiveDirectoryIterator ($ root , \FilesystemIterator::SKIP_DOTS ),
139+ \RecursiveIteratorIterator::SELF_FIRST ,
140+ );
141+
142+ foreach ($ iterator as $ entry ) {
143+ if (count ($ items ) >= $ maxItems ) {
144+ $ items [] = '... truncated ... ' ;
145+ break ;
146+ }
147+
148+ $ depth = $ iterator ->getDepth ();
149+
150+ if ($ depth > $ maxDepth ) {
151+ continue ;
152+ }
153+
154+ $ relative = substr ($ entry ->getPathname (), $ rootLength );
155+
156+ if ($ relative === false || $ relative === '' ) {
157+ continue ;
158+ }
159+
160+ $ items [] = ($ entry ->isDir () ? '[D] ' : '[F] ' ) . str_replace ('\\' , '/ ' , $ relative );
161+ }
162+ } catch (Throwable $ throwable ) {
163+ $ items [] = 'Failed to list tree: ' . $ throwable ->getMessage ();
164+ }
165+
166+ return $ items ;
167+ }
58168}
0 commit comments