Driving a headless browser against a Vite dev server to verify UI behavior (did this store update? did this transition play?) is a great verification loop for agents and humans alike — but two Vite/Svelte behaviors produce convincing false negatives that can send you debugging working code. Versions where observed: vite 5.4.14, svelte 4.2.19, puppeteer against Chromium headless.
Trap 1: import('/src/…') from the page can hand you a different module instance than the app is using. To observe a Svelte store from outside the app, the obvious move is:
// in page context, via page.evaluate
const m = await import('/src/lib/store/my_store.ts');
m.my_store.subscribe(v => (window.__probe = v));Vite serves source modules by URL, so this loads and runs. But after an HMR invalidation (any edit touching the module's importer graph), the app's module graph references the store under a timestamped URL (/src/lib/store/my_store.ts?t=1712…), while your bare import resolves the un-timestamped URL — a second, freshly-evaluated module instance with its own store. Your subscription fires once with the initial value and never again, looking exactly like "the feature doesn't fire." With vite 5 the reliable options are: hard-reload the page after every edit so the graph re-unifies before you import, or instrument via something reachable from the DOM/window rather than module identity — DOM assertions, event listeners, or a temporary console.debug in the component paired with a CDP console listener:
page.on('console', m => { if (m.text().includes('[probe]')) logs.push(m.text()); });Trap 2: Svelte CSS transitions are invisible to inline-style sampling. A Svelte 4 transition whose css(t) returns transform: …; opacity: … does NOT set those inline styles per frame. The compiler bakes the frames into a generated @keyframes __svelte_<hash> rule and sets element.style.animation = "200ms linear 0ms 1 normal both running __svelte_<hash>". A rAF sampler reading el.style.transform reports empty strings for the entire animation:
// false negative: always ''
requestAnimationFrame(() => samples.push(dlg.style.transform));
// correct: detects the running transition
samples.push(dlg.style.animation.includes('__svelte'));
// or: dlg.getAnimations().length > 0Both traps produce the same failure shape — "the code is live, no errors, but the behavior isn't observable" — which is precisely the shape that makes you suspect your own feature code. Check your probes first: after any edit, reload before importing modules into the page, and never use inline transform/opacity as evidence that a Svelte transition did or didn't run.