Merge pull request #15259 from muniter/muniter/checkhealth-from-lua

feat(checkhealth): support Lua healthchecks
This commit is contained in:
Matthieu Coudron
2021-10-05 11:27:07 +02:00
committed by GitHub
9 changed files with 445 additions and 135 deletions

View File

@@ -26,8 +26,8 @@ endfunction
" Runs all discovered healthchecks if a:plugin_names is empty. " Runs all discovered healthchecks if a:plugin_names is empty.
function! health#check(plugin_names) abort function! health#check(plugin_names) abort
let healthchecks = empty(a:plugin_names) let healthchecks = empty(a:plugin_names)
\ ? s:discover_health_checks() \ ? s:discover_healthchecks()
\ : s:to_fn_names(a:plugin_names) \ : s:get_healthcheck(a:plugin_names)
tabnew tabnew
setlocal wrap breakindent linebreak setlocal wrap breakindent linebreak
@@ -42,24 +42,28 @@ function! health#check(plugin_names) abort
else else
redraw|echo 'Running healthchecks...' redraw|echo 'Running healthchecks...'
for c in healthchecks for c in healthchecks
let output = '' let [name, func, type] = c
call append('$', split(printf("\n%s\n%s", c, repeat('=',72)), "\n")) let s:output = []
try try
let output = "\n\n".execute('call '.c.'()') if func == ''
throw 'healthcheck_not_found'
endif
eval type == 'v' ? call(func, []) : luaeval(func)
catch catch
if v:exception =~# '^Vim\%((\a\+)\)\=:E117.*\V'.c let s:output = [] " Clear the output
let output = execute( if v:exception =~# 'healthcheck_not_found'
\ 'call health#report_error(''No healthcheck found for "' call health#report_error('No healthcheck found for "'.name.'" plugin.')
\ .s:to_plugin_name(c)
\ .'" plugin.'')')
else else
let output = execute( call health#report_error(printf(
\ 'call health#report_error(''Failed to run healthcheck for "' \ "Failed to run healthcheck for \"%s\" plugin. Exception:\n%s\n%s",
\ .s:to_plugin_name(c) \ name, v:throwpoint, v:exception))
\ .'" plugin. Exception:''."\n".v:throwpoint."\n".v:exception)')
endif endif
endtry endtry
call append('$', split(output, "\n") + ['']) let header = [name. ': ' . func, repeat('=', 72)]
" remove empty line after header from report_start
let s:output = s:output[0] == '' ? s:output[1:] : s:output
let s:output = header + s:output + ['']
call append('$', s:output)
redraw redraw
endfor endfor
endif endif
@@ -71,9 +75,13 @@ function! health#check(plugin_names) abort
redraw|echo '' redraw|echo ''
endfunction endfunction
function! s:collect_output(output)
let s:output += split(a:output, "\n", 1)
endfunction
" Starts a new report. " Starts a new report.
function! health#report_start(name) abort function! health#report_start(name) abort
echo "\n## " . a:name call s:collect_output("\n## " . a:name)
endfunction endfunction
" Indents lines *except* line 1 of a string if it contains newlines. " Indents lines *except* line 1 of a string if it contains newlines.
@@ -119,21 +127,21 @@ endfunction " }}}
" Use {msg} to report information in the current section " Use {msg} to report information in the current section
function! health#report_info(msg) abort " {{{ function! health#report_info(msg) abort " {{{
echo s:format_report_message('INFO', a:msg) call s:collect_output(s:format_report_message('INFO', a:msg))
endfunction " }}} endfunction " }}}
" Reports a successful healthcheck. " Reports a successful healthcheck.
function! health#report_ok(msg) abort " {{{ function! health#report_ok(msg) abort " {{{
echo s:format_report_message('OK', a:msg) call s:collect_output(s:format_report_message('OK', a:msg))
endfunction " }}} endfunction " }}}
" Reports a health warning. " Reports a health warning.
" a:1: Optional advice (string or list) " a:1: Optional advice (string or list)
function! health#report_warn(msg, ...) abort " {{{ function! health#report_warn(msg, ...) abort " {{{
if a:0 > 0 if a:0 > 0
echo s:format_report_message('WARNING', a:msg, a:1) call s:collect_output(s:format_report_message('WARNING', a:msg, a:1))
else else
echo s:format_report_message('WARNING', a:msg) call s:collect_output(s:format_report_message('WARNING', a:msg))
endif endif
endfunction " }}} endfunction " }}}
@@ -141,37 +149,52 @@ endfunction " }}}
" a:1: Optional advice (string or list) " a:1: Optional advice (string or list)
function! health#report_error(msg, ...) abort " {{{ function! health#report_error(msg, ...) abort " {{{
if a:0 > 0 if a:0 > 0
echo s:format_report_message('ERROR', a:msg, a:1) call s:collect_output(s:format_report_message('ERROR', a:msg, a:1))
else else
echo s:format_report_message('ERROR', a:msg) call s:collect_output(s:format_report_message('ERROR', a:msg))
endif endif
endfunction " }}} endfunction " }}}
function! s:filepath_to_function(name) abort " From a path return a list [{name}, {func}, {type}] representing a healthcheck
return substitute(substitute(substitute(a:name, '.*autoload[\/]', '', ''), function! s:filepath_to_healthcheck(path) abort
\ '\.vim', '#check', ''), '[\/]', '#', 'g') if a:path =~# 'vim$'
let name = matchstr(a:path, '\zs[^\/]*\ze\.vim$')
let func = 'health#'.name.'#check'
let type = 'v'
else
let base_path = substitute(a:path,
\ '.*lua[\/]\(.\{-}\)[\/]health\([\/]init\)\?\.lua$',
\ '\1', '')
let name = substitute(base_path, '[\/]', '.', 'g')
let func = 'require("'.name.'.health").check()'
let type = 'l'
endif
return [name, func, type]
endfunction endfunction
function! s:discover_health_checks() abort function! s:discover_healthchecks() abort
let healthchecks = globpath(&runtimepath, 'autoload/health/*.vim', 1, 1) return s:get_healthcheck('*')
let healthchecks = map(healthchecks, '<SID>filepath_to_function(v:val)')
return healthchecks
endfunction endfunction
" Translates a list of plugin names to healthcheck function names. " Returns list of lists [ [{name}, {func}, {type}] ] representing healthchecks
function! s:to_fn_names(plugin_names) abort function! s:get_healthcheck(plugin_names) abort
let healthchecks = [] let healthchecks = []
let plugin_names = type('') ==# type(a:plugin_names) let plugin_names = type('') == type(a:plugin_names)
\ ? split(a:plugin_names, ' ', v:false) \ ? split(a:plugin_names, ' ', v:false)
\ : a:plugin_names \ : a:plugin_names
for p in plugin_names for p in plugin_names
call add(healthchecks, 'health#'.p.'#check') " support vim/lsp/health{/init/}.lua as :checkhealth vim.lsp
let p = substitute(p, '\.', '/', 'g')
let p = substitute(p, '*$', '**', 'g') " find all submodule e.g vim*
let paths = nvim_get_runtime_file('autoload/health/'.p.'.vim', v:true)
\ + nvim_get_runtime_file('lua/**/'.p.'/health/init.lua', v:true)
\ + nvim_get_runtime_file('lua/**/'.p.'/health.lua', v:true)
if len(paths) == 0
let healthchecks += [[p, '', '']] " healthchek not found
else
let healthchecks += map(uniq(sort(paths)),
\'<SID>filepath_to_healthcheck(v:val)')
end
endfor endfor
return healthchecks return healthchecks
endfunction endfunction
" Extracts 'foo' from 'health#foo#check'.
function! s:to_plugin_name(fn_name) abort
return substitute(a:fn_name,
\ '\v.*health\#(.+)\#check.*', '\1', '')
endfunction

