From cb687fbf99b3b855d3bd5504c56e4cecbe3dfaa3 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Thu, 4 Jun 2026 18:00:30 +0100 Subject: [PATCH] fix(e2e): stop files-page tests racing the skeleton-grid render (#6533) --- .../stubbed/files-page-screenshots.spec.ts | 112 +++++++++++++----- .../src/core/tests/stubbed/files-page.spec.ts | 12 +- 2 files changed, 90 insertions(+), 34 deletions(-) diff --git a/frontend/editor/src/core/tests/stubbed/files-page-screenshots.spec.ts b/frontend/editor/src/core/tests/stubbed/files-page-screenshots.spec.ts index d37a2739a..081af705a 100644 --- a/frontend/editor/src/core/tests/stubbed/files-page-screenshots.spec.ts +++ b/frontend/editor/src/core/tests/stubbed/files-page-screenshots.spec.ts @@ -12,6 +12,28 @@ interface SeedFile { } async function seedFiles(page: Page, files: SeedFile[]): Promise { + // Build the server-side view from the cloud entries so reconcileServerFiles + // sees them as still-existing on the server (otherwise they get detached + // and the cloud cards vanish before the screenshot is taken). + const serverFiles = files + .filter((f) => f.remoteStorageId != null) + .map((f) => ({ + id: f.remoteStorageId, + fileName: f.name, + contentType: "application/pdf", + sizeBytes: 1024, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + owner: "testuser", + ownedByCurrentUser: true, + accessRole: "owner", + shareLinks: [], + filePurpose: "generic", + folderId: null, + })); + await page.route("**/api/v1/storage/files", (route: Route) => + route.fulfill({ json: serverFiles }), + ); await page.addInitScript((records) => { const open = window.indexedDB.open("stirling-pdf-files", 4); open.onupgradeneeded = (event) => { @@ -141,8 +163,10 @@ test.describe("Files page screenshots", () => { { id: "cloud-c", name: "cloud-c.pdf", remoteStorageId: 1001 }, ]); await page.goto("/files", { waitUntil: "domcontentloaded" }); - await expect(page.locator(".files-page-card").first()).toBeVisible({ - timeout: 5_000, + await expect( + page.locator(".files-page-card:not(.files-page-skeleton-card)").first(), + ).toBeVisible({ + timeout: 10_000, }); await settle(page); await page.screenshot({ path: shotPath("03_subtoolbar_with_files") }); @@ -154,8 +178,10 @@ test.describe("Files page screenshots", () => { { id: "alpha", name: "alpha.pdf", remoteStorageId: null }, ]); await page.goto("/files", { waitUntil: "domcontentloaded" }); - await expect(page.locator(".files-page-card").first()).toBeVisible({ - timeout: 5_000, + await expect( + page.locator(".files-page-card:not(.files-page-skeleton-card)").first(), + ).toBeVisible({ + timeout: 10_000, }); const card = page .locator(".files-page-card:not(.is-folder)") @@ -174,8 +200,10 @@ test.describe("Files page screenshots", () => { { id: "cloud-c", name: "cloud-c.pdf", remoteStorageId: 1001 }, ]); await page.goto("/files", { waitUntil: "domcontentloaded" }); - await expect(page.locator(".files-page-card").first()).toBeVisible({ - timeout: 5_000, + await expect( + page.locator(".files-page-card:not(.files-page-skeleton-card)").first(), + ).toBeVisible({ + timeout: 10_000, }); const card = page .locator(".files-page-card:not(.is-folder)") @@ -193,8 +221,10 @@ test.describe("Files page screenshots", () => { { id: "alpha", name: "alpha.pdf", remoteStorageId: null }, ]); await page.goto("/files", { waitUntil: "domcontentloaded" }); - await expect(page.locator(".files-page-card").first()).toBeVisible({ - timeout: 5_000, + await expect( + page.locator(".files-page-card:not(.files-page-skeleton-card)").first(), + ).toBeVisible({ + timeout: 10_000, }); await page .locator(".files-page-card:not(.is-folder)") @@ -213,8 +243,10 @@ test.describe("Files page screenshots", () => { { id: "alpha", name: "alpha.pdf", remoteStorageId: null }, ]); await page.goto("/files", { waitUntil: "domcontentloaded" }); - await expect(page.locator(".files-page-card").first()).toBeVisible({ - timeout: 5_000, + await expect( + page.locator(".files-page-card:not(.files-page-skeleton-card)").first(), + ).toBeVisible({ + timeout: 10_000, }); const card = page .locator(".files-page-card:not(.is-folder)") @@ -234,8 +266,10 @@ test.describe("Files page screenshots", () => { { id: "alpha", name: "alpha.pdf", remoteStorageId: null }, ]); await page.goto("/files", { waitUntil: "domcontentloaded" }); - await expect(page.locator(".files-page-card").first()).toBeVisible({ - timeout: 5_000, + await expect( + page.locator(".files-page-card:not(.files-page-skeleton-card)").first(), + ).toBeVisible({ + timeout: 10_000, }); const card = page .locator(".files-page-card:not(.is-folder)") @@ -263,8 +297,10 @@ test.describe("Files page screenshots", () => { ]); await page.setViewportSize({ width: 900, height: 700 }); await page.goto("/files", { waitUntil: "domcontentloaded" }); - await expect(page.locator(".files-page-card").first()).toBeVisible({ - timeout: 5_000, + await expect( + page.locator(".files-page-card:not(.files-page-skeleton-card)").first(), + ).toBeVisible({ + timeout: 10_000, }); await settle(page); await page.screenshot({ path: shotPath("09_subtoolbar_narrow_viewport") }); @@ -298,8 +334,10 @@ test.describe("Files page screenshots", () => { { times: 5 }, ); await page.goto("/files", { waitUntil: "domcontentloaded" }); - await expect(page.locator(".files-page-card").first()).toBeVisible({ - timeout: 5_000, + await expect( + page.locator(".files-page-card:not(.files-page-skeleton-card)").first(), + ).toBeVisible({ + timeout: 10_000, }); const card = page .locator(".files-page-card:not(.is-folder)") @@ -349,8 +387,10 @@ test.describe("Files page screenshots", () => { { id: "bravo", name: "bravo.pdf", remoteStorageId: null }, ]); await page.goto("/files", { waitUntil: "domcontentloaded" }); - await expect(page.locator(".files-page-card").first()).toBeVisible({ - timeout: 5_000, + await expect( + page.locator(".files-page-card:not(.files-page-skeleton-card)").first(), + ).toBeVisible({ + timeout: 10_000, }); await settle(page); await page.screenshot({ path: shotPath("12_dark_subtoolbar_with_files") }); @@ -363,8 +403,10 @@ test.describe("Files page screenshots", () => { { id: "alpha", name: "alpha.pdf", remoteStorageId: null }, ]); await page.goto("/files", { waitUntil: "domcontentloaded" }); - await expect(page.locator(".files-page-card").first()).toBeVisible({ - timeout: 5_000, + await expect( + page.locator(".files-page-card:not(.files-page-skeleton-card)").first(), + ).toBeVisible({ + timeout: 10_000, }); const card = page .locator(".files-page-card:not(.is-folder)") @@ -412,8 +454,10 @@ test.describe("Files page screenshots", () => { { id: "bravo", name: "bravo.pdf", remoteStorageId: null }, ]); await page.goto("/files", { waitUntil: "domcontentloaded" }); - await expect(page.locator(".files-page-card").first()).toBeVisible({ - timeout: 5_000, + await expect( + page.locator(".files-page-card:not(.files-page-skeleton-card)").first(), + ).toBeVisible({ + timeout: 10_000, }); await settle(page); await page.screenshot({ path: shotPath("16_rtl_subtoolbar_with_files") }); @@ -426,8 +470,10 @@ test.describe("Files page screenshots", () => { { id: "alpha", name: "alpha.pdf", remoteStorageId: null }, ]); await page.goto("/files", { waitUntil: "domcontentloaded" }); - await expect(page.locator(".files-page-card").first()).toBeVisible({ - timeout: 5_000, + await expect( + page.locator(".files-page-card:not(.files-page-skeleton-card)").first(), + ).toBeVisible({ + timeout: 10_000, }); const card = page .locator(".files-page-card:not(.is-folder)") @@ -451,8 +497,10 @@ test.describe("Files page screenshots", () => { { id: "alpha", name: "alpha.pdf", remoteStorageId: null }, ]); await page.goto("/files", { waitUntil: "domcontentloaded" }); - await expect(page.locator(".files-page-card").first()).toBeVisible({ - timeout: 5_000, + await expect( + page.locator(".files-page-card:not(.files-page-skeleton-card)").first(), + ).toBeVisible({ + timeout: 10_000, }); await page .locator(".files-page-card:not(.is-folder)") @@ -472,8 +520,10 @@ test.describe("Files page screenshots", () => { { id: "alpha", name: "alpha.pdf", remoteStorageId: null }, ]); await page.goto("/files", { waitUntil: "domcontentloaded" }); - await expect(page.locator(".files-page-card").first()).toBeVisible({ - timeout: 5_000, + await expect( + page.locator(".files-page-card:not(.files-page-skeleton-card)").first(), + ).toBeVisible({ + timeout: 10_000, }); await page .locator(".files-page-card:not(.is-folder)") @@ -545,8 +595,10 @@ test.describe("Files page screenshots", () => { ]); await page.setViewportSize({ width: 500, height: 900 }); await page.goto("/files", { waitUntil: "domcontentloaded" }); - await expect(page.locator(".files-page-card").first()).toBeVisible({ - timeout: 5_000, + await expect( + page.locator(".files-page-card:not(.files-page-skeleton-card)").first(), + ).toBeVisible({ + timeout: 10_000, }); await settle(page); await page.screenshot({ path: shotPath("10_subtoolbar_phone_hidden") }); diff --git a/frontend/editor/src/core/tests/stubbed/files-page.spec.ts b/frontend/editor/src/core/tests/stubbed/files-page.spec.ts index 7aa5e2656..d1bda5720 100644 --- a/frontend/editor/src/core/tests/stubbed/files-page.spec.ts +++ b/frontend/editor/src/core/tests/stubbed/files-page.spec.ts @@ -120,12 +120,16 @@ async function stubStorageApis( ); } -/** Navigate to /files and wait for at least one seeded card. */ +/** Navigate to /files and wait for at least one real (non-skeleton) card. + * `.files-page-card` also matches the loading-state skeleton placeholders, and + * their parent grid carries `aria-busy="true"` which intercepts pointer events + * -- so waiting for any `.files-page-card` races the skeleton→real transition + * and causes flaky timeouts on slower CI runners. */ async function gotoFilesPage(page: Page): Promise { await page.goto("/files", { waitUntil: "domcontentloaded" }); - await expect(page.locator(".files-page-card").first()).toBeVisible({ - timeout: 5_000, - }); + await expect( + page.locator(".files-page-card:not(.files-page-skeleton-card)").first(), + ).toBeVisible({ timeout: 10_000 }); } test.describe("Files page", () => {