104 lines
4.1 KiB
TypeScript
104 lines
4.1 KiB
TypeScript
import type { BlockConcept, KindIconName } from './types'
|
|
import { renderToStaticMarkup } from 'react-dom/server'
|
|
import { describe, expect, it } from 'vitest'
|
|
import { KIND_ICONS } from '../../../src/codeReader/contract'
|
|
import { KIND_ICON_COMPONENTS, KindIcon } from './kindIcons'
|
|
|
|
function render(concepts: readonly BlockConcept[]): string {
|
|
return renderToStaticMarkup(<KindIcon concepts={concepts} />)
|
|
}
|
|
|
|
function concept(id: string, label: string, icon: KindIconName, color?: BlockConcept['color']): BlockConcept {
|
|
return { id, label, icon, ...(color && { color }) }
|
|
}
|
|
|
|
/** 标签之间的字:图标(svg)没有字 */
|
|
const visibleText = (html: string): string => html.replace(/<[^>]*>/g, '').trim()
|
|
|
|
describe('块的种类图标', () => {
|
|
it('内置种类各有一个图标,和原型的一一对应', () => {
|
|
expect(KIND_ICONS).toEqual({
|
|
import: 'import',
|
|
function: 'square-function',
|
|
class: 'box',
|
|
trait: 'network',
|
|
impl: 'square-function',
|
|
module: 'layers',
|
|
attribute: 'sliders-horizontal',
|
|
type: 'braces',
|
|
interface: 'braces',
|
|
enum: 'list-ordered',
|
|
exception: 'triangle-alert',
|
|
field: 'tag',
|
|
const: 'lock',
|
|
variable: 'variable',
|
|
if: 'split',
|
|
else: 'corner-down-right',
|
|
loop: 'repeat',
|
|
try: 'shield',
|
|
catch: 'shield-alert',
|
|
finally: 'shield-check',
|
|
return: 'corner-down-left',
|
|
statement: 'code',
|
|
comment: 'message-square-text',
|
|
interpreter: 'terminal',
|
|
options: 'sliders-horizontal',
|
|
case: 'signpost',
|
|
command: 'square-terminal',
|
|
pipeline: 'square-terminal',
|
|
directive: 'terminal',
|
|
stage: 'layers',
|
|
run: 'square-terminal',
|
|
copy: 'copy',
|
|
setting: 'sliders-horizontal',
|
|
label: 'tag',
|
|
health: 'activity',
|
|
start: 'play',
|
|
})
|
|
})
|
|
|
|
it('这组图标里每个名字画的就是 lucide 里同名的图标', () => {
|
|
// 名字里带数字的图标 lucide 另加一个按组件名起的类(share-2 的 lucide-share2),同名的那个类排在最后
|
|
for (const name of Object.keys(KIND_ICON_COMPONENTS) as KindIconName[]) {
|
|
const html = render([concept(name, name, name)])
|
|
expect(html, name).toMatch(new RegExp(`class="lucide (?:[\\w-]+ )?lucide-${name}"`))
|
|
}
|
|
})
|
|
|
|
it('只画图标不带字,名字在悬停提示(data-tooltip,不用原生 title)里;读屏念这个名字;20px 的框、16px 的图形', () => {
|
|
const html = render([concept('function', '函数', 'square-function')])
|
|
expect(visibleText(html)).toBe('')
|
|
expect(html).toContain('role="img" aria-label="函数"')
|
|
expect(html).toContain('data-tooltip="函数"')
|
|
expect(html).toContain('data-kind="function"')
|
|
expect(html).not.toContain(' title=')
|
|
expect(html).toContain('lucide-square-function')
|
|
expect(html).toContain('width="16" height="16"')
|
|
expect(html).toContain('size-5')
|
|
})
|
|
|
|
it('认到几个就横排几个:悬停各自的名字,读屏把名字连起来念;规则的图标用规则给的颜色', () => {
|
|
const html = render([
|
|
concept('class', '类', 'box'),
|
|
concept('dataclasses.dataclass', '数据类', 'package', { dark: '#ef7fb0', light: '#b3306c' }),
|
|
concept('dataclasses.frozen', '不可修改', 'lock', { dark: '#9cdcfe', light: '#001080' }),
|
|
])
|
|
expect(visibleText(html)).toBe('')
|
|
expect(html).toContain('aria-label="类,数据类,不可修改"')
|
|
expect(html).toContain('data-tooltip="类"')
|
|
expect(html).toContain('data-tooltip="数据类"')
|
|
expect(html).toContain('data-tooltip="不可修改"')
|
|
expect(html).toContain('data-kind="class"')
|
|
expect(html).toContain('lucide-box')
|
|
expect(html).toContain('lucide-package')
|
|
expect(html).toContain('lucide-lock')
|
|
expect(html).toContain('--kind-dark:#ef7fb0')
|
|
expect(html).toContain('--kind-light:#b3306c')
|
|
expect(html).toContain('--kind-dark:#9cdcfe')
|
|
expect(html).toContain('--kind-light:#001080')
|
|
expect(html).not.toContain(' title=')
|
|
expect(html.match(/size-5/g)).toHaveLength(3)
|
|
expect(html).toContain('gap-0.5')
|
|
})
|
|
})
|