View File

@@ -23,27 +23,102 @@ Commands *health-commands*
*:checkhealth* *:CheckHealth* *:checkhealth* *:CheckHealth*
:checkhealth Run all healthchecks. :checkhealth Run all healthchecks.
*E5009* *E5009*
Nvim depends on |$VIMRUNTIME| and 'runtimepath' to find Nvim depends on |$VIMRUNTIME|, 'runtimepath' and 'packpath' to
the standard "runtime files" for syntax highlighting, find the standard "runtime files" for syntax highlighting,
filetype-specific behavior, and standard plugins filetype-specific behavior, and standard plugins (including
(including :checkhealth). If the runtime files cannot :checkhealth). If the runtime files cannot be found then
be found then those features will not work. those features will not work.
:checkhealth {plugins} :checkhealth {plugins}
Run healthcheck(s) for one or more plugins. E.g. to run Run healthcheck(s) for one or more plugins. E.g. to run only
only the standard Nvim healthcheck: > the standard Nvim healthcheck: >
:checkhealth nvim :checkhealth nvim
< To run the healthchecks for the "foo" and "bar" plugins <
(assuming these plugins are on your 'runtimepath' and To run the healthchecks for the "foo" and "bar" plugins
they have implemented health#foo#check() and (assuming these plugins are on 'runtimepath' or 'packpath' and
health#bar#check(), respectively): > they have implemented the Lua or Vimscript interface
require("foo.health").check() and health#bar#check(),
respectively): >
:checkhealth foo bar :checkhealth foo bar
<
To run healthchecks for lua submodules, use dot notation or
"*" to refer to all submodules. For example nvim provides
`vim.lsp` and `vim.treesitter` >
:checkhealth vim.lsp vim.treesitter
:checkhealth vim*
< <
============================================================================== ==============================================================================
Functions *health-functions* Lua Functions *health-functions-lua* *health-lua*
health.vim functions are for creating new healthchecks. They mostly just do The Lua "health" module can be used to create new healthchecks (see also
some layout and formatting, to give users a consistent presentation. |health-functions-vim|). To get started, simply use: >
local health = require('health')
<
health.report_start({name}) *health.report_start()*
Starts a new report. Most plugins should call this only once, but if
you want different sections to appear in your report, call this once
per section.
health.report_info({msg}) *health.report_info()*
Reports an informational message.
health.report_ok({msg}) *health.report_ok()*
Reports a "success" message.
health.report_warn({msg} [, {advice}]) *health.report_warn()*
Reports a warning. {advice} is an optional List of suggestions.
health.report_error({msg} [, {advice}]) *health.report_error()*
Reports an error. {advice} is an optional List of suggestions.
==============================================================================
Create a Lua healthcheck *health-dev-lua*
Healthchecks are functions that check the user environment, configuration,
etc. Nvim has built-in healthchecks in $VIMRUNTIME/autoload/health/.
To add a new healthcheck for your own plugin, simply define a Lua module in
your plugin that returns a table with a "check()" function. |:checkhealth|
will automatically find and invoke this function.
If your plugin is named "foo", then its healthcheck module should be a file in
one of these locations on 'runtimepath' or 'packpath':
- `lua/foo/health/init.lua`
- `lua/foo/health.lua`
If your plugin provides a submodule named "bar" for which you want a separate
healthcheck, define the healthcheck at one of these locations on 'runtimepath'
or 'packpath':
- `lua/foo/bar/health/init.lua`
- `lua/foo/bar/health.lua`
All submodules should return a Lua table containing the method `check()`.
Copy this sample code into `lua/foo/health/init.lua` or `lua/foo/health.lua`,
replacing "foo" in the path with your plugin name: >
local M = {}
local health = require("health")
M.check = function()
health.report_start("my_plugin report")
-- make sure setup function parameters are ok
if check_setup() then
health.report_ok("Setup function is correct")
else
health.report_error("Setup function is incorrect")
end
-- do some more checking
-- ...
end
return M
==============================================================================
Vimscript Functions *health-functions-vimscript* *health-vimscript*
health.vim functions are for creating new healthchecks. (See also
|health-functions-lua|)
health#report_start({name}) *health#report_start* health#report_start({name}) *health#report_start*
Starts a new report. Most plugins should call this only once, but if Starts a new report. Most plugins should call this only once, but if
@@ -56,10 +131,10 @@ health#report_info({msg}) *health#report_info*
health#report_ok({msg}) *health#report_ok* health#report_ok({msg}) *health#report_ok*
Reports a "success" message. Reports a "success" message.
health#report_warn({msg}, [{advice}]) *health#report_warn* health#report_warn({msg} [, {advice}]) *health#report_warn*
Reports a warning. {advice} is an optional List of suggestions. Reports a warning. {advice} is an optional List of suggestions.
health#report_error({msg}, [{advice}]) *health#report_error* health#report_error({msg} [, {advice}]) *health#report_error*
Reports an error. {advice} is an optional List of suggestions. Reports an error. {advice} is an optional List of suggestions.
health#{plugin}#check() *health.user_checker* health#{plugin}#check() *health.user_checker*
@@ -71,12 +146,8 @@ health#{plugin}#check() *health.user_checker*
silent call s:check_python_configuration() silent call s:check_python_configuration()
endfunction endfunction
< <
All output will be captured from the healthcheck. Use the
health#report_* functions so that your healthcheck has a format
consistent with the standard healthchecks.
============================================================================== ==============================================================================
Create a healthcheck *health-dev* Create a healthcheck *health-dev-vim*
Healthchecks are functions that check the user environment, configuration, Healthchecks are functions that check the user environment, configuration,
etc. Nvim has built-in healthchecks in $VIMRUNTIME/autoload/health/. etc. Nvim has built-in healthchecks in $VIMRUNTIME/autoload/health/.
@@ -88,7 +159,7 @@ health#{plugin}#check() function in autoload/health/{plugin}.vim.
If your plugin is named "foo", then its healthcheck function must be > If your plugin is named "foo", then its healthcheck function must be >
health#foo#check() health#foo#check()
defined in this file on 'runtimepath': > defined in this file on 'runtimepath' or 'packpath': >
autoload/health/foo.vim autoload/health/foo.vim
Copy this sample code into autoload/health/foo.vim and replace "foo" with your Copy this sample code into autoload/health/foo.vim and replace "foo" with your
@@ -106,6 +177,4 @@ plugin name: >
endif endif
endfunction endfunction
============================================================================== vim:noet tw=78:ts=8:ft=help:fdm=marker
vim:tw=78:ts=8:ft=help:fdm=marker

