-
-
Notifications
You must be signed in to change notification settings - Fork 65
/
diff.test.js
113 lines (108 loc) · 5.02 KB
/
diff.test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import { simpleDiffString, simpleDiffArray, simpleDiffStringWithCursor } from './diff.js'
import * as prng from './prng.js'
import * as f from './function.js'
import * as t from './testing.js'
import * as str from './string.js'
/**
* @param {string} a
* @param {string} b
* @param {{index: number,remove:number,insert:string}} expected
*/
function runDiffTest (a, b, expected) {
const result = simpleDiffString(a, b)
t.compare(result, expected)
t.compare(result, simpleDiffStringWithCursor(a, b, a.length)) // check that the withCursor approach returns the same result
const recomposed = str.splice(a, result.index, result.remove, result.insert)
t.compareStrings(recomposed, b)
const arrResult = simpleDiffArray(Array.from(a), Array.from(b))
const arrRecomposed = Array.from(a)
arrRecomposed.splice(arrResult.index, arrResult.remove, ...arrResult.insert)
t.compareStrings(arrRecomposed.join(''), b)
}
/**
* @param {t.TestCase} tc
*/
export const testDiffing = tc => {
runDiffTest('abc', 'axc', { index: 1, remove: 1, insert: 'x' })
runDiffTest('bc', 'xc', { index: 0, remove: 1, insert: 'x' })
runDiffTest('ab', 'ax', { index: 1, remove: 1, insert: 'x' })
runDiffTest('b', 'x', { index: 0, remove: 1, insert: 'x' })
runDiffTest('', 'abc', { index: 0, remove: 0, insert: 'abc' })
runDiffTest('abc', 'xyz', { index: 0, remove: 3, insert: 'xyz' })
runDiffTest('axz', 'au', { index: 1, remove: 2, insert: 'u' })
runDiffTest('ax', 'axy', { index: 2, remove: 0, insert: 'y' })
// These strings share high-surrogate characters
runDiffTest('\u{d83d}\u{dc77}'/* '👷' */, '\u{d83d}\u{dea7}\u{d83d}\u{dc77}'/* '🚧👷' */, { index: 0, remove: 0, insert: '🚧' })
runDiffTest('\u{d83d}\u{dea7}\u{d83d}\u{dc77}'/* '🚧👷' */, '\u{d83d}\u{dc77}'/* '👷' */, { index: 0, remove: 2, insert: '' })
// These strings share low-surrogate characters
runDiffTest('\u{d83d}\u{dfe6}\u{d83d}\u{dfe6}'/* '🟦🟦' */, '\u{d83c}\u{dfe6}\u{d83d}\u{dfe6}'/* '🏦🟦' */, { index: 0, remove: 2, insert: '🏦' })
// check 4-character unicode symbols
runDiffTest('🇦🇨', '🇦🇩', { index: 2, remove: 2, insert: '🇩' })
runDiffTest('a🇧🇩', '🇦🇩', { index: 0, remove: 3, insert: '🇦' })
}
/**
* @param {t.TestCase} tc
*/
export const testRepeatDiffing = tc => {
const a = prng.word(tc.prng)
const b = prng.word(tc.prng)
const change = simpleDiffString(a, b)
const recomposed = str.splice(a, change.index, change.remove, change.insert)
t.compareStrings(recomposed, b)
}
/**
* @param {t.TestCase} tc
*/
export const testSimpleDiffWithCursor = tc => {
const initial = 'Hello WorldHello World'
const expected = 'Hello World'
{
const change = simpleDiffStringWithCursor(initial, 'Hello World', 0) // should delete the first hello world
t.compare(change, { insert: '', remove: 11, index: 0 })
const recomposed = str.splice(initial, change.index, change.remove, change.insert)
t.compareStrings(expected, recomposed)
}
{
const change = simpleDiffStringWithCursor(initial, 'Hello World', 11) // should delete the second hello world
t.compare(change, { insert: '', remove: 11, index: 11 })
const recomposedSecond = str.splice(initial, change.index, change.remove, change.insert)
t.compareStrings(recomposedSecond, expected)
}
{
const change = simpleDiffStringWithCursor(initial, 'Hello World', 5) // should delete in the midst of Hello World
t.compare(change, { insert: '', remove: 11, index: 5 })
const recomposed = str.splice(initial, change.index, change.remove, change.insert)
t.compareStrings(expected, recomposed)
}
{
const initial = 'Hello my World'
const change = simpleDiffStringWithCursor(initial, 'Hello World', 0) // Should delete after the current cursor position
t.compare(change, { insert: '', remove: 3, index: 5 })
const recomposed = str.splice(initial, change.index, change.remove, change.insert)
t.compareStrings(expected, recomposed)
}
{
const initial = '🚧🚧🚧'
const change = simpleDiffStringWithCursor(initial, '🚧🚧', 2) // Should delete after the midst of 🚧
t.compare(change, { insert: '', remove: 2, index: 2 })
const recomposed = str.splice(initial, change.index, change.remove, change.insert)
t.compareStrings('🚧🚧', recomposed)
}
{
const initial = '🚧👷🚧👷'
const change = simpleDiffStringWithCursor(initial, '🚧🚧', 2) // Should delete after the first 🚧 and insert 🚧
t.compare(change, { insert: '🚧', remove: 6, index: 2 })
const recomposed = str.splice(initial, change.index, change.remove, change.insert)
t.compareStrings('🚧🚧', recomposed)
}
}
/**
* @param {t.TestCase} tc
*/
export const testArrayDiffing = tc => {
const a = [[1, 2], { x: 'x' }]
const b = [[1, 2], { x: 'x' }]
t.compare(simpleDiffArray(a, b, f.equalityFlat), { index: 2, remove: 0, insert: [] })
t.compare(simpleDiffArray(a, b, f.equalityStrict), { index: 0, remove: 2, insert: b })
t.compare(simpleDiffArray([{ x: 'y' }, []], a, f.equalityFlat), { index: 0, remove: 2, insert: b })
}