Skip to content

Commit f36a376

Browse files
authored
chore(test): replace unit-style specs with e2e integration tests (#498)
* chore(test): replace unit-style specs with e2e integration tests Old specs only checked LSP attach/capabilities against an empty buffer. New integration_spec runs against a real Maven fixture project (copied to a temp dir so root markers resolve correctly) and exercises plugin features end-to-end: jdtls attach, extension bundling, project import, dap config, diagnostics, built-in runner, test runner, report viewer, profile UI and runtime switching. Closes #497 * fix(pkgm): downloads and extractions fail on Windows when 'shell' is pwsh vim.fn.system() with a command string is parsed by &shell; nvim nightly on Windows defaults &shell to pwsh, breaking cmd.exe-style quoting. Pass argv lists so no shell is involved.
1 parent bb12076 commit f36a376

20 files changed

Lines changed: 554 additions & 210 deletions

File tree

.github/workflows/test.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ on:
99
jobs:
1010
test:
1111
runs-on: ${{ matrix.os }}
12+
timeout-minutes: 40
1213
strategy:
14+
fail-fast: false
1315
matrix:
1416
os: [ubuntu-latest, macos-latest, windows-latest]
1517
nvim-versions: ["stable", "nightly"]

.luacheckrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ globals = {
55
'vim.bo',
66
'vim.opt',
77
'vim.lsp',
8+
'vim.ui',
89
}
910
read_globals = {
1011
'vim',

CLAUDE.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,22 +76,22 @@ plugin/java.lua # User command registration
7676

7777
```
7878
tests/
79-
├── assets/ # Test fixtures and assets (e.g., HelloWorld.java)
80-
├── constants/ # Test constants (e.g., capabilities.lua)
79+
├── fixtures/ # Test projects (e.g., demo/ - Maven project with JUnit tests)
8180
├── utils/ # Test utilities and config files
8281
│ ├── lsp-utils.lua # LSP test helpers
82+
│ ├── project.lua # Fixture project + wait/assert helpers
8383
│ ├── prepare-config.lua # Lazy.nvim test setup
84-
│ └── test-config.lua # Manual test setup
84+
│ └── test-config.lua # Minimal init for plenary child nvim
8585
└── specs/ # Test specifications
86-
├── lsp_spec.lua # All LSP-related tests
87-
└── pkgm_spec.lua # All pkgm-related tests
86+
└── integration_spec.lua # End-to-end plugin feature tests
8887
```
8988

9089
**Test Guidelines:**
91-
- Group related tests in single spec file (e.g., all pkgm tests in `pkgm_spec.lua`)
90+
- Tests are end-to-end: real Neovim + real JDTLS against fixture Maven project
91+
- Fixture projects are copied to a temp dir at runtime (root markers prefer `.git`, so they must run outside the repo)
92+
- Spec `it` blocks run sequentially and share JDTLS session state; order matters
9293
- Extract reusable logic to `utils/` to keep test steps clean
93-
- Store test data/fixtures in `assets/`
94-
- Store constants (capabilities, expected values) in `constants/`
94+
- Store test projects in `fixtures/`
9595

9696
## Code Patterns
9797

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ TESTS_ROOT=tests
33
TESTS_DIR?=${TESTS_ROOT}/specs
44
PREPARE_CONFIG=${TESTS_ROOT}/utils/prepare-config.lua
55
TEST_CONFIG=${TESTS_ROOT}/utils/test-config.lua
6-
TEST_TIMEOUT?=60000
6+
TEST_TIMEOUT?=600000
77

88
.PHONY: test tests lint format all
99

lua/pkgm/downloaders/curl.lua

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,17 @@ end
3939
---@return string|nil # Error message if failed
4040
function Curl:download()
4141
log.debug('curl downloading:', self.url, 'to', self.dest)
42-
local cmd = string.format(
43-
'curl --retry %d --connect-timeout %d -o %s %s',
44-
self.retry_count,
45-
self.timeout,
46-
vim.fn.shellescape(self.dest),
47-
vim.fn.shellescape(self.url)
48-
)
42+
-- argv list so no shell quoting is involved
43+
local cmd = {
44+
'curl',
45+
'--retry',
46+
tostring(self.retry_count),
47+
'--connect-timeout',
48+
tostring(self.timeout),
49+
'-o',
50+
self.dest,
51+
self.url,
52+
}
4953
log.debug('curl command:', cmd)
5054

5155
local result = vim.fn.system(cmd)

lua/pkgm/downloaders/powershell.lua

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,19 @@ function PowerShell:download()
4949
self.dest
5050
)
5151

52-
local cmd = string.format(
53-
-- luacheck: ignore
54-
"%s -NoProfile -NonInteractive -Command \"$ProgressPreference = 'SilentlyContinue'; $ErrorActionPreference = 'Stop'; [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; %s\"",
52+
-- pass an argv list so no shell is involved; a single command string
53+
-- breaks when &shell is pwsh (nvim nightly default on Windows)
54+
local cmd = {
5555
pwsh,
56-
pwsh_cmd
57-
)
56+
'-NoProfile',
57+
'-NonInteractive',
58+
'-Command',
59+
string.format(
60+
-- luacheck: ignore
61+
"$ProgressPreference = 'SilentlyContinue'; $ErrorActionPreference = 'Stop'; [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; %s",
62+
pwsh_cmd
63+
),
64+
}
5865
log.debug('PowerShell command:', cmd)
5966

6067
local result = vim.fn.system(cmd)

lua/pkgm/downloaders/wget.lua

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,17 @@ end
3939
---@return string|nil # Error message if failed
4040
function Wget:download()
4141
log.debug('wget downloading:', self.url, 'to', self.dest)
42-
local cmd = string.format(
43-
'wget -t %d -T %d -O %s %s',
44-
self.retry_count,
45-
self.timeout,
46-
vim.fn.shellescape(self.dest),
47-
vim.fn.shellescape(self.url)
48-
)
42+
-- argv list so no shell quoting is involved
43+
local cmd = {
44+
'wget',
45+
'-t',
46+
tostring(self.retry_count),
47+
'-T',
48+
tostring(self.timeout),
49+
'-O',
50+
self.dest,
51+
self.url,
52+
}
4953
log.debug('wget command:', cmd)
5054

5155
local result = vim.fn.system(cmd)

lua/pkgm/extractors/powershell.lua

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,19 @@ function PowerShellExtractor:extract()
4242
self.dest
4343
)
4444

