diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -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:
diff --git a/lsp-test.cabal b/lsp-test.cabal
--- a/lsp-test.cabal
+++ b/lsp-test.cabal
@@ -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
diff --git a/src/Language/Haskell/LSP/Test.hs b/src/Language/Haskell/LSP/Test.hs
--- a/src/Language/Haskell/LSP/Test.hs
+++ b/src/Language/Haskell/LSP/Test.hs
@@ -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
 
diff --git a/src/Language/Haskell/LSP/Test/Session.hs b/src/Language/Haskell/LSP/Test/Session.hs
--- a/src/Language/Haskell/LSP/Test/Session.hs
+++ b/src/Language/Haskell/LSP/Test/Session.hs
@@ -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
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -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
