Before: Save g:ale_echo_msg_format Save g:ale_echo_cursor " We should prefer the error message at column 10 instead of the warning. let g:ale_buffer_info = { \ bufnr('%'): { \ 'loclist': [ \ { \ 'lnum': 1, \ 'col': 10, \ 'bufnr': bufnr('%'), \ 'vcol': 0, \ 'linter_name': 'eslint', \ 'nr': -1, \ 'type': 'W', \ 'code': 'semi', \ 'text': 'Ignore me.', \ }, \ { \ 'lnum': 1, \ 'col': 10, \ 'bufnr': bufnr('%'), \ 'vcol': 0, \ 'linter_name': 'eslint', \ 'nr': -1, \ 'type': 'E', \ 'code': 'semi', \ 'text': 'Missing semicolon.', \ 'detail': "Every statement should end with a semicolon\nsecond line", \ }, \ { \ 'lnum': 1, \ 'col': 14, \ 'bufnr': bufnr('%'), \ 'vcol': 0, \ 'linter_name': 'eslint', \ 'nr': -1, \ 'type': 'I', \ 'text': 'Some information', \ }, \ { \ 'lnum': 2, \ 'col': 10, \ 'bufnr': bufnr('%'), \ 'vcol': 0, \ 'linter_name': 'eslint', \ 'nr': -1, \ 'type': 'W', \ 'code': 'space-infix-ops', \ 'text': 'Infix operators must be spaced.', \ }, \ { \ 'lnum': 2, \ 'col': 15, \ 'bufnr': bufnr('%'), \ 'vcol': 0, \ 'linter_name': 'eslint', \ 'nr': -1, \ 'type': 'E', \ 'code': 'radix', \ 'text': 'Missing radix parameter', \ }, \ { \ 'lnum': 3, \ 'col': 1, \ 'bufnr': bufnr('%'), \ 'vcol': 0, \ 'linter_name': 'eslint', \ 'nr': -1, \ 'type': 'E', \ 'text': 'lowercase error', \ }, \ ], \ }, \} " Turn off other features, we only care about this one feature in this test. let g:ale_set_loclist = 0 let g:ale_set_signs = 0 let g:ale_set_highlights = 0 let g:ale_echo_cursor = 1 function GetLastMessage() redir => l:output silent mess redir END let l:lines = split(l:output, "\n") return empty(l:lines) ? '' : l:lines[-1] endfunction After: Restore call cursor(1, 1) let g:ale_set_loclist = 1 let g:ale_set_signs = 1 let g:ale_set_highlights = 1 let g:ale_buffer_info = {} unlet! g:output unlet! b:ale_loclist_msg_format delfunction GetLastMessage " Clearing the messages breaks tests on NeoVim for some reason, but all " we need to do for these tests is just make it so the last message isn't " carried over between test cases. echomsg '' " Close the preview window if it's open. if &filetype is# 'ale-preview' noautocmd :q! endif Given javascript(A Javscript file with warnings/errors): var x = 3 + 12345678 var x = 5*2 + parseInt("10"); // comment Execute(Messages should be shown for the correct lines): call cursor(1, 1) call ale#cursor#EchoCursorWarning() AssertEqual 'semi: Missing semicolon.', GetLastMessage() Execute(Messages should be shown for earlier columns): call cursor(2, 1) call ale#cursor#EchoCursorWarning() AssertEqual 'space-infix-ops: Infix operators must be spaced.', GetLastMessage() Execute(Messages should be shown for later columns): call cursor(2, 16) call ale#cursor#EchoCursorWarning() AssertEqual 'radix: Missing radix parameter', GetLastMessage() Execute(The message at the cursor should be shown when linting ends): call cursor(1, 1) call ale#engine#SetResults( \ bufnr('%'), \ g:ale_buffer_info[bufnr('%')].loclist, \) AssertEqual 'semi: Missing semicolon.', GetLastMessage() Execute(The message at the cursor should be shown on InsertLeave): call cursor(2, 9) doautocmd InsertLeave AssertEqual 'space-infix-ops: Infix operators must be spaced.', GetLastMessage() Execute(ALEDetail should print 'detail' attributes): call cursor(1, 1) ALEDetail AssertEqual \ ['Every statement should end with a semicolon', 'second line'], \ getline(1, '$') Execute(ALEDetail should print regular 'text' attributes): call cursor(2, 10) ALEDetail " ALEDetail opens a window, so check the text in it. AssertEqual \ ['Infix operators must be spaced.'], \ getline(1, '$') Execute(ALEDetail should not capitlise cursor messages): call cursor(3, 1) call ale#cursor#EchoCursorWarning() AssertEqual 'lowercase error', GetLastMessage() Execute(The linter name should be formatted into the message correctly): let g:ale_echo_msg_format = '%linter%: %s' call cursor(2, 9) call ale#cursor#EchoCursorWarning() AssertEqual \ 'eslint: Infix operators must be spaced.', \ GetLastMessage() Execute(The severity should be formatted into the message correctly): let g:ale_echo_msg_format = '%severity%: %s' call cursor(2, 9) call ale#cursor#EchoCursorWarning() AssertEqual \ 'Warning: Infix operators must be spaced.', \ GetLastMessage() call cursor(1, 10) call ale#cursor#EchoCursorWarning() AssertEqual 'Error: Missing semicolon.', GetLastMessage() call cursor(1, 14) call ale#cursor#EchoCursorWarning() AssertEqual 'Info: Some information', GetLastMessage() Execute(The %code% and %ifcode% should show the code and some text): let g:ale_echo_msg_format = '%(code) %%s' call cursor(2, 9) call ale#cursor#EchoCursorWarning() AssertEqual \ '(space-infix-ops) Infix operators must be spaced.', \ GetLastMessage() Execute(The %code% and %ifcode% should be removed when there's no code): let g:ale_echo_msg_format = '%(code) %%s' call cursor(1, 14) call ale#cursor#EchoCursorWarning() AssertEqual 'Some information', GetLastMessage() Execute(The buffer message format option should take precedence): let g:ale_echo_msg_format = '%(code) %%s' let b:ale_echo_msg_format = 'FOO %s' call cursor(1, 14) call ale#cursor#EchoCursorWarning() AssertEqual 'FOO Some information', GetLastMessage() Execute(The cursor message shouldn't be echoed if the option is off): let g:ale_echo_cursor = 0 echom 'foo' call cursor(1, 1) call ale#cursor#EchoCursorWarning() AssertEqual 'foo', GetLastMessage()