ui_spec.lua (6195B)
1 local t = require('test.testutil') 2 local n = require('test.functional.testnvim')() 3 local Screen = require('test.functional.ui.screen') 4 5 local clear = n.clear 6 local command = n.command 7 local eq = t.eq 8 local eval = n.eval 9 local exec = n.exec 10 local feed = n.feed 11 local api = n.api 12 local request = n.request 13 local poke_eventloop = n.poke_eventloop 14 local pcall_err = t.pcall_err 15 local uv = vim.uv 16 17 describe('nvim_ui_attach()', function() 18 before_each(function() 19 clear() 20 end) 21 22 it('handles very large width/height #2180', function() 23 local _ = Screen.new(999, 999) 24 eq(999, eval('&lines')) 25 eq(999, eval('&columns')) 26 end) 27 28 it('validation', function() 29 eq('No such UI option: foo', pcall_err(api.nvim_ui_attach, 80, 24, { foo = { 'foo' } })) 30 31 eq( 32 "Invalid 'ext_linegrid': expected Boolean, got Array", 33 pcall_err(api.nvim_ui_attach, 80, 24, { ext_linegrid = {} }) 34 ) 35 eq( 36 "Invalid 'override': expected Boolean, got Array", 37 pcall_err(api.nvim_ui_attach, 80, 24, { override = {} }) 38 ) 39 eq( 40 "Invalid 'rgb': expected Boolean, got Array", 41 pcall_err(api.nvim_ui_attach, 80, 24, { rgb = {} }) 42 ) 43 eq( 44 "Invalid 'term_name': expected String, got Boolean", 45 pcall_err(api.nvim_ui_attach, 80, 24, { term_name = true }) 46 ) 47 eq( 48 "Invalid 'term_colors': expected Integer, got Boolean", 49 pcall_err(api.nvim_ui_attach, 80, 24, { term_colors = true }) 50 ) 51 eq( 52 "Invalid 'stdin_fd': expected Integer, got String", 53 pcall_err(api.nvim_ui_attach, 80, 24, { stdin_fd = 'foo' }) 54 ) 55 eq( 56 "Invalid 'stdin_tty': expected Boolean, got String", 57 pcall_err(api.nvim_ui_attach, 80, 24, { stdin_tty = 'foo' }) 58 ) 59 eq( 60 "Invalid 'stdout_tty': expected Boolean, got String", 61 pcall_err(api.nvim_ui_attach, 80, 24, { stdout_tty = 'foo' }) 62 ) 63 64 eq('UI not attached to channel: 1', pcall_err(request, 'nvim_ui_try_resize', 40, 10)) 65 eq('UI not attached to channel: 1', pcall_err(request, 'nvim_ui_set_option', 'rgb', true)) 66 eq('UI not attached to channel: 1', pcall_err(request, 'nvim_ui_detach')) 67 68 local _ = Screen.new(nil, nil, { rgb = false }) 69 eq( 70 'UI already attached to channel: 1', 71 pcall_err(request, 'nvim_ui_attach', 40, 10, { rgb = false }) 72 ) 73 end) 74 75 it('does not crash if maximum UI count is reached', function() 76 local server = api.nvim_get_vvar('servername') 77 local screens = {} --- @type test.functional.ui.screen[] 78 for i = 1, 16 do 79 screens[i] = Screen.new(nil, nil, nil, n.connect(server)) 80 end 81 eq( 82 -- 0 is kErrorTypeException 83 { false, { 0, 'Maximum UI count reached' } }, 84 { n.connect(server):request('nvim_ui_attach', 80, 24, {}) } 85 ) 86 for i = 1, 16 do 87 screens[i]:detach() 88 end 89 end) 90 end) 91 92 describe('nvim_ui_send', function() 93 before_each(function() 94 clear() 95 end) 96 97 it('works with stdout_tty', function() 98 local fds = assert(uv.pipe()) 99 100 local read_pipe = assert(uv.new_pipe()) 101 read_pipe:open(fds.read) 102 103 local read_data = {} 104 read_pipe:read_start(function(err, data) 105 assert(not err, err) 106 if data then 107 table.insert(read_data, data) 108 end 109 end) 110 111 local screen = Screen.new(50, 10, { stdout_tty = true }) 112 screen:set_stdout(fds.write) 113 114 api.nvim_ui_send('Hello world') 115 116 poke_eventloop() 117 118 screen:expect([[ 119 ^ | 120 {1:~ }|*8 121 | 122 ]]) 123 124 eq('Hello world', table.concat(read_data)) 125 end) 126 127 it('ignores ui_send event for UIs without stdout_tty', function() 128 local fds = assert(uv.pipe()) 129 130 local read_pipe = assert(uv.new_pipe()) 131 read_pipe:open(fds.read) 132 133 local read_data = {} 134 read_pipe:read_start(function(err, data) 135 assert(not err, err) 136 if data then 137 table.insert(read_data, data) 138 end 139 end) 140 141 local screen = Screen.new(50, 10) 142 screen:set_stdout(fds.write) 143 144 api.nvim_ui_send('Hello world') 145 146 poke_eventloop() 147 148 screen:expect([[ 149 ^ | 150 {1:~ }|*8 151 | 152 ]]) 153 154 eq('', table.concat(read_data)) 155 end) 156 end) 157 158 it('autocmds UIEnter/UILeave', function() 159 clear { args_rm = { '--headless' } } 160 exec([[ 161 let g:evs = [] 162 autocmd UIEnter * call add(g:evs, "UIEnter") | let g:uienter_ev = deepcopy(v:event) 163 autocmd UILeave * call add(g:evs, "UILeave") | let g:uileave_ev = deepcopy(v:event) 164 autocmd VimEnter * call add(g:evs, "VimEnter") 165 ]]) 166 local screen = Screen.new() 167 eq({ chan = 1 }, eval('g:uienter_ev')) 168 screen:detach() 169 eq({ chan = 1 }, eval('g:uileave_ev')) 170 eq({ 171 'VimEnter', 172 'UIEnter', 173 'UILeave', 174 }, eval('g:evs')) 175 end) 176 177 it('autocmds VimSuspend/VimResume #22041', function() 178 clear() 179 local screen = Screen.new() 180 exec([[ 181 let g:ev = [] 182 autocmd VimResume * :call add(g:ev, 'r') 183 autocmd VimSuspend * :call add(g:ev, 's') 184 ]]) 185 186 eq(false, screen.suspended) 187 feed('<C-Z>') 188 screen:expect(function() 189 eq(true, screen.suspended) 190 end) 191 eq({ 's' }, eval('g:ev')) 192 screen.suspended = false 193 feed('<Ignore>') 194 eq({ 's', 'r' }, eval('g:ev')) 195 196 command('suspend') 197 screen:expect(function() 198 eq(true, screen.suspended) 199 end) 200 eq({ 's', 'r', 's' }, eval('g:ev')) 201 screen.suspended = false 202 api.nvim_input_mouse('move', '', '', 0, 0, 0) 203 eq({ 's', 'r', 's', 'r' }, eval('g:ev')) 204 205 feed('<C-Z><C-Z><C-Z>') 206 screen:expect(function() 207 eq(true, screen.suspended) 208 end) 209 api.nvim_ui_set_focus(false) 210 eq({ 's', 'r', 's', 'r', 's' }, eval('g:ev')) 211 screen.suspended = false 212 api.nvim_ui_set_focus(true) 213 eq({ 's', 'r', 's', 'r', 's', 'r' }, eval('g:ev')) 214 215 command('suspend | suspend | suspend') 216 screen:expect(function() 217 eq(true, screen.suspended) 218 end) 219 screen:detach() 220 eq({ 's', 'r', 's', 'r', 's', 'r', 's' }, eval('g:ev')) 221 screen.suspended = false 222 screen:attach() 223 eq({ 's', 'r', 's', 'r', 's', 'r', 's', 'r' }, eval('g:ev')) 224 end)