You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/scripts/probe-toast-dismiss.ts

113 lines
3.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* One-shot Playwright probe to verify the Toast dismiss flow emits
* `data-event*` perceptual signals on the item element.
*
* Usage:
* 1. `npm run dev` in another terminal (defaults to port 5173)
* 2. `node --import tsx/esm scripts/probe-toast-dismiss.ts`
*
* Output: list of mutations seen during the dismiss interaction. If the
* runtime + semantic engine are wired correctly, you should see at minimum:
* - data-event="dismiss" added
* - data-event-id="sig-N" added
* - data-event-phase="active" added
* - data-event-family="emerge" added
* …followed shortly after by their removal as the cleanup tick runs.
*/
import { chromium } from 'playwright';
const URL = process.env.PROBE_URL ?? 'http://localhost:5173/uix/components/toast';
async function main() {
const browser = await chromium.launch();
const page = await browser.newPage();
const consoleLines: string[] = [];
page.on('console', (msg) => consoleLines.push(`[${msg.type()}] ${msg.text()}`));
await page.goto(URL, { waitUntil: 'networkidle' });
// 1. Trigger a default toast (the demo page has an "Add default" button).
const triggerBtn = page.getByRole('button', { name: /^default$/i }).first();
await triggerBtn.click();
// 2. Wait for the item to mount.
const item = page.locator('[data-toast-item]').first();
await item.waitFor({ state: 'attached', timeout: 5000 });
// 3. Install a MutationObserver in the page context that watches the item.
await page.evaluate(() => {
const item = document.querySelector('[data-toast-item]') as HTMLElement | null;
if (!item) {
(window as unknown as Record<string, unknown>).__probeResult = {
error: 'item not found'
};
return;
}
const captured: Array<{
time: number;
attr: string;
oldValue: string | null;
newValue: string | null;
}> = [];
const start = performance.now();
const observer = new MutationObserver((mutations) => {
for (const m of mutations) {
if (m.type !== 'attributes' || !m.attributeName) continue;
captured.push({
time: Math.round(performance.now() - start),
attr: m.attributeName,
oldValue: m.oldValue,
newValue: (m.target as HTMLElement).getAttribute(m.attributeName)
});
}
});
observer.observe(item, { attributes: true, attributeOldValue: true });
(window as unknown as Record<string, unknown>).__probeStop = () => {
observer.disconnect();
return captured;
};
});
// 4. Click the close button (× inside the toast item).
const closeBtn = item.locator('[data-toast-close]').first();
await closeBtn.click();
// 5. Wait long enough for the dismiss + cleanup to complete (~5 frames).
await page.waitForTimeout(200);
// 6. Pull the captured mutations out.
const result = (await page.evaluate(() => {
const stop = (window as unknown as { __probeStop?: () => unknown; __probeResult?: unknown })
.__probeStop;
const errResult = (window as unknown as { __probeResult?: unknown }).__probeResult;
if (errResult) return errResult;
return stop ? stop() : { error: 'observer not installed' };
})) as Array<{ time: number; attr: string; oldValue: string | null; newValue: string | null }>;
console.log('\n=== Console messages ===');
for (const line of consoleLines) console.log(line);
console.log('\n=== Mutations on the toast item during dismiss ===');
if (Array.isArray(result) && result.length === 0) {
console.log('(none)');
} else if (Array.isArray(result)) {
for (const m of result) {
console.log(
`+${m.time}ms ${m.attr}: ${JSON.stringify(m.oldValue)} → ${JSON.stringify(m.newValue)}`
);
}
const sawSignal = result.some((m) => m.attr === 'data-event' && m.newValue === 'dismiss');
console.log(`\nSignal observed: ${sawSignal ? '✅ YES' : '❌ NO'}`);
} else {
console.log('error result:', result);
}
await browser.close();
}
main().catch((err) => {
console.error(err);
process.exit(1);
});

Powered by TurnKey Linux.