Skip to content

Commit 3738794

Browse files
committed
test: migrate batch 3 specs to Lua/Plenary (bullets, nested_bullets)
Completes full test suite migration — all 63 tests passing. Additional learnings: - set expandtab=false + shiftwidth/tabstop=4 in before_each for indent tests - visual mode selection is re-entered by plugin after </> ops; subsequent operations stay in visual — no <Esc> needed between chained motions - A<CR><CR> in one feedkeys call handles the empty-bullet deletion case (both CRs fire while in insert mode, second deletes the empty bullet) - .strip in Ruby tests hides trailing "- " (with space); Lua tests assert the actual content including the trailing space - mid-test config changes (e.g. g:bullets_enable_roman_list) work by setting the global between separate feedkeys calls
1 parent abc6983 commit 3738794

2 files changed

Lines changed: 786 additions & 6 deletions

File tree

test/bullets_spec.lua

Lines changed: 306 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,312 @@ local helpers = require("test.helpers")
22

33
describe("Bullets.vim", function()
44
describe("inserting new bullets", function()
5-
it("adds a new bullet if the previous line had a known bullet type", function()
6-
helpers.test_bullet_inserted(
7-
"do that",
8-
{ "# Hello there", "- do this" },
9-
{ "# Hello there", "- do this", "- do that" }
10-
)
5+
before_each(function()
6+
helpers.reset_config()
7+
end)
8+
9+
describe("on return key when cursor is not at EOL", function()
10+
it("splits the line and does not add a bullet", function()
11+
-- G$i places cursor on last char 't' in "- this is the first bullet"
12+
-- i inserts before 't', CR is deferred (not at EOL), splits the line
13+
-- then "second bullet" is typed before 't': "second bullett"
14+
-- Temporarily disable formatoptions 'r' to avoid comment-leader insertion
15+
local saved_fo = vim.o.formatoptions
16+
vim.cmd("set formatoptions-=r")
17+
helpers.new_buffer({
18+
"# Hello there",
19+
"- this is the first bullet",
20+
})
21+
-- Position cursor on 't' (last char, 0-indexed col 25), enter insert before it
22+
-- CR is deferred by plugin (not at EOL); 'x' flag drains the deferred CR → split
23+
-- We end up in normal mode on new line with 't'
24+
helpers.feedkeys("G$i<CR>")
25+
-- Now in normal mode at col 0 of "t"; insert before 't' and type
26+
helpers.feedkeys("isecond bullet<Esc>")
27+
vim.o.formatoptions = saved_fo
28+
assert.are.same({
29+
"# Hello there",
30+
"- this is the first bulle",
31+
"second bullett",
32+
}, helpers.get_lines())
33+
end)
34+
end)
35+
36+
describe("on return key when cursor is at EOL", function()
37+
it("adds a new bullet if the previous line had a known bullet type", function()
38+
helpers.test_bullet_inserted(
39+
"do that",
40+
{ "# Hello there", "- do this" },
41+
{ "# Hello there", "- do this", "- do that" }
42+
)
43+
end)
44+
45+
it("adds a new latex bullet", function()
46+
helpers.test_bullet_inserted(
47+
"Second item",
48+
{
49+
"\\documentclass{article}",
50+
" \\begin{document}",
51+
"",
52+
" \\begin{itemize}",
53+
" \\item First item",
54+
},
55+
{
56+
"\\documentclass{article}",
57+
" \\begin{document}",
58+
"",
59+
" \\begin{itemize}",
60+
" \\item First item",
61+
" \\item Second item",
62+
}
63+
)
64+
end)
65+
66+
it("adds a pandoc bullet if the prev line had one", function()
67+
helpers.test_bullet_inserted(
68+
"second bullet",
69+
{ "Hello there", "#. this is the first bullet" },
70+
{ "Hello there", "#. this is the first bullet", "#. second bullet" }
71+
)
72+
end)
73+
74+
it("adds an Org mode bullet if the prev line had one", function()
75+
helpers.test_bullet_inserted(
76+
"second bullet",
77+
{ "Hello there", "**** this is the first bullet" },
78+
{ "Hello there", "**** this is the first bullet", "**** second bullet" }
79+
)
80+
end)
81+
82+
it("adds a new numeric bullet if the previous line had numeric bullet", function()
83+
helpers.test_bullet_inserted(
84+
"second bullet",
85+
{ "# Hello there", "1) this is the first bullet" },
86+
{ "# Hello there", "1) this is the first bullet", "2) second bullet" }
87+
)
88+
end)
89+
90+
it("adds a new numeric bullet with right padding", function()
91+
helpers.test_bullet_inserted(
92+
"second bullet",
93+
{ "# Hello there", "1. this is the first bullet" },
94+
{ "# Hello there", "1. this is the first bullet", "2. second bullet" }
95+
)
96+
end)
97+
98+
it("maintains total bullet width from 9. to 10. with reduced padding", function()
99+
vim.g.bullets_renumber_on_change = 0
100+
helpers.test_bullet_inserted(
101+
"second bullet",
102+
{ "# Hello there", "9. this is the first bullet" },
103+
{ "# Hello there", "9. this is the first bullet", "10. second bullet" }
104+
)
105+
end)
106+
107+
it("adds a new - bullet with right padding", function()
108+
helpers.test_bullet_inserted(
109+
"second bullet",
110+
{ "# Hello there", "- this is the first bullet" },
111+
{ "# Hello there", "- this is the first bullet", "- second bullet" }
112+
)
113+
end)
114+
115+
it("does not insert a new numeric bullet for decimal numbers", function()
116+
-- "3.14159 is an approximation of pi." is not a bullet line
117+
-- CR on non-bullet line is deferred, use two-call pattern
118+
helpers.new_buffer({
119+
"# Hello there",
120+
"3.14159 is an approximation of pi.",
121+
})
122+
helpers.feedkeys("A<CR>")
123+
helpers.feedkeys("isecond line<Esc>")
124+
assert.are.same({
125+
"# Hello there",
126+
"3.14159 is an approximation of pi.",
127+
"second line",
128+
}, helpers.get_lines())
129+
end)
130+
131+
it("adds a new roman numeral bullet", function()
132+
vim.g.bullets_pad_right = 0
133+
helpers.new_buffer({
134+
"# Hello there",
135+
"I. this is the first bullet",
136+
})
137+
helpers.feedkeys("A<CR>second bullet<CR>third bullet<CR>fourth bullet<CR>fifth bullet<Esc>")
138+
assert.are.same({
139+
"# Hello there",
140+
"I. this is the first bullet",
141+
"II. second bullet",
142+
"III. third bullet",
143+
"IV. fourth bullet",
144+
"V. fifth bullet",
145+
}, helpers.get_lines())
146+
end)
147+
148+
it("adds a new lowercase roman numeral bullet", function()
149+
vim.g.bullets_pad_right = 0
150+
helpers.new_buffer({
151+
"# Hello there",
152+
"i. this is the first bullet",
153+
})
154+
helpers.feedkeys("A<CR>second bullet<CR>third bullet<CR>fourth bullet<CR>fifth bullet<Esc>")
155+
assert.are.same({
156+
"# Hello there",
157+
"i. this is the first bullet",
158+
"ii. second bullet",
159+
"iii. third bullet",
160+
"iv. fourth bullet",
161+
"v. fifth bullet",
162+
}, helpers.get_lines())
163+
end)
164+
165+
it("does not confuse with the 'ignorecase' option", function()
166+
vim.cmd("set ignorecase")
167+
-- "Vi." is mixed case / not a valid roman numeral bullet → non-bullet CR
168+
helpers.new_buffer({
169+
"# Hello there",
170+
"Vi. this is the first line",
171+
})
172+
helpers.feedkeys("A<CR>")
173+
helpers.feedkeys("isecond line<Esc>")
174+
assert.are.same({
175+
"# Hello there",
176+
"Vi. this is the first line",
177+
"second line",
178+
}, helpers.get_lines())
179+
end)
180+
181+
it("does not insert a new roman bullets without following spaces", function()
182+
-- "m.example.com is a site." has no space after the dot → not a bullet
183+
helpers.new_buffer({
184+
"# Hello there",
185+
"m.example.com is a site.",
186+
})
187+
helpers.feedkeys("A<CR>")
188+
helpers.feedkeys("isecond line<Esc>")
189+
assert.are.same({
190+
"# Hello there",
191+
"m.example.com is a site.",
192+
"second line",
193+
}, helpers.get_lines())
194+
end)
195+
196+
it("does not insert a new roman bullets for invalid roman numbers", function()
197+
-- "LID." is not a valid roman numeral, so no bullet continuation
198+
-- However lines typed after non-bullet lines also get no bullet
199+
helpers.new_buffer({
200+
"# Hello there",
201+
"LID. the first line",
202+
})
203+
-- First CR after "LID. the first line" (non-bullet) → deferred
204+
helpers.feedkeys("A<CR>")
205+
helpers.feedkeys("isecond line<Esc>")
206+
-- Now on "second line" (non-bullet) → deferred CR
207+
helpers.feedkeys("A<CR>")
208+
helpers.feedkeys("ivim. third line<Esc>")
209+
-- Now on "vim. third line" (non-bullet) → deferred CR
210+
helpers.feedkeys("A<CR>")
211+
helpers.feedkeys("ifourth line<Esc>")
212+
assert.are.same({
213+
"# Hello there",
214+
"LID. the first line",
215+
"second line",
216+
"vim. third line",
217+
"fourth line",
218+
}, helpers.get_lines())
219+
end)
220+
221+
it("deletes the last bullet if it is empty", function()
222+
helpers.new_buffer({
223+
"# Hello there",
224+
"- this is the first bullet",
225+
})
226+
-- First CR creates "- " empty bullet, second CR on empty bullet deletes it
227+
helpers.feedkeys("A<CR><CR>")
228+
local lines = helpers.get_lines()
229+
-- strip trailing empty lines (mirrors Ruby .strip behaviour)
230+
while #lines > 0 and lines[#lines] == "" do
231+
table.remove(lines)
232+
end
233+
assert.are.same({
234+
"# Hello there",
235+
"- this is the first bullet",
236+
}, lines)
237+
end)
238+
239+
it("promote the last bullet when configured to", function()
240+
vim.g.bullets_delete_last_bullet_if_empty = 2
241+
helpers.new_buffer({
242+
"# Hello there",
243+
"- this is the first bullet",
244+
" - this is the second bullet",
245+
})
246+
-- First CR creates new child bullet " - ", second CR promotes (dedents)
247+
helpers.feedkeys("A<CR><CR>")
248+
local lines = helpers.get_lines()
249+
-- strip trailing empty lines
250+
while #lines > 0 and lines[#lines] == "" do
251+
table.remove(lines)
252+
end
253+
-- The promoted bullet has a trailing space ("- ") matching plugin output
254+
assert.are.same({
255+
"# Hello there",
256+
"- this is the first bullet",
257+
" - this is the second bullet",
258+
"- ",
259+
}, lines)
260+
end)
261+
262+
it("does not delete the last bullet when configured not to", function()
263+
vim.g.bullets_delete_last_bullet_if_empty = 0
264+
helpers.new_buffer({
265+
"# Hello there",
266+
"- this is the first bullet",
267+
})
268+
-- First CR creates "- " empty bullet, second CR on empty bullet
269+
-- with config=0 does NOT delete it; a plain CR fires leaving "- " intact
270+
helpers.feedkeys("A<CR><CR>")
271+
local lines = helpers.get_lines()
272+
-- strip trailing empty lines
273+
while #lines > 0 and lines[#lines] == "" do
274+
table.remove(lines)
275+
end
276+
-- The non-deleted bullet retains trailing space ("- ") matching plugin output
277+
assert.are.same({
278+
"# Hello there",
279+
"- this is the first bullet",
280+
"- ",
281+
}, lines)
282+
end)
283+
284+
it("toggles roman numeral bullets with g:bullets_enable_roman_list", function()
285+
-- Disable alpha lists to isolate test to roman numerals
286+
vim.g.bullets_max_alpha_characters = 0
287+
vim.g.bullets_enable_roman_list = 1
288+
helpers.new_buffer({
289+
"# Hello there",
290+
"i. this is the first bullet",
291+
})
292+
-- Type second and third bullets (roman numeral bullets)
293+
helpers.feedkeys("A<CR>second bullet<CR>third bullet<Esc>")
294+
-- Disable roman list mid-test
295+
vim.g.bullets_enable_roman_list = 0
296+
-- Type fourth and fifth (no roman numeral prefix now)
297+
-- We're in normal mode, need to append and continue
298+
helpers.feedkeys("A<CR>")
299+
helpers.feedkeys("ifourth bullet<Esc>")
300+
helpers.feedkeys("A<CR>")
301+
helpers.feedkeys("ififth bullet<Esc>")
302+
assert.are.same({
303+
"# Hello there",
304+
"i. this is the first bullet",
305+
"ii. second bullet",
306+
"iii. third bullet",
307+
"fourth bullet",
308+
"fifth bullet",
309+
}, helpers.get_lines())
310+
end)
11311
end)
12312
end)
13313
end)

0 commit comments

Comments
 (0)