mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-18 17:16:46 +03:00
fix: hydrate attribute-bound each values and guard style directives
Addresses two cursor review findings:
- {#each} bodies whose bound values appear in attributes (href={link.href},
src={item.img}) now record attr slots; the browser hydrates them from the
rendered attribute so component previews no longer mount with empty links.
Single-expression attributes hydrate exactly; mixed values stay unhydrated
as before. A new slot classifier also refuses shapes that would crash a
shallow hydration item (deep paths, method calls, bare item renders) and
routes them to source-preview mode instead.
- Style directives now run the mixed loop/outer identifier check before the
free-identifier param check, so style:width={base + r.pct} falls back
instead of minting a broken param.
Tests: attr-slot analysis units, crashy/lossy fallback units, an attribute-
bound anchor in the stateful SvelteKit fixture asserted through accept, and
a mountedDomProbe e2e hook that reads the hydrated href off the mounted
variant DOM (verified to fail when hydration is disabled).
AI-assisted (Claude Code).
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Code
parent
6997e4bdb5
commit
39f233ac24
@@ -512,6 +512,32 @@ for (const { name, fixture } of fixtures) {
|
||||
);
|
||||
};
|
||||
await assertVisibleVariantStyle(visible);
|
||||
// Optional fixture hook: assert attribute/text values inside the
|
||||
// MOUNTED variant DOM. Component previews hydrate collection items
|
||||
// from the rendered page (text slots and attribute slots); a probe
|
||||
// here catches a preview that mounts but with empty hydrated values,
|
||||
// which every other assertion (style, counter, accept) misses.
|
||||
if (Array.isArray(fixture.runtime.mountedDomProbe)) {
|
||||
for (const probe of fixture.runtime.mountedDomProbe) {
|
||||
const actual = await evaluatePageWithTimeout(
|
||||
page,
|
||||
({ sel, attr }) => {
|
||||
const query = window.__impeccableLiveQuery || ((s) => document.querySelector(s));
|
||||
const el = query(sel) || document.querySelector(sel);
|
||||
if (!el) return null;
|
||||
return attr ? el.getAttribute(attr) : (el.textContent || '').trim();
|
||||
},
|
||||
{ sel: probe.selector, attr: probe.attr || null },
|
||||
5_000,
|
||||
'mounted DOM probe',
|
||||
);
|
||||
assert.equal(
|
||||
actual,
|
||||
probe.expect,
|
||||
`mounted variant DOM: ${probe.selector}${probe.attr ? ` [${probe.attr}]` : ' text'}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
for (const targetVariant of cycleSequence) {
|
||||
t.diagnostic(`Cycling to variant ${targetVariant}`);
|
||||
visible = await cycleToVariant(page, targetVariant, expectedCount, {
|
||||
|
||||
Reference in New Issue
Block a user