curses_menu 0.0.1 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +28 -0
- data/LICENSE.md +31 -0
- data/README.md +78 -0
- data/examples/actions.rb +25 -25
- data/examples/automatic_key_presses.rb +49 -49
- data/examples/formatting.rb +148 -130
- data/examples/hello.rb +8 -8
- data/examples/refresh.rb +22 -22
- data/examples/scrolling.rb +9 -9
- data/examples/several_items.rb +18 -18
- data/examples/sub_menus.rb +20 -20
- data/examples/utf_8.rb +8 -0
- data/lib/curses_menu.rb +248 -241
- data/lib/curses_menu/curses_row.rb +151 -150
- data/lib/curses_menu/version.rb +5 -0
- data/spec/curses_menu_test.rb +131 -0
- data/spec/curses_menu_test/actions_spec.rb +221 -0
- data/spec/curses_menu_test/formatting_spec.rb +411 -0
- data/spec/curses_menu_test/rubocop_spec.rb +31 -0
- data/spec/curses_menu_test/scrolling_spec.rb +95 -0
- data/spec/curses_menu_test/simple_navigation_spec.rb +123 -0
- data/spec/spec_helper.rb +105 -0
- metadata +89 -10
@@ -0,0 +1,411 @@
|
|
1
|
+
describe CursesMenu do
|
2
|
+
|
3
|
+
it 'displays a single string' do
|
4
|
+
test_menu do |menu|
|
5
|
+
menu.item 'Simple string'
|
6
|
+
end
|
7
|
+
assert_line 3, 'Simple string'
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'displays a single string in UTF-8' do
|
11
|
+
test_menu do |menu|
|
12
|
+
menu.item 'Simple string - 単純な文字列'
|
13
|
+
end
|
14
|
+
# Ruby curses does not handle wide characters correctly in the inch method.
|
15
|
+
# This test is pending a better support for UTF-8.
|
16
|
+
# cf https://github.com/ruby/curses/issues/65
|
17
|
+
# TODO: Uncomment when Ruby curses will be fixed.
|
18
|
+
# rubocop:disable Style/AsciiComments
|
19
|
+
# assert_line 3, 'Simple string - 単純な文字列'
|
20
|
+
# rubocop:enable Style/AsciiComments
|
21
|
+
assert_line 3, /^Simple string - .+$/
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'displays a single string in a CursesRow' do
|
25
|
+
test_menu do |menu|
|
26
|
+
menu.item CursesMenu::CursesRow.new({ cell: { text: 'Simple string' } })
|
27
|
+
end
|
28
|
+
assert_line 3, 'Simple string'
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'displays a different color' do
|
32
|
+
test_menu do |menu|
|
33
|
+
menu.item CursesMenu::CursesRow.new(
|
34
|
+
{
|
35
|
+
cell: {
|
36
|
+
text: 'Selected colored string',
|
37
|
+
color_pair: CursesMenu::COLORS_GREEN
|
38
|
+
}
|
39
|
+
}
|
40
|
+
)
|
41
|
+
menu.item CursesMenu::CursesRow.new(
|
42
|
+
{
|
43
|
+
cell: {
|
44
|
+
text: 'Non-selected colored string',
|
45
|
+
color_pair: CursesMenu::COLORS_GREEN
|
46
|
+
}
|
47
|
+
}
|
48
|
+
)
|
49
|
+
end
|
50
|
+
assert_colored_line 3, 'Selected colored string', :COLORS_MENU_ITEM_SELECTED
|
51
|
+
assert_colored_line 4, 'Non-selected colored string', :COLORS_GREEN
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'adds prefixes' do
|
55
|
+
test_menu do |menu|
|
56
|
+
menu.item CursesMenu::CursesRow.new(
|
57
|
+
{
|
58
|
+
cell: {
|
59
|
+
text: 'Simple string',
|
60
|
+
begin_with: 'PRE'
|
61
|
+
}
|
62
|
+
}
|
63
|
+
)
|
64
|
+
end
|
65
|
+
assert_line 3, 'PRESimple string'
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'adds suffixes' do
|
69
|
+
test_menu do |menu|
|
70
|
+
menu.item CursesMenu::CursesRow.new(
|
71
|
+
{
|
72
|
+
cell: {
|
73
|
+
text: 'Simple string',
|
74
|
+
end_with: 'POST'
|
75
|
+
}
|
76
|
+
}
|
77
|
+
)
|
78
|
+
end
|
79
|
+
assert_line 3, 'Simple stringPOST'
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'limits fixed-size strings that exceed size' do
|
83
|
+
test_menu do |menu|
|
84
|
+
menu.item CursesMenu::CursesRow.new(
|
85
|
+
{
|
86
|
+
cell: {
|
87
|
+
text: 'Simple string',
|
88
|
+
fixed_size: 5
|
89
|
+
}
|
90
|
+
}
|
91
|
+
)
|
92
|
+
end
|
93
|
+
assert_line 3, 'Simpl'
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'pads fixed-size strings that do not exceed size' do
|
97
|
+
test_menu do |menu|
|
98
|
+
menu.item CursesMenu::CursesRow.new(
|
99
|
+
{
|
100
|
+
cell: {
|
101
|
+
text: 'Simple string',
|
102
|
+
fixed_size: 15,
|
103
|
+
pad: '*'
|
104
|
+
}
|
105
|
+
}
|
106
|
+
)
|
107
|
+
end
|
108
|
+
assert_line 3, 'Simple string**'
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'pads fixed-size strings that do not exceed size with multi-chars padding' do
|
112
|
+
test_menu do |menu|
|
113
|
+
menu.item CursesMenu::CursesRow.new(
|
114
|
+
{
|
115
|
+
cell: {
|
116
|
+
text: 'Simple string',
|
117
|
+
fixed_size: 20,
|
118
|
+
pad: '12345'
|
119
|
+
}
|
120
|
+
}
|
121
|
+
)
|
122
|
+
end
|
123
|
+
assert_line 3, 'Simple string1234512'
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'does not pad fixed-size strings that exceed size' do
|
127
|
+
test_menu do |menu|
|
128
|
+
menu.item CursesMenu::CursesRow.new(
|
129
|
+
{
|
130
|
+
cell: {
|
131
|
+
text: 'Simple string',
|
132
|
+
fixed_size: 5,
|
133
|
+
pad: '*'
|
134
|
+
}
|
135
|
+
}
|
136
|
+
)
|
137
|
+
end
|
138
|
+
assert_line 3, 'Simpl'
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'left-justifies fixed-size strings that do not exceed size' do
|
142
|
+
test_menu do |menu|
|
143
|
+
menu.item CursesMenu::CursesRow.new(
|
144
|
+
{
|
145
|
+
cell: {
|
146
|
+
text: 'Simple string',
|
147
|
+
fixed_size: 15,
|
148
|
+
pad: '*',
|
149
|
+
justify: :left
|
150
|
+
}
|
151
|
+
}
|
152
|
+
)
|
153
|
+
end
|
154
|
+
assert_line 3, 'Simple string**'
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'right-justifies fixed-size strings that do not exceed size' do
|
158
|
+
test_menu do |menu|
|
159
|
+
menu.item CursesMenu::CursesRow.new(
|
160
|
+
{
|
161
|
+
cell: {
|
162
|
+
text: 'Simple string',
|
163
|
+
fixed_size: 15,
|
164
|
+
pad: '*',
|
165
|
+
justify: :right
|
166
|
+
}
|
167
|
+
}
|
168
|
+
)
|
169
|
+
end
|
170
|
+
assert_line 3, '**Simple string'
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'never truncates prefixes when size exceeds fixed size' do
|
174
|
+
test_menu do |menu|
|
175
|
+
menu.item CursesMenu::CursesRow.new(
|
176
|
+
{
|
177
|
+
cell: {
|
178
|
+
text: 'Simple string',
|
179
|
+
fixed_size: 15,
|
180
|
+
begin_with: 'PRE'
|
181
|
+
}
|
182
|
+
}
|
183
|
+
)
|
184
|
+
end
|
185
|
+
assert_line 3, 'PRESimple strin'
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'never truncates suffixes when size exceeds fixed size' do
|
189
|
+
test_menu do |menu|
|
190
|
+
menu.item CursesMenu::CursesRow.new(
|
191
|
+
{
|
192
|
+
cell: {
|
193
|
+
text: 'Simple string',
|
194
|
+
fixed_size: 15,
|
195
|
+
end_with: 'POST'
|
196
|
+
}
|
197
|
+
}
|
198
|
+
)
|
199
|
+
end
|
200
|
+
assert_line 3, 'Simple striPOST'
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'never truncates prefixes and suffixes when size exceeds fixed size' do
|
204
|
+
test_menu do |menu|
|
205
|
+
menu.item CursesMenu::CursesRow.new(
|
206
|
+
{
|
207
|
+
cell: {
|
208
|
+
text: 'Simple string',
|
209
|
+
fixed_size: 15,
|
210
|
+
begin_with: 'PRE',
|
211
|
+
end_with: 'POST'
|
212
|
+
}
|
213
|
+
}
|
214
|
+
)
|
215
|
+
end
|
216
|
+
assert_line 3, 'PRESimple sPOST'
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'displays several cells' do
|
220
|
+
test_menu do |menu|
|
221
|
+
menu.item CursesMenu::CursesRow.new(
|
222
|
+
{
|
223
|
+
cell_1: { text: 'Cell 1' },
|
224
|
+
cell_2: { text: 'Cell 2' },
|
225
|
+
cell_3: { text: 'Cell 3' }
|
226
|
+
}
|
227
|
+
)
|
228
|
+
end
|
229
|
+
assert_line 3, 'Cell 1 Cell 2 Cell 3'
|
230
|
+
end
|
231
|
+
|
232
|
+
it 'displays several cells with a different separator' do
|
233
|
+
test_menu do |menu|
|
234
|
+
menu.item CursesMenu::CursesRow.new(
|
235
|
+
{
|
236
|
+
cell_1: { text: 'Cell 1' },
|
237
|
+
cell_2: { text: 'Cell 2' },
|
238
|
+
cell_3: { text: 'Cell 3' }
|
239
|
+
},
|
240
|
+
separator: 'SEP'
|
241
|
+
)
|
242
|
+
end
|
243
|
+
assert_line 3, 'Cell 1SEPCell 2SEPCell 3'
|
244
|
+
end
|
245
|
+
|
246
|
+
it 'does not exceed line when several cells are too long' do
|
247
|
+
nbr_visible_chars = Curses.stdscr.maxx
|
248
|
+
nbr_chars_per_cell = nbr_visible_chars / 3 + 1
|
249
|
+
test_menu do |menu|
|
250
|
+
menu.item CursesMenu::CursesRow.new(
|
251
|
+
{
|
252
|
+
cell_1: { text: '1' * nbr_chars_per_cell },
|
253
|
+
cell_2: { text: '2' * nbr_chars_per_cell },
|
254
|
+
cell_3: { text: '3' * nbr_chars_per_cell },
|
255
|
+
cell_4: { text: '4' * nbr_chars_per_cell }
|
256
|
+
}
|
257
|
+
)
|
258
|
+
menu.item 'Menu item 2'
|
259
|
+
end
|
260
|
+
assert_line 3, "#{'1' * nbr_chars_per_cell} #{'2' * nbr_chars_per_cell} #{'3' * (nbr_visible_chars - 2 * nbr_chars_per_cell - 3)}"
|
261
|
+
assert_line 4, 'Menu item 2'
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'does not exceed line when several cells are too long due to separators' do
|
265
|
+
nbr_visible_chars = Curses.stdscr.maxx
|
266
|
+
nbr_chars_per_cell = nbr_visible_chars / 3 + 1
|
267
|
+
test_menu do |menu|
|
268
|
+
menu.item CursesMenu::CursesRow.new(
|
269
|
+
{
|
270
|
+
cell_1: { text: '1' * nbr_chars_per_cell },
|
271
|
+
cell_3: { text: '3' * nbr_chars_per_cell }
|
272
|
+
},
|
273
|
+
separator: '2' * nbr_chars_per_cell
|
274
|
+
)
|
275
|
+
menu.item 'Menu item 2'
|
276
|
+
end
|
277
|
+
assert_line 3, "#{'1' * nbr_chars_per_cell}#{'2' * nbr_chars_per_cell}#{'3' * (nbr_visible_chars - 2 * nbr_chars_per_cell - 1)}"
|
278
|
+
assert_line 4, 'Menu item 2'
|
279
|
+
end
|
280
|
+
|
281
|
+
it 'displays several cells with different properties' do
|
282
|
+
test_menu do |menu|
|
283
|
+
menu.item CursesMenu::CursesRow.new(
|
284
|
+
{
|
285
|
+
cell_1: {
|
286
|
+
text: 'Cell 1',
|
287
|
+
begin_with: 'PRE'
|
288
|
+
},
|
289
|
+
cell_2: {
|
290
|
+
text: 'Cell 2',
|
291
|
+
color_pair: CursesMenu::COLORS_GREEN,
|
292
|
+
end_with: 'POST'
|
293
|
+
},
|
294
|
+
cell_3: {
|
295
|
+
text: 'Cell 3',
|
296
|
+
fixed_size: 10,
|
297
|
+
pad: '*',
|
298
|
+
justify: :right
|
299
|
+
},
|
300
|
+
cell_4: {
|
301
|
+
text: 'Cell 4',
|
302
|
+
fixed_size: 2
|
303
|
+
},
|
304
|
+
cell_5: {
|
305
|
+
text: 'Cell 5',
|
306
|
+
fixed_size: 10,
|
307
|
+
pad: '='
|
308
|
+
}
|
309
|
+
}
|
310
|
+
)
|
311
|
+
end
|
312
|
+
# TODO: Find a way to test colors
|
313
|
+
assert_line 3, 'PRECell 1 Cell 2POST ****Cell 3 Ce Cell 5===='
|
314
|
+
end
|
315
|
+
|
316
|
+
it 'can reorder cells' do
|
317
|
+
row = CursesMenu::CursesRow.new(
|
318
|
+
{
|
319
|
+
cell_1: { text: 'Cell 1' },
|
320
|
+
cell_2: { text: 'Cell 2' },
|
321
|
+
cell_3: { text: 'Cell 3' }
|
322
|
+
}
|
323
|
+
)
|
324
|
+
row.cells_order(%i[cell_3 cell_2 cell_1])
|
325
|
+
test_menu { |menu| menu.item row }
|
326
|
+
assert_line 3, 'Cell 3 Cell 2 Cell 1'
|
327
|
+
end
|
328
|
+
|
329
|
+
it 'can reorder cells and ignore unknown ones' do
|
330
|
+
row = CursesMenu::CursesRow.new(
|
331
|
+
{
|
332
|
+
cell_1: { text: 'Cell 1' },
|
333
|
+
cell_2: { text: 'Cell 2' },
|
334
|
+
cell_3: { text: 'Cell 3' }
|
335
|
+
}
|
336
|
+
)
|
337
|
+
row.cells_order(%i[cell_4 cell_3 cell_5 cell_2 cell_1])
|
338
|
+
test_menu { |menu| menu.item row }
|
339
|
+
assert_line 3, 'Cell 3 Cell 2 Cell 1'
|
340
|
+
end
|
341
|
+
|
342
|
+
it 'can reorder cells and create unknown ones' do
|
343
|
+
row = CursesMenu::CursesRow.new(
|
344
|
+
{
|
345
|
+
cell_1: { text: 'Cell 1' },
|
346
|
+
cell_2: { text: 'Cell 2' },
|
347
|
+
cell_3: { text: 'Cell 3' }
|
348
|
+
}
|
349
|
+
)
|
350
|
+
row.cells_order(%i[cell_4 cell_3 cell_5 cell_2 cell_1], unknown_cells: 'Cell X')
|
351
|
+
test_menu { |menu| menu.item row }
|
352
|
+
assert_line 3, 'Cell X Cell 3 Cell X Cell 2 Cell 1'
|
353
|
+
end
|
354
|
+
|
355
|
+
it 'can reorder cells and create unknown ones with properties' do
|
356
|
+
row = CursesMenu::CursesRow.new(
|
357
|
+
{
|
358
|
+
cell_1: { text: 'Cell 1' },
|
359
|
+
cell_2: { text: 'Cell 2' },
|
360
|
+
cell_3: { text: 'Cell 3' }
|
361
|
+
}
|
362
|
+
)
|
363
|
+
row.cells_order(
|
364
|
+
%i[cell_4 cell_3 cell_5 cell_2 cell_1],
|
365
|
+
unknown_cells: {
|
366
|
+
text: 'Cell X',
|
367
|
+
begin_with: '{',
|
368
|
+
end_with: '}'
|
369
|
+
}
|
370
|
+
)
|
371
|
+
test_menu { |menu| menu.item row }
|
372
|
+
assert_line 3, '{Cell X} Cell 3 {Cell X} Cell 2 Cell 1'
|
373
|
+
end
|
374
|
+
|
375
|
+
it 'can change cells properties' do
|
376
|
+
row = CursesMenu::CursesRow.new(
|
377
|
+
{
|
378
|
+
cell_1: {
|
379
|
+
text: 'Cell 1',
|
380
|
+
begin_with: 'PRE',
|
381
|
+
end_with: 'POST'
|
382
|
+
},
|
383
|
+
cell_2: {
|
384
|
+
text: 'Cell 2'
|
385
|
+
},
|
386
|
+
cell_3: {
|
387
|
+
text: 'Cell 3',
|
388
|
+
fixed_size: 10,
|
389
|
+
pad: '*'
|
390
|
+
}
|
391
|
+
}
|
392
|
+
)
|
393
|
+
row.change_cells(
|
394
|
+
{
|
395
|
+
cell_1: {
|
396
|
+
begin_with: 'PRE2'
|
397
|
+
},
|
398
|
+
cell_2: {
|
399
|
+
fixed_size: 2
|
400
|
+
},
|
401
|
+
cell_3: {
|
402
|
+
text: 'Cell X',
|
403
|
+
pad: '-='
|
404
|
+
}
|
405
|
+
}
|
406
|
+
)
|
407
|
+
test_menu { |menu| menu.item row }
|
408
|
+
assert_line 3, 'PRE2Cell 1POST Ce Cell X-=-='
|
409
|
+
end
|
410
|
+
|
411
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
describe 'Coding guidelines' do
|
4
|
+
|
5
|
+
it 'makes sure code style follow Rubocop guides' do
|
6
|
+
rubocop_report = JSON.parse(`bundle exec rubocop --format json`)
|
7
|
+
expect(rubocop_report['summary']['offense_count']).to(
|
8
|
+
eq(0),
|
9
|
+
proc do
|
10
|
+
# Format a great error message to help
|
11
|
+
wrong_files = rubocop_report['files'].reject { |file_info| file_info['offenses'].empty? }
|
12
|
+
<<~EO_ERROR
|
13
|
+
#{wrong_files.size} files have Rubocop issues:
|
14
|
+
#{
|
15
|
+
wrong_files.map do |file_info|
|
16
|
+
offenses = file_info['offenses'].map { |offense_info| "L#{offense_info['location']['start_line']}: #{offense_info['cop_name']} - #{offense_info['message']}" }
|
17
|
+
"* #{file_info['path']}:#{
|
18
|
+
if offenses.size == 1
|
19
|
+
" #{offenses.first}"
|
20
|
+
else
|
21
|
+
" #{offenses.size} offenses:\n#{offenses.map { |offense| " - #{offense}" }.join("\n")}"
|
22
|
+
end
|
23
|
+
}"
|
24
|
+
end.join("\n")
|
25
|
+
}
|
26
|
+
EO_ERROR
|
27
|
+
end
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
describe CursesMenu do
|
2
|
+
|
3
|
+
it 'does not span items on more than 1 line' do
|
4
|
+
nbr_visible_chars = Curses.stdscr.maxx
|
5
|
+
test_menu do |menu|
|
6
|
+
menu.item '1' * nbr_visible_chars * 2
|
7
|
+
menu.item 'Menu item 2'
|
8
|
+
end
|
9
|
+
assert_line 3, '1' * (nbr_visible_chars - 1)
|
10
|
+
assert_line 4, 'Menu item 2'
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'scrolls by using right key' do
|
14
|
+
nbr_visible_chars = Curses.stdscr.maxx
|
15
|
+
test_menu(keys: [Curses::KEY_RIGHT, Curses::KEY_RIGHT, Curses::KEY_RIGHT]) do |menu|
|
16
|
+
menu.item "abcde#{'1' * (nbr_visible_chars - 5)}23456789"
|
17
|
+
end
|
18
|
+
assert_line 3, "de#{'1' * (nbr_visible_chars - 5)}23"
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'scrolls by using left key' do
|
22
|
+
nbr_visible_chars = Curses.stdscr.maxx
|
23
|
+
test_menu(keys: [Curses::KEY_RIGHT, Curses::KEY_RIGHT, Curses::KEY_RIGHT, Curses::KEY_LEFT]) do |menu|
|
24
|
+
menu.item "abcde#{'1' * (nbr_visible_chars - 5)}23456789"
|
25
|
+
end
|
26
|
+
assert_line 3, "cde#{'1' * (nbr_visible_chars - 5)}2"
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'scrolls by using down key' do
|
30
|
+
nbr_visible_items = Curses.stdscr.maxy - 5
|
31
|
+
test_menu(keys: [Curses::KEY_NPAGE, Curses::KEY_DOWN, Curses::KEY_DOWN]) do |menu|
|
32
|
+
(nbr_visible_items * 2).times do |idx|
|
33
|
+
menu.item "Menu item #{idx}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
assert_line 3, 'Menu item 2'
|
37
|
+
assert_line(-3, "Menu item #{nbr_visible_items + 1}")
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'scrolls by using up key' do
|
41
|
+
nbr_visible_items = Curses.stdscr.maxy - 5
|
42
|
+
test_menu(keys: [Curses::KEY_END, Curses::KEY_PPAGE, Curses::KEY_UP, Curses::KEY_UP]) do |menu|
|
43
|
+
(nbr_visible_items * 2).times do |idx|
|
44
|
+
menu.item "Menu item #{idx}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
assert_line 3, "Menu item #{nbr_visible_items - 2}"
|
48
|
+
assert_line(-3, "Menu item #{2 * nbr_visible_items - 3}")
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'scrolls by using page down key' do
|
52
|
+
nbr_visible_items = Curses.stdscr.maxy - 5
|
53
|
+
test_menu(keys: [Curses::KEY_NPAGE, Curses::KEY_NPAGE]) do |menu|
|
54
|
+
(nbr_visible_items * 3).times do |idx|
|
55
|
+
menu.item "Menu item #{idx}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
assert_line 3, "Menu item #{nbr_visible_items - 1}"
|
59
|
+
assert_line(-3, "Menu item #{nbr_visible_items * 2 - 2}")
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'scrolls by using page up key' do
|
63
|
+
nbr_visible_items = Curses.stdscr.maxy - 5
|
64
|
+
test_menu(keys: [Curses::KEY_END, Curses::KEY_PPAGE, Curses::KEY_PPAGE]) do |menu|
|
65
|
+
(nbr_visible_items * 3).times do |idx|
|
66
|
+
menu.item "Menu item #{idx}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
assert_line 3, "Menu item #{nbr_visible_items + 2 - 1}"
|
70
|
+
assert_line(-3, "Menu item #{nbr_visible_items * 2}")
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'scrolls by using end key' do
|
74
|
+
nbr_visible_items = Curses.stdscr.maxy - 5
|
75
|
+
test_menu(keys: [Curses::KEY_END]) do |menu|
|
76
|
+
(nbr_visible_items * 2).times do |idx|
|
77
|
+
menu.item "Menu item #{idx}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
assert_line 3, "Menu item #{nbr_visible_items}"
|
81
|
+
assert_line(-3, "Menu item #{nbr_visible_items * 2 - 1}")
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'scrolls by using home key' do
|
85
|
+
nbr_visible_items = Curses.stdscr.maxy - 5
|
86
|
+
test_menu(keys: [Curses::KEY_END, Curses::KEY_HOME]) do |menu|
|
87
|
+
(nbr_visible_items * 3).times do |idx|
|
88
|
+
menu.item "Menu item #{idx}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
assert_line 3, 'Menu item 0'
|
92
|
+
assert_line(-3, "Menu item #{nbr_visible_items - 1}")
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|