A concentrated dose of LSP testing power!
This library is currently a work in progress and is not ready for use in other projects!
Provide an easy way to perform integration tests on language servers implemented in Rust.
First, add lspresso-shot as a dependency to your Rust project:
cargo add --dev lspresso-shot
Write a test:
#[test]
fn it_does_the_hover_thing() {
let hover_test_case = TestCase::new(
"Path to server",
TestFile::new("Source file name", "Contents")
)
.cursor_pos(Some(Position::new(0, 0)))
.other_file( // Optional
TestFile::new("Other file name", "Other contents")
);
lspresso_shot!(test_hover(
hover_test_case,
Hover {
range: Some(Range {
start: lsp_types::Position {
line: 1,
character: 2,
},
end: lsp_types::Position {
line: 1,
character: 3,
},
}),
contents: lsp_types::HoverContents::Markup(MarkupContent {
kind: lsp_types::MarkupKind::Markdown,
value: "Hover window contents here".to_string(),
})
}
));
}
That's it!
Neovim must be available on your $PATH
. See the project's documentation
for installation instructions. (TODO: Figure out what versions are compatible)
- The library's test corpus uses rust-analyzer. See
src/test.rs
for examples of how to use the library. - TODO: Add asm-lsp/other LSPs here once it's being used.
- Refactor to use the type definitions from the lsp-types crate
- Use neovim's builtin api to serialize lsp responses into JSON rather than hand-encoding information to TOML
- Try to find a better way to determine when a
$/progress
-style server has fully started up, rather than the current polling approach - Place Lua logic into dedicated files rather than as strings within the Rust files
- Clean up Lua logic (I'm unfamiliar with the neovim API)
- Add Lua unit tests? (Do we roll our own/ is there an easy framework?)
- Add CI and whatnot (Improvements to current lua workflow?)
- Rework treatement of "empty" results. This should allow for test cases in which no results are expected to be returned. After this refactor, both the rust-analyzer and dummy test cases should be augmented to match.
- For organizational purposes, we may want a separate test file for each request type. We'll definitely want to add more test coverage for each method. In addition, as consumers run into issues, we'll add additional regression tests.
- Provide a means to optionally specify the path to nvim. This will be necessary if there is a version mismatch between the user's personal installation and the version required by the lib. Also, users may not want to add nvim to their path. Maybe an environmental variable could help here?
As an eventual end goal, we'd obviously like to provide test coverage for all LSP methods. To start though, let's focus on the following TODOs:
- Create a very simple test server so we can ensure coverage of all type variants
- The basic thought here is to have the server's response defined so that it can be accessed on the Rust side by both the testing library and test server.
- There will be a simple event loop, matching against each covered request type.
- For methods with multiple return types (i.e.
textDocument/completion
, we'll have multiple predefined responses for each. The expected response type can be communicated from the test to the test server through one or more of the request params (i.e. line number).
- Sync up test server test coverage with current rust-analyzer coverage
-
textDocument/hover
-
textDocument/publishDiagnostics
-
textDocument/references
-
textDocument/definition
-
textDocument/completion
-
textDocument/formatting
-
textDocument/rename
-
textDocument/documentSymbol
- Figure out what methods we want to add next.
-
If your server undergoes some sort of indexing process at startup before it's ready to service a given request, you need to account for this by specifying
ServerStartType::Progress(NonZeroU32, String)
to the test case. TheNonZeroU32
specifies whichend
message to issue the request after (in case there are multiple). TheString
provides the relevant progress token. -
String comparison of results: Many LSP client implementations do some post processing of responses returned by a given language server, primarily removing newlines. Your expected response may need to be minimally altered from what you originally expect in order for tests to pass.
-
Variance in LSP client implementation: The LSP Spec is somewhat loosely defined, leaving plenty of room for client implementations to behave differently from one another. This project utilizes neovim's, meaning that unexpected behavior may occur when your server is used with other editors' clients.
- In addition to neovim, working on this project also requires having having
rust-analyzer 1.85 on your
$PATH
, as it is used in the project's test suite.