packages feed

lsp-test 0.4.0.0 → 0.5.0.0

raw patch · 5 files changed

+65/−42 lines, 5 filesdep ~basePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

+ Language.Haskell.LSP.Test: [lspConfig] :: SessionConfig -> Maybe Value
- Language.Haskell.LSP.Test: SessionConfig :: Int -> Bool -> Bool -> Bool -> SessionConfig
+ Language.Haskell.LSP.Test: SessionConfig :: Int -> Bool -> Bool -> Bool -> Maybe Value -> SessionConfig

Files

README.md view
@@ -1,4 +1,4 @@-# lsp-test [![Build Status](https://travis-ci.com/Bubba/lsp-test.svg?branch=master)](https://travis-ci.com/Bubba/lsp-test) [![Hackage](https://img.shields.io/hackage/v/lsp-test.svg)](https://hackage.haskell.org/package/lsp-test-0.1.0.0)+# lsp-test [![Build Status](https://travis-ci.com/bubba/lsp-test.svg?branch=master)](https://travis-ci.com/bubba/lsp-test) [![Hackage](https://img.shields.io/hackage/v/lsp-test.svg)](https://hackage.haskell.org/package/lsp-test-0.1.0.0) lsp-test is a functional testing framework for Language Server Protocol servers.  ```haskell@@ -35,7 +35,7 @@ ```  Try out the example tests in the `example` directory with `cabal new-test`.-For more examples check the [Wiki](https://github.com/Bubba/lsp-test/wiki/Introduction)+For more examples check the [Wiki](https://github.com/bubba/lsp-test/wiki/Introduction)  ## Developing To test make sure you have the following language servers installed:
lsp-test.cabal view
@@ -1,5 +1,5 @@ name:                lsp-test-version:             0.4.0.0+version:             0.5.0.0 synopsis:            Functional test framework for LSP servers. description:   A test framework for writing tests against @@ -36,7 +36,7 @@                      , parser-combinators:Control.Applicative.Combinators   default-language:    Haskell2010   build-depends:       base >= 4.7 && < 5-                     , haskell-lsp == 0.8.*+                     , haskell-lsp >= 0.8 && < 0.9                      , aeson                      , aeson-pretty                      , ansi-terminal@@ -78,7 +78,7 @@   build-depends:       base >= 4.7 && < 5                      , hspec                      , lens-                     , haskell-lsp == 0.8.*+                     , haskell-lsp >= 0.8 && < 0.9                      , lsp-test                      , data-default                      , aeson
src/Language/Haskell/LSP/Test.hs view
@@ -155,6 +155,10 @@        sendNotification Initialized InitializedParams +      case lspConfig config of+        Just cfg -> sendNotification WorkspaceDidChangeConfiguration (DidChangeConfigurationParams cfg)+        Nothing -> return ()+       -- Run the actual test       result <- session 
src/Language/Haskell/LSP/Test/Session.hs view
@@ -1,7 +1,9 @@+{-# LANGUAGE CPP               #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}  module Language.Haskell.LSP.Test.Session   ( Session@@ -32,6 +34,9 @@ import Control.Monad import Control.Monad.IO.Class import Control.Monad.Except+#if __GLASGOW_HASKELL__ >= 806+import Control.Monad.Fail+#endif import Control.Monad.Trans.Reader (ReaderT, runReaderT) import qualified Control.Monad.Trans.Reader as Reader (ask) import Control.Monad.Trans.State (StateT, runStateT)@@ -69,17 +74,25 @@  type Session = ParserStateReader FromServerMessage SessionState SessionContext IO +#if __GLASGOW_HASKELL__ >= 806+instance MonadFail Session where+  fail s = do+    lastMsg <- fromJust . lastReceivedMessage <$> get+    liftIO $ throw (UnexpectedMessage s lastMsg)+#endif+ -- | Stuff you can configure for a 'Session'. data SessionConfig = SessionConfig   { messageTimeout :: Int  -- ^ Maximum time to wait for a message in seconds, defaults to 60.   , logStdErr      :: Bool -- ^ Redirect the server's stderr to this stdout, defaults to False.-  , logMessages    :: Bool -- ^ Trace the messages sent and received to stdout, defaults to True.+  , logMessages    :: Bool -- ^ Trace the messages sent and received to stdout, defaults to False.   , logColor       :: Bool -- ^ Add ANSI color to the logged messages, defaults to True.+  , lspConfig      :: Maybe Value -- ^ The initial LSP config as JSON value, defaults to Nothing.   }  -- | The configuration used in 'Language.Haskell.LSP.Test.runSession'. defaultConfig :: SessionConfig-defaultConfig = SessionConfig 60 False False True+defaultConfig = SessionConfig 60 False False True Nothing  instance Default SessionConfig where   def = defaultConfig@@ -148,7 +161,7 @@ runSession context state session = runReaderT (runStateT conduit state) context   where     conduit = runConduit $ chanSource .| watchdog .| updateStateC .| runConduitParser (catchError session handler)-        +     handler (Unexpected "ConduitParser.empty") = do       lastMsg <- fromJust . lastReceivedMessage <$> get       name <- getParserName@@ -257,7 +270,7 @@                 msg = NotificationMessage "2.0" TextDocumentDidOpen (DidOpenTextDocumentParams item)             liftIO $ B.hPut (serverIn ctx) $ addHeader (encode msg) -            modifyM $ \s -> do +            modifyM $ \s -> do               newVFS <- liftIO $ openVFS (vfs s) msg               return $ s { vfs = newVFS } @@ -288,14 +301,14 @@ withTimeout :: Int -> Session a -> Session a withTimeout duration f = do   chan <- asks messageChan-  timeoutId <- curTimeoutId <$> get +  timeoutId <- curTimeoutId <$> get   modify $ \s -> s { overridingTimeout = True }   liftIO $ forkIO $ do     threadDelay (duration * 1000000)     writeChan chan (TimeoutMessage timeoutId)   res <- f   modify $ \s -> s { curTimeoutId = timeoutId + 1,-                     overridingTimeout = False +                     overridingTimeout = False                    }   return res @@ -319,5 +332,5 @@         color           | t == LogServer  = Magenta           | otherwise       = Cyan-  +         showPretty = B.unpack . encodePretty
test/Test.hs view
@@ -31,21 +31,21 @@   describe "Session" $ do     it "fails a test" $       -- TODO: Catch the exception in haskell-lsp-test and provide nicer output-      let session = runSession "hie --lsp" fullCaps "test/data/renamePass" $ do+      let session = runSession "hie" fullCaps "test/data/renamePass" $ do                       openDoc "Desktop/simple.hs" "haskell"                       skipMany loggingNotification                       anyRequest         in session `shouldThrow` anyException-    it "initializeResponse" $ runSession "hie --lsp" fullCaps "test/data/renamePass" $ do+    it "initializeResponse" $ runSession "hie" fullCaps "test/data/renamePass" $ do       rsp <- initializeResponse       liftIO $ rsp ^. result `shouldNotBe` Nothing      it "runSessionWithConfig" $-      runSession "hie --lsp" didChangeCaps "test/data/renamePass" $ return ()+      runSession "hie" didChangeCaps "test/data/renamePass" $ return ()      describe "withTimeout" $ do       it "times out" $-        let sesh = runSession "hie --lsp" fullCaps "test/data/renamePass" $ do+        let sesh = runSession "hie" fullCaps "test/data/renamePass" $ do                     openDoc "Desktop/simple.hs" "haskell"                     -- won't receive a request - will timeout                     -- incoming logging requests shouldn't increase the@@ -56,12 +56,12 @@           in timeout 6000000 sesh `shouldThrow` anySessionException                  it "doesn't time out" $-        let sesh = runSession "hie --lsp" fullCaps "test/data/renamePass" $ do+        let sesh = runSession "hie" fullCaps "test/data/renamePass" $ do                     openDoc "Desktop/simple.hs" "haskell"                     withTimeout 5 $ skipManyTill anyMessage publishDiagnosticsNotification           in void $ timeout 6000000 sesh -      it "further timeout messages are ignored" $ runSession "hie --lsp" fullCaps "test/data/renamePass" $ do+      it "further timeout messages are ignored" $ runSession "hie" fullCaps "test/data/renamePass" $ do         doc <- openDoc "Desktop/simple.hs" "haskell"         withTimeout 3 $ getDocumentSymbols doc         liftIO $ threadDelay 5000000@@ -71,7 +71,7 @@        it "overrides global message timeout" $         let sesh =-              runSessionWithConfig (def { messageTimeout = 5 }) "hie --lsp" fullCaps "test/data/renamePass" $ do+              runSessionWithConfig (def { messageTimeout = 5 }) "hie" fullCaps "test/data/renamePass" $ do                 doc <- openDoc "Desktop/simple.hs" "haskell"                 -- shouldn't time out in here since we are overriding it                 withTimeout 10 $ liftIO $ threadDelay 7000000@@ -81,7 +81,7 @@        it "unoverrides global message timeout" $         let sesh =-              runSessionWithConfig (def { messageTimeout = 5 }) "hie --lsp" fullCaps "test/data/renamePass" $ do+              runSessionWithConfig (def { messageTimeout = 5 }) "hie" fullCaps "test/data/renamePass" $ do                 doc <- openDoc "Desktop/simple.hs" "haskell"                 -- shouldn't time out in here since we are overriding it                 withTimeout 10 $ liftIO $ threadDelay 7000000@@ -93,13 +93,13 @@      describe "SessionException" $ do       it "throw on time out" $-        let sesh = runSessionWithConfig (def {messageTimeout = 10}) "hie --lsp" fullCaps "test/data/renamePass" $ do+        let sesh = runSessionWithConfig (def {messageTimeout = 10}) "hie" fullCaps "test/data/renamePass" $ do                 skipMany loggingNotification                 _ <- message :: Session ApplyWorkspaceEditRequest                 return ()         in sesh `shouldThrow` anySessionException -      it "don't throw when no time out" $ runSessionWithConfig (def {messageTimeout = 5}) "hie --lsp" fullCaps "test/data/renamePass" $ do+      it "don't throw when no time out" $ runSessionWithConfig (def {messageTimeout = 5}) "hie" fullCaps "test/data/renamePass" $ do         loggingNotification         liftIO $ threadDelay 10         _ <- openDoc "Desktop/simple.hs" "haskell"@@ -109,7 +109,7 @@         it "throws when there's an unexpected message" $           let selector (UnexpectedMessage "Publish diagnostics notification" (NotLogMessage _)) = True               selector _ = False-            in runSession "hie --lsp" fullCaps "test/data/renamePass" publishDiagnosticsNotification `shouldThrow` selector+            in runSession "hie" fullCaps "test/data/renamePass" publishDiagnosticsNotification `shouldThrow` selector         it "provides the correct types that were expected and received" $           let selector (UnexpectedMessage "ResponseMessage WorkspaceEdit" (RspDocumentSymbols _)) = True               selector _ = False@@ -118,17 +118,17 @@                 sendRequest TextDocumentDocumentSymbol (DocumentSymbolParams doc)                 skipMany anyNotification                 message :: Session RenameResponse -- the wrong type-            in runSession "hie --lsp" fullCaps "test/data/renamePass" sesh+            in runSession "hie" fullCaps "test/data/renamePass" sesh               `shouldThrow` selector    describe "replaySession" $     -- This is too fickle at the moment     -- it "passes a test" $-    --   replaySession "hie --lsp" "test/data/renamePass"+    --   replaySession "hie" "test/data/renamePass"     it "fails a test" $       let selector (ReplayOutOfOrder _ _) = True           selector _ = False-        in replaySession "hie --lsp" "test/data/renameFail" `shouldThrow` selector+        in replaySession "hie" "test/data/renameFail" `shouldThrow` selector    describe "manual javascript session" $     it "passes a test" $@@ -145,7 +145,7 @@    describe "text document VFS" $     it "sends back didChange notifications" $-      runSession "hie --lsp" def "test/data/refactor" $ do+      runSession "hie" def "test/data/refactor" $ do         doc <- openDoc "Main.hs" "haskell"          let args = toJSON $ AOP (doc ^. uri)@@ -168,7 +168,7 @@    describe "getDocumentEdit" $     it "automatically consumes applyedit requests" $-      runSession "hie --lsp" fullCaps "test/data/refactor" $ do+      runSession "hie" fullCaps "test/data/refactor" $ do         doc <- openDoc "Main.hs" "haskell"          let args = toJSON $ AOP (doc ^. uri)@@ -188,7 +188,7 @@       liftIO $ action ^. title `shouldBe` "Apply hint:Redundant bracket"    describe "getAllCodeActions" $-    it "works" $ runSession "hie --lsp" fullCaps "test/data/refactor" $ do+    it "works" $ runSession "hie" fullCaps "test/data/refactor" $ do       doc <- openDoc "Main.hs" "haskell"       _ <- waitForDiagnostics       actions <- getAllCodeActions doc@@ -198,7 +198,7 @@         action ^. command . _Just . command `shouldSatisfy` T.isSuffixOf ":applyrefact:applyOne"    describe "getDocumentSymbols" $-    it "works" $ runSession "hie --lsp" fullCaps "test/data/renamePass" $ do+    it "works" $ runSession "hie" fullCaps "test/data/renamePass" $ do       doc <- openDoc "Desktop/simple.hs" "haskell"        skipMany loggingNotification@@ -213,13 +213,13 @@         mainSymbol ^. range `shouldBe` Range (Position 3 0) (Position 5 30)    describe "applyEdit" $ do-    it "increments the version" $ runSession "hie --lsp" docChangesCaps "test/data/renamePass" $ do+    it "increments the version" $ runSession "hie" docChangesCaps "test/data/renamePass" $ do       doc <- openDoc "Desktop/simple.hs" "haskell"       VersionedTextDocumentIdentifier _ (Just oldVersion) <- getVersionedDoc doc       let edit = TextEdit (Range (Position 1 1) (Position 1 3)) "foo"        VersionedTextDocumentIdentifier _ (Just newVersion) <- applyEdit doc edit       liftIO $ newVersion `shouldBe` oldVersion + 1-    it "changes the document contents" $ runSession "hie --lsp" fullCaps "test/data/renamePass" $ do+    it "changes the document contents" $ runSession "hie" fullCaps "test/data/renamePass" $ do       doc <- openDoc "Desktop/simple.hs" "haskell"       let edit = TextEdit (Range (Position 0 0) (Position 0 2)) "foo"        applyEdit doc edit@@ -227,8 +227,14 @@       liftIO $ contents `shouldSatisfy` T.isPrefixOf "foodule"    describe "getCompletions" $-    it "works" $ runSession "hie --lsp" def "test/data/renamePass" $ do+    it "works" $ runSession "hie" def "test/data/renamePass" $ do       doc <- openDoc "Desktop/simple.hs" "haskell"++      -- wait for module to be loaded+      skipMany loggingNotification+      noDiagnostics+      noDiagnostics+       item:_ <- getCompletions doc (Position 5 5)       liftIO $ do         item ^. label `shouldBe` "interactWithUser"@@ -236,7 +242,7 @@         item ^. detail `shouldBe` Just "Items -> IO ()\nMain"    describe "getReferences" $-    it "works" $ runSession "hie --lsp" fullCaps "test/data/renamePass" $ do+    it "works" $ runSession "hie" fullCaps "test/data/renamePass" $ do       doc <- openDoc "Desktop/simple.hs" "haskell"       let pos = Position 40 3 -- interactWithUser           uri = doc ^. LSP.uri@@ -248,14 +254,14 @@         ]    describe "getDefinitions" $-    it "works" $ runSession "hie --lsp" fullCaps "test/data/renamePass" $ do+    it "works" $ runSession "hie" fullCaps "test/data/renamePass" $ do       doc <- openDoc "Desktop/simple.hs" "haskell"       let pos = Position 49 25 -- addItem       defs <- getDefinitions doc pos       liftIO $ defs `shouldBe` [Location (doc ^. uri) (mkRange 28 0 28 7)]    describe "waitForDiagnosticsSource" $-    it "works" $ runSession "hie --lsp" fullCaps "test/data" $ do+    it "works" $ runSession "hie" fullCaps "test/data" $ do       openDoc "Error.hs" "haskell"       [diag] <- waitForDiagnosticsSource "ghcmod"       liftIO $ do@@ -263,13 +269,13 @@         diag ^. source `shouldBe` Just "ghcmod"    describe "rename" $-    it "works" $ runSession "hie --lsp" fullCaps "test/data" $ do+    it "works" $ runSession "hie" fullCaps "test/data" $ do       doc <- openDoc "Rename.hs" "haskell"       rename doc (Position 1 0) "bar"       documentContents doc >>= liftIO . shouldBe "main = bar\nbar = return 42\n"    describe "getHover" $-    it "works" $ runSession "hie --lsp" fullCaps "test/data/renamePass" $ do+    it "works" $ runSession "hie" fullCaps "test/data/renamePass" $ do       doc <- openDoc "Desktop/simple.hs" "haskell"       -- hover returns nothing until module is loaded       skipManyTill loggingNotification $ count 2 noDiagnostics@@ -277,21 +283,21 @@       liftIO $ hover `shouldSatisfy` isJust    describe "getHighlights" $-    it "works" $ runSession "hie --lsp" fullCaps "test/data/renamePass" $ do+    it "works" $ runSession "hie" fullCaps "test/data/renamePass" $ do       doc <- openDoc "Desktop/simple.hs" "haskell"       skipManyTill loggingNotification $ count 2 noDiagnostics       highlights <- getHighlights doc (Position 27 4) -- addItem       liftIO $ length highlights `shouldBe` 4    describe "formatDoc" $-    it "works" $ runSession "hie --lsp" fullCaps "test/data" $ do+    it "works" $ runSession "hie" fullCaps "test/data" $ do       doc <- openDoc "Format.hs" "haskell"       oldContents <- documentContents doc       formatDoc doc (FormattingOptions 4 True)       documentContents doc >>= liftIO . (`shouldNotBe` oldContents)    describe "formatRange" $-    it "works" $ runSession "hie --lsp" fullCaps "test/data" $ do+    it "works" $ runSession "hie" fullCaps "test/data" $ do       doc <- openDoc "Format.hs" "haskell"       oldContents <- documentContents doc       formatRange doc (FormattingOptions 4 True) (Range (Position 1 10) (Position 2 10))@@ -300,7 +306,7 @@   describe "closeDoc" $     it "works" $       let sesh =-            runSession "hie --lsp" fullCaps "test/data" $ do+            runSession "hie" fullCaps "test/data" $ do               doc <- openDoc "Format.hs" "haskell"               closeDoc doc               -- need to evaluate to throw