content: module CaptureSpec where
  
  import Test.Hspec
  
  import Polysemy
  import Polysemy.Capture
  import Polysemy.Writer
  import Polysemy.Reader
  import Polysemy.Error
  
  test1 :: (String, Maybe ())
  test1 =
      run
    . runReader (1 :: Int)
    . runWriter
    . runCapture
    $ do
    capture $ \c -> do
      _ <- local (+1) (c ())
      _ <- censor (show . (+2) . (read :: String -> Int)) (c ())
      tell "important"
      local (+3) (c ())
    j <- ask
    tell (show j)
  
  test2 :: (String, Maybe ())
  test2 =
      run
    . runReader (1 :: Int)
    . runWriter
    . runCapture
    $ do
    delimit $ capture $ \c -> do
      _ <- local (+1) (c ())
      _ <- local (+2) (c ())
      tell "important"
      local (+3) (c ())
    j <- ask
    tell (show j)
  
  test3 :: (String, Maybe ())
  test3 =
      run
    . runReader (1 :: Int)
    . runWriter
    . runCapture
    $ do
    censor (++"!") $ capture $ \c -> do
      _ <- local (+1) (c ())
      _ <- local (+2) (c ())
      tell "important"
      local (+3) (c ())
    j <- ask
    tell (show j)
  
  test4 :: Maybe (String, ())
  test4 =
      run
    . runReader (1 :: Int)
    . runCapture
    . runWriter
    $ do
    capture $ \c -> do
      _ <- local (+1) (c ())
      _ <- local (+2) (c ())
      tell "important"
      local (+3) (c ())
    j <- ask
    tell (show j)
  
  test5 :: Maybe (Either () ())
  test5 =
      run
    . runCapture
    . runError
    $ do
    capture $ \_ -> do
      throw ()
  
  test6 :: Maybe (Either () ())
  test6 =
      run
    . runCapture
    . runError
    $ do
    r <- delimit' $ capture $ \_ -> do
      throw ()
    case r of
      Just g -> return g
      _      -> return ()
  
  spec :: Spec
  spec = do
    describe "runCapture" $ do
      it "should have global state semantics, and\
       \ have higher-order effects affect continuations" $
        test1 `shouldBe` ("23important4", Just ())
  
      it "should have global state semantics, but\
       \ 'delimit' should delimit the continuation." $
        test2 `shouldBe` ("important1", Just ())
  
      it "should have global state semantics, and\
          \ 'censor' should delimit the continuation" $
        test3 `shouldBe` ("important!1", Just ())
  
      it "should treat writer with local state semantics, but\
         \ reader with global state semantics." $
        test4 `shouldBe` Just ("4", ())
  
      it "should fail from failing locally" $
        test5 `shouldBe` Nothing
  
      it "should recover from failing locally" $
        test6 `shouldBe` Just (Right ())
  