|
1 |
| -local spy = require('luassert.spy') |
2 |
| -local match = require('luassert.match') |
3 | 1 | local load_fixture = require "tests.load_fixture"
|
4 |
| -local stub = require 'luassert.stub' |
5 | 2 | local assert = require "luassert"
|
| 3 | +local stub = require 'luassert.stub' |
6 | 4 | local tw = require 'treewalker'
|
7 | 5 | local h = require 'tests.treewalker.helpers'
|
8 | 6 | local operations = require 'treewalker.operations'
|
9 | 7 |
|
10 |
| --- Test for highlight clear-before-highlight behavior |
11 |
| -describe("Clears previous highlights before applying new", function() |
12 |
| - local clear_spy, hlrange_spy |
| 8 | +describe("Highlights", function() |
| 9 | + load_fixture("/lua.lua") |
13 | 10 |
|
14 | 11 | before_each(function()
|
15 |
| - clear_spy = spy.on(vim.api, "nvim_buf_clear_namespace") |
16 |
| - hlrange_spy = spy.on(vim.hl, "range") |
17 |
| - end) |
18 |
| - |
19 |
| - after_each(function() |
20 |
| - clear_spy:revert() |
21 |
| - hlrange_spy:revert() |
22 |
| - end) |
23 |
| - |
24 |
| - it("calls clear_namespace before every highlight", function() |
25 |
| - local range1 = { 1, 2, 3, 4 } |
26 |
| - local range2 = { 10, 2, 12, 4 } |
27 |
| - operations.highlight(range1, 50, "CursorLine") |
28 |
| - operations.highlight(range2, 50, "CursorLine") |
29 |
| - |
30 |
| - -- For each highlight call, we should first clear, then range highlight |
31 |
| - assert.spy(clear_spy).was.called_with(0, match.is_number(), 0, -1) |
32 |
| - assert.spy(clear_spy).was.called(3) |
33 |
| - assert.spy(hlrange_spy).was.called(2) |
34 |
| - -- check arguments |
35 |
| - local call1 = hlrange_spy.calls[1].vals |
36 |
| - local call2 = hlrange_spy.calls[2].vals |
37 |
| - assert.equal(0, call1[1]) |
38 |
| - assert.is_number(call1[2]) |
39 |
| - assert.equal("CursorLine", call1[3]) |
40 |
| - assert.same({1,2}, call1[4]) |
41 |
| - assert.same({3,4}, call1[5]) |
42 |
| - assert.same({ inclusive = true }, call1[6]) |
43 |
| - |
44 |
| - assert.equal(0, call2[1]) |
45 |
| - assert.is_number(call2[2]) |
46 |
| - assert.equal("CursorLine", call2[3]) |
47 |
| - assert.same({10,2}, call2[4]) |
48 |
| - assert.same({12,4}, call2[5]) |
49 |
| - assert.same({ inclusive = true }, call2[6]) |
50 |
| - end) |
51 |
| -end) |
| 12 | + -- Clear any leftover namespaces from previous tests |
| 13 | + local ns_id = vim.api.nvim_create_namespace("treewalker.nvim-movement-highlight") |
| 14 | + vim.api.nvim_buf_clear_namespace(0, ns_id, 0, -1) |
52 | 15 |
|
53 |
| -describe("Highlights in a lua spec file: ", function() |
54 |
| - local highlight_stub |
| 16 | + tw.setup({ highlight = true, highlight_duration = 5 }) |
| 17 | + end) |
55 | 18 |
|
56 |
| - load_fixture("/lua-spec.lua") |
| 19 | + it("creates visible highlights when moving and clears them after timeout", function() |
| 20 | + -- Start with clean state - count initial highlights |
| 21 | + local initial_count = h.get_highlight_count() |
| 22 | + assert.equal(0, initial_count) |
57 | 23 |
|
58 |
| - before_each(function() |
59 |
| - highlight_stub = stub.new(operations, "highlight") |
60 |
| - end) |
| 24 | + vim.fn.cursor(10, 1) |
| 25 | + tw.move_down() |
61 | 26 |
|
62 |
| - after_each(function() |
63 |
| - highlight_stub:revert() |
64 |
| - end) |
| 27 | + local after_move_count = h.get_highlight_count() |
| 28 | + assert.equal(1, after_move_count, "No OG highlight detected") |
65 | 29 |
|
66 |
| - it("highlights full block on move_in() (identified in gh #30)", function() |
67 |
| - vim.fn.cursor(64, 3) |
68 |
| - tw.move_in() |
69 |
| - h.assert_highlighted(67, 5, 85, 8, highlight_stub, "it block") |
| 30 | + -- Wait for timeout and verify highlights are cleared |
| 31 | + vim.wait(20, function() return false end) |
| 32 | + local after_timeout_count = h.get_highlight_count() |
| 33 | + assert.equal(0, after_timeout_count, "Highlights not cleared after timeout") |
70 | 34 | end)
|
71 |
| -end) |
72 | 35 |
|
73 |
| -describe("Highlights in a regular lua file: ", function() |
74 |
| - local highlight_stub |
| 36 | + it("clears previous highlights when making new movement", function() |
| 37 | + assert.equal(0, h.get_highlight_count()) |
75 | 38 |
|
76 |
| - load_fixture("/lua.lua") |
| 39 | + vim.fn.cursor(10, 1) |
| 40 | + tw.move_down() |
| 41 | + tw.move_up() |
77 | 42 |
|
78 |
| - before_each(function() |
79 |
| - highlight_stub = stub.new(operations, "highlight") |
| 43 | + assert.equal(1, h.get_highlight_count()) |
80 | 44 | end)
|
81 | 45 |
|
82 |
| - after_each(function() |
83 |
| - highlight_stub:revert() |
84 |
| - end) |
| 46 | + it("does not create highlights when highlight option is disabled", function() |
| 47 | + tw.setup({ highlight = false }) |
| 48 | + assert.equal(0, h.get_highlight_count()) |
85 | 49 |
|
86 |
| - it("respects default highlight option", function() |
87 |
| - tw.setup() -- highlight defaults to true, doesn't blow up with empty setup |
88 |
| - vim.fn.cursor(23, 5) |
89 |
| - tw.move_out() |
| 50 | + vim.fn.cursor(10, 1) |
90 | 51 | tw.move_down()
|
91 | 52 | tw.move_up()
|
92 | 53 | tw.move_in()
|
93 |
| - assert.equal(4, #highlight_stub.calls) |
| 54 | + tw.move_out() |
| 55 | + |
| 56 | + assert.equal(0, h.get_highlight_count(), "Highlights created when disabled") |
94 | 57 | end)
|
95 | 58 |
|
96 |
| - it("respects highlight config option", function() |
97 |
| - highlight_stub = stub.new(operations, "highlight") |
98 |
| - tw.setup({ highlight = false }) |
99 |
| - vim.fn.cursor(23, 5) |
100 |
| - tw.move_out() |
101 |
| - tw.move_down() |
102 |
| - tw.move_up() |
| 59 | + it("highlights appear when moving in any direction", function() |
| 60 | + assert.equal(0, h.get_highlight_count()) |
| 61 | + |
| 62 | + vim.fn.cursor(10, 1) |
103 | 63 | tw.move_in()
|
104 |
| - assert.equal(0, #highlight_stub.calls) |
105 | 64 |
|
106 |
| - highlight_stub = stub(operations, "highlight") |
107 |
| - tw.setup({ highlight = true }) |
108 |
| - vim.fn.cursor(23, 5) |
109 |
| - tw.move_out() |
110 |
| - tw.move_down() |
111 |
| - tw.move_up() |
| 65 | + assert.equal(1, h.get_highlight_count()) |
| 66 | + end) |
| 67 | + |
| 68 | + it("highlights full block on move_in() (identified in gh #30)", function() |
| 69 | + vim.fn.cursor(21, 1) |
112 | 70 | tw.move_in()
|
113 |
| - assert.equal(4, #highlight_stub.calls) |
| 71 | + h.assert_highlighted(22, 3, 26, 5) |
114 | 72 | end)
|
115 | 73 |
|
116 | 74 | it("respects default highlight_duration", function()
|
117 |
| - tw.setup({ highlight = true }) |
118 |
| - tw.move_out() |
119 |
| - local duration_arg = highlight_stub.calls[1].refs[2] |
120 |
| - assert.equal(250, duration_arg) |
121 |
| - end) |
| 75 | + -- Clear any leftover namespaces from previous tests |
| 76 | + local ns_id = vim.api.nvim_create_namespace("treewalker.nvim-movement-highlight") |
| 77 | + vim.api.nvim_buf_clear_namespace(0, ns_id, 0, -1) |
| 78 | + |
| 79 | + -- Directly set opts to default values to bypass before_each |
| 80 | + local tw_init = require('treewalker') |
| 81 | + tw_init.opts = { |
| 82 | + highlight = true, |
| 83 | + highlight_duration = 250, |
| 84 | + highlight_group = "CursorLine", |
| 85 | + jumplist = true, |
| 86 | + } |
| 87 | + |
| 88 | + -- Stub the highlight function to capture arguments |
| 89 | + local highlight_stub = stub.new(operations, "highlight") |
122 | 90 |
|
123 |
| - it("respects highlight_duration config option", function() |
124 |
| - local duration = 50 |
125 |
| - tw.setup({ highlight = true, highlight_duration = duration }) |
126 |
| - tw.move_out() |
| 91 | + vim.fn.cursor(10, 1) |
127 | 92 | tw.move_down()
|
128 |
| - tw.move_up() |
129 |
| - tw.move_in() |
130 |
| - assert.stub(highlight_stub).was.called(4) |
| 93 | + |
| 94 | + -- Verify highlight function was called with default duration (250) |
| 95 | + assert.stub(highlight_stub).was.called(1) |
131 | 96 | local duration_arg = highlight_stub.calls[1].refs[2]
|
132 |
| - assert.equal(duration, duration_arg) |
| 97 | + assert.equal(250, duration_arg) |
| 98 | + |
| 99 | + -- Restore the original function |
| 100 | + highlight_stub:revert() |
133 | 101 | end)
|
134 | 102 |
|
135 | 103 | it("respects default highlight_group", function()
|
136 |
| - tw.setup({ highlight = true, highlight_duration = 250 }) |
| 104 | + tw.setup({ highlight = true }) |
| 105 | + |
| 106 | + vim.fn.cursor(10, 1) |
137 | 107 | tw.move_down()
|
138 |
| - local hl_group_arg = highlight_stub.calls[1].refs[3] |
139 |
| - assert.equal("CursorLine", hl_group_arg) |
| 108 | + |
| 109 | + -- Verify the highlight uses the default group |
| 110 | + local ns_id = vim.api.nvim_create_namespace("treewalker.nvim-movement-highlight") |
| 111 | + local highlights = vim.api.nvim_buf_get_extmarks(0, ns_id, 0, -1, { details = true }) |
| 112 | + |
| 113 | + assert.equal(1, #highlights) |
| 114 | + assert.equal("CursorLine", highlights[1][4].hl_group) |
140 | 115 | end)
|
141 | 116 |
|
142 | 117 | it("respects highlight_group config option", function()
|
143 |
| - tw.setup({ highlight = true, highlight_duration = 50, highlight_group = "DiffAdd" }) |
| 118 | + tw.setup({ highlight = true, highlight_group = "DiffAdd" }) |
| 119 | + |
| 120 | + vim.fn.cursor(10, 1) |
144 | 121 | tw.move_down()
|
145 |
| - local hl_group_arg = highlight_stub.calls[1].refs[3] |
146 |
| - assert.equal("DiffAdd", hl_group_arg) |
| 122 | + |
| 123 | + -- Verify the highlight uses the configured group |
| 124 | + local ns_id = vim.api.nvim_create_namespace("treewalker.nvim-movement-highlight") |
| 125 | + local highlights = vim.api.nvim_buf_get_extmarks(0, ns_id, 0, -1, { details = true }) |
| 126 | + |
| 127 | + assert.equal(1, #highlights) |
| 128 | + assert.equal("DiffAdd", highlights[1][4].hl_group) |
147 | 129 | end)
|
148 | 130 |
|
149 | 131 | it("highlights whole functions", function()
|
150 | 132 | vim.fn.cursor(10, 1)
|
151 | 133 | tw.move_down()
|
152 |
| - h.assert_highlighted(21, 1, 28, 3, highlight_stub, "is_jump_target function") |
| 134 | + h.assert_highlighted(21, 1, 28, 3) |
153 | 135 | end)
|
154 | 136 |
|
155 | 137 | it("highlights whole lines starting with identifiers", function()
|
156 | 138 | vim.fn.cursor(134, 5)
|
157 | 139 | tw.move_up()
|
158 |
| - h.assert_highlighted(133, 5, 133, 33, highlight_stub, "table.insert call") |
| 140 | + h.assert_highlighted(133, 5, 133, 33) |
159 | 141 | end)
|
160 | 142 |
|
161 | 143 | it("highlights whole lines starting with assignments", function()
|
162 | 144 | vim.fn.cursor(133, 5)
|
163 | 145 | tw.move_down()
|
164 |
| - h.assert_highlighted(134, 5, 134, 18, highlight_stub, "child = iter()") |
| 146 | + h.assert_highlighted(134, 5, 134, 18) |
165 | 147 | end)
|
166 | 148 |
|
167 | 149 | it("highlights out reliably", function()
|
168 | 150 | vim.fn.cursor(133, 5)
|
169 | 151 | tw.move_out()
|
170 |
| - h.assert_highlighted(132, 3, 135, 5, highlight_stub, "while child") |
| 152 | + h.assert_highlighted(132, 3, 135, 5) |
171 | 153 | end)
|
172 | 154 |
|
173 | 155 | it("highlights out reliably", function()
|
174 | 156 | vim.fn.cursor(132, 3)
|
175 | 157 | tw.move_out()
|
176 |
| - h.assert_highlighted(128, 1, 137, 3, highlight_stub, "local f get_children") |
| 158 | + h.assert_highlighted(128, 1, 137, 3) |
177 | 159 | end)
|
178 | 160 |
|
179 | 161 | it("doesn't highlight the whole file", function()
|
180 | 162 | vim.fn.cursor(3, 1)
|
181 | 163 | tw.move_up()
|
182 |
| - h.assert_highlighted(1, 1, 1, 39, highlight_stub, "first line") |
| 164 | + h.assert_highlighted(1, 1, 1, 39) |
183 | 165 | end)
|
184 | 166 |
|
185 | 167 | -- Note this is highly language dependent, so this test is not so powerful
|
186 | 168 | it("highlights only the first item in a block", function()
|
187 | 169 | vim.fn.cursor(27, 3)
|
188 | 170 | tw.move_up()
|
189 |
| - h.assert_highlighted(22, 3, 26, 5, highlight_stub, "for _") |
| 171 | + h.assert_highlighted(22, 3, 26, 5) |
190 | 172 | end)
|
191 | 173 |
|
192 | 174 | it("given in a line with no parent, move_out highlights the whole node", function()
|
193 | 175 | vim.fn.cursor(21, 16) -- |is_jump_target
|
194 | 176 | tw.move_out()
|
195 | 177 | h.assert_cursor_at(21, 1)
|
196 |
| - h.assert_highlighted(21, 1, 28, 3, highlight_stub, "is_jump_target function") |
| 178 | + h.assert_highlighted(21, 1, 28, 3) |
197 | 179 | end)
|
198 | 180 | end)
|
199 | 181 |
|
0 commit comments