45-
local cmd = string.format(
46-
--luacheck: ignore
47-
"%s -NoProfile -NonInteractive -Command \"$ProgressPreference = 'SilentlyContinue'; $ErrorActionPreference = 'Stop'; %s\"",
45+
-- pass an argv list so no shell is involved; a single command string
46+
-- breaks when &shell is pwsh (nvim nightly default on Windows)
47+
local cmd = {
4848
pwsh,
49-
pwsh_cmd
50-
)
49+
'-NoProfile',
50+
'-NonInteractive',
51+
'-Command',
52+
string.format(
53+
-- luacheck: ignore
54+
"$ProgressPreference = 'SilentlyContinue'; $ErrorActionPreference = 'Stop'; %s",
55+
pwsh_cmd
56+
),
57+
}
5158
log.debug('PowerShell command:', cmd)
5259

5360
local result = vim.fn.system(cmd)

lua/pkgm/extractors/tar.lua

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,27 +37,24 @@ function Tar:extract()
3737
log.debug('tar extracting:', self.source, 'to', self.dest)
3838
log.debug('Using tar binary:', tar_cmd)
3939

40-
local cmd
40+
local source = self.source
41+
local dest = self.dest
42+
43+
-- argv list so no shell quoting is involved (&shell may be pwsh on
44+
-- Windows nvim nightly)
45+
local cmd = { tar_cmd, '--no-same-owner' }
46+
4147
if system.get_os() == 'win' then
4248
-- Windows: convert backslashes to forward slashes (tar accepts them)
43-
local source = self.source:gsub('\\', '/')
44-
local dest = self.dest:gsub('\\', '/')
45-
cmd = string.format(
46-
'%s --no-same-owner %s -xf "%s" -C "%s"',
47-
tar_cmd,
48-
self:tar_supports_force_local(tar_cmd) and '--force-local' or '',
49-
source,
50-
dest
51-
)
52-
else
53-
-- Unix: use shellescape
54-
cmd = string.format(
55-
'%s --no-same-owner -xf %s -C %s',
56-
tar_cmd,
57-
vim.fn.shellescape(self.source),
58-
vim.fn.shellescape(self.dest)
59-
)
49+
source = source:gsub('\\', '/')
50+
dest = dest:gsub('\\', '/')
51+
52+
if self:tar_supports_force_local(tar_cmd) then
53+
table.insert(cmd, '--force-local')
54+
end
6055
end
56+
57+
vim.list_extend(cmd, { '-xf', source, '-C', dest })
6158
log.debug('tar command:', cmd)
6259

6360
local result = vim.fn.system(cmd)

lua/pkgm/extractors/unzip.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ end
2121
---@return string|nil # Error message if failed
2222
function Unzip:extract()
2323
log.debug('unzip extracting:', self.source, 'to', self.dest)
24-
local cmd = string.format('unzip -q -o %s -d %s', vim.fn.shellescape(self.source), vim.fn.shellescape(self.dest))
24+
-- argv list so no shell quoting is involved
25+
local cmd = { 'unzip', '-q', '-o', self.source, '-d', self.dest }
2526
log.debug('unzip command:', cmd)
2627

2728
local result = vim.fn.system(cmd)

0 commit comments

Comments
 (0)