Skip to content

[Test] stabilize the Firefox blog listing E2E visit / 稳定 Firefox 博客列表 E2E 访问 - #1263

Merged
edwingao28 merged 1 commit into
masterfrom
fix/blog-listing-e2e-firefox-load
Oct 3, 2026
Merged

edwingao28 merged 1 commit into
masterfrom
fix/blog-listing-e2e-firefox-load

Conversation

@edwingao28

@edwingao28 edwingao28 commented Oct 3, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Stabilize the recurring Firefox E2E failure Blog › Blog listing page › "before all" hook for "renders the blog page with heading" (Timed out after waiting 60000ms for your remote page to load).

Evidence. Across the last 30 failed tests-e2e runs, 16 failed on exactly this hook, all on E2E (firefox, shard 1) and never on Chrome (examples: 37076830984, 36959125845, 36952749489, 36622355367). In passing runs the same listing visit plus first assertion completes in ~200 ms in both browsers, so this is a lost load event, not a slow page. The hang survived the earlier Substack-only 1×1 stub (#1166), so a remote-only stub is not sufficient.

Why the hook fails wholesale. The listing visit lived in a before (before-all) hook. Cypress does not retry before-all hooks, so one lost load event failed the hook and skipped the other three listing tests. The visit's load event depended on every eager card thumbnail (featured card + first grid row) passing through /_next/image, one of which is a remote Substack source; Firefox routes all of that through the Cypress HTTP/1.1 proxy.

Change (packages/app/cypress/e2e/blog.cy.ts only).

  • Stub every /_next/image request on the listing with the existing 1x1.png fixture, so the visit never waits on image resizing or a remote thumbnail host.
  • Visit per test in beforeEach with a 20 s bound, so the configured retries.runMode: 2 covers a lost load event at bounded cost.
  • Add serves local card thumbnails through the image optimizer, which cy.requests the first local thumbnail's real optimizer URL (200 + image/*), keeping optimizer coverage the stub would otherwise remove.

No production code changes. Other before hooks in the spec have not flaked and are left as they are.

AI model disclosure

  • Model/version: Claude Fable 5.1 (identifier as exposed by the Perplexity Computer runtime).
  • Role: CI log analysis, local reproduction attempts, fix, verification and PR preparation.
  • No delegated agents contributed.
  • I have completed the AI model disclosure and kept it current

Validation

Local production build (E2E_FIXTURES=1 bun run build && bun run start), Cypress 15.21.1, Firefox 157 and Electron.

  • Repro attempts of the raw flake: 20+ cold-profile Firefox runs of blog.cy.ts and one full Firefox shard-1 replay (11 specs in CI order) all passed, so the raw race could not be forced locally. The failure mechanism was simulated instead:
  • Before (master spec) with a 70 s stalled eager local thumbnail, Firefox: "before all" hook … Timed out, Skipped: 3, no retry (same signature as CI).
  • After with the same stall, Firefox and Electron: 16/16 passing, 0 skipped.
  • After with the first /blog document load stalled once: (Attempt 1 of 3) then 16/16 passing, 0 skipped. Confirms the retry path and bounded cost.
  • Unstubbed blog.cy.ts on the new spec: 16/16 passing in Firefox.
  • bunx oxlint, bunx oxfmt --check on the changed file, bun run typecheck, bun run check:typography: pass.

Not verified: the raw CI race itself (not reproducible locally); CI results will be reported after this PR's checks finish.

中文说明

修复 Firefox E2E 中反复出现的 Blog › Blog listing page before-all 钩子超时(60 秒内页面未触发 load 事件)。最近 30 次失败的 E2E 运行中有 16 次正是该钩子,且全部发生在 E2E (firefox, shard 1),Chrome 从未出现;通过的运行里同一访问加首个断言只需约 200 毫秒,说明是 load 事件丢失而非页面变慢。之前仅针对 Substack 缩略图的 1×1 桩(#1166)未能消除该问题。

原因:列表页访问放在 before-all 钩子中,而 Cypress 不会重试 before-all,一次 load 丢失就导致钩子失败并跳过其余三个用例;该 load 事件依赖首屏所有缩略图经 /_next/image 加载(其中一张来自远端 Substack),Firefox 下这些请求全部经由 Cypress 的 HTTP/1.1 代理。

改动仅限 packages/app/cypress/e2e/blog.cy.ts:统一用 1x1.png 桩替换列表页全部 /_next/image 请求;改为在 beforeEach 中按用例访问并限制 20 秒超时,使已配置的重试生效;新增用例直接请求首个本地缩略图的真实优化器地址(200 且 image/*),保留对图片优化器的覆盖。未改动生产代码。

验证:本地生产构建 + Cypress 15.21.1(Firefox 157、Electron)。20 余次冷配置 Firefox 运行及完整 shard-1 顺序回放均未能复现原始竞态,因此改为模拟机制:旧用例在首屏缩略图停滞 70 秒时出现与 CI 相同的 before-all 超时并跳过 3 个用例;新用例在同样条件下 Firefox 与 Electron 均 16/16 通过;仅使首个 /blog 文档加载停滞时,新用例经一次重试后全部通过。lint、格式、类型检查与排版检查通过。原始 CI 竞态本身无法在本地复现,CI 结果将在检查完成后汇报。

AI 模型:Claude Fable 5.1(Perplexity Computer 运行环境提供的标识),负责 CI 日志分析、本地复现尝试、修复、验证与 PR 准备;未使用委派 agent。


Note

Low Risk
Changes are limited to Cypress E2E in blog.cy.ts; no production or runtime behavior is modified.

Overview
Stabilizes flaky Firefox E2E on the blog listing suite by changing how /blog is visited and how card images are stubbed.

The listing hook moves from before → beforeEach with a 20s visit timeout so Cypress run-mode retries can recover from a lost load event instead of failing the whole block. cy.intercept now stubs every GET /_next/image with the existing 1x1.png fixture (not only Substack URLs), so eager featured/grid thumbnails do not block the page load on resizing or remote hosts.

A new test serves local card thumbnails through the image optimizer uses cy.request against the first local grid thumbnail’s real /_next/image URL to assert 200 and an image/* content type, preserving optimizer coverage that the broad stub removes from the browser path.

Reviewed by Cursor Bugbot for commit aa3be4b. Bugbot is set up for automated code reviews on this repo. Configure here.

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 请求,并直接请求本地缩略图的优化器响应以保留覆盖。
@edwingao28
edwingao28 requested a review from adibarra as a code owner October 3, 2026 08:02
@vercel

vercel Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
inferencemax-app Ready Ready Preview Oct 3, 2026 8:03am UTC

Request Review

@github-actions

github-actions Bot commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @edwingao28's task in 1m 44s —— View job


Review complete

  • Read the changed spec in full context
  • Analyze the stabilization approach and new test correctness
  • Check CI status
  • Post review

🟢 LGTM — no blocking issues found.

This is a well-reasoned, test-only change (packages/app/cypress/e2e/blog.cy.ts). I verified each assumption the diff relies on:

  • beforeEach + per-test cy.visit('/blog', { timeout: 20_000 }) correctly leverages retries.runMode: 2 (confirmed in cypress.config.ts:13-16). Moving off the before-all hook is the right fix: Cypress doesn't retry before-all hooks, so a single lost Firefox load event previously failed the hook and skipped the whole suite. Re-registering the intercept in beforeEach is also necessary, not just stylistic — cy.intercept routes are cleared between tests even with testIsolation: false, so a stub left in the old before would not have applied to tests 2–4.
  • Stubbing all /_next/image removes the remote-thumbnail / optimizer-resize work from the visit's load event, which matches the diagnosis (lost load, not a slow page).
  • New serves local card thumbnails… test preserves the optimizer coverage the stub removes. The key correctness detail holds: cy.request is not intercepted by cy.intercept, so it hits the real optimizer rather than the fixture. The selector img[src^="/_next/image?url=%2Fimages%2F"] is valid — optimizedThumbnailSrc (src/lib/blog-thumbnail-src.ts:13) emits exactly /_next/image?url=%2Fimages%2F…&w=…&q=75 for local figure thumbnails, and data-testid="blog-post-grid" exists (blog-index-content.tsx:126).

One minor, non-blocking observation: the new test's .first() assumes at least one grid card carries a local /images/ thumbnail (posts without a figure render the text-free tile with no <img>). That holds today given the published posts with figures; if the listing ever showed only figure-less posts the .first() would fail with no match — acceptable for a test given current content.

No production code, no user-visible Chinese strings, and no new interactive elements, so coverage/analytics//zh requirements don't apply. The change adds coverage rather than removing it. CI: Lint & Format passed; Unit and E2E were still in progress at review time.
· branch fix/blog-listing-e2e-firefox-load

@edwingao28
edwingao28 merged commit 3a153dc into master Oct 3, 2026
25 checks passed
@edwingao28
edwingao28 deleted the fix/blog-listing-e2e-firefox-load branch October 3, 2026 08:19

This branch was successfully deployed

1 active deployment
Preview — aa3be4ba Deployed Oct 3, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant