diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 325463d4..38bf6fb3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -161,15 +161,16 @@ jobs: - uses: actions/setup-node@v5 with: node-version: ${{ env.NODE_VERSION }} + cache: 'pnpm' - - name: Restore node_modules - uses: actions/cache/restore@v5 - with: - path: | - node_modules - apps/*/node_modules - packages/*/node_modules - key: modules-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }} + # e2e launches the REAL Electron app, so it needs Electron's runtime binary + # and better-sqlite3 rebuilt for Electron. The shared `setup` cache is + # installed with --ignore-scripts (no binary) and restoring it makes a + # later install a no-op, so this job does its own full install WITH scripts + # (fresh node_modules → electron's install.js downloads the binary, + # desktop postinstall runs electron-builder install-app-deps). + - name: Install dependencies (with postinstall scripts) + run: pnpm install --frozen-lockfile - name: Install Playwright system deps working-directory: apps/desktop diff --git a/apps/desktop/e2e/smoke.spec.ts b/apps/desktop/e2e/smoke.spec.ts index 2ca924ce..1f6f9511 100644 --- a/apps/desktop/e2e/smoke.spec.ts +++ b/apps/desktop/e2e/smoke.spec.ts @@ -13,7 +13,17 @@ test.describe('app launch (smoke)', () => { // First window must render *something* — a element with non-zero // size is a low bar that catches the regression class from PR #266 // (editor mount crashes that produced a blank window). - const bodyBox = await window.locator('body').boundingBox(); + // launchApp only waits for `domcontentloaded`, which fires before the + // first paint/layout, so the body can briefly measure 0×0. Poll until it + // actually lays out before measuring (this is a render race, not a blank + // window). + const body = window.locator('body'); + await expect + .poll(async () => (await body.boundingBox())?.width ?? 0, { + message: 'body should lay out with non-zero width', + }) + .toBeGreaterThan(0); + const bodyBox = await body.boundingBox(); expect(bodyBox).not.toBeNull(); expect(bodyBox!.width).toBeGreaterThan(0); expect(bodyBox!.height).toBeGreaterThan(0);