import type { Inline, ShownName, WebviewToExtension } from './types' import { renderToStaticMarkup } from 'react-dom/server' import { describe, expect, it, vi } from 'vitest' import { acceptNames, DisplayNameContext, documentNames, nameMap, shownName } from './displayNames' import { OccurrenceHighlight } from './occurrences' import { SegmentText } from './SegmentText' // 高亮的上下文所在的模块连着和 VS Code 收发消息的那一套,渲染成 HTML 用不着 vi.mock('./useOccurrences', async () => { const { createContext } = await import('react') return { HighlightContext: createContext(undefined) } }) const CURRENT_USER: ShownName = { offset: 40, length: 12, name: '当前用户', definition: true } const USE: ShownName = { offset: 90, length: 12, name: '当前用户' } const ADMIN: ShownName = { offset: 130, length: 5, name: '管理员' } function render(segments: Inline[], names: ShownName[]): string { return renderToStaticMarkup( , ) } describe('页面上的中文名', () => { it('收到新文档换成它带来的;查到的是页面上这个版本的才换上,迟到的旧版本不理', () => { const current = documentNames(3, [USE]) expect([...current.names.values()]).toEqual([USE]) expect(acceptNames(current, 2, [ADMIN])).toBe(current) expect([...acceptNames(current, 3, [USE, ADMIN])!.names.values()]).toEqual([USE, ADMIN]) expect(acceptNames(undefined, 3, [ADMIN])).toBeUndefined() }) it('只认下标和长度都对得上的名字:没下标的译词、长度不一样的(名字改长了)不换', () => { const names = nameMap([USE]) expect(shownName({ text: 'current_user', role: 'variable', offset: 90 }, names)).toBe(USE) expect(shownName({ text: 'current_userx', role: 'variable', offset: 90 }, names)).toBeUndefined() expect(shownName({ text: 'current_user', role: 'variable' }, names)).toBeUndefined() expect(shownName({ text: 'current_user', role: 'variable', offset: 91 }, names)).toBeUndefined() }) it('用到的地方显示中文名,悬停写「原名 x」,下标照旧(⌘ 点击跳到定义、单击高亮都认它)', () => { const html = render([ { text: '如果', role: 'keyword' }, { text: ' ', role: 'plain' }, { text: 'current_user', role: 'variable', offset: 90 }, { text: '.', role: 'plain' }, { text: 'role', role: 'variable', offset: 103 }, { text: ' 不等于 ', role: 'operator' }, { text: 'UserRole', role: 'variable', offset: 120 }, { text: '.', role: 'plain' }, { text: 'ADMIN', role: 'variable', offset: 130 }, ], [USE, ADMIN]) expect(html.replace(/<[^>]*>/g, '')).toBe('如果 当前用户.role 不等于 UserRole.管理员') expect(html).toContain('当前用户') expect(html).toContain('role') expect(html).not.toContain('cr-original') }) it('定义处本身(名称格子、名称行):中文名后面跟着淡淡的原名;框里的名字同样换', () => { const html = render([ { text: 'current_user', role: 'variable', offset: 40 }, { style: 'iteration', label: '列表', segments: [{ text: 'ADMIN', role: 'variable', offset: 130 }] }, ], [CURRENT_USER, ADMIN]) expect(html).toContain('data-offset="40" data-name="当前用户" data-tooltip="原名 current_user">当前用户current_user') expect(html).toContain('data-offset="130" data-name="管理员" data-tooltip="原名 ADMIN">管理员') }) it('单击显示成中文名的名字:筛选栏写中文名,当前那一处按点中的下标认', () => { const sent: WebviewToExtension[] = [] let shown: string | undefined const highlight = new OccurrenceHighlight(msg => sent.push(msg), next => shown = next && `${next.name} ${next.current}`) highlight.setDocument(1, 'zh') highlight.click({ kind: 'find', offset: 90, name: '当前用户' }) const asked = sent.at(-1) expect(asked).toMatchObject({ type: 'findOccurrences', offset: 90 }) highlight.answer(asked?.type === 'findOccurrences' ? asked.id : -1, [{ start: 40, end: 52, kind: 'write' }, { start: 90, end: 102, kind: 'read' }]) expect(shown).toBe('当前用户 1') }) })