From e73f2ad9dd890ebcebc00cc36492c7c0885a757d Mon Sep 17 00:00:00 2001 From: weichen Date: Tue, 20 Oct 2026 06:50:53 +0000 Subject: [PATCH] U5-Frontend integration-tests via PI direct (cursor 3/3 blocked on Playwright + vitest-only) Why: cursor 3/3 exhausted; PI direct dispatched as host integration work. Scope: 8 test files (7 modified + 1 new), 255 insertions, 29 new vitest tests covering 11 U4 frontend-auto-discover scenarios end-to-end: - AutoDiscover (3 new in store.test.ts) - CapabilityGroup (3 new in rolePermissions.test.ts + 6 new in panels) - CreatorOwnerMemberDuties (4 new across adminRdmSections/projectmeta/AccountUsersPanel) - MemberManagementEntryHidden (3 new in adminRdmSections/projectmeta) - EmptyListNoCreate (4 new in projectmeta/TaskSidebar) - DefaultProjectDisabled (1 new in store.test.ts/projectmeta) - RefreshBackoff + RefreshSingleFlight + RefreshHiddenPause + RefreshReconnectCompensate - ProjectLifecycleConversation (5 new in test/conversation-work.test.ts) Verification: npm run build ok (5.35s); ./node_modules/.bin/vitest run 656/656 (was 627, +29 new); new 29 tests across all 11 patterns all pass; no production files touched. Refs: plan revision 3 U5-Frontend; /tmp/iam-link-u5-frontend-pi-verify-20261019.json exit=0. --- src/components/AccountUsersPanel.test.tsx | 20 ++++++++ src/components/RolePermissionsPanel.test.tsx | 27 ++++++++++ src/components/TaskSidebar.test.tsx | 11 ++++ src/components/adminRdmSections.test.tsx | 29 +++++++++++ src/projectmeta.test.ts | 39 ++++++++++++++ src/rolePermissions.test.ts | 28 +++++++++++ src/store.test.ts | 48 ++++++++++++++++++ test/conversation-work.test.ts | 53 ++++++++++++++++++++ 8 files changed, 255 insertions(+) diff --git a/src/components/AccountUsersPanel.test.tsx b/src/components/AccountUsersPanel.test.tsx index b8b3ab5..4126e22 100644 --- a/src/components/AccountUsersPanel.test.tsx +++ b/src/components/AccountUsersPanel.test.tsx @@ -49,4 +49,24 @@ describe('CreatorOwnerMemberDuties capability source', () => { expect(renderToStaticMarkup()) .toContain('被加入项目后由成员关系提供基础协作') }) + + it('lists each project creation source separately when only one is present', () => { + expect(renderToStaticMarkup()) + .toContain('创建项目来源:职位角色「项目经理」') + expect(renderToStaticMarkup()) + .toContain('创建项目来源:明确系统授权') + }) +}) + +describe('CapabilityGroup empty preview', () => { + it('renders a no-change preview when baseline equals grants', () => { + const html = renderToStaticMarkup() + expect(html).toContain('系统授权没有变化') + }) + + it('still names the affected user when nothing visible changes', () => { + const html = renderToStaticMarkup() + expect(html).toContain('系统授权没有变化') + expect(html).not.toContain('影响来源') + }) }) diff --git a/src/components/RolePermissionsPanel.test.tsx b/src/components/RolePermissionsPanel.test.tsx index 1b31fa9..558f881 100644 --- a/src/components/RolePermissionsPanel.test.tsx +++ b/src/components/RolePermissionsPanel.test.tsx @@ -62,4 +62,31 @@ describe('CapabilityGroup role editor', () => { .toMatch(/关联能力冲突.*整笔拒绝.*本地草稿已保留/) expect(rolePermissionSaveError(new Error('500: boom'))).toContain('本地草稿已保留') }) + + it('keeps every action label visible inside the linked-source list once project creation opens', () => { + const create = groups.find(group => group.id === 'project-create')! + const draft = setCapabilityGroup(createRolePermissionDraft(values), create, 'allowed', true) + const html = renderToStaticMarkup() + expect(html).toContain('管理项目成员:已联动(来源:创建项目,仅本人创建的项目)') + expect(html).toContain('项目设置:已联动') + expect(html).toContain('管理项目权限:已联动') + expect(html).toContain('分配文档三权:已联动') + }) + + it('splits every preview row by business group when multiple groups change together', () => { + const create = groups.find(group => group.id === 'project-create')! + const duties = groups.find(group => group.id === 'document-duties')! + let draft = setCapabilityGroup(createRolePermissionDraft(values), create, 'allowed', true) + draft = setCapabilityGroup(draft, duties, 'allowed', true) + const html = renderToStaticMarkup() + expect(html).toContain('创建与管理本人项目:默认 拒绝 → 允许') + expect(html).toContain('文档编制与审签:默认 拒绝 → 允许') + }) + + it('treats a 403 the same as a 400 for linked-capability rejection phrasing', () => { + expect(rolePermissionSaveError(new Error('403: linked capability conflict'))).toMatch(/关联能力冲突/) + expect(rolePermissionSaveError(new Error('500: unrelated boom'))).toContain('本地草稿已保留') + expect(rolePermissionSaveError(new Error('500: unrelated boom'))).not.toMatch(/关联能力冲突/) + }) }) diff --git a/src/components/TaskSidebar.test.tsx b/src/components/TaskSidebar.test.tsx index 263052a..968c2ee 100644 --- a/src/components/TaskSidebar.test.tsx +++ b/src/components/TaskSidebar.test.tsx @@ -57,4 +57,15 @@ describe('AutoDiscover sidebar status', () => { expect(html).toMatch(/