import { describe, expect, it } from 'vitest'; import { render, screen } from '@testing-library/react'; import React from 'react'; import PermissionChip, { permissionModeHint, ENFORCEMENT_LABEL, } from '../../src/components/PermissionChip'; /** * 权限档位徽标。 * * 判据集中在「三个强制力必须可区分」——因为把它显示错的代价不对称: * - 高估(partial 显示成 native):人以为档位是硬保证,把它当安全边界依赖 * - 低估(partial 显示成 advisory):人以为平台完全不拦,在能依赖的边界上过度保守 * 这张徽标是这两个事实唯一的对外呈现,所以点形与文案都必须区分。 */ describe('PermissionChip 档位显示', () => { it('档位为空或非法时不渲染(人→人的信、旧会话)', () => { const { container: c1 } = render(React.createElement(PermissionChip, {})); expect(c1.firstChild).toBeNull(); const { container: c2 } = render(React.createElement(PermissionChip, { mode: 'nonsense' })); expect(c2.firstChild).toBeNull(); }); it('三个档位各有中文短标签', () => { for (const [mode, label] of [['plan', '只读'], ['workspace', '目录内'], ['full', '全权']]) { const { unmount } = render( React.createElement(PermissionChip, { mode, enforcement: 'native' }) ); expect(screen.getByText(label)).toBeInTheDocument(); unmount(); } }); }); describe('PermissionChip 强制力三态', () => { it('native 用实心点,不带 partial/advisory 的标记', () => { render(React.createElement(PermissionChip, { mode: 'plan', enforcement: 'native' })); expect(screen.queryByTestId('chip-partial')).toBeNull(); expect(screen.queryByTestId('chip-advisory')).toBeNull(); }); it('partial 渲染为靶心(与实心、空心都不同形)', () => { render(React.createElement(PermissionChip, { mode: 'plan', enforcement: 'partial' })); expect(screen.getByTestId('chip-partial')).toBeInTheDocument(); expect(screen.queryByTestId('chip-advisory')).toBeNull(); }); it('advisory 渲染为空心点', () => { render(React.createElement(PermissionChip, { mode: 'plan', enforcement: 'advisory' })); expect(screen.getByTestId('chip-advisory')).toBeInTheDocument(); expect(screen.queryByTestId('chip-partial')).toBeNull(); }); it('认不出的强制力按 advisory 处理(保守方向,与后端 Normalize 同语义)', () => { render(React.createElement(PermissionChip, { mode: 'plan', enforcement: 'PARTIAL' })); expect(screen.getByTestId('chip-advisory')).toBeInTheDocument(); expect(screen.queryByTestId('chip-partial')).toBeNull(); }); it('tooltip 里给出强制力的中文标签', () => { render(React.createElement(PermissionChip, { mode: 'workspace', enforcement: 'partial' })); const chip = screen.getByText('目录内').closest('span'); expect(chip?.getAttribute('title')).toContain(ENFORCEMENT_LABEL.partial); }); }); describe('permissionModeHint 三态文案', () => { it('三种强制力的说明两两不同', () => { for (const mode of ['plan', 'workspace']) { const nat = permissionModeHint(mode, 'native'); const par = permissionModeHint(mode, 'partial'); const adv = permissionModeHint(mode, 'advisory'); expect(par).not.toBe(nat); expect(par).not.toBe(adv); } }); it('partial 必须说明覆盖不完整,且不能说「平台不强制」', () => { for (const mode of ['plan', 'workspace']) { const par = permissionModeHint(mode, 'partial'); // 「不完整」或「缺口」必须出现:否则人无法知道拦截不可完全依赖 expect(par).toMatch(/不完整|缺口/); // 「平台不强制」是 advisory 的说法,对 partial 是假话 expect(par).not.toMatch(/平台不强制/); } }); it('advisory 仍明说平台不强制', () => { expect(permissionModeHint('plan', 'advisory')).toMatch(/平台不强制/); expect(permissionModeHint('workspace', 'advisory')).toMatch(/平台不强制/); }); it('full 档不提强制力差异(全权档本来就不需要授权)', () => { for (const e of ['native', 'partial', 'advisory']) { expect(permissionModeHint('full', e)).toMatch(/全权/); } }); });