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')
})
})