From 9a8b7477b67bcd9f36858a07491f7b075b011887 Mon Sep 17 00:00:00 2001 From: shunli Date: Thu, 16 Jul 2026 16:46:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B8=85=E7=90=86=E6=97=A7=20Portal=20?= =?UTF-8?q?=E5=AF=BC=E8=88=AA=E5=85=BC=E5=AE=B9=EF=BC=8807-16-legacy-porta?= =?UTF-8?q?l-navigation-compat-cleanup=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .trellis/spec/hyb-oa/deployment-trialrun.md | 49 ++++++++++--------- .../e2e/oafront3-pc-readonly-visual.spec.ts | 2 - 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/.trellis/spec/hyb-oa/deployment-trialrun.md b/.trellis/spec/hyb-oa/deployment-trialrun.md index 3355202e..25208e06 100644 --- a/.trellis/spec/hyb-oa/deployment-trialrun.md +++ b/.trellis/spec/hyb-oa/deployment-trialrun.md @@ -90,8 +90,8 @@ SYNC_ENV=0 bash deploy/trialrun/deploy.sh ### 1. Scope / Trigger -- Trigger: frontend shell, navigation labels, sidebar grouping, Portal/workbench - copy, or live smoke assertions change. +- Trigger: frontend shell, navigation labels, sidebar grouping, workbench copy, + or live smoke assertions change. - Purpose: prevent public deployment from being marked failed only because smoke tests look for stale navigation copy while the page itself is healthy. @@ -102,45 +102,48 @@ SYNC_ENV=0 bash deploy/trialrun/deploy.sh - Shared assertions: `client/tests/e2e/helpers/smokeAssertions.ts` - Workbench route: `/portal` - Current primary workbench nav label: `工作台` -- Historical nav label still allowed in mocks or older fixtures: `Portal` +- Stale user-facing label that must not be accepted by current mocks or smoke: + `Portal` ### 3. Contracts - `assertPortalLoaded(page)` must assert route and page content first: `/portal` URL and the `今日待处理` heading. -- Navigation-label assertions for the workbench link must accept both `工作台` - and `Portal` while older mocks still use English labels. +- Navigation-label assertions for the workbench link must require the exact + current label `工作台`; mocks and fixtures must use the same contract. - Navigation assertions must be role-aware. Admin/manager smoke may assert team/admin entries such as `团队`, but ordinary employee smoke must not require links that `NavLinks` intentionally hides for that role. - Smoke tests must not require a copy string that is not a product contract for public availability. -- If the product intentionally renames the primary workbench label again, update - the shared smoke helper rather than duplicating route-specific assertions in - each live smoke test. +- If the product intentionally renames the primary workbench label again, + update the product contract, fixtures and shared smoke helper together rather + than adding an ad hoc fallback in one live smoke test. ### 4. Validation & Error Matrix - Page reaches `/portal`, `今日待处理` is visible, but nav label is `工作台` -> smoke should pass. +- Page reaches `/portal` and renders `Portal` as the user-facing nav label -> + smoke should fail as a stale-copy regression. - Employee reaches `/portal`, role-aware navigation hides `团队`, and employee pages such as `项目` remain reachable -> smoke should pass. - Page reaches `/portal`, but `今日待处理` is missing -> smoke should fail. - Page stays on login, `/403`, error fallback or another route -> smoke should fail. -- New shell label appears only in one live smoke test -> move the compatibility - logic into `smokeAssertions.ts`. +- New shell label appears only in one live smoke test -> stop and align the + product contract, fixtures and shared helper before changing smoke. ### 5. Good/Base/Bad Cases -- Good: `assertPortalLoaded` checks `/portal`, `今日待处理`, and a workbench link - matching either `工作台` or `Portal`. +- Good: `assertPortalLoaded` checks `/portal`, `今日待处理`, and an exact + `工作台` workbench link. - Good: `assertMainNavVisible(page, { expectTeam: false })` is used for ordinary employee live smoke. -- Base: mocked E2E fixtures may still emit `Portal`; live public navigation may - emit `工作台`. -- Bad: live smoke hard-codes only `Portal` and blocks deployment after a valid - Chinese navigation rollout. +- Base: the internal route and helper name may retain `portal`, while all + user-facing navigation fixtures and assertions use `工作台`. +- Bad: a mock emits `Portal` and smoke accepts it as a valid current label, + masking a user-facing English-copy regression. - Bad: employee live smoke requires the `团队` sidebar link after role-aware navigation intentionally hides it. @@ -148,6 +151,8 @@ SYNC_ENV=0 bash deploy/trialrun/deploy.sh - After changing live smoke assertions, run: `cd client && npm run typecheck` +- Load the focused visual and shell specs with Playwright `--list` when changing + fixture/report contracts. - For public deploy verification, run live smoke or the readiness wrapper: `LIVE_SMOKE_BASE_URL=https://oa.hyinda.com bash scripts/qa/run-live-smoke-readiness.sh` - When changing the shell or Portal page, include a focused Playwright check @@ -158,17 +163,17 @@ SYNC_ENV=0 bash deploy/trialrun/deploy.sh #### Wrong ```ts -await expect(page.getByRole("link", { name: "Portal" }).first()).toBeVisible(); +await expect( + page.getByRole("link", { name: "工作台", exact: true }) + .or(page.getByRole("link", { name: "Portal", exact: true })) + .first(), +).toBeVisible(); ``` #### Correct ```ts -await expect( - page.getByRole("link", { name: "工作台", exact: true }) - .or(page.getByRole("link", { name: "Portal", exact: true })) - .first(), - ).toBeVisible(); +await expect(page.getByRole("link", { name: "工作台", exact: true }).first()).toBeVisible(); ``` ## Scenario: Trial Run Runtime Navigation Baseline diff --git a/client/tests/e2e/oafront3-pc-readonly-visual.spec.ts b/client/tests/e2e/oafront3-pc-readonly-visual.spec.ts index e174a39d..b84f6f51 100644 --- a/client/tests/e2e/oafront3-pc-readonly-visual.spec.ts +++ b/client/tests/e2e/oafront3-pc-readonly-visual.spec.ts @@ -250,7 +250,6 @@ async function readMetrics(page: Page) { clippedControls, forbiddenLike: forbiddenPage, appErrorLike: text.includes("页面加载失败") || text.includes("加载失败") || text.includes("出错了"), - navPortalCopy: text.includes("Portal"), }; }, ENGLISH_PRIMARY_TERMS); } @@ -413,7 +412,6 @@ async function auditRoute(page: Page, plan: RoutePlan) { clippedCount: metrics.clippedControls.length, forbiddenLike: metrics.forbiddenLike, appErrorLike: metrics.appErrorLike, - navPortalCopy: metrics.navPortalCopy, }, }); }