From 4c37fceeb40615276561da93ed0a9b603b58157f Mon Sep 17 00:00:00 2001 From: shunli Date: Thu, 8 Oct 2026 09:49:20 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E9=97=A8=E7=A6=81=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E5=AE=9A=E4=BD=8D=E4=B8=8E=E5=8A=A8=E7=94=BB=E6=B5=8B?= =?UTF-8?q?=E9=87=8F=EF=BC=8809-17-company-loan-principal-repayment?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 保留原断言、容差及运行配置;两份完整测试定向 61/61 通过,补充可复用规约及失败门禁记录。提交后对固定干净候选重跑 verify-candidate。真实回单、人员与独立业务验收仍待核实;本轮不推送、不部署。 --- .../spec/hyb-oa/frontend-react-vite-design.md | 5 ++++- .../implement.md | 21 +++++++++++++++++++ .../e2e/r92-mobile-invoice-usability.spec.ts | 2 +- .../e2e/system-action-confirmation.spec.ts | 10 +++++++-- 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/.trellis/spec/hyb-oa/frontend-react-vite-design.md b/.trellis/spec/hyb-oa/frontend-react-vite-design.md index 9c15cd29..c8eb47ca 100644 --- a/.trellis/spec/hyb-oa/frontend-react-vite-design.md +++ b/.trellis/spec/hyb-oa/frontend-react-vite-design.md @@ -159,6 +159,7 @@ and verification contracts. Do not copy broad aesthetic guidance from - At the narrowest viewport where the fixed sidebar appears, the main detail column is at least `560px`, the action column is at least `280px`, and the document has no horizontal overflow beyond a `2px` rendering tolerance. - Business identifiers and normal company-time date strings use DOM line-count or geometry assertions; `position: sticky` alone is not proof that the layout is usable. - A Playwright spec writes screenshots only to its own current output directory. Never reuse an archived Trellis task's evidence directory as a live test target. +- When comparing alignment inside an animated ancestor (for example `.page-scaffold`'s `page-reveal`), read all relevant `getBoundingClientRect()` values in one synchronous browser `evaluate`/`evaluateAll` callback. Sequential `boundingBox()` calls, or calls grouped with `Promise.all`, can observe different animation frames. Keep the original alignment assertions and pixel tolerances; do not hide the race with sleeps, retries or disabled page animations. ### 4. Validation & Error Matrix @@ -997,7 +998,9 @@ point and prevents each route from inventing a different title/action layout. hidden unless `leave.manage`; attendance correction forms are hidden unless `attendance.manage`. Labels must say `OA 应急` / `提交应急审批` / `提交应急修正` instead of generic `提交`. -- When a page repeats the same title in the page header and a content section, +- Title assertions should use an exact heading role within the intended panel; + broad `getByText("票据详情")` can also match transient loading copy. When a + page repeats the same title in the page header and a content section, Playwright assertions should target the page header (`h1` or the header test id) rather than `getByRole("heading", { name })`, which becomes ambiguous. - `个人设置` stays in the topbar account menu. Notifications stay in the topbar diff --git a/.trellis/tasks/09-17-company-loan-principal-repayment/implement.md b/.trellis/tasks/09-17-company-loan-principal-repayment/implement.md index cbf955a0..00b5b380 100644 --- a/.trellis/tasks/09-17-company-loan-principal-repayment/implement.md +++ b/.trellis/tasks/09-17-company-loan-principal-repayment/implement.md @@ -1,3 +1,24 @@ +## 2026-10-08 测试稳定性集中检查与新候选门禁 + +用户已批准集中检查、必要测试修正、本地提交及对新干净候选运行正式门禁。本轮不推送、不部署、不查询生产、不执行远端备份操作;任务仍为进行中。 + +- [x] 检查两份失败测试、此前修正的审批测试,以及邻近布局用例:严格同排对齐修正为同一次浏览器执行取值;其余宽高/横向比较、带足够间隔的上下顺序及非同类动画场景不机械改写。检查详情标题与加载提示,当前需修正的仍为下方已验证的两处。 +- [x] 保留两份测试全部原有断言和运行配置;没有新增用例、修改业务实现、增加容差、超时或重试。被测输入未变,复用下方受管定向 61/61 通过结果,不为本次文档更新重复运行。 +- [x] 将同次几何取值、精确标题定位两条已验证的规则补入既有前端规约;按任务、治理、流程合同、文档注册及 diff 检查后,本地提交两份测试、规约和本记录。 +- [ ] 对新提交执行 `bash scripts/qa/run-release-gate.sh verify-candidate`,保留两次失败回执,新结果写入独立的 `artifacts/release-gate/` 目录。此处为提交前执行计划,不提前宣称通过;候选冻结后不再修改受版本控制的记录,最终状态以该候选的正式回执为准。 +- 真实建行样本、官方查询材料和编号对应关系、合格复核人员及独立业务验收继续待外部核实;正式本地门禁不替代这些条件。 + +## 2026-10-08 第二轮正式门禁及新增测试稳定性修正 + +用户确认后,仅将此前的审批按钮测量修正和任务记录本地提交为 `1dd84065`,工作区干净;对该固定候选执行 `bash scripts/qa/run-release-gate.sh verify-candidate`。未推送、部署、查询生产或执行远端备份操作。 + +- 正式回执 `artifacts/release-gate/loan-1dd84065-20261008/release-result.json` 为 **FAIL,不具备发布资格**。static 和 full-local 的前 11 个阶段通过,服务端单测 4480 通过、1 项原有跳过;网页 370/372 通过、2 失败、0 跳过、0 重试。默认关闭的 7 个可选服务端专项不计通过。上一轮失败的审批按钮用例已在本轮完整回归中通过。 +- 两个新增失败来自既有测试:`r92-mobile-invoice-usability.spec.ts:335` 的宽泛文字定位同时命中标题与“加载票据详情…”提示,上传步骤尚未执行;`system-action-confirmation.spec.ts:835` 顺序读取动画中两个按钮的位置,中心差约 3.69px,超过原有 2px 上限。此次候选仅改动另一份审批测试及记录,没有直接修改这两个用例或业务页面。 +- 本轮仅局部修正两份测试:票据标题改用精确的 heading 定位;两个布局坐标改为同一次浏览器执行读取。保留中心差小于 2px、按钮顺序、侧栏宽度和批量上传计数等原有断言,不修改业务代码、不增大容差或跳过用例。 +- [x] 官方受管 `retained-local` 验证这两个完整文件:61/61 通过、0 跳过、0 重试,包含原失败用例、批量上传计数及 1280/1440/1920 布局断言;运行中源码/仓库未变,环境和自有容器/运行目录清理通过。结果位于 `artifacts/qa-flow/loan-gate-followup-1dd84065-20261008/`,不替代两轮正式失败回执。 +- 定向入口:`QA_FULL_REPORT_DIR=artifacts/qa-flow/loan-gate-followup-1dd84065-20261008 QA_RETAINED_SPECS='r92-mobile-invoice-usability.spec.ts system-action-confirmation.spec.ts' bash scripts/qa/run-web-gates.sh retained-local`;另显式指定本轮专用浏览器副本和受控 BIFF8 Python。任务校验、治理、流程合同及 `git diff --check` 通过。 +- 正式运行全程源码/仓库未变,隔离容器及运行目录清理通过。新修正与本记录尚未提交,后续仍需固定新的已提交候选重跑正式门禁;真实建行材料、人员核实和独立业务验收继续待完成。 + ## 2026-10-08 正式本地发布门禁及测量时序修正 用户同意对固定干净候选 `7a48a1e7` 运行正式本地门禁;执行 `bash scripts/qa/run-release-gate.sh verify-candidate`,未推送、部署、查询生产或执行远端备份切换。专用浏览器经官方安装及受控复制,Chromium/WebKit 原生隔离检查通过。原始回执保留在 `artifacts/release-gate/loan-7a48a1e7-20261008/release-result.json`,结论 **FAIL,不具备发布资格**,不以针对性重验覆盖它。 diff --git a/client/tests/e2e/r92-mobile-invoice-usability.spec.ts b/client/tests/e2e/r92-mobile-invoice-usability.spec.ts index 9e865db7..511e23bd 100644 --- a/client/tests/e2e/r92-mobile-invoice-usability.spec.ts +++ b/client/tests/e2e/r92-mobile-invoice-usability.spec.ts @@ -332,7 +332,7 @@ test.describe("R92 手机端票据与报销可用性", () => { await expect(page.getByTestId("invoice-pool-table")).toBeHidden(); await page.getByTestId("invoice-mobile-detail-button").click(); await expect(page.getByTestId("invoice-detail-panel")).toBeVisible(); - await expect(page.getByText("票据详情")).toBeVisible(); + await expect(page.getByRole("heading", { name: "票据详情", exact: true })).toBeVisible(); await attachScreenshot(page, testInfo, "r97-invoice-pool-mobile.png"); await page.goto("/invoice-pool"); diff --git a/client/tests/e2e/system-action-confirmation.spec.ts b/client/tests/e2e/system-action-confirmation.spec.ts index 068b7ac1..3da35f4b 100644 --- a/client/tests/e2e/system-action-confirmation.spec.ts +++ b/client/tests/e2e/system-action-confirmation.spec.ts @@ -830,8 +830,14 @@ test.describe("报销付款交接一致性", () => { } widths.push((await panel.locator("../..").boundingBox())!.width); const row = panel.getByTestId("detail-inline-actions"); - const primary = await row.locator("a, button").first().boundingBox(); - const more = await row.getByRole("button", { name: "更多", exact: true }).boundingBox(); + const measuredActions = row.locator("a, button").first() + .or(row.getByRole("button", { name: "更多", exact: true })); + await expect(measuredActions).toHaveCount(2); + // Both positions must come from the same animation frame. + const [primary, more] = await measuredActions.evaluateAll((elements) => elements.map((element) => { + const { x, y, width, height } = element.getBoundingClientRect(); + return { x, y, width, height }; + })); expect(Math.abs(primary!.y + primary!.height / 2 - more!.y - more!.height / 2)).toBeLessThan(2); expect(more!.x).toBeGreaterThan(primary!.x + primary!.width); await row.getByRole("button", { name: "更多", exact: true }).click();