// RDM 角色权限面板拒绝态(2026-10-13 8788 dev 锁死复现):rdm.role.list 被拒后 // 表格停留「加载中…」且错误为原始 400 JSON——测纯函数两件事:占位行不再假装 // 加载中;域管理员权限拒绝映射为人话 + 恢复通道。UI 不重算权限(KTD5),文案 // 只描述拒绝事实,不判权限。 import { describe, expect, it } from 'vitest' import { rolesListPlaceholder, describeRoleListError } from '../src/rdmManagement' describe('rolesListPlaceholder', () => { it('keeps 加载中 only while loading without error', () => { expect(rolesListPlaceholder(null, '')).toBe('加载中…') }) it('replaces the loading row with a failure row once the fetch rejected', () => { expect(rolesListPlaceholder(null, 'Error: 400: {"receipt":…}')).toBe('角色清单未加载(见下方提示)') }) it('returns the empty label for an empty list and nothing otherwise', () => { expect(rolesListPlaceholder([], '')).toBe('暂无专业角色') expect(rolesListPlaceholder([{ roleId: 'r1' }], '')).toBe('') // 已有数据时即便残留 err 也不再渲染占位行(表格有内容即事实来源) expect(rolesListPlaceholder([{ roleId: 'r1' }], 'stale')).toBe('') }) }) describe('describeRoleListError', () => { const denied = 'Error: 400: {"receipt":{"commandId":"rdm.role.list","state":"rejected",' + '"reason":"rejected: 权限拒绝:weichen 不是系统管理员(全局动作 project.settings)"}}' it('maps the domain-admin denial to a readable message with the transfer channel', () => { const got = describeRoleListError(denied) expect(got).toContain('不是 RDM 域管理员') expect(got).toContain('rdm.perm.transfer') expect(got).not.toContain('"receipt"') }) it('passes other errors through untouched', () => { expect(describeRoleListError('Error: 500: boom')).toBe('Error: 500: boom') }) })