FossilRepo

fossilrepo / tests / test_split_diff.py
Blame History Raw 165 lines
1
"""Tests for the split-diff view helper (_compute_split_lines)."""
2
3
from fossil.views import _compute_split_lines
4
5
6
def _make_line(text, line_type, old_num="", new_num=""):
7
"""Build a diff-line dict matching the shape produced by checkin_detail."""
8
if line_type in ("add", "del", "context") and text:
9
prefix = text[0]
10
code = text[1:]
11
else:
12
prefix = ""
13
code = text
14
return {
15
"text": text,
16
"type": line_type,
17
"old_num": old_num,
18
"new_num": new_num,
19
"prefix": prefix,
20
"code": code,
21
}
22
23
24
class TestComputeSplitLines:
25
"""Unit tests for _compute_split_lines."""
26
27
def test_context_lines_appear_on_both_sides(self):
28
lines = [
29
_make_line(" hello", "context", old_num=1, new_num=1),
30
_make_line(" world", "context", old_num=2, new_num=2),
31
]
32
left, right = _compute_split_lines(lines)
33
assert len(left) == 2
34
assert len(right) == 2
35
assert left[0]["text"] == " hello"
36
assert right[0]["text"] == " hello"
37
assert left[1]["text"] == " world"
38
assert right[1]["text"] == " world"
39
40
def test_deletion_only_on_left(self):
41
lines = [
42
_make_line("-removed", "del", old_num=5),
43
]
44
left, right = _compute_split_lines(lines)
45
assert len(left) == 1
46
assert len(right) == 1
47
assert left[0]["type"] == "del"
48
assert left[0]["text"] == "-removed"
49
assert right[0]["type"] == "empty"
50
assert right[0]["text"] == ""
51
52
def test_addition_only_on_right(self):
53
lines = [
54
_make_line("+added", "add", new_num=10),
55
]
56
left, right = _compute_split_lines(lines)
57
assert len(left) == 1
58
assert len(right) == 1
59
assert left[0]["type"] == "empty"
60
assert right[0]["type"] == "add"
61
assert right[0]["text"] == "+added"
62
63
def test_paired_del_add_block(self):
64
"""Adjacent del+add lines should be paired row-by-row."""
65
lines = [
66
_make_line("-old_a", "del", old_num=1),
67
_make_line("-old_b", "del", old_num=2),
68
_make_line("+new_a", "add", new_num=1),
69
_make_line("+new_b", "add", new_num=2),
70
]
71
left, right = _compute_split_lines(lines)
72
assert len(left) == 2
73
assert len(right) == 2
74
assert left[0]["type"] == "del"
75
assert right[0]["type"] == "add"
76
assert left[1]["type"] == "del"
77
assert right[1]["type"] == "add"
78
79
def test_unequal_del_add_pads_with_empty(self):
80
"""When there are more dels than adds, right side gets empty placeholders."""
81
lines = [
82
_make_line("-old_a", "del", old_num=1),
83
_make_line("-old_b", "del", old_num=2),
84
_make_line("-old_c", "del", old_num=3),
85
_make_line("+new_a", "add", new_num=1),
86
]
87
left, right = _compute_split_lines(lines)
88
assert len(left) == 3
89
assert len(right) == 3
90
assert left[0]["type"] == "del"
91
assert right[0]["type"] == "add"
92
assert left[1]["type"] == "del"
93
assert right[1]["type"] == "empty"
94
assert left[2]["type"] == "del"
95
assert right[2]["type"] == "empty"
96
97
def test_more_adds_than_dels_pads_left(self):
98
"""When there are more adds than dels, left side gets empty placeholders."""
99
lines = [
100
_make_line("-old", "del", old_num=1),
101
_make_line("+new_a", "add", new_num=1),
102
_make_line("+new_b", "add", new_num=2),
103
]
104
left, right = _compute_split_lines(lines)
105
assert len(left) == 2
106
assert len(right) == 2
107
assert left[0]["type"] == "del"
108
assert right[0]["type"] == "add"
109
assert left[1]["type"] == "empty"
110
assert right[1]["type"] == "add"
111
112
def test_hunk_and_header_lines_on_both_sides(self):
113
lines = [
114
_make_line("--- a/file.py", "header"),
115
_make_line("+++ b/file.py", "header"),
116
_make_line("@@ -1,3 +1,3 @@", "hunk"),
117
_make_line(" ctx", "context", old_num=1, new_num=1),
118
]
119
left, right = _compute_split_lines(lines)
120
assert len(left) == 4
121
assert len(right) == 4
122
assert left[0]["type"] == "header"
123
assert right[0]["type"] == "header"
124
assert left[2]["type"] == "hunk"
125
assert right[2]["type"] == "hunk"
126
assert left[3]["type"] == "context"
127
assert right[3]["type"] == "context"
128
129
def test_mixed_sequence(self):
130
"""Full realistic sequence: header, hunk, context, del, add, context."""
131
lines = [
132
_make_line("--- a/f.py", "header"),
133
_make_line("+++ b/f.py", "header"),
134
_make_line("@@ -1,4 +1,4 @@", "hunk"),
135
_make_line(" line1", "context", old_num=1, new_num=1),
136
_make_line("-old2", "del", old_num=2),
137
_make_line("+new2", "add", new_num=2),
138
_make_line(" line3", "context", old_num=3, new_num=3),
139
]
140
left, right = _compute_split_lines(lines)
141
# header(2) + hunk(1) + context(1) + paired del/add(1) + context(1) = 6
142
assert len(left) == 6
143
assert len(right) == 6
144
# Check paired del/add at index 4
145
assert left[4]["type"] == "del"
146
assert right[4]["type"] == "add"
147
148
def test_empty_input(self):
149
left, right = _compute_split_lines([])
150
assert left == []
151
assert right == []
152
153
def test_orphan_add_without_preceding_del(self):
154
"""An add line not preceded by a del should still work."""
155
lines = [
156
_make_line(" ctx", "context", old_num=1, new_num=1),
157
_make_line("+new", "add", new_num=2),
158
_make_line(" ctx2", "context", old_num=2, new_num=3),
159
]
160
left, right = _compute_split_lines(lines)
161
assert len(left) == 3
162
assert len(right) == 3
163
assert left[1]["type"] == "empty"
164
assert right[1]["type"] == "add"
165

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button