import type { WrittenBlock } from './testBlocks' import type { BlockView } from './types' import { describe, expect, it } from 'vitest' import { coveredByEditing, startEditing } from './editing' import { placementOf } from './placement' import { revealPlan, uncoveredPlan } from './reveal' import { placed } from './testBlocks' function block(id: string, kind: string, lines: [number, number], children: WrittenBlock[] = []): WrittenBlock { return { id, anchor: id, kind, lines, attributes: { kind }, concepts: [{ id: kind, label: kind, icon: 'box' }], children, properties: [] } } /** * 编辑范围是块的完整源码:库规则的卡片(1)是整个类(2–12 行),两个字段中间写着的方法(1.0)和它的主体(1.0.0)、 * 类末尾的方法(1.1)都在这段里;普通的类(2)同样盖住它的方法(2.0);`} else {` 写在一行时 if(3)和 else(4)共用第 20 行。 */ const BLOCKS = placed([ block('0', 'import', [0, 0]), block('1', 'sqlalchemy.table', [2, 12], [ block('1.0', 'function', [5, 6], [block('1.0.0', 'return', [6, 6])]), block('1.1', 'function', [11, 12]), ]), block('2', 'class', [14, 16], [block('2.0', 'function', [15, 16])]), block('3', 'if', [18, 20], [block('3.0', 'return', [19, 19])]), block('4', 'else', [20, 22], [block('4.0', 'return', [21, 21])]), ]) const PLACEMENT = placementOf(BLOCKS) describe('同一行不会同时在两处能改', () => { it('块编辑时它的子孙都不画(代码都在它的编辑框里),跳到它们时改闪它', () => { expect(coveredByEditing(BLOCKS, new Set(['1']))).toEqual(new Map([['1.0', '1'], ['1.0.0', '1'], ['1.1', '1']])) expect(coveredByEditing(BLOCKS, new Set(['2']))).toEqual(new Map([['2.0', '2']])) }) it('子块编辑时只盖住它自己的子孙,父块、兄弟块照常画', () => { expect(coveredByEditing(BLOCKS, new Set(['1.0']))).toEqual(new Map([['1.0.0', '1.0']])) expect(coveredByEditing(BLOCKS, new Set(['1.1', '3']))).toEqual(new Map([['3.0', '3']])) }) it('祖先和子孙都记着在编辑时(文档刷新前的状态),算页面上画着的最外层那块', () => { expect(coveredByEditing(BLOCKS, new Set(['1', '1.0']))).toEqual(new Map([['1.0', '1'], ['1.0.0', '1'], ['1.1', '1']])) }) it('点「编辑」:编辑范围和它重叠的别的块(祖先、子孙、共用一行的兄弟块)退出编辑,不重叠的留着', () => { expect(startEditing(PLACEMENT, ['1.0', '1.1', '2'], '1')).toEqual(['2', '1']) expect(startEditing(PLACEMENT, ['1', '2'], '1.0')).toEqual(['2', '1.0']) expect(startEditing(PLACEMENT, ['2'], '2.0')).toEqual(['2.0']) expect(startEditing(PLACEMENT, ['0', '3'], '4')).toEqual(['0', '4']) }) it('任何时候正在编辑、画出来的几块,编辑范围两两不重叠', () => { const all = (list: BlockView[]): BlockView[] => list.flatMap(item => [item, ...all(item.children)]) let editing: string[] = [] for (const id of ['1.0', '1.0.0', '2', '2.0', '1', '3.0', '3', '4', '1.1']) editing = startEditing(PLACEMENT, editing, id) const covered = coveredByEditing(BLOCKS, new Set(editing)) const shown = all(BLOCKS).filter(item => editing.includes(item.id) && !covered.has(item.id)) for (const a of shown) { for (const b of shown.filter(other => other !== a)) { const [x, y] = [PLACEMENT.of(a.id)!, PLACEMENT.of(b.id)!] expect(x.line > y.endLine || y.line > x.endLine, `${a.id} / ${b.id}`).toBe(true) } } }) it('跳到定义的目标被盖住:闪盖住它的那块,展开那块的祖先', () => { const covered = coveredByEditing(BLOCKS, new Set(['1'])) expect(uncoveredPlan({ id: '1.0.0', expand: ['1', '1.0'] }, covered)).toEqual({ id: '1', expand: [] }) const plain = revealPlan(BLOCKS, PLACEMENT, 15, 999) expect(plain && uncoveredPlan(plain, covered)).toEqual(plain) }) })