diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/functional/core/job_spec.lua | 20 | ||||
-rw-r--r-- | test/functional/normal/macro_spec.lua | 30 | ||||
-rw-r--r-- | test/functional/options/defaults_spec.lua | 45 | ||||
-rw-r--r-- | test/functional/options/keymap_spec.lua | 233 | ||||
-rw-r--r-- | test/functional/provider/nodejs_spec.lua | 12 | ||||
-rw-r--r-- | test/functional/ui/inccommand_spec.lua | 15 | ||||
-rw-r--r-- | test/functional/viml/completion_spec.lua | 145 |
7 files changed, 393 insertions, 107 deletions
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua index e90339b0cd..4a21444ee0 100644 --- a/test/functional/core/job_spec.lua +++ b/test/functional/core/job_spec.lua @@ -433,9 +433,25 @@ describe('jobs', function() let cmd = ['sh', '-c', 'for i in $(seq 1 5); do echo $i; sleep 0.1; done'] endif call jobwait([jobstart(cmd, d)]) - call rpcnotify(g:channel, 'data', d.data) ]]) - eq({'notification', 'data', {{{'1', ''}, {'2', ''}, {'3', ''}, {'4', ''}, {'5', ''}, {''}}}}, next_msg()) + + local expected = {'1', '2', '3', '4', '5', ''} + local chunks = eval('d.data') + local received = {''} + for i, chunk in ipairs(chunks) do + if i < #chunks then + -- if chunks got joined, a spurious [''] callback was not sent + neq({''}, chunk) + else + -- but EOF callback is still sent + eq({''}, chunk) + end + received[#received] = received[#received]..chunk[1] + for j = 2, #chunk do + received[#received+1] = chunk[j] + end + end + eq(expected, received) end) it('jobstart() works with partial functions', function() diff --git a/test/functional/normal/macro_spec.lua b/test/functional/normal/macro_spec.lua new file mode 100644 index 0000000000..102d8fc723 --- /dev/null +++ b/test/functional/normal/macro_spec.lua @@ -0,0 +1,30 @@ +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local eval = helpers.eval +local feed = helpers.feed +local clear = helpers.clear +local expect = helpers.expect +local command = helpers.command + +describe('macros', function() + before_each(clear) + it('can be recorded and replayed', function() + feed('qiahello<esc>q') + expect('hello') + eq(eval('@i'), 'ahello') + feed('@i') + expect('hellohello') + eq(eval('@i'), 'ahello') + end) + it('applies maps', function() + command('imap x l') + command('nmap l a') + feed('qilxxx<esc>q') + expect('lll') + eq(eval('@i'), 'lxxx') + feed('@i') + expect('llllll') + eq(eval('@i'), 'lxxx') + end) +end) diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua index f452cafd22..787ec366b8 100644 --- a/test/functional/options/defaults_spec.lua +++ b/test/functional/options/defaults_spec.lua @@ -10,6 +10,7 @@ local eval = helpers.eval local eq = helpers.eq local funcs = helpers.funcs local insert = helpers.insert +local iswin = helpers.iswin local neq = helpers.neq local mkdir = helpers.mkdir local rmdir = helpers.rmdir @@ -170,8 +171,7 @@ describe('startup defaults', function() end) describe('$NVIM_LOG_FILE', function() - -- TODO(jkeyes): use stdpath('data') instead. - local datasubdir = helpers.iswin() and 'nvim-data' or 'nvim' + local datasubdir = iswin() and 'nvim-data' or 'nvim' local xdgdir = 'Xtest-startup-xdg-logpath' local xdgdatadir = xdgdir..'/'..datasubdir after_each(function() @@ -428,7 +428,24 @@ end) describe('stdpath()', function() + -- Windows appends 'nvim-data' instead of just 'nvim' to prevent collisions + -- due to XDG_CONFIG_HOME and XDG_DATA_HOME being the same. + local datadir = iswin() and 'nvim-data' or 'nvim' + + it('acceptance', function() + clear() -- Do not explicitly set any env vars. + + eq('nvim', funcs.fnamemodify(funcs.stdpath('cache'), ':t')) + eq('nvim', funcs.fnamemodify(funcs.stdpath('config'), ':t')) + eq(datadir, funcs.fnamemodify(funcs.stdpath('data'), ':t')) + eq('table', type(funcs.stdpath('config_dirs'))) + eq('table', type(funcs.stdpath('data_dirs'))) + -- Check for crash. #8393 + eq(2, eval('1+1')) + end) + context('returns a String', function() + describe('with "config"' , function () it('knows XDG_CONFIG_HOME', function() clear({env={ @@ -463,32 +480,20 @@ describe('stdpath()', function() end) describe('with "data"' , function () - local appended_dir - setup(function() - -- Windows appends 'nvim-data' instead of just 'nvim' to - -- prevent collisions due to XDG_CONFIG_HOME and XDG_DATA_HOME - -- being the same. - if helpers.iswin() then - appended_dir = '/nvim-data' - else - appended_dir = '/nvim' - end - end) - it('knows XDG_DATA_HOME', function() clear({env={ XDG_DATA_HOME=alter_slashes('/home/docwhat/.local'), }}) - eq(alter_slashes('/home/docwhat/.local' .. appended_dir), funcs.stdpath('data')) + eq(alter_slashes('/home/docwhat/.local/'..datadir), funcs.stdpath('data')) end) it('handles changes during runtime', function() clear({env={ XDG_DATA_HOME=alter_slashes('/home/original'), }}) - eq(alter_slashes('/home/original' .. appended_dir), funcs.stdpath('data')) + eq(alter_slashes('/home/original/'..datadir), funcs.stdpath('data')) command("let $XDG_DATA_HOME='"..alter_slashes('/home/new').."'") - eq(alter_slashes('/home/new' .. appended_dir), funcs.stdpath('data')) + eq(alter_slashes('/home/new/'..datadir), funcs.stdpath('data')) end) it("doesn't expand $VARIABLES", function() @@ -496,14 +501,14 @@ describe('stdpath()', function() XDG_DATA_HOME='$VARIABLES', VARIABLES='this-should-not-happen', }}) - eq(alter_slashes('$VARIABLES' .. appended_dir), funcs.stdpath('data')) + eq(alter_slashes('$VARIABLES/'..datadir), funcs.stdpath('data')) end) it("doesn't expand ~/", function() clear({env={ XDG_DATA_HOME=alter_slashes('~/frobnitz'), }}) - eq(alter_slashes('~/frobnitz' .. appended_dir), funcs.stdpath('data')) + eq(alter_slashes('~/frobnitz/'..datadir), funcs.stdpath('data')) end) end) @@ -544,7 +549,7 @@ describe('stdpath()', function() context('returns a List', function() -- Some OS specific variables the system would have set. local function base_env() - if helpers.iswin() then + if iswin() then return { HOME='C:\\Users\\docwhat', -- technically, is not a usual PATH HOMEDRIVE='C:', diff --git a/test/functional/options/keymap_spec.lua b/test/functional/options/keymap_spec.lua new file mode 100644 index 0000000000..7f6d623dc7 --- /dev/null +++ b/test/functional/options/keymap_spec.lua @@ -0,0 +1,233 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear, feed, eq = helpers.clear, helpers.feed, helpers.eq +local expect, command, eval = helpers.expect, helpers.command, helpers.eval +local insert, call = helpers.insert, helpers.call +local funcs, dedent = helpers.funcs, helpers.dedent + +-- First test it's implemented using the :lmap and :lnoremap commands, then +-- check those mappings behave as expected. +describe("'keymap' / :lmap", function() + clear() + before_each(function() + clear() + insert("lllaaa") + command('set iminsert=1') + command('set imsearch=1') + command('lmap l a') + feed('gg0') + end) + + describe("'keymap' as :lmap", function() + -- Shows that 'keymap' sets language mappings that allows remapping. + -- This equivalence allows us to only test :lmap commands and assert they + -- behave the same as 'keymap' settings. + -- It does rely on the absence of special code that implements 'keymap' + -- and :lmap differently but shows mappings from the 'keymap' after + -- typing :lmap. + -- At the moment this is the case. + it("'keymap' mappings are shown with :lmap", function() + command('lmapclear') + command('lmapclear <buffer>') + command('set keymap=dvorak') + command('set nomore') + local bindings = funcs.nvim_command_output('lmap') + eq(dedent([[ + + l " @_ + l ' @- + l + @} + l , @w + l - @[ + l . @v + l / @z + l : @S + l ; @s + l < @W + l = @] + l > @V + l ? @Z + l A @A + l B @X + l C @J + l D @E + l E @> + l F @U + l G @I + l H @D + l I @C + l J @H + l K @T + l L @N + l M @M + l N @B + l O @R + l P @L + l Q @" + l R @P + l S @O + l T @Y + l U @G + l V @K + l W @< + l X @Q + l Y @F + l Z @: + l [ @/ + l \ @\ + l ] @= + l _ @{ + l a @a + l b @x + l c @j + l d @e + l e @. + l f @u + l g @i + l h @d + l i @c + l j @h + l k @t + l l @n + l m @m + l n @b + l o @r + l p @l + l q @' + l r @p + l s @o + l t @y + l u @g + l v @k + l w @, + l x @q + l y @f + l z @; + l { @? + l | @| + l } @+]]), bindings) + end) + end) + describe("'iminsert' option", function() + it("Uses :lmap in insert mode when ON", function() + feed('il<esc>') + expect('alllaaa') + end) + it("Ignores :lmap in insert mode when OFF", function() + command('set iminsert=0') + feed('il<esc>') + expect('llllaaa') + end) + it("Can be toggled with <C-^> in insert mode", function() + feed('i<C-^>l<C-^>l<esc>') + expect('lalllaaa') + eq(eval('&iminsert'), 1) + feed('i<C-^><esc>') + eq(eval('&iminsert'), 0) + end) + end) + describe("'imsearch' option", function() + it("Uses :lmap at search prompt when ON", function() + feed('/lll<cr>3x') + expect('lll') + end) + it("Ignores :lmap at search prompt when OFF", function() + command('set imsearch=0') + feed('gg/lll<cr>3x') + expect('aaa') + end) + it("Can be toggled with C-^", function() + eq(eval('&imsearch'), 1) + feed('/<C-^>lll<cr>3x') + expect('aaa') + eq(eval('&imsearch'), 0) + feed('u0/<C-^>lll<cr>3x') + expect('lll') + eq(eval('&imsearch'), 1) + end) + it("can follow 'iminsert'", function() + command('set imsearch=-1') + feed('/lll<cr>3x') + expect('lll') + eq(eval('&imsearch'), -1) + eq(eval('&iminsert'), 1) + feed('u/<C-^>lll<cr>3x') + expect('aaa') + eq(eval('&imsearch'), -1) + eq(eval('&iminsert'), 0) + end) + end) + it(":lmap not applied to macros", function() + command("call setreg('a', 'il')") + feed('@a') + expect('llllaaa') + eq(call('getreg', 'a'), 'il') + end) + it(":lmap applied to macro recording", function() + feed('qail<esc>q@a') + expect('aalllaaa') + eq(call('getreg', 'a'), 'ia') + end) + it(":lmap not applied to mappings", function() + command('imap t l') + feed('it<esc>') + expect('llllaaa') + end) + it("mappings applied to keys created with :lmap", function() + command('imap a x') + feed('il<esc>') + expect('xlllaaa') + end) + it("mappings not applied to keys gotten with :lnoremap", function() + command('lmapclear') + command('lnoremap l a') + command('imap a x') + feed('il<esc>') + expect('alllaaa') + end) + -- This is a problem introduced when introducting :lmap and macro + -- compatibility. There are no plans to fix this as the complexity involved + -- seems too great. + pending('mappings not applied to macro replay of :lnoremap', function() + command('lmapclear') + command('lnoremap l a') + command('imap a x') + feed('qail<esc>q') + expect('alllaaa') + feed('@a') + expect('aalllaaa') + end) + it("is applied when using f/F t/T", function() + feed('flx') + expect('lllaa') + feed('0ia<esc>4lFlx') + expect('lllaa') + feed('tllx') + expect('llla') + feed('0ia<esc>4lTlhx') + expect('llla') + end) + it('takes priority over :imap mappings', function() + command('imap l x') + feed('il<esc>') + expect('alllaaa') + command('lmapclear') + command('lmap l a') + feed('il') + expect('aalllaaa') + end) + it('does not cause recursive mappings', function() + command('lmap a l') + feed('qaila<esc>q') + expect('allllaaa') + feed('u@a') + expect('allllaaa') + end) + it('can handle multicharacter mappings', function() + command("lmap 'a x") + command("lmap '' '") + feed("qai'a''a<esc>q") + expect("x'alllaaa") + feed('u@a') + expect("x'alllaaa") + end) +end) diff --git a/test/functional/provider/nodejs_spec.lua b/test/functional/provider/nodejs_spec.lua index d9af020bfe..f69c3e7c78 100644 --- a/test/functional/provider/nodejs_spec.lua +++ b/test/functional/provider/nodejs_spec.lua @@ -45,15 +45,13 @@ describe('nodejs host', function() const nvim = neovim.attach({socket: socket}); class TestPlugin { - hello() { - this.nvim.command('let g:job_out = "hello-plugin"') - } + hello() { + this.nvim.command('let g:job_out = "hello-plugin"'); + } } - const PluginClass = neovim.Plugin(TestPlugin); - const plugin = new PluginClass(nvim); - plugin.hello(); - nvim.command('call jobstop(g:job_id)'); + const plugin = new neovim.NvimPlugin(null, PluginClass, nvim); + plugin.instance.hello(); ]]) command('let g:job_id = jobstart(["node", "'..fname..'"])') retry(nil, 2000, function() eq('hello-plugin', eval('g:job_out')) end) diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua index ee1a3240a2..9cc697a4b6 100644 --- a/test/functional/ui/inccommand_spec.lua +++ b/test/functional/ui/inccommand_spec.lua @@ -1846,8 +1846,7 @@ describe("'inccommand' with 'gdefault'", function() end) describe(":substitute", function() - local screen = Screen.new(30,15) - + local screen = Screen.new(30,15) before_each(function() clear() end) @@ -2471,8 +2470,13 @@ describe(":substitute", function() :%s/some\(thing\)\@!/every/^ | ]]) end) +end) + +it(':substitute with inccommand during :terminal activity', function() + retry(2, nil, function() + local screen = Screen.new(30,15) + clear() - it('with inccommand during :terminal activity', function() command("set cmdwinheight=3") if iswin() then feed([[:terminal for /L \%I in (1,1,5000) do @(echo xxx & echo xxx & echo xxx)<cr>]]) @@ -2484,7 +2488,7 @@ describe(":substitute", function() common_setup(screen, 'split', 'foo bar baz\nbar baz fox\nbar foo baz') command('wincmd =') - -- Allow some terminal output. + -- Wait for terminal output. screen:expect([[ bar baz fox | bar foo ba^z | @@ -2505,7 +2509,7 @@ describe(":substitute", function() feed('gg') feed(':%s/foo/ZZZ') - sleep(50) -- Allow some terminal activity. + sleep(20) -- Allow some terminal activity. screen:expect([[ {12:ZZZ} bar baz | bar baz fox | @@ -2523,5 +2527,6 @@ describe(":substitute", function() {10:[Preview] }| :%s/foo/ZZZ^ | ]]) + end) end) diff --git a/test/functional/viml/completion_spec.lua b/test/functional/viml/completion_spec.lua index 93d3909568..c14f7fc1a6 100644 --- a/test/functional/viml/completion_spec.lua +++ b/test/functional/viml/completion_spec.lua @@ -975,90 +975,89 @@ describe('ui/ext_popupmenu', function() end) end) - describe('TextChangeP autocommand', function() - it('can trigger TextChangedP autocommand as expected', - function() - curbufmeths.set_lines(0, 1, false, { 'foo', 'bar', 'foobar'}) - command('set complete=. completeopt=menuone') - command('let g:foo = []') - command('autocmd! TextChanged * :call add(g:foo, "N")') - command('autocmd! TextChangedI * :call add(g:foo, "I")') - command('autocmd! TextChangedP * :call add(g:foo, "P")') - command('call cursor(3, 1)') + it('TextChangedP autocommand', function() + curbufmeths.set_lines(0, 1, false, { 'foo', 'bar', 'foobar'}) + source([[ + set complete=. completeopt=menuone + let g:foo = [] + autocmd! TextChanged * :call add(g:foo, "N") + autocmd! TextChangedI * :call add(g:foo, "I") + autocmd! TextChangedP * :call add(g:foo, "P") + call cursor(3, 1) + ]]) - command('let g:foo = []') - feed('o') - wait() - feed('<esc>') - assert.same({'I'}, eval('g:foo')) + command('let g:foo = []') + feed('o') + wait() + feed('<esc>') + eq({'I'}, eval('g:foo')) - command('let g:foo = []') - feed('S') - wait() - feed('f') - wait() - assert.same({'I', 'I'}, eval('g:foo')) - feed('<esc>') + command('let g:foo = []') + feed('S') + wait() + feed('f') + wait() + eq({'I', 'I'}, eval('g:foo')) + feed('<esc>') - command('let g:foo = []') - feed('S') - wait() - feed('f') - wait() - feed('<C-n>') - wait() - assert.same({'I', 'I', 'P'}, eval('g:foo')) - feed('<esc>') + command('let g:foo = []') + feed('S') + wait() + feed('f') + wait() + feed('<C-N>') + wait() + eq({'I', 'I', 'P'}, eval('g:foo')) + feed('<esc>') - command('let g:foo = []') - feed('S') - wait() - feed('f') - wait() - feed('<C-n>') - wait() - feed('<C-n>') - wait() - assert.same({'I', 'I', 'P', 'P'}, eval('g:foo')) - feed('<esc>') + command('let g:foo = []') + feed('S') + wait() + feed('f') + wait() + feed('<C-N>') + wait() + feed('<C-N>') + wait() + eq({'I', 'I', 'P', 'P'}, eval('g:foo')) + feed('<esc>') - command('let g:foo = []') - feed('S') - wait() - feed('f') - wait() - feed('<C-n>') - wait() - feed('<C-n>') - wait() - feed('<C-n>') - wait() - assert.same({'I', 'I', 'P', 'P', 'P'}, eval('g:foo')) - feed('<esc>') + command('let g:foo = []') + feed('S') + wait() + feed('f') + wait() + feed('<C-N>') + wait() + feed('<C-N>') + wait() + feed('<C-N>') + wait() + eq({'I', 'I', 'P', 'P', 'P'}, eval('g:foo')) + feed('<esc>') - command('let g:foo = []') - feed('S') - wait() - feed('f') - wait() - feed('<C-n>') - wait() - feed('<C-n>') - wait() - feed('<C-n>') - wait() - feed('<C-n>') - assert.same({'I', 'I', 'P', 'P', 'P', 'P'}, eval('g:foo')) - feed('<esc>') + command('let g:foo = []') + feed('S') + wait() + feed('f') + wait() + feed('<C-N>') + wait() + feed('<C-N>') + wait() + feed('<C-N>') + wait() + feed('<C-N>') + eq({'I', 'I', 'P', 'P', 'P', 'P'}, eval('g:foo')) + feed('<esc>') - assert.same({'foo', 'bar', 'foobar', 'foo'}, eval('getline(1, "$")')) + eq({'foo', 'bar', 'foobar', 'foo'}, eval('getline(1, "$")')) - source([[ + source([[ au! TextChanged au! TextChangedI au! TextChangedP set complete&vim completeopt&vim - ]]) - end) + ]]) end) end) |