Repository navigation
[test-harness] await act(async …) never settles when a test renders the console AppContent surface #5194
Description
Observation-class, found while implementing #4522 (PR #5193); not fixed there — out of that card's scope, and it predates it.
What was measured
In packages/app-shell/src/console/__tests__/, a test that renders AppContent through the router and then awaits act with an async callback does not resume. Every such call sat for the full testTimeout (15000ms) and failed as a timeout, never as an assertion — measured three times in one file, on three different rendered surfaces:
await act(async () => { await new Promise(r => setTimeout(r, 20)); }); // 15007ms, timed out
await act(async () => { pendingRefresh(); }); // 15020ms, timed outReplacing them with a plain await new Promise(r => setTimeout(r, 20)) plus findBy* / waitFor for the act-aware waiting makes the same cases pass in ~1s. That is what AppContent.missingRecheckKeying.test.tsx does today, with the measurement recorded in its settle() docstring so the next author does not re-derive it.
Why it is worth a card rather than only a comment
await act(async …) is ordinary, correct RTL usage and works elsewhere in this repo — 50 test files under packages/*/src use it. So the failure is specific to this surface, and its shape is the expensive kind: not a red assertion pointing at the code under test, but a 15s timeout that reads as "my component hangs". The first reaction is to go looking for a defect in the component being tested.
Cause NOT isolated — please do not treat the parenthetical as the diagnosis
chrome/LoadingScreen.tsx:63 runs a 1200ms setInterval that calls setCurrentStep for its step animation, and it is mounted for exactly the window a readiness re-check is in flight. A never-idle timer is consistent with an async act that never sees a quiet queue, and it is the obvious first suspect.
But it does not explain all three observations: two of them were taken when LoadingScreen had already unmounted (its cleanup clears the interval) and the rendered surface was the not-available Empty screen and the app shell respectively. Something else on this surface — another recurring timer, or pending work from the lazily-imported route modules — is contributing. Nobody has isolated it, and this issue asserts only the measurement above.
Anyone picking this up: confirm the cause before changing LoadingScreen, since an animation interval that is correct in the product would be the wrong thing to remove for a test-harness reason.
Severity note
Graded observation-class at filing time (finding, no pm:queue): nothing user-visible, no test is currently wrong or vacuous because of it, and the working pattern is documented in the file where it bites. The cost is a wasted debugging round for the next author who reaches for act here. Grade it in triage rather than trusting that line.
Activity
os-warren commentedon Aug 19, 2026
Concentrated finding round #4 — first-touch grading (triage seat, session
session_01JEhkB6ShK2HHDzozy7Qwgz, 2026-08-19): hold (pm:on-hold) — seat-graded, not maintainer-ruled.Reason: real and measured three times, but dormant — no test is wrong or vacuous today, the working
settle()pattern is documented exactly where the next author will look (packages/app-shell/src/console/__tests__/AppContent.missingRecheckKeying.test.tsx:240-258, whose docstring cites this card verbatim), and the cause is explicitly not isolated — dispatching now buys an open-ended investigation with no named defect. The suspect timer exists atpackages/app-shell/src/chrome/LoadingScreen.tsx:63(body's path hadconsole/chrome/; actual issrc/chrome/).Restart-when:
git grep -c "await act(async" -- packages/app-shell/src/console/__tests__/returns nonzero (currently 0) — a new test on this surface reaching for the broken pattern means someone is about to lose a debugging round; re-trigger then. Secondary trigger file for the repo:objectui seat's pre-dispatch checklist: any dispatch touchingpackages/app-shell/src/chrome/LoadingScreen.tsxshould link this card so the animation interval is not "fixed" for a test-harness reason.Generated by Claude Code
os-zhuang commentedon Aug 19, 2026
Hold-condition rewrite (triage seat, session
session_014qTKTqjme5Fp5BH9iRmy6t, on-hold weak-hit audit): the current Restart-when grep is permanently self-triggered — its only match on origin/main is line 243 ofAppContent.missingRecheckKeying.test.tsx, inside thesettle()DOCSTRING that documents this very card, so the condition was already nonzero the day it was written ("currently 0" was false at write time). Verified both directions: anchoring the match to non-comment lines excludes the docstring while still finding realawait act(asynccode usage in 64 files repo-wide. The hold itself stands (dormant, cause not isolated, workaround documented in place); the LoadingScreen.tsx secondary trigger also stands.Restart-when:
git grep -qE '^[^*/]*await act\(async' origin/main -- packages/app-shell/src/console/__tests__/exits 0 (code-line usage only; the comment-prefixedsettle()docstring is excluded by construction)Generated by Claude Code
os-zhuang commentedon Aug 23, 2026
Triage:
domain:devx(lane only —pm:on-holduntouched). Landing: the shared test harness —await act(async …)never settling. Test infrastructure, so the engineering stream.Routed via the maintainer direct-dispatch channel, this session, verbatim: 「然后 批 4–5」. PM session
session_0124Qg8rLvpXnQDwCmpKUmaJ. objectui three-stream split (maintainer 2026-08-21); not a Routine triage fire — the triage seat may re-grade.Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
关闭
not_planned—— 维护者同意:测试环境问题,绕开的写法已经写在下一位作者一定会看到的地方分诊席(
session_01Tw7jnJinGHvoGSi8aFkhPJ,objectstack 座位贴 #6015),2026-09-24T12:50Z。objectui 清理第八批(#8587 的挂起卡一次性清点):本席读完了卡面和评论(3 条,全部读到),并在本地 main(62597c5)上重新测量,把建议报给维护者。维护者答:「第⑧批 同意」。本卡说的是什么
测试渲染 console 的
AppContent时,await act(async …)永远等不到结束,15 秒后超时。原因没有查清,LoadingScreen 的 1200ms 定时器只是嫌疑。绕开的写法(普通等待加findBy/waitFor)已经写在AppContent.missingRecheckKeying.test.tsx:240-258,并引用了本卡。和 #4249 属于同一类测试环境问题。本席实测(本地 main
62597c5)重启条件
5345566910给出了一条可以直接运行的检查:实测代码行命中 0 处(
:243只是注释里引用了 #5194)⇒ 没有触发。为什么关
什么时候重开
上面那条
git grep命中(有人在 console 的测试里又写回了await act(async …));或者有人愿意专门查清卡死的根因时。标签:摘
pm:on-hold;以not_planned关闭。Generated by Claude Code