修复 Studio 失败测试并新增合并门禁

把丢失的 box 录像放回 apps/studio/tests/data/,修掉第 3 节 3–10 号与两处过时测试桩,
注册 timing 标记并让根目录收集零错误;新增 tools/gate.ps1 与可选的 pre-push 钩子。
验证:studio 524 通过 19 跳过、shared 467 通过 18 跳过、ui_check 632 项 0 失败、gate.ps1 退出码 0。
细节见 docs/test-repair-plan.zh.md。
This commit is contained in:
ykcheungab
2026-10-18 19:24:31 +08:00
parent dcabd547fa
commit 433b76e43c
38 changed files with 1036 additions and 171 deletions
+22 -6
View File
@@ -1711,8 +1711,9 @@ def main() -> int:
window.force_plots.mode() == "follow",
"the replay view browses before a recording is open",
)
# The replay view is the live arrangement, measured rather than assumed: the
# splitter hands out its handles' width, so compare like with like.
# The replay view shows the live view's panes, and its preset gives the *charts* the
# room (321e52f: "keep each preset's panel priority"), so the splitter is measured
# rather than assumed: slot 1 is the 2D panel, slot 2 the charts.
window.brand_bar.btn_live.click()
for _ in range(3):
app.processEvents()
@@ -1722,8 +1723,13 @@ def main() -> int:
app.processEvents()
replay_sizes = tuple(window.content_splitter.sizes())
check(
replay_sizes == live_sizes,
f"the replay view is not the live arrangement: {replay_sizes} vs {live_sizes}",
live_sizes[1] > 0 and live_sizes[2] > 0,
f"the live view lost a pane: {live_sizes}",
)
check(
replay_sizes[1] < live_sizes[1] and replay_sizes[2] > live_sizes[2],
"the replay view does not give the charts more room than the live view: "
f"{replay_sizes} vs {live_sizes}",
)
check(
not hasattr(window, "replay_bar"),
@@ -2368,13 +2374,23 @@ def main() -> int:
f"a failed start left the recorder in {fail_window.recorder.state!r}",
)
# ...and the operator can simply try again.
# ...and the operator can simply try again. ``start()`` returns once the directory
# exists; the recorder itself moves to ``recording`` on its own writer thread, so
# reading the flag back immediately is a race (measured: one full run in three
# reported "refused to retry" although the retry had been accepted). The claim is
# "retrying works", not "it worked inside one event loop", so wait for it — bounded,
# like the write-error poll below.
_app_module.recordings_dir = lambda: scratch_fail
fail_window.toolbar.btn_record.setChecked(True)
app.processEvents()
deadline = time.monotonic() + 2.0
while not fail_window.recorder.is_recording and time.monotonic() < deadline:
app.processEvents()
time.sleep(0.01)
check(
fail_window.recorder.is_recording,
"the recorder refused to retry after a failed directory",
"the recorder refused to retry after a failed directory "
f"(state {fail_window.recorder.state!r} after 2 s)",
)
# A writer that keeps failing must fail the recording, and the window must