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(/