getExtension() !== 'php') { continue; } $relativePath = str_replace($path.'/', '', $file->getPathname()); // Skip non-blade files if (! str_contains($relativePath, '.blade.php')) { continue; } try { // Get view name from path $viewName = str_replace(['/', '.blade.php'], ['.', ''], $relativePath); // Attempt to compile the view $compiler = app(BladeCompiler::class); $compiler->compile($file->getPathname()); } catch (Throwable $e) { $errors[] = [ 'file' => $relativePath, 'error' => $e->getMessage(), ]; } } } if (! empty($errors)) { $message = "The following views failed to compile:\n"; foreach ($errors as $error) { $message .= " - {$error['file']}: {$error['error']}\n"; } $this->fail($message); } expect($errors)->toBeEmpty(); }); it('view cache command runs without errors', function () { // Clear any existing cache first Artisan::call('view:clear'); // This will fail if any view has syntax errors $exitCode = Artisan::call('view:cache'); expect($exitCode)->toBe(0); // Clean up Artisan::call('view:clear'); }); it('all blade components are resolvable', function () { $viewPaths = config('view.paths'); $missingComponents = []; foreach ($viewPaths as $path) { $bladeFiles = File::allFiles($path); foreach ($bladeFiles as $file) { if (! str_contains($file->getFilename(), '.blade.php')) { continue; } $content = File::get($file->getPathname()); $relativePath = str_replace($path.'/', '', $file->getPathname()); // Find all x-component usages (e.g., ) preg_match_all('/ $relativePath, 'component' => $componentName, 'suggestion' => 'Use FontAwesome instead: ', ]; } } } } if (! empty($missingComponents)) { $message = "Found references to unavailable components:\n"; foreach ($missingComponents as $missing) { $message .= " - {$missing['file']}: x-{$missing['component']}"; if (isset($missing['suggestion'])) { $message .= " ({$missing['suggestion']})"; } $message .= "\n"; } $this->fail($message); } expect($missingComponents)->toBeEmpty(); }); });