23
runtime/lua/health.lua Normal file
View File

@@ -0,0 +1,23 @@
local M = {}
function M.report_start(msg)
vim.fn['health#report_start'](msg)
end
function M.report_info(msg)
vim.fn['health#report_info'](msg)
end
function M.report_ok(msg)
vim.fn['health#report_ok'](msg)
end
function M.report_warn(msg, ...)
vim.fn['health#report_warn'](msg, ...)
end
function M.report_error(msg, ...)
vim.fn['health#report_error'](msg, ...)
end
return M

View File

@@ -230,7 +230,22 @@ static int compl_match_arraysize;
static int compl_startcol; static int compl_startcol;
static int compl_selected; static int compl_selected;
/// |:checkhealth| completion items
///
/// Regenerates on every new command line prompt, to accomodate changes on the
/// runtime files.
typedef struct {
garray_T names; // healthcheck names
unsigned last_gen; // last_prompt_id where names were generated
} CheckhealthComp;
/// Cookie used when converting filepath to name
struct healthchecks_cookie {
garray_T *names; // global healthchecks
bool is_lua; // true if the current entry is a Lua healthcheck
};
static CheckhealthComp healthchecks = { GA_INIT(sizeof(char_u *), 10), 0 };
#ifdef INCLUDE_GENERATED_DECLARATIONS #ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ex_getln.c.generated.h" # include "ex_getln.c.generated.h"
@@ -273,6 +288,68 @@ static void init_incsearch_state(incsearch_state_T *s)
save_viewstate(&s->old_viewstate); save_viewstate(&s->old_viewstate);
} }
/// Completion for |:checkhealth| command.
///
/// Given to ExpandGeneric() to obtain all available heathcheck names.
/// @param[in] idx Index of the healthcheck item.
/// @param[in] xp Not used.
static char_u *get_healthcheck_names(expand_T *xp, int idx)
{
// Generate the first time or on new prompt.
if (healthchecks.last_gen == 0 || healthchecks.last_gen != last_prompt_id) {
ga_clear_strings(&healthchecks.names);
char *patterns[3] = { "autoload/health/**.vim", "lua/**/**/health/init.lua", // NOLINT
"lua/**/**/health.lua" }; // NOLINT
for (int i = 0; i < 3; i++) {
struct healthchecks_cookie hcookie = { .names = &healthchecks.names, .is_lua = i != 0 };
do_in_runtimepath((char_u *)patterns[i], DIP_ALL, get_healthcheck_cb, &hcookie);
if (healthchecks.names.ga_len > 0) {
ga_remove_duplicate_strings(&healthchecks.names);
}
}
// Tracked to regenerate items on next prompt.
healthchecks.last_gen = last_prompt_id;
}
return idx <
(int)healthchecks.names.ga_len ? ((char_u **)(healthchecks.names.ga_data))[idx] : NULL;
}
/// Transform healthcheck file path into it's name.
///
/// Used as a callback for do_in_runtimepath
/// @param[in] path Expanded path to a possible healthcheck.
/// @param[out] cookie Array where names will be inserted.
static void get_healthcheck_cb(char_u *path, void *cookie)
{
if (path != NULL) {
struct healthchecks_cookie *hcookie = (struct healthchecks_cookie *)cookie;
char *pattern;
char *sub = "\\1";
char_u *res;
if (hcookie->is_lua) {
// Lua: transform "../lua/vim/lsp/health.lua" into "vim.lsp"
pattern = ".*lua[\\/]\\(.\\{-}\\)[\\/]health\\([\\/]init\\)\\?\\.lua$";
} else {
// Vim: transform "../autoload/health/provider.vim" into "provider"
pattern = ".*[\\/]\\([^\\/]*\\)\\.vim$";
}
res = do_string_sub(path, (char_u *)pattern, (char_u *)sub, NULL, (char_u *)"g");
if (hcookie->is_lua && res != NULL) {
// Replace slashes with dots as represented by the healthcheck plugin.
char_u *ares = do_string_sub(res, (char_u *)"[\\/]", (char_u *)".", NULL, (char_u *)"g");
xfree(res);
res = ares;
}
if (res != NULL) {
GA_APPEND(char_u *, hcookie->names, res);
}
}
}
// Return true when 'incsearch' highlighting is to be done. // Return true when 'incsearch' highlighting is to be done.
// Sets search_first_line and search_last_line to the address range. // Sets search_first_line and search_last_line to the address range.
static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_state_T *s, static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_state_T *s,
@@ -4902,10 +4979,6 @@ static int ExpandFromContext(expand_T *xp, char_u *pat, int *num_file, char_u **
char *directories[] = { "syntax", "indent", "ftplugin", NULL }; char *directories[] = { "syntax", "indent", "ftplugin", NULL };
return ExpandRTDir(pat, DIP_LUA, num_file, file, directories); return ExpandRTDir(pat, DIP_LUA, num_file, file, directories);
} }
if (xp->xp_context == EXPAND_CHECKHEALTH) {
char *directories[] = { "autoload/health", NULL };
return ExpandRTDir(pat, 0, num_file, file, directories);
}
if (xp->xp_context == EXPAND_USER_LIST) { if (xp->xp_context == EXPAND_USER_LIST) {
return ExpandUserList(xp, num_file, file); return ExpandUserList(xp, num_file, file);
} }
@@ -4982,6 +5055,7 @@ static int ExpandFromContext(expand_T *xp, char_u *pat, int *num_file, char_u **
{ EXPAND_ENV_VARS, get_env_name, true, true }, { EXPAND_ENV_VARS, get_env_name, true, true },
{ EXPAND_USER, get_users, true, false }, { EXPAND_USER, get_users, true, false },
{ EXPAND_ARGLIST, get_arglist_name, true, false }, { EXPAND_ARGLIST, get_arglist_name, true, false },
{ EXPAND_CHECKHEALTH, get_healthcheck_names, true, false },
}; };
int i; int i;

