polysemy/test/InspectorSpec.hs
Sandy Maguire 82f86add29
Custom type error testing (#113)
This PR adds doctests allowing us to write tests for the custom type errors. Having this stuff reified in the test suite means we can iterate on the implementations and give much better QA.
2019-06-15 20:04:11 -04:00

78 lines
1.7 KiB
Haskell

{-# LANGUAGE TemplateHaskell #-}
module InspectorSpec where
import Control.Monad
import Data.IORef
import Polysemy
import Polysemy.Error
import Polysemy.State
import Test.Hspec
data Callback m a where
Callback :: m String -> Callback m ()
makeSem ''Callback
spec :: Spec
spec = parallel $ describe "Inspector" $ do
it "should inspect State effects" $ do
withNewTTY $ \ref -> do
void . (runM .@ runCallback ref)
. runState False
$ do
sendM $ pretendPrint ref "hello world"
callback $ show <$> get @Bool
modify not
callback $ show <$> get @Bool
result <- readIORef ref
result `shouldContain` ["hello world"]
result `shouldContain` ["False", "True"]
it "should not inspect thrown Error effects" $ do
withNewTTY $ \ref -> do
void . (runM .@ runCallback ref)
. runError @()
$ do
callback $ throw ()
callback $ pure "nice"
result <- readIORef ref
result `shouldContain` [":(", "nice"]
runCallback
:: Member (Lift IO) r
=> IORef [String]
-> (forall x. Sem r x -> IO x)
-> Sem (Callback ': r) a
-> Sem r a
runCallback ref lower = interpretH $ \case
Callback cb -> do
cb' <- runT cb
ins <- getInspectorT
sendM $ doCB ref $ do
v <- lower .@ runCallback ref $ cb'
pure $ maybe ":(" id $ inspect ins v
getInitialStateT
doCB :: IORef [String] -> IO String -> IO ()
doCB ref m = m >>= pretendPrint ref
pretendPrint :: IORef [String] -> String -> IO ()
pretendPrint ref msg = modifyIORef ref (++ [msg])
withNewTTY :: (IORef [String] -> IO a) -> IO a
withNewTTY f = do
ref <- newIORef []
f ref