diff options
Diffstat (limited to 'test/fix')
-rw-r--r-- | test/fix/test_ale_fix.vader | 614 | ||||
-rw-r--r-- | test/fix/test_ale_fix_suggest.vader | 102 |
2 files changed, 716 insertions, 0 deletions
diff --git a/test/fix/test_ale_fix.vader b/test/fix/test_ale_fix.vader new file mode 100644 index 00000000..47932930 --- /dev/null +++ b/test/fix/test_ale_fix.vader @@ -0,0 +1,614 @@ +Before: + Save g:ale_fixers + Save &shell + Save g:ale_enabled + Save g:ale_fix_on_save + Save g:ale_lint_on_save + Save g:ale_echo_cursor + + silent! cd /testplugin/test/fix + + let g:ale_enabled = 0 + let g:ale_echo_cursor = 0 + let g:ale_run_synchronously = 1 + let g:ale_set_lists_synchronously = 1 + let g:ale_fix_buffer_data = {} + let g:ale_fixers = { + \ 'testft': [], + \} + + if !has('win32') + let &shell = '/bin/bash' + endif + + call ale#test#SetDirectory('/testplugin/test') + call ale#test#SetFilename('test.txt') + + function AddCarets(buffer, lines) abort + " map() is applied to the original lines here. + " This way, we can ensure that defensive copies are made. + return map(a:lines, '''^'' . v:val') + endfunction + + function AddDollars(buffer, lines) abort + return map(a:lines, '''$'' . v:val') + endfunction + + function DoNothing(buffer, lines) abort + return 0 + endfunction + + function CatLine(buffer, lines) abort + return {'command': 'cat - <(echo d)'} + endfunction + + function CatLineOneArg(buffer) abort + return {'command': 'cat - <(echo d)'} + endfunction + + function ReplaceWithTempFile(buffer, lines) abort + return {'command': 'echo x > %t', 'read_temporary_file': 1} + endfunction + + function RemoveLastLine(buffer, lines) abort + return ['a', 'b'] + endfunction + + function RemoveLastLineOneArg(buffer) abort + return ['a', 'b'] + endfunction + + function! TestCallback(buffer, output) + return [{'lnum': 1, 'col': 1, 'text': 'xxx'}] + endfunction + + function! FirstChainCallback(buffer) + return {'command': 'echo echoline', 'chain_with': 'SecondChainCallback'} + endfunction + + function! FirstChainCallbackSkipped(buffer) + return {'command': '', 'chain_with': 'SecondChainCallback'} + endfunction + + function! FirstChainCallbackSecondSkipped(buffer) + return {'command': 'echo skipit', 'chain_with': 'SecondChainCallback'} + endfunction + + function! SecondChainCallback(buffer, output) + let l:previous_line = empty(a:output) + \ ? 'emptydefault' + \ : join(split(a:output[0])) + + if l:previous_line is# 'skipit' + return {'command': '', 'chain_with': 'ThirdChainCallback'} + endif + + return { + \ 'command': 'echo ' . l:previous_line, + \ 'chain_with': 'ThirdChainCallback', + \} + endfunction + + function! ThirdChainCallback(buffer, output, input) + let l:previous_line = empty(a:output) + \ ? 'thirddefault' + \ : join(split(a:output[0])) + + return a:input + [l:previous_line] + endfunction + + function! ChainWhereLastIsSkipped(buffer) + return {'command': 'echo echoline', 'chain_with': 'ChainEndSkipped'} + endfunction + + function! ChainEndSkipped(buffer, output) + return {'command': ''} + endfunction + + " echo will output a single blank line, and we should ingore it. + function! IgnoredEmptyOutput(buffer, output) + return {'command': has('win32') ? 'echo(' : 'echo'} + endfunction + + function! EchoLineNoPipe(buffer, output) + return {'command': 'echo new line', 'read_buffer': 0} + endfunction + + function! SetUpLinters() + call ale#linter#Define('testft', { + \ 'name': 'testlinter', + \ 'callback': 'TestCallback', + \ 'executable': 'true', + \ 'command': 'true', + \}) + endfunction + + 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 + unlet! g:ale_run_synchronously + unlet! g:ale_set_lists_synchronously + unlet! g:ale_emulate_job_failure + unlet! b:ale_fixers + unlet! b:ale_fix_on_save + delfunction AddCarets + delfunction AddDollars + delfunction DoNothing + delfunction CatLine + delfunction CatLineOneArg + delfunction ReplaceWithTempFile + delfunction RemoveLastLine + delfunction RemoveLastLineOneArg + delfunction TestCallback + delfunction FirstChainCallback + delfunction FirstChainCallbackSkipped + delfunction FirstChainCallbackSecondSkipped + delfunction SecondChainCallback + delfunction ThirdChainCallback + delfunction ChainWhereLastIsSkipped + delfunction ChainEndSkipped + delfunction SetUpLinters + delfunction GetLastMessage + delfunction IgnoredEmptyOutput + delfunction EchoLineNoPipe + + call ale#test#RestoreDirectory() + + call ale#fix#registry#ResetToDefaults() + call ale#linter#Reset() + + setlocal buftype=nofile + + if filereadable('fix_test_file') + call delete('fix_test_file') + endif + + call setloclist(0, []) + + let g:ale_fix_buffer_data = {} + + " Clear the messages between tests. + echomsg '' + +Given testft (A file with three lines): + a + b + c + +Execute(ALEFix should complain when there are no functions to call): + ALEFix + AssertEqual 'No fixers have been defined. Try :ALEFixSuggest', GetLastMessage() + +Execute(ALEFix should apply simple functions): + let g:ale_fixers.testft = ['AddCarets'] + ALEFix + +Expect(The first function should be used): + ^a + ^b + ^c + +Execute(ALEFix should apply simple functions in a chain): + let g:ale_fixers.testft = ['AddCarets', 'AddDollars'] + ALEFix + +Expect(Both functions should be used): + $^a + $^b + $^c + +Execute(ALEFix should allow 0 to be returned to skip functions): + let g:ale_fixers.testft = ['DoNothing', 'AddDollars'] + ALEFix + +Expect(Only the second function should be applied): + $a + $b + $c + +Execute(ALEFix should allow commands to be run): + if has('win32') + " Just skip this test on Windows, we can't run it. + call setline(1, ['a', 'b', 'c', 'd']) + else + let g:ale_fixers.testft = ['CatLine'] + ALEFix + endif + +Expect(An extra line should be added): + a + b + c + d + +Execute(ALEFix should allow temporary files to be read): + if has('win32') + " Just skip this test on Windows, we can't run it. + call setline(1, ['x']) + 2,3d + else + let g:ale_fixers.testft = ['ReplaceWithTempFile'] + ALEFix + endif + +Expect(The line we wrote to the temporary file should be used here): + x + +Execute(ALEFix should allow jobs and simple functions to be combined): + if has('win32') + " Just skip this test on Windows, we can't run it. + call setline(1, ['$x']) + 2,3d + else + let g:ale_fixers.testft = ['ReplaceWithTempFile', 'AddDollars'] + ALEFix + endif + +Expect(The lines from the temporary file should be modified): + $x + +Execute(ALEFix should send lines modified by functions to jobs): + if has('win32') + " Just skip this test on Windows, we can't run it. + call setline(1, ['$a', '$b', '$c', 'd']) + else + let g:ale_fixers.testft = ['AddDollars', 'CatLine'] + ALEFix + endif + +Expect(The lines should first be modified by the function, then the job): + $a + $b + $c + d + +Execute(ALEFix should skip commands when jobs fail to run): + let g:ale_emulate_job_failure = 1 + let g:ale_fixers.testft = ['CatLine', 'AddDollars'] + ALEFix + +Expect(Only the second function should be applied): + $a + $b + $c + +Execute(ALEFix should handle strings for selecting a single function): + let g:ale_fixers.testft = 'AddCarets' + ALEFix + +Expect(The first function should be used): + ^a + ^b + ^c + +Execute(ALEFix should use functions from the registry): + call ale#fix#registry#Add('add_carets', 'AddCarets', [], 'Add some carets') + let g:ale_fixers.testft = ['add_carets'] + ALEFix + +Expect(The registry function should be used): + ^a + ^b + ^c + +Execute(ALEFix should be able to remove the last line for files): + let g:ale_fixers.testft = ['RemoveLastLine'] + ALEFix + +Expect(There should be only two lines): + a + b + +Execute(ALEFix should accept funcrefs): + let g:ale_fixers.testft = [function('RemoveLastLine')] + ALEFix + +Expect(There should be only two lines): + a + b + +Execute(ALEFix should accept lambdas): + if has('nvim') + " NeoVim 0.1.7 can't interpret lambdas correctly, so just set the lines + " to make the test pass. + call setline(1, ['a', 'b', 'c', 'd']) + else + let g:ale_fixers.testft = [{buffer, lines -> lines + ['d']}] + ALEFix + endif + +Expect(There should be an extra line): + a + b + c + d + +Execute(ALEFix should user buffer-local fixer settings): + let g:ale_fixers.testft = ['AddCarets', 'AddDollars'] + let b:ale_fixers = {'testft': ['RemoveLastLine']} + ALEFix + +Expect(There should be only two lines): + a + b + +Execute(ALEFix should allow Lists to be used for buffer-local fixer settings): + let g:ale_fixers.testft = ['AddCarets', 'AddDollars'] + let b:ale_fixers = ['RemoveLastLine'] + ALEFix + +Expect(There should be only two lines): + a + b + +Given testft (A file with three lines): + a + b + c + +Execute(ALEFix should save files on the save event): + let g:ale_fix_on_save = 1 + let g:ale_lint_on_save = 1 + let g:ale_enabled = 1 + + noautocmd silent file fix_test_file + call writefile(getline(1, '$'), 'fix_test_file') + + let g:ale_fixers.testft = ['AddDollars'] + + " We have to set the buftype to empty so the file will be written. + setlocal buftype= + + call SetUpLinters() + call ale#events#SaveEvent(bufnr('')) + + " We should save the file. + AssertEqual ['$a', '$b', '$c'], readfile('fix_test_file') + Assert !&modified, 'The was marked as ''modified''' + + if !has('win32') + " We should have run the linter. + AssertEqual [{ + \ 'bufnr': bufnr('%'), + \ 'lnum': 1, + \ 'vcol': 0, + \ 'col': 1, + \ 'text': 'xxx', + \ 'type': 'E', + \ 'nr': -1, + \ 'pattern': '', + \ 'valid': 1, + \}], getloclist(0) + endif + +Expect(The buffer should be modified): + $a + $b + $c + +Given testft (A file with three lines): + a + b + c + +Execute(ALEFix should still lint with no linters to be applied): + let g:ale_fix_on_save = 1 + let g:ale_lint_on_save = 1 + let g:ale_enabled = 1 + + noautocmd silent file fix_test_file + + let g:ale_fixers.testft = [] + + call SetUpLinters() + call ale#events#SaveEvent(bufnr('')) + + Assert !filereadable('fix_test_file'), 'The file should not have been saved' + + if !has('win32') + " We have run the linter. + AssertEqual [{ + \ 'bufnr': bufnr('%'), + \ 'lnum': 1, + \ 'vcol': 0, + \ 'col': 1, + \ 'text': 'xxx', + \ 'type': 'E', + \ 'nr': -1, + \ 'pattern': '', + \ 'valid': 1, + \}], getloclist(0) + endif + +Expect(The buffer should be the same): + a + b + c + +Execute(ALEFix should still lint when nothing was fixed on save): + let g:ale_fix_on_save = 1 + let g:ale_lint_on_save = 1 + let g:ale_enabled = 1 + + noautocmd silent file fix_test_file + + let g:ale_fixers.testft = ['DoNothing'] + + call SetUpLinters() + call ale#events#SaveEvent(bufnr('')) + + Assert !filereadable('fix_test_file'), 'The file should not have been saved' + + if !has('win32') + " We should have run the linter. + AssertEqual [{ + \ 'bufnr': bufnr('%'), + \ 'lnum': 1, + \ 'vcol': 0, + \ 'col': 1, + \ 'text': 'xxx', + \ 'type': 'E', + \ 'nr': -1, + \ 'pattern': '', + \ 'valid': 1, + \}], getloclist(0) + endif + +Expect(The buffer should be the same): + a + b + c + +Given testft (A file with three lines): + a + b + c + +Execute(ale#fix#InitBufferData() should set up the correct data): + noautocmd silent file fix_test_file + + call ale#fix#InitBufferData(bufnr(''), 'save_file') + + AssertEqual { + \ bufnr(''): { + \ 'temporary_directory_list': [], + \ 'vars': b:, + \ 'filename': ale#path#Winify(getcwd() . '/fix_test_file'), + \ 'done': 0, + \ 'lines_before': ['a', 'b', 'c'], + \ 'should_save': 1, + \ }, + \}, g:ale_fix_buffer_data + +Execute(ALEFix simple functions should be able to accept one argument, the buffer): + let g:ale_fixers.testft = ['RemoveLastLineOneArg'] + ALEFix + +Expect(There should be only two lines): + a + b + +Execute(b:ale_fix_on_save = 1 should override g:ale_fix_on_save = 0): + let g:ale_fix_on_save = 0 + let b:ale_fix_on_save = 1 + + let g:ale_fixers.testft = ['RemoveLastLineOneArg'] + call ale#events#SaveEvent(bufnr('')) + +Expect(There should be only two lines): + a + b + +Execute(b:ale_fix_on_save = 0 should override g:ale_fix_on_save = 1): + let g:ale_fix_on_save = 1 + let b:ale_fix_on_save = 0 + + let g:ale_fixers.testft = ['RemoveLastLineOneArg'] + call ale#events#SaveEvent(bufnr('')) + +Expect(The lines should be the same): + a + b + c + +Execute(ALEFix functions returning jobs should be able to accept one argument): + if has('win32') + " Just skip this test on Windows, we can't run it. + call setline(1, ['a', 'b', 'c', 'd']) + else + let g:ale_fixers.testft = ['CatLine'] + ALEFix + endif + +Expect(An extra line should be added): + a + b + c + d + +Execute(ALE should print a message telling you something isn't a valid fixer when you type some nonsense): + let g:ale_fixers.testft = ['CatLine', 'invalidname'] + ALEFix + + AssertEqual 'There is no fixer named `invalidname`. Check :ALEFixSuggest', GetLastMessage() + +Execute(Test fixing with chained callbacks): + let g:ale_fixers.testft = ['FirstChainCallback'] + ALEFix + + " The buffer shouldn't be piped in for earlier commands in the chain. + AssertEqual + \ [ + \ string(ale#job#PrepareCommand('echo echoline')), + \ string(ale#job#PrepareCommand('echo echoline')), + \ ], + \ map(ale#history#Get(bufnr(''))[-2:-1], 'string(v:val.command)') + +Expect(The echoed line should be added): + a + b + c + echoline + +Execute(Test fixing with chained callback where the first command is skipped): + let g:ale_fixers.testft = ['FirstChainCallbackSkipped'] + ALEFix + +Expect(The default line should be added): + a + b + c + emptydefault + +Execute(Test fixing with chained callback where the second command is skipped): + let g:ale_fixers.testft = ['FirstChainCallbackSecondSkipped'] + ALEFix + +Expect(The default line should be added): + a + b + c + thirddefault + +Execute(Test fixing with chained callback where the final callback is skipped): + let g:ale_fixers.testft = ['ChainWhereLastIsSkipped'] + ALEFix + +Expect(The lines should be the same): + a + b + c + +Execute(Empty output should be ignored): + let g:ale_fixers.testft = ['IgnoredEmptyOutput'] + ALEFix + +Expect(The lines should be the same): + a + b + c + +Execute(A temporary file shouldn't be piped into the command when disabled): + let g:ale_fixers.testft = ['EchoLineNoPipe'] + ALEFix + + AssertEqual + \ string(ale#job#PrepareCommand('echo new line')), + \ string(ale#history#Get(bufnr(''))[-1].command) + + " Remove trailing whitespace for Windows. + if has('win32') + %s/[[:space:]]*$//g + endif + +Expect(The new line should be used): + new line diff --git a/test/fix/test_ale_fix_suggest.vader b/test/fix/test_ale_fix_suggest.vader new file mode 100644 index 00000000..97227b4f --- /dev/null +++ b/test/fix/test_ale_fix_suggest.vader @@ -0,0 +1,102 @@ +Before: + call ale#fix#registry#Clear() + + let g:buffer = bufnr('') + + function GetSuggestions() + silent ALEFixSuggest + + if bufnr('') != g:buffer + let l:lines = getline(1, '$') + else + let l:lines = [] + endif + + return l:lines + endfunction + +After: + if bufnr('') != g:buffer + :q! + endif + + unlet! g:buffer + + call ale#fix#registry#ResetToDefaults() + delfunction GetSuggestions + +Execute(ALEFixSuggest should return something sensible with no suggestions): + AssertEqual + \ [ + \ 'There is nothing in the registry to suggest.', + \ '', + \ 'Press q to close this window', + \ ], + \ GetSuggestions() + +Execute(ALEFixSuggest should set the appropriate settings): + silent ALEFixSuggest + + AssertEqual 'ale-fix-suggest', &filetype + Assert !&modified, 'The buffer was marked as modified' + Assert !&modifiable, 'The buffer was modifiable' + +Execute(ALEFixSuggest output should be correct for only generic handlers): + call ale#fix#registry#Add('zed', 'XYZ', [], 'Zedify things.') + call ale#fix#registry#Add('alpha', 'XYZ', [], 'Alpha things.') + + AssertEqual + \ [ + \ 'Try the following generic fixers:', + \ '', + \ '''alpha'' - Alpha things.', + \ '''zed'' - Zedify things.', + \ '', + \ 'See :help ale-fix-configuration', + \ '', + \ 'Press q to close this window', + \ ], + \ GetSuggestions() + +Execute(ALEFixSuggest output should be correct for only filetype handlers): + let &filetype = 'testft2.testft' + + call ale#fix#registry#Add('zed', 'XYZ', ['testft2'], 'Zedify things.') + call ale#fix#registry#Add('alpha', 'XYZ', ['testft'], 'Alpha things.') + + AssertEqual + \ [ + \ 'Try the following fixers appropriate for the filetype:', + \ '', + \ '''alpha'' - Alpha things.', + \ '''zed'' - Zedify things.', + \ '', + \ 'See :help ale-fix-configuration', + \ '', + \ 'Press q to close this window', + \ ], + \ GetSuggestions() + +Execute(ALEFixSuggest should suggest filetype and generic handlers): + let &filetype = 'testft2.testft' + + call ale#fix#registry#Add('zed', 'XYZ', ['testft2'], 'Zedify things.') + call ale#fix#registry#Add('alpha', 'XYZ', ['testft'], 'Alpha things.') + call ale#fix#registry#Add('generic', 'XYZ', [], 'Generic things.') + + AssertEqual + \ [ + \ 'Try the following fixers appropriate for the filetype:', + \ '', + \ '''alpha'' - Alpha things.', + \ '''zed'' - Zedify things.', + \ '', + \ 'Try the following generic fixers:', + \ '', + \ '''generic'' - Generic things.', + \ '', + \ 'See :help ale-fix-configuration', + \ '', + \ 'Press q to close this window', + \ ], + \ GetSuggestions() |