80 lines
3.3 KiB
TypeScript
80 lines
3.3 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { blockCodes, toBlockViews } from './blockView'
|
|
import { blockReplacement, commonIndent, reindentBlock, replaceLines } from './editText'
|
|
import { createPythonAdapter } from './languages/python'
|
|
import { createTypeScriptAdapter } from './languages/typescript'
|
|
import { readFixture, WASM_DIR, withBlocks } from './testSupport'
|
|
|
|
describe('行替换', () => {
|
|
it('多行块替换后每个非空行补回原来的缩进,空行保持空', () => {
|
|
const source = [
|
|
'function f() {',
|
|
' if (a)',
|
|
' return 1',
|
|
'}',
|
|
].join('\n')
|
|
const edited = replaceLines(source, 1, 2, 'if (a && b) {\n\n return 2\n}')
|
|
expect(edited).toBe([
|
|
'function f() {',
|
|
' if (a && b) {',
|
|
'',
|
|
' return 2',
|
|
' }',
|
|
'}',
|
|
].join('\n'))
|
|
})
|
|
|
|
it('保留 \\r\\n 换行', () => {
|
|
expect(replaceLines('a\r\n b\r\n c\r\n', 1, 1, 'x\ny')).toBe('a\r\n x\r\n y\r\n c\r\n')
|
|
})
|
|
|
|
it('共同缩进逐字符比,混用制表符和空格时只取相同的前缀', () => {
|
|
expect(commonIndent(['\t a', '', '\t b'])).toBe('\t ')
|
|
expect(commonIndent(['\ta', ' b'])).toBe('')
|
|
expect(reindentBlock([' x'], 'a\n b')).toBe(' a\n b')
|
|
})
|
|
|
|
it.each([
|
|
[createTypeScriptAdapter(WASM_DIR), 'typescript', 'envLock.ts.txt'],
|
|
[createTypeScriptAdapter(WASM_DIR), 'typescript', 'issueLock.ts.txt'],
|
|
[createTypeScriptAdapter(WASM_DIR), 'typescript', 'classes.ts.txt'],
|
|
[createPythonAdapter(WASM_DIR), 'python', 'sample.py'],
|
|
[createPythonAdapter(WASM_DIR), 'python', 'routes.py'],
|
|
[createPythonAdapter(WASM_DIR), 'python', 'classes.py'],
|
|
] as const)('%#: 把预览里的 code 原样写回,文件不变(去缩进与补缩进互逆,函数、类头部连着说明也一样)', async (adapter, languageId, fixture) => {
|
|
const source = readFixture(fixture)
|
|
const views = await withBlocks(adapter, languageId, source, blocks => toBlockViews(blocks, { source, language: adapter, markers: [] }, undefined))
|
|
const all = views.flatMap(function flat(view): typeof views {
|
|
return [view, ...view.children.flatMap(flat)]
|
|
})
|
|
for (const view of all)
|
|
expect(replaceLines(source, view.startLine, view.endLine, blockCodes(source)(view)), view.id).toBe(source)
|
|
})
|
|
})
|
|
|
|
describe('块内修改写回的替换范围', () => {
|
|
const doc = ['class A {', ' run() {', ' go()', ' }', '}']
|
|
const lineAt = (n: number): string => doc[n]
|
|
|
|
it('从起始行行首替换到结束行行尾,新文本补回原来的缩进', () => {
|
|
expect(blockReplacement(lineAt, doc.length, 1, 2, 'run(): void {\n go(1)')).toEqual({
|
|
startLine: 1,
|
|
endLine: 2,
|
|
endCharacter: 8,
|
|
text: ' run(): void {\n go(1)',
|
|
unchanged: false,
|
|
})
|
|
})
|
|
|
|
it('改完和原来一样时标记 unchanged', () => {
|
|
expect(blockReplacement(lineAt, doc.length, 1, 2, 'run() {\n go()')?.unchanged).toBe(true)
|
|
})
|
|
|
|
it('行号已不在文档里时不替换', () => {
|
|
expect(blockReplacement(lineAt, doc.length, 3, 5, 'x')).toBeUndefined()
|
|
expect(blockReplacement(lineAt, doc.length, -1, 0, 'x')).toBeUndefined()
|
|
expect(blockReplacement(lineAt, doc.length, 2, 1, 'x')).toBeUndefined()
|
|
expect(blockReplacement(lineAt, doc.length, 0.5, 1, 'x')).toBeUndefined()
|
|
})
|
|
})
|