ionide / FsAutoComplete

F# language server using Language Server Protocol
Other
417 stars 154 forks source link

Need tests for the Fixes.resolveNamespace function #706

Open ScottHutchinson opened 3 years ago

ScottHutchinson commented 3 years ago

There doesn't seem to be any test coverage of the Fixes.resolveNamespace function.

If I can figure out how to do it, I'll add some tests myself.

baronfel commented 3 years ago

There's a bunch of state that has to be set up just right to test codefixes in general, so I'll outline that process here for posterity:

Process overview

we'll be making a test that will:

details

test data

Code fix test data should probably go in a new subfolder of the test/FsAutoComplete.Tests.Lsp/TestCases directory. Inside that directory you can have any project or script file structure you think is relevant to your tests.

create lsp server keyed to your data

There's a bunch of setup here, but in general you'll want to use the serverInitialize function to start a server at some path with a particular configuration of settings. This can go about a billion different ways, all I can say is to check other tests for examples.

Collect diagnostics for a file

once you have a server, you'll want to call server.TextDocumentDidOpen to simulate an open of a file. This will trigger type checking. You can wait for typechecking of that file, and reporting of diagnostics on that file, by using the waitForParseResultsForFile helper function from the Helpers module of the tests project. Once you have those diagnostics, you can start making assertions on them

create the payload

once you have diagnostics, you can use them to create a payload to ask the server what code actions are available at a given position:

let context : CodeActionParams =
   { TextDocument = { Uri = Path.FilePathToUri scriptPath }
     Range = { Start = { Line = 3; Character = 13 }; End = {Line = 3; Character = 13} }
     Context = {
      Diagnostics = [| diags.[0] |]
    }
   }

This the important parts are:

call the codefix function

with this context, you can call server.TextDocumentCodeAction context and match on the results of the call. if you did everything right, the payload will have data that you can match on to do assertions

perform assertions

As a sample, something like the following could be used to check if the open was suggested for the System namespace when the user asked for code actions on the string TimeSpan in a script file. The exact line numbers might not match up exactly, but in general something similar to this would be used. Depending on the kinds of suggestions the codefix you want to test suggestions, your assertions might look different. Here I'm saying that open System should have been suggested at the beginning of the second line.

match server.TextDocumentCodeAction context |> Async.RunSynchronously with
| Ok (Some (TextDocumentCodeActionResult.CodeActions actions)) ->
  Expect.exists actions
   (function
    | { Kind = Some "fix"
        Edit = { DocumentChanges = Some [| {Edits = [| { NewText = "open System"; Range = { Start = {  Line = 2; Character = 0 }; End = { Line = 2; Character = 0 }} } |] }  |] } } -> true
    | _ -> false)
    "should have found a matching diagnostic"
| _ -> failwith "code actions should have returned actions for this file"

A working end-to-end test of this kind can be seen here

baronfel commented 3 years ago

Since this post was written a harness for codefixes has been added to the test suite, so it should be very easy to bring this code fix under test now, following the patterns from the other tests in CodeFixTests.fs