module ErrorSpec where import qualified Control.Exception as X import Polysemy import Polysemy.Async import Polysemy.Error import Polysemy.Resource import Test.Hspec newtype MyExc = MyExc String deriving (Show, Eq) instance X.Exception MyExc spec :: Spec spec = parallel $ do describe "fromException" $ do it "should catch exceptions" $ do a <- runM $ runError $ fromException @MyExc $ do _ <- X.throwIO $ MyExc "hello" pure () a `shouldBe` (Left $ MyExc "hello") it "should not catch non-exceptions" $ do a <- runM $ runError @MyExc $ fromException @MyExc $ pure () a `shouldBe` Right () it "should happen before Resource" $ do a <- runFinal $ embedToFinal @IO $ resourceToIOFinal $ runError @MyExc $ do onException (fromException @MyExc $ do _ <- X.throwIO $ MyExc "hello" pure () ) $ pure $ error "this exception shouldn't happen" a `shouldBe` (Left $ MyExc "hello") describe "errorToIOFinal" $ do it "should catch errors only for the interpreted Error" $ do res1 <- runFinal $ errorToIOFinal @() $ errorToIOFinal @() $ do raise $ throw () `catch` \() -> return () res1 `shouldBe` Right (Right ()) res2 <- runFinal $ errorToIOFinal @() $ errorToIOFinal @() $ do raise (throw ()) `catch` \() -> return () res2 `shouldBe` Left () it "should propagate errors thrown in 'async'" $ do res1 <- runFinal $ errorToIOFinal @() $ asyncToIOFinal $ do a <- async $ throw () await a res1 `shouldBe` (Left () :: Either () (Maybe ())) res2 <- runFinal $ errorToIOFinal @() $ asyncToIOFinal $ do a <- async $ throw () await a `catch` \() -> return $ Just () res2 `shouldBe` Right (Just ())