Before: Save g:ale_echo_msg_format Save g:ale_echo_cursor Save b:ale_lint_on_insert_leave let g:ale_echo_msg_format = '%code: %%s' let b:ale_lint_on_insert_leave = 0 " 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': 'bettercode', \ 'nr': -1, \ 'type': 'W', \ 'code': 'semi', \ 'text': 'Ignore me.', \ }, \ { \ 'lnum': 1, \ 'col': 10, \ 'bufnr': bufnr('%'), \ 'vcol': 0, \ 'linter_name': 'bettercode', \ 'nr': -1, \ 'type': 'E', \ 'code': 'semi', \ 'text': "Missing semicolon.\r", \ 'detail': "Every statement should end with a semicolon\nsecond line", \ }, \ { \ 'lnum': 1, \ 'col': 14, \ 'bufnr': bufnr('%'), \ 'vcol': 0, \ 'linter_name': 'bettercode', \ 'nr': -1, \ 'type': 'I', \ 'text': 'Some information', \ }, \ { \ 'lnum': 2, \ 'col': 10, \ 'bufnr': bufnr('%'), \ 'vcol': 0, \ 'linter_name': 'bettercode', \ 'nr': -1, \ 'type': 'W', \ 'code': 'space-infix-ops', \ 'text': 'Infix operators must be spaced.', \ }, \ { \ 'lnum': 2, \ 'col': 15, \ 'bufnr': bufnr('%'), \ 'vcol': 0, \ 'linter_name': 'bettercode', \ 'nr': -1, \ 'type': 'E', \ 'code': 'radix', \ 'text': 'Missing radix parameter', \ }, \ { \ 'lnum': 3, \ 'col': 1, \ 'bufnr': bufnr('%'), \ 'vcol': 0, \ 'linter_name': 'bettercode', \ '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 runtime autoload/ale/cursor.vim let g:last_message = '' function! ale#cursor#Echom(message) abort let g:last_message = a:message endfunction call ale#linter#Reset() call ale#linter#PreventLoading('javascript') After: Restore unlet! g:last_message runtime autoload/ale/cursor.vim 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 " 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 call ale#linter#Reset() 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.', g:last_message 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.', g:last_message Execute(Messages should be shown for later columns): call cursor(2, 16) call ale#cursor#EchoCursorWarning() AssertEqual 'radix: Missing radix parameter', g:last_message 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.', g:last_message 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.', g:last_message 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', g:last_message 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 \ 'bettercode: Infix operators must be spaced.', \ g:last_message 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.', \ g:last_message call cursor(1, 10) call ale#cursor#EchoCursorWarning() AssertEqual 'Error: Missing semicolon.', g:last_message call cursor(1, 14) call ale#cursor#EchoCursorWarning() AssertEqual 'Info: Some information', g:last_message 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.', \ g:last_message 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', g:last_message 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', g:last_message Execute(The cursor message shouldn't be echoed if the option is off): let g:ale_echo_cursor = 0 let g:last_message = 'foo' call cursor(1, 1) call ale#cursor#EchoCursorWarning() AssertEqual 'foo', g:last_message