Skip to content

Commit 1dbdd3c

Browse files
Use busted directly (#20)
1 parent d1ac5d5 commit 1dbdd3c

File tree

6 files changed

+133
-40
lines changed

6 files changed

+133
-40
lines changed

.busted.example

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
return {
2+
-- Use neotest-busted in all tasks
3+
_all = {
4+
lua = "nvim -l path/to/neotest-busted/scripts/test-runner.lua",
5+
},
6+
-- Default task to run if no task was specified
7+
default = {
8+
verbose = true,
9+
},
10+
integration = {
11+
tags = "integration",
12+
shuffle_files = true,
13+
},
14+
}

.github/workflows/style.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ jobs:
1616
with:
1717
token: ${{ secrets.GITHUB_TOKEN }}
1818
version: 0.16.1
19-
args: --check lua/ tests/
19+
args: --check lua/ tests/ scripts/

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,19 @@ the command will automatically try to find your tests in a `spec/`, `test/`, or
185185
$ nvim -l <path-to-neotest-busted>/scripts/test-runner.lua tests/my_spec.lua
186186
```
187187

188+
### Using busted directly
189+
190+
You can also provide a `.busted` config file and run your tests using busted.
191+
Learn more about busted configuration files from the [official
192+
docs](https://lunarmodules.github.io/busted/#usage) or take a look at the example [here](/.busted.example).
193+
194+
Pass extra arguments to `neotest` to run a specific task. For example, to run
195+
the `"integration"` task in a test file:
196+
197+
```lua
198+
require("neotest").run.run({ vim.fn.expand("%"), extra_args = { "--run", "integration" } })
199+
```
200+
188201
## Debugging tests
189202

190203
`neotest-busted` has support for debugging tests via [`local-lua-debugger-vscode`](https://github.com/tomblind/local-lua-debugger-vscode)

lua/neotest-busted/init.lua

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,10 +253,18 @@ function BustedNeotestAdapter.create_test_command(results_path, paths, filters,
253253

254254
vim.list_extend(arguments, busted_command)
255255

256-
if vim.tbl_islist(config.busted_args) and #config.busted_args > 0 then
256+
if vim.tbl_islist(config.busted_args) then
257257
vim.list_extend(arguments, config.busted_args)
258258
end
259259

260+
if vim.tbl_islist(_options.busted_arguments) then
261+
for _, busted_arg in ipairs(_options.busted_arguments) do
262+
local arg = _options.quote_strings and quote_string(busted_arg) or busted_arg
263+
264+
table.insert(arguments, arg)
265+
end
266+
end
267+
260268
-- Add test filters
261269
for _, filter in ipairs(filters) do
262270
local escaped_filter = escape_test_pattern_filter(filter)

lua/neotest-busted/types.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@
1313
---@field lua_cpaths string[]
1414

1515
---@class neotest-busted.TestCommandOptions
16+
---@field busted_arguments string[]?
1617
---@field busted_output_handler string?
1718
---@field busted_output_handler_options string[]?
18-
---@field quote_strings boolean
19+
---@field quote_strings boolean?
1920

2021
---@class neotest-busted.TestCommandConfig
2122
---@field nvim_command string

scripts/test-runner.lua

100644100755
Lines changed: 94 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
local help_message = [[test-runner [...options] [...test_files] [-- [...busted_options]
2+
3+
Run tests using neotest-busted from the commandline. Options given after '--'
4+
are forwarded to busted.
5+
6+
Usage:
7+
8+
-h, --help Show this help message.
9+
]]
10+
11+
---@class ParsedArgs
12+
---@field help boolean
13+
---@field paths string[]
14+
---@field busted_args string[]
15+
116
---@enum Color
217
local Color = {
318
Red = 31,
@@ -32,93 +47,127 @@ local level_options = {
3247
color = Color.White,
3348
hl_group = "MoreMsg",
3449
},
50+
[vim.log.levels.OFF] = {
51+
name = "",
52+
color = Color.Reset,
53+
hl_group = "",
54+
},
3555
}
3656

57+
local function is_windows()
58+
if jit then
59+
return not vim.tbl_contains({ "linux", "osx", "bsd", "posix", "other" }, jit.os:lower())
60+
else
61+
return package.config:sub(1, 1) == "\\"
62+
end
63+
end
64+
65+
local _is_windows = is_windows()
66+
3767
local function is_headless()
3868
return #vim.api.nvim_list_uis() == 0
3969
end
4070

4171
---@param color integer
4272
---@return string
4373
local function color_code(color)
74+
if _is_windows then
75+
return ""
76+
end
77+
4478
return ("\x1b[%dm"):format(color)
4579
end
4680

4781
---@param message string
4882
---@param level vim.log.levels?
4983
local function print_level(message, level)
50-
local options = level_options[level] or level_options[vim.log.levels.ERROR]
84+
local _level = level or vim.log.levels.OFF
85+
local options = level_options[_level]
86+
local prefix = ""
5187

5288
if is_headless() then
53-
io.stderr:write(
54-
("%s%s%s: %s\n"):format(
89+
if _level ~= vim.log.levels.OFF then
90+
prefix = ("%s%s%s: "):format(
5591
color_code(options.color),
5692
options.name,
57-
color_code(Color.Reset),
58-
message
93+
color_code(Color.Reset)
5994
)
60-
)
95+
end
96+
97+
io.stderr:write(("%s%s\n"):format(prefix, message))
6198
else
99+
if _level ~= vim.log.levels.OFF then
100+
prefix = ("[neotest-busted:%s]: "):format(options.name)
101+
end
102+
62103
vim.api.nvim_echo({
63-
{ ("[neotest-busted:%s]: "):format(options.name), options.hl_group },
104+
{ prefix, options.hl_group },
64105
{ message },
65106
}, true, {})
66107
end
67108
end
68109

69110
---@return string?
70111
local function find_minimal_init()
71-
-- NOTE: Do not use util.glob as we haven't loaded neotest-busted at this point
72112
local glob_matches = vim.fn.glob("**/minimal_init.lua", false, true)
73113

74114
if #glob_matches == 0 then
75-
print_level("Could not find minimal_init.lua")
115+
print_level("Could not find minimal_init.lua", vim.log.levels.ERROR)
76116
return
77117
end
78118

79119
return glob_matches[1]
80120
end
81121

82-
---@param module_name string
83-
---@return any
84-
local function require_checked(module_name)
85-
local ok, module_or_error = pcall(require, module_name)
86-
87-
if not ok then
88-
return nil
122+
---@return ParsedArgs
123+
local function parse_args()
124+
local parsed_args = {
125+
help = false,
126+
paths = {},
127+
busted_args = {},
128+
}
129+
130+
-- Start from the third argument to skip busted executable and "--ignore-lua" flag
131+
-- TODO: Should we just use them instead of skipping them?
132+
for idx = 3, #_G.arg do
133+
local arg = _G.arg[idx]
134+
135+
if arg == "-h" or arg == "--help" then
136+
parsed_args.help = true
137+
elseif arg == "--" then
138+
vim.list_extend(parsed_args.busted_args, _G.arg, idx + 1)
139+
break
140+
else
141+
table.insert(parsed_args.paths, arg)
142+
end
89143
end
90144

91-
return module_or_error
92-
end
93-
94-
---@return string[]
95-
local function parse_args()
96-
return vim.list_slice(_G.arg, 1)
145+
return parsed_args
97146
end
98147

99148
---@return string[]
100149
local function collect_tests()
101150
local tests = {}
102151
local util = require("neotest-busted.util")
103152

104-
vim.list_extend(tests, util.glob("./test/**/*_spec.lua"))
105-
vim.list_extend(tests, util.glob("./tests/**/*_spec.lua"))
106-
vim.list_extend(tests, util.glob("./spec/**/*_spec.lua"))
153+
-- TODO: Support other test file patterns (via .busted)
154+
vim.list_extend(tests, util.glob("test/**/*_spec.lua"))
155+
vim.list_extend(tests, util.glob("tests/**/*_spec.lua"))
156+
vim.list_extend(tests, util.glob("spec/**/*_spec.lua"))
107157

108158
return tests
109159
end
110160

111161
local function run()
112162
if not is_headless() then
113-
print_level("Script must be run from the command line")
163+
print_level("Script must be run from the command line", vim.log.levels.ERROR)
114164
return
115165
end
116166

117-
local paths = parse_args()
118167
local minimal_init = find_minimal_init()
119168

120169
if not minimal_init then
121-
print_level("Could not find a minimal_init.lua file")
170+
print_level("Could not find a minimal_init.lua file", vim.log.levels.ERROR)
122171
return
123172
end
124173

@@ -135,25 +184,33 @@ local function run()
135184
return
136185
end
137186

138-
if #paths == 0 then
139-
paths = collect_tests()
187+
local parsed_args = parse_args()
188+
189+
if parsed_args.help then
190+
print_level(help_message)
191+
return
140192
end
141193

142-
local busted = adapter_or_error.create_test_command(nil, paths, {}, {
194+
local paths = #parsed_args.paths > 0 and parsed_args.paths or collect_tests()
195+
196+
local test_command = adapter_or_error.create_test_command(nil, paths, {}, {
143197
busted_output_handler = "utfTerminal",
144198
busted_output_handler_options = { "--color" },
199+
-- If we don't add --ignore-lua the subsequent busted command (run via
200+
-- neovim) will use the .busted config file and use the 'lua' option
201+
-- again for running the tests (this script) which will cause an
202+
-- infinite process spawning loop
203+
busted_arguments = vim.list_extend({ "--ignore-lua" }, parsed_args.busted_args),
145204
})
146205

147-
if not busted then
148-
print_level("Could not find a busted executable")
206+
if not test_command then
207+
print_level("Could not find a busted executable", vim.log.levels.ERROR)
149208
return
150209
end
151210

152-
local command = vim.list_extend({ busted.nvim_command }, busted.arguments)
211+
local command = vim.list_extend({ test_command.nvim_command }, test_command.arguments)
153212

154-
io.stdout:write(
155-
vim.fn.system(table.concat(vim.tbl_map(vim.fn.shellescape, command), " "))
156-
)
213+
io.stdout:write(vim.fn.system(table.concat(vim.tbl_map(vim.fn.shellescape, command), " ")))
157214
end
158215

159216
run()

0 commit comments

Comments
 (0)