function! s:test_diags() abort return { \ 'gopls': { \ 'method': 'textDocument/publishDiagnostics', \ 'jsonrpc': '2.0', \ 'params': { \ 'uri': 'file:///path/to/dummy.txt', \ 'diagnostics': [ \ { \ 'source': 'compiler', \ 'range': { \ 'end': {'character': 4, 'line': 4}, \ 'start': {'character': 1, 'line': 4} \ }, \ 'message': 'error message 1', \ 'severity': 1 \ }, \ { \ 'source': 'compiler', \ 'range': { \ 'end': {'character': 4, 'line': 4}, \ 'start': {'character': 1, 'line': 4} \ }, \ 'message': 'warning message 1', \ 'severity': 2 \ } \ ] \ } \ } \} endfunction function! s:test_locs() abort return [[ \ { \ 'lnum': 5, \ 'col': 2, \ 'filename': '/path/to/dummy.txt', \ 'text': 'compiler:Error:error message 1' \ }, \ { \ 'lnum': 5, \ 'col': 2, \ 'filename': '/path/to/dummy.txt', \ 'text': 'compiler:Warning:warning message 1' \ } \ ]] endfunction function! s:test_diags_all_severities() abort let diags = s:test_diags() let diag = diags.gopls.params.diagnostics[0] let diags.gopls.params.diagnostics = [] for [sev, name] in [[1, 'error'], [2, 'warning'], [3, 'info'], [4, 'hint']] let d = copy(diag) let d.severity = sev let d.message = name . ' message' let diags.gopls.params.diagnostics += [d] endfor return diags endfunction function! s:test_locs_all_severities() abort let loc = s:test_locs()[0][0] let locs = [] for [sev, name] in [[1, 'Error'], [2, 'Warning'], [3, 'Info'], [4, 'Hint']] let l = copy(loc) let l.text = 'compiler:' . name . ':' . tolower(name) . ' message' let locs += [l] endfor return [locs] endfunction function! s:test_expected_locs_all_severities() abort let loc = s:test_locs()[0][0] let locs = [] for [sev, name, type] in [[1, 'Error', 'E'], [2, 'Warning', 'W'], [3, 'Info', 'I'], [4, 'Hint', 'H']] let l = copy(loc) let l.type = type let l.text = '[gopls] compiler:' . name . ':' . tolower(name) . ' message' let locs += [l] endfor return locs endfunction function! s:modify_loc_item(item, type) abort let a:item.type = a:type let a:item.text = '[gopls] ' . a:item.text return a:item endfunction Describe vim-lsp-ale Before all " Set bufffer name to 'foo' file /path/to/dummy.txt End Before each call lsp#ale#_reset_prev_num_diags() call lsp#callbag#reset() call ale#other_source#reset() call lsp#ui#vim#utils#reset() call lsp#utils#mock_buf_name('/path/to/dummy.txt') let g:lsp_ale_test_mock_diags = {} let g:lsp_ale_test_mock_bufnr = bufnr('') doautocmd User lsp_setup let g:ale_want_results_buffer = bufnr('') End After each call lsp#ale#disable() End It enables vim-lsp's diagnostics and disables to output diagnostics Assert True(g:lsp_diagnostics_enabled) Assert False(g:lsp_diagnostics_highlights_enabled) Assert False(g:lsp_diagnostics_signs_enabled) Assert False(g:lsp_diagnostics_echo_cursor) Assert False(g:lsp_diagnostics_virtual_text_enabled) End It disables ALE's LSP support Assert True(g:ale_disable_lsp) End It defines plugin-lsp-ale autocmd group Assert True(exists('g:loaded_lsp_ale')) redir => autocmds autocmd plugin-lsp-ale redir END Assert True(stridx(autocmds, 'lsp_setup') >= 0, autocmds) Assert True(stridx(autocmds, 'ALEWantResults') >= 0, autocmds) End It subscribes notification stream on lsp_setup autocmd event Assert True(lsp#callbag#piped()) End It stops subscribing stream when lsp#ale#disable() is called call lsp#ale#enable() Assert True(lsp#ale#enabled()) call lsp#ale#disable() Assert False(lsp#ale#enabled()) Assert True(lsp#callbag#disposed()) call lsp#ale#disable() Assert False(lsp#ale#enabled()) End Context ALEWantResults It does not notify results when vim-lsp-ale is disabled call lsp#ale#disable() doautocmd User ALEWantResults Assert Equals(ale#other_source#last_start_checking(), v:null) End It does not notify results when the buffer disables LSP Assert Equals(ale#other_source#last_start_checking(), v:null) let g:lsp_ale_test_mock_bufnr = -1 doautocmd User ALEWantResults Assert Equals(ale#other_source#last_start_checking(), v:null) End It does not notify on no diagnostics error Assert Equals(ale#other_source#last_start_checking(), v:null) Assert Equals(ale#other_source#last_show_results(), v:null) let g:lsp_ale_test_mock_diags = {} let bufnr = bufnr('') doautocmd User ALEWantResults call ale#other_source#check_show_no_result() Assert Equals(ale#other_source#last_start_checking(), v:null) Assert Equals(ale#other_source#last_show_results(), v:null) End It notifies location list items converted from diagnostics results Assert Equals(ale#other_source#last_start_checking(), v:null) Assert Equals(ale#other_source#last_show_results(), v:null) call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs()) let g:lsp_ale_test_mock_diags = s:test_diags() let bufnr = bufnr('') doautocmd User ALEWantResults call ale#other_source#wait_until_show_results() Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) let [show_bufnr, show_name, loclist] = ale#other_source#last_show_results() Assert Equals(show_bufnr, bufnr) Assert Equals(show_name, 'vim-lsp') let expected_locs = s:test_locs()[0] call s:modify_loc_item(expected_locs[0], 'E') call s:modify_loc_item(expected_locs[1], 'W') Assert Equals(loclist, expected_locs) End It filters diagnostics results by severity Assert Equals(ale#other_source#last_start_checking(), v:null) Assert Equals(ale#other_source#last_show_results(), v:null) call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs()) let actual_diags = s:test_diags() " Set 'hint' severity. Default threshold is 'info' let actual_diags.gopls.params.diagnostics[1].severity = 4 let g:lsp_ale_test_mock_diags = actual_diags let bufnr = bufnr('') doautocmd User ALEWantResults call ale#other_source#wait_until_show_results() Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) let [show_bufnr, show_name, loclist] = ale#other_source#last_show_results() Assert Equals(show_bufnr, bufnr) Assert Equals(show_name, 'vim-lsp') Assert Equals(len(loclist), 1, string(loclist)) End It skips notifying results to ALE when no error continues to happen let bufnr = bufnr('') " Prepare empty results let diags = s:test_diags() let diags.gopls.params.diagnostics = [] let g:lsp_ale_test_mock_diags = diags " First notification doautocmd User ALEWantResults call ale#other_source#wait_until_show_results() Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) Assert Equals(ale#other_source#last_show_results(), [bufnr, 'vim-lsp', []]) call ale#other_source#reset() " Second notification doautocmd User ALEWantResults call ale#other_source#check_show_no_result() Assert Equals(ale#other_source#last_start_checking(), v:null) End End Context textDocument/publishDiagnostics notification It notifies diagnostics results to ALE Assert Equals(ale#other_source#last_start_checking(), v:null) Assert Equals(ale#other_source#last_show_results(), v:null) let bufnr = bufnr('') call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs()) let g:lsp_ale_test_mock_diags = s:test_diags() let response = { 'response': s:test_diags()['gopls'], 'server': 'gopls' } call lsp#callbag#mock_receive(response) call ale#other_source#wait_until_show_results() Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) let [show_bufnr, show_name, loclist] = ale#other_source#last_show_results() Assert Equals(show_bufnr, bufnr) Assert Equals(show_name, 'vim-lsp') let expected_locs = s:test_locs()[0] call s:modify_loc_item(expected_locs[0], 'E') call s:modify_loc_item(expected_locs[1], 'W') Assert Equals(loclist, expected_locs) End It does nothing when receiving notification other than textDocument/publishDiagnostics call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs()) let g:lsp_ale_test_mock_diags = s:test_diags() let response = { \ 'server': 'gopls', \ 'response': { \ 'method': 'something/doSomethihg', \ 'jsonrpc': '2.0', \ 'params': {}, \ } \ } call lsp#callbag#mock_receive(response) call ale#other_source#check_show_no_result() Assert Equals(ale#other_source#last_start_checking(), v:null) End It does nothing when method or server is missing in the notification call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs()) let g:lsp_ale_test_mock_diags = s:test_diags() for response in [ \ { \ 'response': { \ 'method': 'something/doSomethihg', \ 'jsonrpc': '2.0', \ 'params': {}, \ } \ }, \ { \ 'server': 'gopls', \ 'response': { \ 'jsonrpc': '2.0', \ 'params': {}, \ } \ } \ ] call lsp#callbag#mock_receive(response) endfor call ale#other_source#check_show_no_result() Assert Equals(ale#other_source#last_start_checking(), v:null) End It does nothing when received notification is for buffer which doesn't exist let bufnr = bufnr('') call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs()) let g:lsp_ale_test_mock_diags = s:test_diags() call lsp#utils#mock_buf_name('/path/to/somewhere/else.txt') let response = { 'response': s:test_diags()['gopls'], 'server': 'gopls' } call lsp#callbag#mock_receive(response) call ale#other_source#check_show_no_result() Assert Equals(ale#other_source#last_start_checking(), v:null) End It notifies empty list when notification says no lint error was found let bufnr = bufnr('') let response = { 'response': s:test_diags()['gopls'], 'server': 'gopls' } let response.response.params.diagnostics = [] call lsp#callbag#mock_receive(response) call ale#other_source#wait_until_show_results() Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) Assert Equals(ale#other_source#last_show_results(), [bufnr, 'vim-lsp', []]) End It skips sending results to ALE when no error continues to happen let bufnr = bufnr('') let diags = s:test_diags() let diags.gopls.params.diagnostics = [] " First notification let response = { 'response': diags.gopls, 'server': 'gopls' } call lsp#callbag#mock_receive(response) call ale#other_source#wait_until_show_results() Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) Assert Equals(ale#other_source#last_show_results(), [bufnr, 'vim-lsp', []]) call ale#other_source#reset() " Second notification call lsp#callbag#mock_receive(response) call ale#other_source#check_show_no_result() Assert Equals(ale#other_source#last_start_checking(), v:null) End End Describe g:lsp_ale_diagnostics_severity Before let saved_diagnostics_severity = g:lsp_ale_diagnostics_severity End After let g:lsp_ale_diagnostics_severity = saved_diagnostics_severity End It filters results by severity 'error' let g:lsp_ale_diagnostics_severity = 'error' call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs_all_severities()) let g:lsp_ale_test_mock_diags = s:test_diags_all_severities() let bufnr = bufnr('') doautocmd User ALEWantResults call ale#other_source#wait_until_show_results() Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) let expected = s:test_expected_locs_all_severities() call filter(expected, {_, l -> l.type ==# 'E'}) Assert Equals(ale#other_source#last_show_results(), [bufnr, 'vim-lsp', expected]) End It filters results by severity 'warning' let g:lsp_ale_diagnostics_severity = 'warning' call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs_all_severities()) let g:lsp_ale_test_mock_diags = s:test_diags_all_severities() let bufnr = bufnr('') doautocmd User ALEWantResults call ale#other_source#wait_until_show_results() Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) let expected = s:test_expected_locs_all_severities() call filter(expected, {_, l -> l.type =~# 'E\|W'}) Assert Equals(ale#other_source#last_show_results(), [bufnr, 'vim-lsp', expected]) End It filters results by severity 'information' let g:lsp_ale_diagnostics_severity = 'information' call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs_all_severities()) let g:lsp_ale_test_mock_diags = s:test_diags_all_severities() let bufnr = bufnr('') doautocmd User ALEWantResults call ale#other_source#wait_until_show_results() Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) let expected = s:test_expected_locs_all_severities() call filter(expected, {_, l -> l.type =~# 'E\|W\|I'}) Assert Equals(ale#other_source#last_show_results(), [bufnr, 'vim-lsp', expected]) End It filters results by severity 'hint' let g:lsp_ale_diagnostics_severity = 'hint' call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs_all_severities()) let g:lsp_ale_test_mock_diags = s:test_diags_all_severities() let bufnr = bufnr('') doautocmd User ALEWantResults call ale#other_source#wait_until_show_results() Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) let expected = s:test_expected_locs_all_severities() Assert Equals(ale#other_source#last_show_results(), [bufnr, 'vim-lsp', expected]) End It throws an error when invalid value is set let g:lsp_ale_diagnostics_severity = 'invalid!' let bufnr = bufnr('') call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs()) let g:lsp_ale_test_mock_diags = s:test_diags() call lsp#callbag#mock_receive({ 'response': s:test_diags().gopls, 'server': 'gopls' }) if has('nvim') Throws /^vim-lsp-ale: Unexpected severity/ ale#other_source#wait_until_show_results() else " XXX: No way to catch exception thrown while sleeping. Indirectly " check the error was handled correctly by checking the result is " set to empty. call ale#other_source#wait_until_show_results() Assert Equals(ale#other_source#last_show_results(), [bufnr, 'vim-lsp', []]) endif End End End " vim: set ft=vim: