This commit is contained in:
nuno maduro
2026-05-01 22:36:15 +01:00
parent 53db68e005
commit bf48e20880
35 changed files with 21 additions and 923 deletions
-10
View File
@@ -16,9 +16,6 @@ final readonly class Browser implements WatchDefault
{
public function applicable(): bool
{
// Browser tests can exist in any PHP project. We only activate when
// there is an actual `tests/Browser` directory OR pest-plugin-browser
// is installed.
return class_exists(InstalledVersions::class)
&& InstalledVersions::isInstalled('pestphp/pest-plugin-browser');
}
@@ -37,12 +34,8 @@ final readonly class Browser implements WatchDefault
'resources/css/**/*.css',
'resources/css/**/*.scss',
'resources/css/**/*.less',
// Vite / Webpack build output that browser tests may consume.
'public/build/**/*.js',
'public/build/**/*.css',
// Static public assets can affect browser-rendered pages without
// any PHP file changing (favicons, robots, images, downloaded
// manifests, etc.). Only browser-test targets are invalidated.
'public/**/*.js',
'public/**/*.css',
'public/**/*.svg',
@@ -79,9 +72,6 @@ final readonly class Browser implements WatchDefault
$targets[] = $candidate;
}
// Scan TestRepository via BrowserTestIdentifier if pest-plugin-browser
// is installed to find exact tests using `visit()` outside the
// conventional Browser/ folder.
if (class_exists(BrowserTestIdentifier::class)) {
$repo = TestSuite::getInstance()->tests;
-14
View File
@@ -22,19 +22,6 @@ final readonly class Inertia implements WatchDefault
{
$browserTargets = Browser::detectBrowserTestTargets($projectRoot, $testPath);
// Inertia page components (React / Vue / Svelte). Scoped to
// browser tests only — a Vue/React edit cannot change the
// output of a server-side Inertia test (those assert on the
// component *name* returned by `Inertia::render()`, not its
// client-side implementation). Broad invalidation is only
// meaningful for tests that actually render the DOM. Precise
// per-component edges come from `InertiaEdges` at record
// time and replace this fallback when available.
//
// Both `Pages/` (classic Inertia-Vue) and `pages/` (Laravel
// React starter kit, and other lowercase-by-default setups)
// are emitted — paths from git are case-sensitive on Linux,
// so a single casing would silently miss the other convention.
$patterns = [];
foreach (['Pages', 'pages'] as $pages) {
@@ -49,7 +36,6 @@ final readonly class Inertia implements WatchDefault
}
}
// SSR entry point.
$patterns['resources/js/ssr.js'] = $browserTargets;
$patterns['resources/js/ssr.ts'] = $browserTargets;
$patterns['resources/js/app.js'] = $browserTargets;
-28
View File
@@ -20,42 +20,23 @@ final readonly class Laravel implements WatchDefault
public function defaults(string $projectRoot, string $testPath): array
{
return [
// Config — loaded during app boot (setUp), invisible to coverage.
// Affects both Feature and Unit: Pest.php commonly binds fakes
// and seeds DB based on config values.
'config/*.php' => [$testPath],
'config/**/*.php' => [$testPath],
// Routes — loaded during boot. HTTP/Feature tests depend on them.
'routes/*.php' => [$testPath],
'routes/**/*.php' => [$testPath],
// Service providers / bootstrap — loaded during boot, affect
// bindings, middleware, event listeners, scheduled tasks.
'bootstrap/app.php' => [$testPath],
'bootstrap/providers.php' => [$testPath],
// Migrations — run via RefreshDatabase/FastRefreshDatabase in
// setUp. Schema changes can break any test that touches DB.
'database/migrations/**/*.php' => [$testPath],
// Seeders — often run globally via Pest.php beforeEach.
'database/seeders/**/*.php' => [$testPath],
// Factories — loaded lazily but still PHP that coverage may miss
// if the factory file was already autoloaded before Prepared.
'database/factories/**/*.php' => [$testPath],
// Project fixture data. Laravel apps often keep fake repository
// lockfiles / API payloads here and read them via `storage_path()`
// + `file_get_contents()`, which neither PHP coverage nor static
// import edges can observe.
'storage/fixtures/**/*' => [$testPath],
// Non-PHP templates/data living beside app code. These are often
// read dynamically by services (Dockerfile templates, stubs,
// payload examples) and never appear in coverage because PHP only
// sees the reader method, not the external file.
'app/**/*.tpl' => [$testPath],
'app/**/*.stub' => [$testPath],
'app/**/*.json' => [$testPath],
@@ -63,25 +44,16 @@ final readonly class Laravel implements WatchDefault
'app/**/*.yml' => [$testPath],
'app/**/*.txt' => [$testPath],
// Blade templates — compiled to cache, source file not executed.
'resources/views/**/*.blade.php' => [$testPath],
// Mail / view-adjacent themes can be read dynamically by
// mailables (for example Laravel's markdown mail theme CSS).
'resources/views/**/*.css' => [$testPath],
// Email templates are nested under views/email or views/emails
// by convention and power mailable tests that render markup.
'resources/views/email/**/*.blade.php' => [$testPath],
'resources/views/emails/**/*.blade.php' => [$testPath],
// Translations — JSON translations read via file_get_contents,
// PHP translations loaded via include (but during boot).
'lang/**/*.php' => [$testPath],
'lang/**/*.json' => [$testPath],
'resources/lang/**/*.php' => [$testPath],
'resources/lang/**/*.json' => [$testPath],
// Build tool config — affects compiled assets consumed by
// browser and Inertia tests.
'vite.config.js' => [$testPath],
'vite.config.ts' => [$testPath],
'webpack.mix.js' => [$testPath],
@@ -20,15 +20,10 @@ final readonly class Livewire implements WatchDefault
public function defaults(string $projectRoot, string $testPath): array
{
return [
// Livewire views live alongside Blade views or in a dedicated dir.
'resources/views/livewire/**/*.blade.php' => [$testPath],
'resources/views/components/**/*.blade.php' => [$testPath],
// Volt's second default mount — single-file components used as
// full-page routes. Missing this means editing a Volt page
// doesn't re-run its tests.
'resources/views/pages/**/*.blade.php' => [$testPath],
// Livewire JS interop / Alpine plugins.
'resources/js/**/*.js' => [$testPath],
'resources/js/**/*.ts' => [$testPath],
];
-31
View File
@@ -16,55 +16,24 @@ final readonly class Php implements WatchDefault
public function defaults(string $projectRoot, string $testPath): array
{
// NOTE: composer.json / composer.lock changes are caught by the
// fingerprint (which hashes composer.lock). PHP files are tracked by
// the coverage driver. Only non-PHP, non-fingerprinted files that
// can silently alter test behaviour belong here.
return [
// Environment files — can change DB drivers, feature flags,
// queue connections, etc. Not PHP, not fingerprinted. Covers
// the local-override variants (`.env.local`, `.env.testing.local`)
// that both Laravel and Symfony recommend for machine-specific
// config.
'.env' => [$testPath],
'.env.testing' => [$testPath],
'.env.local' => [$testPath],
'.env.*.local' => [$testPath],
// Docker / CI — can affect integration test infrastructure.
'docker-compose.yml' => [$testPath],
'docker-compose.yaml' => [$testPath],
// PHPUnit / Pest config (XML) — phpunit.xml IS fingerprinted, but
// phpunit.xml.dist and other XML overrides are not individually
// tracked by the coverage driver.
'phpunit.xml.dist' => [$testPath],
// `tests/Pest.php` is loaded once per suite (during BootFiles)
// so its `pest()->extend()`, `expect()->extend()`, helpers,
// etc. execute outside the per-test coverage window — no
// edge captures it. Watch-pattern broadcast triggers a
// replay of every test (results refresh) without a full
// record-mode graph rebuild.
$testPath.'/Pest.php' => [$testPath],
// Pest dataset definitions are loaded once at boot, outside
// the per-test coverage window — no edge captures them. A
// change to a shared dataset can flip the result of any test
// that uses it, so broadcast every dataset edit to the full
// suite.
$testPath.'/Datasets/**/*.php' => [$testPath],
// Test fixtures — data/source snippets consumed by assertions or
// external analysers. Nested `Fixtures/` directories are common
// beside a single test class, and PHP fixtures may be parsed by
// tools without being `require`d, so coverage cannot see them.
$testPath.'/Fixtures/**/*' => [$testPath],
$testPath.'/**/Fixtures/**/*' => [$testPath],
// Pest snapshots — external edits to snapshot files invalidate
// snapshot assertions.
$testPath.'/.pest/snapshots/**/*.snap' => [$testPath],
];
}
-15
View File
@@ -19,12 +19,7 @@ final readonly class Symfony implements WatchDefault
public function defaults(string $projectRoot, string $testPath): array
{
// Symfony boots the kernel in setUp() (before the coverage window).
// PHP config, routes, kernel, and migrations are loaded during boot
// and invisible to the coverage driver. Same reasoning as Laravel.
return [
// Config — YAML, XML, and PHP. All loaded during kernel boot.
'config/*.yaml' => [$testPath],
'config/*.yml' => [$testPath],
'config/*.php' => [$testPath],
@@ -34,37 +29,27 @@ final readonly class Symfony implements WatchDefault
'config/**/*.php' => [$testPath],
'config/**/*.xml' => [$testPath],
// Routes — loaded during boot.
'config/routes/*.yaml' => [$testPath],
'config/routes/*.php' => [$testPath],
'config/routes/*.xml' => [$testPath],
'config/routes/**/*.yaml' => [$testPath],
// Kernel / bootstrap — loaded during boot.
'src/Kernel.php' => [$testPath],
// Migrations — run during setUp (before coverage window).
// DoctrineMigrationsBundle's default is `migrations/` at the
// project root; many Symfony projects relocate to
// `src/Migrations/` — both covered.
'migrations/**/*.php' => [$testPath],
'src/Migrations/**/*.php' => [$testPath],
// Twig templates — compiled, source not PHP-executed.
'templates/**/*.html.twig' => [$testPath],
'templates/**/*.twig' => [$testPath],
// Translations (YAML / XLF / XLIFF).
'translations/**/*.yaml' => [$testPath],
'translations/**/*.yml' => [$testPath],
'translations/**/*.xlf' => [$testPath],
'translations/**/*.xliff' => [$testPath],
// Doctrine XML/YAML mappings.
'config/doctrine/**/*.xml' => [$testPath],
'config/doctrine/**/*.yaml' => [$testPath],
// Webpack Encore / asset-mapper config + frontend sources.
'webpack.config.js' => [$testPath],
'importmap.php' => [$testPath],
'assets/**/*.js' => [$testPath],
@@ -9,9 +9,6 @@ namespace Pest\Plugins\Tia\WatchDefaults;
*/
interface WatchDefault
{
/**
* Whether this default set applies to the current project.
*/
public function applicable(): bool;
/**