test/unit/test_line_cursor_mode.rb (5881B) - raw
1 require "test_helper"
2 require "dummy_buffer"
3
4 require "sup"
5
6 class TestLineCursorMode < Minitest::Test
7 def setup
8 $config = {
9 :load_more_threads_hysteresis => 0,
10 :load_more_threads_when_scrolling => true,
11 :continuous_scroll => false,
12 }
13 Redwood::BufferManager.init
14 @modes_to_cleanup = []
15 @lines = []
16 @load_more = Thread::Queue.new
17 @buffer_height = 41 # 1 for status line, 40 usable lines
18 end
19
20 def teardown
21 @modes_to_cleanup.each { |mode| mode.cleanup }
22 Redwood::BufferManager.deinstantiate!
23 $config = nil
24 end
25
26 def make_mode
27 mode = Redwood::LineCursorMode.new
28 @modes_to_cleanup << mode
29 lines = @lines
30 mode.define_singleton_method(:lines) { lines.length }
31 mode.define_singleton_method(:[]) { |i| lines[i] }
32 mode.send(:to_load_more) { |n| @load_more << n }
33 mode.buffer = Redwood::DummyBuffer.new 100, @buffer_height
34 mode.spawned
35 mode.draw
36 mode
37 end
38
39 def expect_load_more n
40 begin
41 requested = @load_more.pop :timeout => 0.1
42 rescue ThreadError
43 ## Ruby < 3.2 does not obey the timeout for Queue#pop
44 sleep 0.1
45 requested = @load_more.pop true
46 end
47 refute_nil requested, "Expected load_more callbacks to fire"
48 assert_equal n, requested
49 (0...n).map { |i| @lines << "line #{i}" }
50 end
51
52 def test_cursor_down
53 mode = make_mode
54 expect_load_more 41
55 mode.draw # curpos gets messed up without this call, why?
56
57 21.times do
58 mode.handle_input Ncurses::CharCode.character('j')
59 end
60 assert_equal 21, mode.curpos
61 assert_equal 0, mode.topline
62
63 ## Two past halfway, load_more callbacks are triggered.
64 mode.handle_input Ncurses::CharCode.character('j')
65 assert_equal 22, mode.curpos
66 expect_load_more 40
67
68 17.times do
69 mode.handle_input Ncurses::CharCode.character('j')
70 end
71 assert_equal 39, mode.curpos
72 assert_equal 0, mode.topline
73
74 ## From the bottom line, it wraps back to the top of the next page.
75 mode.handle_input Ncurses::CharCode.character('j')
76 assert_equal 40, mode.curpos
77 assert_equal 40, mode.topline
78 end
79
80 def test_scroll_down
81 mode = make_mode
82 expect_load_more 41
83
84 ## When the cursor is already at the top, it moves with the scroll.
85 assert_equal 0, mode.curpos
86 assert_equal 0, mode.topline
87 mode.handle_input Ncurses::CharCode.character('J')
88 assert_equal 1, mode.curpos
89 assert_equal 1, mode.topline
90
91 3.times do
92 mode.handle_input Ncurses::CharCode.character('j')
93 end
94 assert_equal 4, mode.curpos
95 assert_equal 1, mode.topline
96
97 ## When the cursor is not at the top, it keeps its place and the
98 ## buffer scrolls underneath it.
99 mode.handle_input Ncurses::CharCode.character('J')
100 assert_equal 4, mode.curpos
101 assert_equal 2, mode.topline
102
103 ## It always loads 10 more if we would scroll past the bottom.
104 expect_load_more 10
105 end
106
107 def test_page_down
108 mode = make_mode
109 expect_load_more 41
110
111 mode.handle_input Ncurses::CharCode.keycode(Ncurses::KEY_NPAGE)
112 assert_equal 40, mode.curpos
113 assert_equal 40, mode.topline
114 expect_load_more 40
115
116 mode.handle_input Ncurses::CharCode.keycode(Ncurses::KEY_NPAGE)
117 assert_equal 80, mode.curpos
118 assert_equal 80, mode.topline
119 assert_equal 81, mode.lines
120 expect_load_more 40
121 end
122
123 def test_page_down_when_fully_populated
124 mode = make_mode
125 expect_load_more 41
126 (0...119).map { |i| @lines << "more line #{i}" } # enough for 4 full pages
127
128 mode.handle_input Ncurses::CharCode.keycode(Ncurses::KEY_NPAGE)
129 assert_equal 40, mode.curpos
130 assert_equal 40, mode.topline
131
132 ## Relative cursor position is preserved when paging down.
133 3.times do
134 mode.handle_input Ncurses::CharCode.character('j')
135 end
136 assert_equal 43, mode.curpos
137 assert_equal 40, mode.topline
138 mode.handle_input Ncurses::CharCode.keycode(Ncurses::KEY_NPAGE)
139 assert_equal 83, mode.curpos
140 assert_equal 80, mode.topline
141 end
142
143 def test_half_page_down
144 mode = make_mode
145 expect_load_more 41
146
147 mode.handle_input Ncurses::CharCode.character("\C-d")
148 assert_equal 20, mode.curpos
149 assert_equal 20, mode.topline
150 expect_load_more 40
151
152 mode.handle_input Ncurses::CharCode.character("\C-d")
153 assert_equal 40, mode.curpos
154 assert_equal 40, mode.topline
155 end
156
157 def test_half_page_down_when_fully_populated
158 mode = make_mode
159 expect_load_more 41
160 (0...119).map { |i| @lines << "more line #{i}" } # enough for 4 full pages
161
162 mode.handle_input Ncurses::CharCode.character("\C-d")
163 assert_equal 20, mode.curpos
164 assert_equal 20, mode.topline
165
166 25.times do
167 mode.handle_input Ncurses::CharCode.character('j')
168 end
169 assert_equal 45, mode.curpos
170 assert_equal 20, mode.topline
171 mode.handle_input Ncurses::CharCode.character("\C-d")
172 assert_equal 45, mode.curpos
173 assert_equal 40, mode.topline
174 end
175
176 def test_half_page_up
177 mode = make_mode
178 expect_load_more 41
179 (0...119).map { |i| @lines << "more line #{i}" } # enough for 4 full pages
180
181 mode.handle_input Ncurses::CharCode.keycode(Ncurses::KEY_NPAGE)
182 assert_equal 40, mode.curpos
183 assert_equal 40, mode.topline
184
185 mode.handle_input Ncurses::CharCode.character("\C-u")
186 assert_equal 40, mode.curpos
187 assert_equal 20, mode.topline
188
189 mode.handle_input Ncurses::CharCode.character('j')
190 assert_equal 41, mode.curpos
191 assert_equal 20, mode.topline
192
193 mode.handle_input Ncurses::CharCode.character("\C-u")
194 assert_equal 40, mode.curpos
195 assert_equal 0, mode.topline
196 end
197
198 def test_jump_to_end
199 mode = make_mode
200 expect_load_more 41
201
202 mode.handle_input Ncurses::CharCode.keycode(Ncurses::KEY_END)
203 assert_equal 40, mode.curpos
204 assert_equal 1, mode.topline
205 assert_equal 41, mode.botline
206 expect_load_more 40
207 end
208 end