@@ -9,6 +9,8 @@ import KDL qualified
99import KDL.TestUtils.Error (decodeErrorMsg )
1010import KDL.Types (Node )
1111import Skeletest
12+ import Skeletest.Predicate qualified as P
13+ import System.FilePath ((</>) )
1214
1315spec :: Spec
1416spec = do
@@ -53,3 +55,58 @@ spec = do
5355 [ " At: foo #1 > bar #0 > baz #3 > prop a"
5456 , " Expected text, got: 1"
5557 ]
58+
59+ describe " decodeFileWith" $ do
60+ it " fails with helpful error if parsing fails" $ do
61+ FixtureKdlFile file <- getFixture
62+ writeFile file " foo hello= 123"
63+ let decoder = KDL. document $ KDL. node @ Node " foo"
64+ KDL. decodeFileWith decoder file
65+ `shouldSatisfy` (P. returns . decodeErrorMsg)
66+ [ " Failed to decode " <> Text. pack file <> " :"
67+ , " 1:10:"
68+ , " |"
69+ , " 1 | foo hello= 123"
70+ , " | ^^"
71+ , " unexpected \" = \" "
72+ , " expecting Node Child, Node Space, or Node Terminator"
73+ ]
74+
75+ it " fails with user-defined error" $ do
76+ FixtureKdlFile file <- getFixture
77+ writeFile file " foo -1"
78+ let decoder =
79+ KDL. document . KDL. argAtWith " foo" $
80+ KDL. withDecoder KDL. number $ \ x -> do
81+ when (x < 0 ) $ do
82+ KDL. failM $ " Got negative number: " <> (Text. pack . show ) x
83+ pure x
84+ KDL. decodeFileWith decoder file
85+ `shouldSatisfy` (P. returns . decodeErrorMsg)
86+ [ " Failed to decode " <> Text. pack file <> " :"
87+ , " At: foo #0 > arg #0"
88+ , " Got negative number: -1.0"
89+ ]
90+
91+ it " shows context in deeply nested error" $ do
92+ FixtureKdlFile file <- getFixture
93+ writeFile file " foo; foo { bar { baz; baz; baz; baz a=1; }; }"
94+ let decoder =
95+ KDL. document
96+ . (KDL. many . KDL. nodeWith " foo" . KDL. children)
97+ . (KDL. many . KDL. nodeWith " bar" . KDL. children)
98+ . (KDL. many . KDL. nodeWith " baz" )
99+ $ KDL. optional (KDL. prop @ Text " a" )
100+ KDL. decodeFileWith decoder file
101+ `shouldSatisfy` (P. returns . decodeErrorMsg)
102+ [ " Failed to decode " <> Text. pack file <> " :"
103+ , " At: foo #1 > bar #0 > baz #3 > prop a"
104+ , " Expected text, got: 1"
105+ ]
106+
107+ newtype FixtureKdlFile = FixtureKdlFile FilePath
108+
109+ instance Fixture FixtureKdlFile where
110+ fixtureAction = do
111+ FixtureTmpDir tmpdir <- getFixture
112+ pure . noCleanup $ FixtureKdlFile (tmpdir </> " kdl-hs-test.kdl" )
0 commit comments