View File

@@ -0,0 +1,8 @@
function! health#full_render#check()
call health#report_start("report 1")
call health#report_ok("life is fine")
call health#report_warn("no what installed", ["pip what", "make what"])
call health#report_start("report 2")
call health#report_info("stuff is stable")
call health#report_error("why no hardcopy", [":h :hardcopy", ":h :TOhtml"])
endfunction

View File

@@ -0,0 +1,11 @@
local M = {}
local health = require("health")
M.check = function()
health.report_start("report 1")
health.report_ok("everything is fine")
health.report_start("report 2")
health.report_ok("nothing to see here")
end
return M

View File

@@ -0,0 +1,11 @@
local M = {}
local health = require("health")
M.check = function()
health.report_start("report 1")
health.report_ok("everything is fine")
health.report_start("report 2")
health.report_ok("nothing to see here")
end
return M

View File

@@ -0,0 +1,12 @@
local M = {}
local health = require("health")
M.check = function()
health.report_start("report 1")
health.report_ok("everything is fine")
health.report_warn("About to add a number to nil")
local a = nil + 2
return a
end
return M

View File

@@ -1,4 +1,5 @@
local helpers = require('test.functional.helpers')(after_each) local helpers = require('test.functional.helpers')(after_each)
local global_helpers = require('test.helpers')
local Screen = require('test.functional.ui.screen') local Screen = require('test.functional.ui.screen')
local clear = helpers.clear local clear = helpers.clear
@@ -35,6 +36,7 @@ describe(':checkhealth', function()
clear() clear()
eq('nvim', getcompletion('nvim', 'checkhealth')[1]) eq('nvim', getcompletion('nvim', 'checkhealth')[1])
eq('provider', getcompletion('prov', 'checkhealth')[1]) eq('provider', getcompletion('prov', 'checkhealth')[1])
eq('vim.lsp', getcompletion('vim.ls', 'checkhealth')[1])
end) end)
end) end)
@@ -48,42 +50,34 @@ describe('health.vim', function()
command("set runtimepath+=test/functional/fixtures") command("set runtimepath+=test/functional/fixtures")
end) end)
it("health#report_*()", function()
helpers.source([[
let g:health_report = execute([
\ "call health#report_start('Check Bar')",
\ "call health#report_ok('Bar status')",
\ "call health#report_ok('Other Bar status')",
\ "call health#report_warn('Zub')",
\ "call health#report_start('Baz')",
\ "call health#report_warn('Zim', ['suggestion 1', 'suggestion 2'])"
\ ])
]])
local result = helpers.eval("g:health_report")
helpers.eq(helpers.dedent([[
## Check Bar
- OK: Bar status
- OK: Other Bar status
- WARNING: Zub
## Baz
- WARNING: Zim
- ADVICE:
- suggestion 1
- suggestion 2]]),
result)
end)
describe(":checkhealth", function() describe(":checkhealth", function()
it("concatenates multiple reports", function() it("functions health#report_*() render correctly", function()
command("checkhealth success1 success2") command("checkhealth full_render")
helpers.expect([[ helpers.expect([[
health#success1#check full_render: health#full_render#check
========================================================================
## report 1
- OK: life is fine
- WARNING: no what installed
- ADVICE:
- pip what
- make what
## report 2
- INFO: stuff is stable
- ERROR: why no hardcopy
- ADVICE:
- :help |:hardcopy|
- :help |:TOhtml|
]])
end)
it("concatenates multiple reports", function()
command("checkhealth success1 success2 test_plug")
helpers.expect([[
success1: health#success1#check
======================================================================== ========================================================================
## report 1 ## report 1
- OK: everything is fine - OK: everything is fine
@@ -91,25 +85,109 @@ describe('health.vim', function()
## report 2 ## report 2
- OK: nothing to see here - OK: nothing to see here
health#success2#check success2: health#success2#check
======================================================================== ========================================================================
## another 1 ## another 1
- OK: ok - OK: ok
test_plug: require("test_plug.health").check()
========================================================================
## report 1
- OK: everything is fine
## report 2
- OK: nothing to see here
]]) ]])
end) end)
it("lua plugins", function()
command("checkhealth test_plug")
helpers.expect([[
test_plug: require("test_plug.health").check()
========================================================================
## report 1
- OK: everything is fine
## report 2
- OK: nothing to see here
]])
end)
it("lua plugins submodules", function()
command("checkhealth test_plug.submodule")
helpers.expect([[
test_plug.submodule: require("test_plug.submodule.health").check()
========================================================================
## report 1
- OK: everything is fine
## report 2
- OK: nothing to see here
]])
end)
it("lua plugins submodules with expression '*'", function()
command("checkhealth test_plug*")
local buf_lines = helpers.curbuf('get_lines', 0, -1, true)
-- avoid dealing with path separators
local received = table.concat(buf_lines, '\n', 1, #buf_lines - 2)
local expected = helpers.dedent([[
test_plug: require("test_plug.health").check()
========================================================================
## report 1
- OK: everything is fine
## report 2
- OK: nothing to see here
test_plug.submodule: require("test_plug.submodule.health").check()
========================================================================
## report 1
- OK: everything is fine
## report 2
- OK: nothing to see here
test_plug.submodule_failed: require("test_plug.submodule_failed.health").check()
========================================================================
- ERROR: Failed to run healthcheck for "test_plug.submodule_failed" plugin. Exception:
function health#check, line 24]])
eq(expected, received)
end)
it("gracefully handles broken healthcheck", function() it("gracefully handles broken healthcheck", function()
command("checkhealth broken") command("checkhealth broken")
helpers.expect([[ helpers.expect([[
health#broken#check broken: health#broken#check
======================================================================== ========================================================================
- ERROR: Failed to run healthcheck for "broken" plugin. Exception: - ERROR: Failed to run healthcheck for "broken" plugin. Exception:
function health#check[21]..health#broken#check, line 1 function health#check[24]..health#broken#check, line 1
caused an error caused an error
]]) ]])
end) end)
it("gracefully handles broken lua healthcheck", function()
command("checkhealth test_plug.submodule_failed")
local buf_lines = helpers.curbuf('get_lines', 0, -1, true)
local received = table.concat(buf_lines, '\n', 1, #buf_lines - 2)
-- avoid dealing with path separators
local lua_err = "attempt to perform arithmetic on a nil value"
local last_line = buf_lines[#buf_lines - 1]
assert(string.find(last_line, lua_err) ~= nil, "Lua error not present")
local expected = global_helpers.dedent([[
test_plug.submodule_failed: require("test_plug.submodule_failed.health").check()
========================================================================
- ERROR: Failed to run healthcheck for "test_plug.submodule_failed" plugin. Exception:
function health#check, line 24]])
eq(expected, received)
end)
it("highlights OK, ERROR", function() it("highlights OK, ERROR", function()
local screen = Screen.new(72, 10) local screen = Screen.new(72, 10)
screen:attach() screen:attach()
@@ -126,11 +204,11 @@ describe('health.vim', function()
command("set laststatus=0") command("set laststatus=0")
screen:expect{grid=[[ screen:expect{grid=[[
^ | ^ |
{Heading:health#foo#check} | {Heading:foo: } |
{Bar:========================================================================}| {Bar:========================================================================}|
{Bullet: -} {Error:ERROR:} No healthcheck found for "foo" plugin. | {Bullet: -} {Error:ERROR:} No healthcheck found for "foo" plugin. |
| |
{Heading:health#success1#check} | {Heading:success1: health#success1#check} |
{Bar:========================================================================}| {Bar:========================================================================}|
{Heading2:##}{Heading: report 1} | {Heading2:##}{Heading: report 1} |
{Bullet: -} {Ok:OK:} everything is fine | {Bullet: -} {Ok:OK:} everything is fine |
@@ -140,9 +218,10 @@ describe('health.vim', function()
it("gracefully handles invalid healthcheck", function() it("gracefully handles invalid healthcheck", function()
command("checkhealth non_existent_healthcheck") command("checkhealth non_existent_healthcheck")
-- luacheck: ignore 613
helpers.expect([[ helpers.expect([[
health#non_existent_healthcheck#check non_existent_healthcheck:
======================================================================== ========================================================================
- ERROR: No healthcheck found for "non_existent_healthcheck" plugin. - ERROR: No healthcheck found for "non_existent_healthcheck" plugin.
]]) ]])