Run the design guard's smoke test with missingStylesheets(), as Blade resolves
Plan step 41 review: the committed smoke test scanned the package's views without the stylesheet check, so the claim that the package, showcase and Workbench pass it through all.css was untested; it now runs it, and checks the showcase's plain tags do need imports from a foundation-only entry, so the pass is not vacuous. Doing so exposed that a component class one test evals leaked into every later check in the process: the shadow check now guesses the class the way Blade does (Blade::component() aliases, component namespaces, the application's own root namespace), and the test gives its class a namespace of its own. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
co-authored by
Claude Opus 5
parent
2073480da4
commit
2d75091b82
@@ -3,9 +3,11 @@
|
|||||||
namespace NoNameWeb\LivewireMaterial\Testing;
|
namespace NoNameWeb\LivewireMaterial\Testing;
|
||||||
|
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\View\Compilers\ComponentTagCompiler;
|
||||||
use NoNameWeb\LivewireMaterial\Support\Layout;
|
use NoNameWeb\LivewireMaterial\Support\Layout;
|
||||||
use NoNameWeb\LivewireMaterial\Support\Stylesheets;
|
use NoNameWeb\LivewireMaterial\Support\Stylesheets;
|
||||||
use NoNameWeb\LivewireMaterial\Support\SvgFile;
|
use NoNameWeb\LivewireMaterial\Support\SvgFile;
|
||||||
|
use RuntimeException;
|
||||||
use SplFileInfo;
|
use SplFileInfo;
|
||||||
use Symfony\Component\Finder\Finder;
|
use Symfony\Component\Finder\Finder;
|
||||||
|
|
||||||
@@ -1227,15 +1229,31 @@ class DesignGuard
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the application defines its own component of this name — an anonymous
|
* Whether the application defines its own component of this name, found the way Blade itself
|
||||||
* `resources/views/components/<name>.blade.php`, found the way Blade itself falls back to it
|
* looks before it reaches this package's anonymous path: an alias registered with
|
||||||
* (the base view finder's `components.<name>`, which `resource_path('views/components')`
|
* `Blade::component()`, a class under the application's `View\\Components` namespace (its own
|
||||||
* feeds by default), or an `App\View\Components` class. Either wins over this package's
|
* root namespace, as Blade guesses it), or an anonymous
|
||||||
* `<x-{$name}>` in Blade's own resolution order.
|
* `resources/views/components/<name>.blade.php` (the base view finder's `components.<name>`).
|
||||||
*/
|
*/
|
||||||
protected function shadowedByApplication(string $name): bool
|
protected function shadowedByApplication(string $name): bool
|
||||||
{
|
{
|
||||||
return view()->exists('components.'.$name) || class_exists('App\\View\\Components\\'.Str::studly($name));
|
if (view()->exists('components.'.$name)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$blade = app('blade.compiler');
|
||||||
|
$compiler = new ComponentTagCompiler($blade->getClassComponentAliases(), $blade->getClassComponentNamespaces(), $blade);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$class = $compiler->guessClassName($name);
|
||||||
|
} catch (RuntimeException) {
|
||||||
|
return false; // No application namespace to guess a class in.
|
||||||
|
}
|
||||||
|
|
||||||
|
return isset($blade->getClassComponentAliases()[$name])
|
||||||
|
|| $compiler->findClassByComponent($name) !== null
|
||||||
|
|| class_exists($class)
|
||||||
|
|| class_exists($class.'\\'.Str::afterLast($class, '\\'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -486,8 +486,12 @@ it('reports a package tag the application shadows with its own anonymous compone
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('reports a package tag the application shadows with its own component class', function () {
|
it('reports a package tag the application shadows with its own component class', function () {
|
||||||
if (! class_exists('App\View\Components\Card', false)) {
|
// Under a namespace of its own, which Blade's class guess reads from the application, so the
|
||||||
eval('namespace App\View\Components; class Card {}');
|
// class cannot shadow `<x-card>` for any later test in this process.
|
||||||
|
(fn () => $this->namespace = 'DesignGuardShadow\\')->call(app());
|
||||||
|
|
||||||
|
if (! class_exists('DesignGuardShadow\View\Components\Card', false)) {
|
||||||
|
eval('namespace DesignGuardShadow\View\Components; class Card {}');
|
||||||
}
|
}
|
||||||
|
|
||||||
$violations = fixtureRelative(DesignGuard::scan(realpath(GUARD_FIXTURES.'/stylesheets/views/shadow-class.blade.php'))
|
$violations = fixtureRelative(DesignGuard::scan(realpath(GUARD_FIXTURES.'/stylesheets/views/shadow-class.blade.php'))
|
||||||
@@ -539,8 +543,11 @@ it('never reads a Tailwind-shaped word out of running text', function () {
|
|||||||
expect($violations)->toBe([]);
|
expect($violations)->toBe([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('passes the package\'s own views', function () {
|
it('passes the package\'s own views, showcase and Workbench, every stylesheet imported through all.css', function () {
|
||||||
$violations = DesignGuard::scan([__DIR__.'/../../resources/views', __DIR__.'/../../resources/js', __DIR__.'/../../src'])->violations();
|
$root = realpath(__DIR__.'/../..');
|
||||||
|
$paths = [$root.'/resources/views', $root.'/resources/js', $root.'/src', $root.'/workbench/resources'];
|
||||||
|
|
||||||
expect($violations)->toBe([]);
|
expect(DesignGuard::scan($paths)->missingStylesheets($root.'/resources/css/all.css')->violations())->toBe([])
|
||||||
|
// …and the stylesheet check is not vacuous there: the showcase's plain tags do need imports.
|
||||||
|
->and(DesignGuard::scan($root.'/resources/views/showcase')->missingStylesheets(realpath(GUARD_FIXTURES.'/stylesheets/foundation-only.css'))->violations())->not->toBe([]);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user