mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-07-11 09:42:22 +00:00
## Summary On first launch, the templates modal flashed open for a split second before a deeplinked template (`?template=`) loaded, which felt broken. ## Changes - **What**: Gate the first-launch templates modal on template URL intent, alongside the existing shared-workflow (`?share=`) check. When a template is being opened directly from the URL, the template modal no longer opens. Behavior is unchanged when no template is in the URL — the template modal still shows for first-time users. - Test util: Added browser_tests/fixtures/utils/flashDetector.ts — installs a pre-navigation requestAnimationFrame sampler that flags if a [data-testid] element ever renders, even for a single frame. This catches a brief flash that toBeHidden() (final-state only) cannot. ## Review Focus `hasTemplateUrlIntent()` mirrors the existing `hasSharedWorkflowIntent()` (direct `route.query` check plus preserved-query fallback for the `/user-select` redirect path). Two regression tests cover both the URL-param and preserved-intent cases. **Coverage:** - Unit (useWorkflowPersistenceV2.test.ts): the modal is not opened when a template param is in the URL, and when template intent is preserved across the /user-select redirect. - E2E (templates.spec.ts): templates dialog never flashes when first-time user opens a template link — verified red-without-fix, green-with-fix. Screen Recording https://github.com/user-attachments/assets/636094d4-0ef0-4e42-af32-d4e6c7ec5731 closes #12836
46 lines
1.4 KiB
TypeScript
46 lines
1.4 KiB
TypeScript
import type { Page } from '@playwright/test'
|
|
|
|
function flagAttributeFor(testId: string) {
|
|
const encoded = Array.from(testId, (ch) =>
|
|
ch.charCodeAt(0).toString(16)
|
|
).join('')
|
|
return `data-flashed-${encoded}`
|
|
}
|
|
|
|
/**
|
|
* Flags the first time an element matching `[data-testid="<testId>"]` is
|
|
* present and rendered, sampled every frame via `requestAnimationFrame` from
|
|
* page load. Catches a dialog that mounts and unmounts within a few frames,
|
|
* which `toBeHidden()` (final state only) cannot.
|
|
*
|
|
* Must be called before navigation (e.g. before `comfyPage.setup()`).
|
|
*/
|
|
export async function trackElementFlash(
|
|
page: Page,
|
|
testId: string
|
|
): Promise<{ hasFlashed: () => Promise<boolean> }> {
|
|
const flagAttribute = flagAttributeFor(testId)
|
|
|
|
await page.addInitScript(
|
|
({ id, attribute }: { id: string; attribute: string }) => {
|
|
const sample = () => {
|
|
const el = document.querySelector(`[data-testid="${CSS.escape(id)}"]`)
|
|
if (el instanceof HTMLElement) {
|
|
const rect = el.getBoundingClientRect()
|
|
if (rect.width > 0 && rect.height > 0) {
|
|
document.documentElement.setAttribute(attribute, 'true')
|
|
}
|
|
}
|
|
requestAnimationFrame(sample)
|
|
}
|
|
requestAnimationFrame(sample)
|
|
},
|
|
{ id: testId, attribute: flagAttribute }
|
|
)
|
|
|
|
return {
|
|
hasFlashed: async () =>
|
|
(await page.locator('html').getAttribute(flagAttribute)) === 'true'
|
|
}
|
|
}
|