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();
});
});