From aa3be4bae4a3cdcdc6798b0eecb75c9d9a702c4e Mon Sep 17 00:00:00 2001 From: Wenyao Gao <105094497+edwingao28@users.noreply.github.com> Date: Sat, 3 Oct 2026 08:01:36 +0000 Subject: [PATCH] test(blog): make the listing visit hermetic and retryable in Firefox MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The listing suite visited /blog once in a before-all hook whose load event depended on every eager card thumbnail going through the image optimizer, including a remote Substack source. Firefox shard 1 lost that load event in 16 of the last 30 failed E2E runs; before-all hooks are not retried, so one lost event failed the hook and skipped the suite. Stub every /_next/image request with the 1x1 fixture, visit per test with a 20s bound so retries cover a lost load event, and cover the real optimizer with a direct request for the first local thumbnail. 中文:博客列表测试原先在 before-all 中访问 /blog,页面 load 事件依赖所有首屏缩略图经由图片优化器加载(含远端 Substack 来源),Firefox 下该事件偶发丢失且 before-all 不会重试,导致整个套件被跳过。现改为按用例访问并限制 20 秒超时以启用重试,统一用 1x1 图片桩替换所有 /_next/image 请求,并直接请求本地缩略图的优化器响应以保留覆盖。 --- packages/app/cypress/e2e/blog.cy.ts | 34 ++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/packages/app/cypress/e2e/blog.cy.ts b/packages/app/cypress/e2e/blog.cy.ts index a527bff8b..f9252546f 100644 --- a/packages/app/cypress/e2e/blog.cy.ts +++ b/packages/app/cypress/e2e/blog.cy.ts @@ -38,19 +38,19 @@ describe('Blog', () => { }); describe('Blog listing page', () => { - before(() => { - // Stub remote Substack thumbnails with a real 1×1 PNG. A 204 empty body - // can prevent Firefox from firing `window.load` while eager card images - // stay pending, which times out `cy.visit` in before-all. + // Card thumbnails are the only load-blocking subresources the listing adds + // on top of the shared chrome, and the featured card plus the first grid + // row are eager. Serve every optimizer request from a fixture so the visit + // never waits on image resizing or a remote thumbnail host; the optimizer + // itself is covered by the cy.request check below. Visiting per test + // instead of once in before-all lets Cypress retries cover a lost Firefox + // load event, which otherwise fails the hook and skips the whole suite. + beforeEach(() => { cy.intercept( - { - method: 'GET', - pathname: '/_next/image', - query: { url: /^https:\/\/substack-post-media\.s3\.amazonaws\.com\// }, - }, + { method: 'GET', pathname: '/_next/image' }, { fixture: '1x1.png', headers: { 'content-type': 'image/png' } }, ); - cy.visit('/blog'); + cy.visit('/blog', { timeout: 20_000 }); }); it('renders the blog page with heading', () => { @@ -74,6 +74,20 @@ describe('Blog', () => { it('post cards link to individual posts', () => { cy.get('a[href^="/blog/"]').should('have.length.gte', 1); }); + + it('serves local card thumbnails through the image optimizer', () => { + // The browser never fetches these (stubbed above), so check the real + // optimizer response directly for the first local thumbnail on the page. + cy.get('[data-testid="blog-post-grid"] img[src^="/_next/image?url=%2Fimages%2F"]') + .first() + .invoke('attr', 'src') + .then((src) => { + cy.request({ url: String(src), encoding: 'binary' }).then((response) => { + expect(response.status).to.eq(200); + expect(response.headers['content-type']).to.match(/^image\//u); + }); + }); + }); }); describe('Blog post page', () => {