module Test.ParserSpec where import Data.List (isInfixOf) import Effectful import Effectful.Error.Static import Effectful.NonDet import Skeletest import Skeletest.Predicate qualified as P import Telescope.Data.Parser spec :: Spec spec = do describe "Data.Parser" $ do describe "parsing" $ do it "parses something" $ do res <- runParseTest $ do pure "hello" res `shouldBe` Right ("hello" :: String) it "can handle alternatives" $ do let pa = pure () res <- runParseTest pa res `shouldBe` Right () let pb = pure () res2 <- runParseTest $ runParserAlts (parseFail "Empty") empty res2 `shouldSatisfy` P.left P.anything res3 <- runParseTest $ runParserAlts (parseFail "Empty") (empty <|> pb) res3 `shouldBe` Right () describe "location " $ do it "changes failure to location" $ do res <- runParseTest $ do parseAt (Child "hello") $ parseAt (Index 2) $ do parseFail "nope" case res of Left (ParseFailure path err) -> do path `shouldBe` Path [Child "hello", Index 2] err `shouldBe` "nope" Right _ -> failTest "Expected failure" it "gives good expected messages" $ do res :: Either ParseError () <- runParseTest $ do parseAt (Child "child") $ parseAt (Index 2) $ expected "Number" (1 :: Int) ("child/2" `isInfixOf` show res) `shouldBe` True ("1" `isInfixOf` show res) `shouldBe` True ("Number" `isInfixOf` show res) `shouldBe` True runParseTest :: Eff [Parser, Error ParseError, IOE] a -> IO (Either ParseError a) runParseTest eff = do runEff . runErrorNoCallStack @ParseError . runParser $ eff