Repository navigation
Commit 1fd0c32
test(app-shell): unmount before unstubbing fetch in the ImpersonationBanner test (#30502)
<!-- claude-projects-attribution: {"github_login":"os-sales"} -->
_Requested by **Sales** · [project
thread](https://claude.ai/code/project/chan_01D5bWFY3rFzgJcytD5gD4Uu?thread=cmsg_01D5bWFY3rFzgJcytD5gD4UuXpPPZiBKyj1HzrdQ6La3ZH)_
domain:ui#6 · os-sales · session_01L6bhgUR8Nu4M7tbtgES7q2
Fixes #30434
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:只改 `ImpersonationBanner.test.tsx` 一个测试文件:`afterEach` 先
`cleanup()` 卸载组件,再 `vi.unstubAllGlobals()` 撤掉 fetch
替身;另加一条用例,钉住测试体结束后才发出的 `sys_user` 读取仍落到替身。
- 为什么改:原顺序先撤替身、后由根 setup 卸载,卸载时补跑的读取打到真实 `localhost:3000`,网络逃逸守卫随机把无关 PR
的 `Test UI` 判红(PR #30417 就为此白查一轮)。
- 风险与回滚:仅测试代码,不进任何发布包;回滚即 revert 本提交。
-
先看:`ui/packages/app-shell/src/layout/__tests__/ImpersonationBanner.test.tsx`
的 `afterEach` 与文件末尾新增用例。
- 两分钟验证:`pnpm --dir ui exec vitest run
packages/app-shell/src/layout/__tests__/ImpersonationBanner.test.tsx`,预期
14 条全绿。
- 需要你做的:无,席位落地(PR 需带 `skip-changeset` 标签)。
## What changes
- `afterEach` now calls RTL `cleanup()` before `vi.unstubAllGlobals()`.
Vitest runs this file's hook before the root setup's `cleanup()` and
before the network-escape guard. With the old order the tree was still
mounted when the real `fetch` came back, so a banner `sys_user` read
whose effect was still pending when the body returned went out during
that cleanup's act-flush. That is the shape the guard's message names
(objectui#7439). The banner issues `fetch` synchronously inside its
effect, so once the tree is unmounted nothing in this file can issue a
read. Cleanup-first is therefore enough, and it is the smaller of the
two shapes the guard offers.
- New case `a read that lands AFTER the test body still reaches the
double, never the network`. A small probe issues the banner's own
administrator read (same URL, same `createAuthenticatedFetch` lane) from
its unmount. That is the exact moment the teardown order decides. An
`onTestFinished` check, which runs after every `afterEach` including the
guard, asserts the double served it. A probe stands in for the banner's
effect because React's passive-effect timing cannot be held open on
purpose. The probe lands a read in that window every time.
- `ImpersonationBanner.tsx` is not touched.
## Tests
- File on the fix: 14/14 passed (13 before plus the new case).
- Positive control: the old teardown order restored through
`scripts/ablation-replace.mjs`, which records the mutation on disk and
restores from HEAD. The new case goes red twice, and the other 13 stay
green.
- Stability: 20 consecutive runs of the file, 20/20 green, with zero
`Network escape` lines across all 20 logs.
## Acceptance notes
- `skip-changeset`: test-only. The file is under `src/**/__tests__` and
is not shipped in any package's published files.
- Local `type-check` of `@object-ui/app-shell` (`tsc -p
tsconfig.test.json`) was NOT MEASURED. In this container the sibling
`@object-ui/*` packages are unbuilt, so every error is TS2307 module
resolution, including those in untouched files. CI's `Type Check UI`
lane covers it.
## Verification
Head `b244cccb8d`.
<details><summary>Positive control: old order (unstub, then the root
setup's cleanup)</summary>
```
ablation-replace: ok mutation landed: anchor 1 -> 0, blob d3570d9 -> 58c6112e115d
FAIL |dom| packages/app-shell/src/layout/__tests__/ImpersonationBanner.test.tsx > ImpersonationBanner (#4467) > a read that lands AFTER the test body still reaches the double, never the network
Error: Network escape: this test reached a REAL socket at http://localhost:3000/api/v1/data/sys_user/usr_admin.
FAIL |dom| ... > a read that lands AFTER the test body still reaches the double, never the network
AssertionError: expected 1 to be 2 // Object.is equality
Test Files 1 failed (1)
Tests 1 failed | 13 passed (14)
ablation-replace: ok restored: blob == HEAD (d3570d9) and `git diff HEAD` is empty
```
The URL is the one the CI flake reported (PR #30417, job 127192655114).
</details>
<details><summary>Fix: one run, then 20 in a row</summary>
```
Test Files 1 passed (1)
Tests 14 passed (14)
run 1..20: Tests 14 passed (14) (each)
LOOP pass=20 fail=0
os-verify-lock: VERDICT command-exit 0
```
</details>
<details><summary>Derived gates (dispatch-gates --commands, 26
families)</summary>
All 26 exited 0, including `pnpm --dir ui exec vitest run scripts/`
(Test Files 170 passed, 2 skipped; Tests 4985 passed, 2 skipped) and
`pnpm check:type-check-debt`.
```
Run reconciliation — 26 derived, 26 run, 0 NOT-MEASURED, 0 UNRUN.
✓ dispatch-gates --ran: 26 derived famil(ies) accounted for — 26 run, 0 NOT-MEASURED
```
</details>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01L6bhgUR8Nu4M7tbtgES7q2
<!-- signed: domain:ui#6 · os-sales · session_01L6bhgUR8Nu4M7tbtgES7q2
-->
Co-authored-by: Claude <noreply@anthropic.com>1 parent 5174603 commit 1fd0c32
1 file changed
Lines changed: 47 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
33 | | - | |
34 | | - | |
| 33 | + | |
| 34 | + | |
35 | 35 | | |
36 | | - | |
| 36 | + | |
| 37 | + | |
37 | 38 | | |
38 | 39 | | |
39 | 40 | | |
| |||
131 | 132 | | |
132 | 133 | | |
133 | 134 | | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
134 | 152 | | |
135 | 153 | | |
136 | 154 | | |
137 | 155 | | |
138 | 156 | | |
139 | 157 | | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
140 | 165 | | |
141 | 166 | | |
142 | 167 | | |
| |||
307 | 332 | | |
308 | 333 | | |
309 | 334 | | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
310 | 354 | | |
311 | 355 | | |
312 | 356 | | |
| |||
0 commit comments