Functional tests setup for the LSP server (#1396)
* Functional tests setup for the LSP server * Add nix derivation for lsp-test-0.6.1.0 * Register fixture files * Enable functional tests on appveyor * Attempt to fix Position errors * Fix `dhall-lsp-server` to specify a UTF8 locale Related to https://github.com/dhall-lang/dhall-haskell/issues/1356#issuecomment-536840612 * Specify utf8 encoding for tests * Add test for hovering functionality * Add glob to list fixture files * Remove extra do
This commit is contained in:
parent
1dba96c2c8
commit
645b71d6b3
|
@ -54,7 +54,8 @@ for:
|
||||||
- chcp 65001 && stack test dhall
|
- chcp 65001 && stack test dhall
|
||||||
- stack test dhall-json
|
- stack test dhall-json
|
||||||
- stack test dhall-bash
|
- stack test dhall-bash
|
||||||
# - stack test dhall-lsp-server # Disabled while the tests are broken.
|
# - stack test dhall-lsp-server:doctest # Disabled while the tests are broken.
|
||||||
|
- stack test dhall-lsp-server:tests
|
||||||
- stack bench dhall --benchmark-arguments "--quick --min-duration=0 --include-first-iter"
|
- stack bench dhall --benchmark-arguments "--quick --min-duration=0 --include-first-iter"
|
||||||
|
|
||||||
-
|
-
|
||||||
|
|
|
@ -15,6 +15,7 @@ import Data.Monoid ((<>))
|
||||||
import qualified Data.Version
|
import qualified Data.Version
|
||||||
import qualified Dhall.LSP.Server
|
import qualified Dhall.LSP.Server
|
||||||
import qualified Paths_dhall_lsp_server
|
import qualified Paths_dhall_lsp_server
|
||||||
|
import qualified GHC.IO.Encoding
|
||||||
|
|
||||||
-- | Top-level program options
|
-- | Top-level program options
|
||||||
data Options = Options {
|
data Options = Options {
|
||||||
|
@ -74,5 +75,9 @@ runCommand Options {..} = do
|
||||||
|
|
||||||
-- | Entry point for the @dhall-lsp-server@ executable
|
-- | Entry point for the @dhall-lsp-server@ executable
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do options <- Options.Applicative.execParser parserInfoOptions
|
main = do
|
||||||
runCommand options
|
GHC.IO.Encoding.setLocaleEncoding GHC.IO.Encoding.utf8
|
||||||
|
|
||||||
|
options <- Options.Applicative.execParser parserInfoOptions
|
||||||
|
|
||||||
|
runCommand options
|
||||||
|
|
|
@ -13,6 +13,10 @@ build-type: Simple
|
||||||
extra-source-files:
|
extra-source-files:
|
||||||
README.md
|
README.md
|
||||||
ChangeLog.md
|
ChangeLog.md
|
||||||
|
tests/fixtures/completion/*.dhall
|
||||||
|
tests/fixtures/diagnostics/*.dhall
|
||||||
|
tests/fixtures/linting/*.dhall
|
||||||
|
tests/fixtures/hovering/*.dhall
|
||||||
|
|
||||||
source-repository head
|
source-repository head
|
||||||
type: git
|
type: git
|
||||||
|
@ -102,3 +106,17 @@ Test-Suite doctest
|
||||||
-- See: https://ghc.haskell.org/trac/ghc/ticket/10970
|
-- See: https://ghc.haskell.org/trac/ghc/ticket/10970
|
||||||
if impl(ghc < 8.0)
|
if impl(ghc < 8.0)
|
||||||
Buildable: False
|
Buildable: False
|
||||||
|
|
||||||
|
Test-Suite tests
|
||||||
|
Type: exitcode-stdio-1.0
|
||||||
|
Hs-Source-Dirs: tests
|
||||||
|
Main-Is: Main.hs
|
||||||
|
GHC-Options: -Wall
|
||||||
|
Build-Depends:
|
||||||
|
base ,
|
||||||
|
haskell-lsp-types >= 0.15.0 && < 0.16 ,
|
||||||
|
lsp-test >= 0.6 && < 0.7 ,
|
||||||
|
tasty >= 0.11.2 && < 1.3 ,
|
||||||
|
tasty-hspec >= 1.1 && < 1.2 ,
|
||||||
|
text >= 0.11 && < 1.3
|
||||||
|
Default-Language: Haskell2010
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
|
import Control.Monad.IO.Class (liftIO)
|
||||||
|
import Data.Maybe (fromJust)
|
||||||
|
import qualified Data.Text as T
|
||||||
|
import qualified GHC.IO.Encoding
|
||||||
|
import Language.Haskell.LSP.Test
|
||||||
|
import Language.Haskell.LSP.Types
|
||||||
|
( CompletionItem (..),
|
||||||
|
Diagnostic (..),
|
||||||
|
DiagnosticSeverity (..),
|
||||||
|
Hover (..),
|
||||||
|
HoverContents (..),
|
||||||
|
MarkupContent (..),
|
||||||
|
Position (..),
|
||||||
|
)
|
||||||
|
import Test.Tasty
|
||||||
|
import Test.Tasty.Hspec
|
||||||
|
|
||||||
|
baseDir :: FilePath -> FilePath
|
||||||
|
baseDir d = "tests/fixtures/" <> d
|
||||||
|
|
||||||
|
hoveringSpec :: FilePath -> Spec
|
||||||
|
hoveringSpec dir =
|
||||||
|
describe "Dhall.Hover"
|
||||||
|
$ it "reports types on hover"
|
||||||
|
$ runSession "dhall-lsp-server" fullCaps dir
|
||||||
|
$ do
|
||||||
|
docId <- openDoc "Types.dhall" "dhall"
|
||||||
|
let typePos = Position 0 5
|
||||||
|
functionPos = Position 2 7
|
||||||
|
extractContents = _contents . fromJust
|
||||||
|
getValue = T.unpack . _value
|
||||||
|
typeHover <- getHover docId typePos
|
||||||
|
funcHover <- getHover docId functionPos
|
||||||
|
liftIO $ do
|
||||||
|
case (extractContents typeHover, extractContents funcHover) of
|
||||||
|
(HoverContents typeContent, HoverContents functionContent) -> do
|
||||||
|
getValue typeContent `shouldBe` "Type"
|
||||||
|
getValue functionContent `shouldBe` "{ home : Text, name : Text }"
|
||||||
|
_ -> error "test failed"
|
||||||
|
pure ()
|
||||||
|
|
||||||
|
lintingSpec :: FilePath -> Spec
|
||||||
|
lintingSpec fixtureDir =
|
||||||
|
describe "Dhall.Lint" $ do
|
||||||
|
it "reports unused bindings"
|
||||||
|
$ runSession "dhall-lsp-server" fullCaps fixtureDir
|
||||||
|
$ do
|
||||||
|
_ <- openDoc "UnusedBindings.dhall" "dhall"
|
||||||
|
diags <- waitForDiagnosticsSource "Dhall.Lint"
|
||||||
|
_ <-
|
||||||
|
liftIO $
|
||||||
|
mapM
|
||||||
|
( \diag -> do
|
||||||
|
_severity diag `shouldBe` Just DsHint
|
||||||
|
T.unpack (_message diag) `shouldContain` "Unused let binding"
|
||||||
|
)
|
||||||
|
diags
|
||||||
|
pure ()
|
||||||
|
it "reports multiple hints"
|
||||||
|
$ runSession "dhall-lsp-server" fullCaps fixtureDir
|
||||||
|
$ do
|
||||||
|
_ <- openDoc "SuperfluousIn.dhall" "dhall"
|
||||||
|
diags <- waitForDiagnosticsSource "Dhall.Lint"
|
||||||
|
liftIO $ length diags `shouldBe` 2
|
||||||
|
let diag1 = head diags
|
||||||
|
diag2 = diags !! 1
|
||||||
|
liftIO $ do
|
||||||
|
_severity diag1 `shouldBe` Just DsHint
|
||||||
|
T.unpack (_message diag1) `shouldContain` "Superfluous 'in'"
|
||||||
|
_severity diag2 `shouldBe` Just DsHint
|
||||||
|
T.unpack (_message diag2) `shouldContain` "Unused let binding"
|
||||||
|
|
||||||
|
codeCompletionSpec :: FilePath -> Spec
|
||||||
|
codeCompletionSpec fixtureDir =
|
||||||
|
describe "Dhall.Completion" $ do
|
||||||
|
it "suggests user defined types"
|
||||||
|
$ runSession "dhall-lsp-server" fullCaps fixtureDir
|
||||||
|
$ do
|
||||||
|
docId <- openDoc "CustomTypes.dhall" "dhall"
|
||||||
|
cs <- getCompletions docId (Position {_line = 2, _character = 35})
|
||||||
|
liftIO $ do
|
||||||
|
let firstItem = head cs
|
||||||
|
_label firstItem `shouldBe` "Config"
|
||||||
|
_detail firstItem `shouldBe` Just "Type"
|
||||||
|
it "suggests user defined functions"
|
||||||
|
$ runSession "dhall-lsp-server" fullCaps fixtureDir
|
||||||
|
$ do
|
||||||
|
docId <- openDoc "CustomFunctions.dhall" "dhall"
|
||||||
|
cs <- getCompletions docId (Position {_line = 6, _character = 7})
|
||||||
|
liftIO $ do
|
||||||
|
let firstItem = head cs
|
||||||
|
_label firstItem `shouldBe` "makeUser"
|
||||||
|
_detail firstItem `shouldBe` Just "\8704(user : Text) \8594 { home : Text }"
|
||||||
|
it "suggests user defined bindings"
|
||||||
|
$ runSession "dhall-lsp-server" fullCaps fixtureDir
|
||||||
|
$ do
|
||||||
|
docId <- openDoc "Bindings.dhall" "dhall"
|
||||||
|
cs <- getCompletions docId (Position {_line = 0, _character = 59})
|
||||||
|
liftIO $ do
|
||||||
|
let firstItem = head cs
|
||||||
|
_label firstItem `shouldBe` "bob"
|
||||||
|
_detail firstItem `shouldBe` Just "Text"
|
||||||
|
it "suggests functions from imports"
|
||||||
|
$ runSession "dhall-lsp-server" fullCaps fixtureDir
|
||||||
|
$ do
|
||||||
|
docId <- openDoc "ImportedFunctions.dhall" "dhall"
|
||||||
|
cs <- getCompletions docId (Position {_line = 0, _character = 33})
|
||||||
|
liftIO $ do
|
||||||
|
let firstItem = head cs
|
||||||
|
_label firstItem `shouldBe` "makeUser"
|
||||||
|
_detail firstItem `shouldBe` Just "\8704(user : Text) \8594 { home : Text }"
|
||||||
|
|
||||||
|
diagnosticsSpec :: FilePath -> Spec
|
||||||
|
diagnosticsSpec fixtureDir = do
|
||||||
|
describe "Dhall.TypeCheck" $ do
|
||||||
|
it "reports unbound variables"
|
||||||
|
$ runSession "dhall-lsp-server" fullCaps fixtureDir
|
||||||
|
$ do
|
||||||
|
_ <- openDoc "UnboundVar.dhall" "dhall"
|
||||||
|
[diag] <- waitForDiagnosticsSource "Dhall.TypeCheck"
|
||||||
|
liftIO $ do
|
||||||
|
_severity diag `shouldBe` Just DsError
|
||||||
|
T.unpack (_message diag) `shouldContain` "Unbound variable"
|
||||||
|
it "reports wrong type"
|
||||||
|
$ runSession "dhall-lsp-server" fullCaps fixtureDir
|
||||||
|
$ do
|
||||||
|
_ <- openDoc "WrongType.dhall" "dhall"
|
||||||
|
[diag] <- waitForDiagnosticsSource "Dhall.TypeCheck"
|
||||||
|
liftIO $ do
|
||||||
|
_severity diag `shouldBe` Just DsError
|
||||||
|
T.unpack (_message diag) `shouldContain` "Expression doesn't match annotation"
|
||||||
|
describe "Dhall.Import" $ do
|
||||||
|
it "reports invalid imports"
|
||||||
|
$ runSession "dhall-lsp-server" fullCaps fixtureDir
|
||||||
|
$ do
|
||||||
|
_ <- openDoc "InvalidImport.dhall" "dhall"
|
||||||
|
[diag] <- waitForDiagnosticsSource "Dhall.Import"
|
||||||
|
liftIO $ do
|
||||||
|
_severity diag `shouldBe` Just DsError
|
||||||
|
T.unpack (_message diag) `shouldContain` "Invalid input"
|
||||||
|
it "reports missing imports"
|
||||||
|
$ runSession "dhall-lsp-server" fullCaps fixtureDir
|
||||||
|
$ do
|
||||||
|
_ <- openDoc "MissingImport.dhall" "dhall"
|
||||||
|
[diag] <- waitForDiagnosticsSource "Dhall.Import"
|
||||||
|
liftIO $ do
|
||||||
|
_severity diag `shouldBe` Just DsError
|
||||||
|
T.unpack (_message diag) `shouldContain` "Missing file"
|
||||||
|
describe "Dhall.Parser"
|
||||||
|
$ it "reports invalid syntax"
|
||||||
|
$ runSession "dhall-lsp-server" fullCaps fixtureDir
|
||||||
|
$ do
|
||||||
|
_ <- openDoc "InvalidSyntax.dhall" "dhall"
|
||||||
|
[diag] <- waitForDiagnosticsSource "Dhall.Parser"
|
||||||
|
liftIO $ _severity diag `shouldBe` Just DsError
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
GHC.IO.Encoding.setLocaleEncoding GHC.IO.Encoding.utf8
|
||||||
|
diagnostics <- testSpec "Diagnostics" (diagnosticsSpec (baseDir "diagnostics"))
|
||||||
|
linting <- testSpec "Linting" (lintingSpec (baseDir "linting"))
|
||||||
|
completion <- testSpec "Completion" (codeCompletionSpec (baseDir "completion"))
|
||||||
|
hovering <- testSpec "Hovering" (hoveringSpec (baseDir "hovering"))
|
||||||
|
defaultMain
|
||||||
|
( testGroup "Tests"
|
||||||
|
[ diagnostics,
|
||||||
|
linting,
|
||||||
|
completion,
|
||||||
|
hovering
|
||||||
|
]
|
||||||
|
)
|
|
@ -0,0 +1 @@
|
||||||
|
let alice = "Alice" let bob = "Bob" in { result = bob ++ al }
|
|
@ -0,0 +1,7 @@
|
||||||
|
let makeUser =
|
||||||
|
λ(user : Text)
|
||||||
|
→ let home = "/home/${user}"
|
||||||
|
|
||||||
|
in { home = home }
|
||||||
|
|
||||||
|
in [ m
|
|
@ -0,0 +1,3 @@
|
||||||
|
let Config = { name : Text, age : Natural }
|
||||||
|
|
||||||
|
in { name = "alice", age = 20 } : C
|
|
@ -0,0 +1 @@
|
||||||
|
let Lib = ./Library.dhall in Lib.
|
|
@ -0,0 +1,3 @@
|
||||||
|
let makeUser = λ(user : Text) → let home = "/home/${user}" in { home = home }
|
||||||
|
|
||||||
|
in { makeUser = makeUser }
|
|
@ -0,0 +1 @@
|
||||||
|
./InvalidSyntax.dhall
|
|
@ -0,0 +1 @@
|
||||||
|
let a = 2 + 2/
|
|
@ -0,0 +1 @@
|
||||||
|
./NonExistent.dhall
|
|
@ -0,0 +1 @@
|
||||||
|
unboundVar
|
|
@ -0,0 +1 @@
|
||||||
|
let a = "dhall" : List Text in a
|
|
@ -0,0 +1,11 @@
|
||||||
|
let User = { name : Text, home : Text }
|
||||||
|
|
||||||
|
let mkUser =
|
||||||
|
λ(_isAdmin : Bool)
|
||||||
|
→ if _isAdmin
|
||||||
|
|
||||||
|
then { name = "admin", home = "/home/admin" }
|
||||||
|
|
||||||
|
else { name = "default", home = "/home/user" }
|
||||||
|
|
||||||
|
in mkUser True : User
|
|
@ -0,0 +1,3 @@
|
||||||
|
let alice = { name = "Alice", age = 20 }
|
||||||
|
|
||||||
|
in let carl = { name = "Carl", age = 22 } in alice
|
|
@ -0,0 +1,7 @@
|
||||||
|
let alice = { name = "Alice", age = 20 }
|
||||||
|
|
||||||
|
let bob = { name = "Bob", age = 21 }
|
||||||
|
|
||||||
|
let carl = { name = "Carl", age = 22 }
|
||||||
|
|
||||||
|
in alice
|
|
@ -0,0 +1,24 @@
|
||||||
|
{ mkDerivation, aeson, aeson-pretty, ansi-terminal, async, base
|
||||||
|
, bytestring, conduit, conduit-parse, containers, data-default
|
||||||
|
, Diff, directory, filepath, haskell-lsp, hspec, lens, mtl
|
||||||
|
, parser-combinators, process, rope-utf16-splay, stdenv, text
|
||||||
|
, transformers, unix, unordered-containers
|
||||||
|
}:
|
||||||
|
mkDerivation {
|
||||||
|
pname = "lsp-test";
|
||||||
|
version = "0.6.1.0";
|
||||||
|
sha256 = "d15103bc8c84f74ff90220b66cacebe4bcd135ef1e31ddd10c808a94484db7a4";
|
||||||
|
libraryHaskellDepends = [
|
||||||
|
aeson aeson-pretty ansi-terminal async base bytestring conduit
|
||||||
|
conduit-parse containers data-default Diff directory filepath
|
||||||
|
haskell-lsp lens mtl parser-combinators process rope-utf16-splay
|
||||||
|
text transformers unix unordered-containers
|
||||||
|
];
|
||||||
|
testHaskellDepends = [
|
||||||
|
aeson base data-default haskell-lsp hspec lens text
|
||||||
|
unordered-containers
|
||||||
|
];
|
||||||
|
homepage = "https://github.com/bubba/lsp-test#readme";
|
||||||
|
description = "Functional test framework for LSP servers";
|
||||||
|
license = stdenv.lib.licenses.bsd3;
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ extra-deps:
|
||||||
- HsYAML-0.2.0.0@sha256:4e554ee481650156a26a71b40f233979cd943f22ee887b70dae3b8b24de2932f,5273
|
- HsYAML-0.2.0.0@sha256:4e554ee481650156a26a71b40f233979cd943f22ee887b70dae3b8b24de2932f,5273
|
||||||
- HsYAML-aeson-0.2.0.0@sha256:04796abfc01cffded83f37a10e6edba4f0c0a15d45bef44fc5bb4313d9c87757,1791
|
- HsYAML-aeson-0.2.0.0@sha256:04796abfc01cffded83f37a10e6edba4f0c0a15d45bef44fc5bb4313d9c87757,1791
|
||||||
- ordered-containers-0.2.2@sha256:ebf2be3f592d9cf148ea6b8375f8af97148d44f82d8d04476899285e965afdbf,810
|
- ordered-containers-0.2.2@sha256:ebf2be3f592d9cf148ea6b8375f8af97148d44f82d8d04476899285e965afdbf,810
|
||||||
|
- lsp-test-0.6.1.0@sha256:df0fc403c03b6d036be13de3ff23d9951ae2506080135cd6862eded2c969a6da,3483
|
||||||
nix:
|
nix:
|
||||||
packages:
|
packages:
|
||||||
- ncurses
|
- ncurses
|
||||||
|
|
Loading…
Reference in New Issue