3import Control.Exception
7import Data.List.NonEmpty (NonEmpty(..))
8import qualified Data.List.NonEmpty as NE
10import Data.Text (Text)
12import Text.Shakespeare.Text (lt)
14import Text.XML.DOM.Parser
17data TestStructure = TestStructure
20 , tsBools :: NonEmpty Bool
23testStructureFromDom :: (Monad m) => DomParserT Identity m TestStructure
24testStructureFromDom = do
25 tsName <- inElem "name" fromDom
26 tsInts <- inElemAll "int" intFromDom
27 tsBools <- inElemNe "bool" boolFromDom
28 return TestStructure{..}
30testStructureAttributes :: (Monad m) => DomParserT Identity m TestStructure
31testStructureAttributes = do
32 name <- getCurrentName
33 int <- parseAttribute "int" readContent
34 bool <- parseAttribute "bool" readBool
35 return $ TestStructure
36 { tsName = nameLocalName name
38 , tsBools = pure bool }
41docStruct = parseText_ def [lt|
42<?xml version="1.0" encoding="utf-8"?>
51docAttrStruct :: Document
52docAttrStruct = parseText_ def [lt|
53<?xml version="1.0" encoding="utf-8"?>
54<structure int="10" bool="t">
59docNone = parseText_ def [lt|
60<?xml version="1.0" encoding="utf-8"?>
65docSimpleAttr :: Document
66docSimpleAttr = parseText_ def [lt|
67<?xml version="1.0" encoding="utf-8"?>
73docMultipleAttr :: Document
74docMultipleAttr = parseText_ def [lt|
75<?xml version="1.0" encoding="utf-8"?>
83docSingleEmpty :: Document
84docSingleEmpty = parseText_ def [lt|
85<?xml version="1.0" encoding="utf-8"?>
92docSimple = parseText_ def [lt|
93<?xml version="1.0" encoding="utf-8"?>
99docMultiple :: Document
100docMultiple = parseText_ def [lt|
101<?xml version="1.0" encoding="utf-8"?>
110docDeep = parseText_ def [lt|
111<?xml version="1.0" encoding="utf-8"?>
113 <a><b>content</b></a>
117docDeepWithContent :: Document
118docDeepWithContent = parseText_ def [lt|
119<?xml version="1.0" encoding="utf-8"?>
121 <a>content<b>content</b>content</a>
125docDeepMultiple1 :: Document
126docDeepMultiple1 = parseText_ def [lt|
127<?xml version="1.0" encoding="utf-8"?>
140docDeepMultiple2 :: Document
141docDeepMultiple2 = parseText_ def [lt|
142<?xml version="1.0" encoding="utf-8"?>
156 :: String -- ^ Name of spec
157 -> Document -- ^ Document to parse
158 -> (a -> Maybe String) -- ^ Value checker, Nothing if all ok
159 -> DomParser Identity a -- ^ Parser itself
161specParser name doc check parser = it name $ do
162 result <- either throwIO return $ runDomParser doc parser
165 Just e -> throwIO $ ErrorCall e
169 => String -- ^ Name of spec
170 -> Document -- ^ Document to parse
171 -> a -- ^ Value parser should return
172 -> DomParser Identity a -- ^ Parser itself
174specParserEq name doc a parser = specParser name doc check parser
176 check x | x == a = Nothing
177 | otherwise = Just $ "should be " ++ show a
178 ++ " but got " ++ show x
184 -> DomParser Identity a
186specParserFailed name doc parser = it name $ example $ do
187 let result = runDomParser doc parser
189 Right a -> fail $ "Expected parser to fail, but returned" ++ (show a)
194 => String -- ^ Name of spec
196 -> DomPath -- ^ Expteced path in error
197 -> DomParser Identity a
199specParserFailedPath name doc path parser = it name $ example $ do
200 let result = runDomParser doc parser
202 Right a -> fail $ "Expected parser to fail, but returned" ++ (show a)
203 Left (ParserErrors errs) -> case errs ^? folded . pePath of
204 Nothing -> fail $ "Parser failed, but got no errors to analyze path"
205 Just p | p == path -> return ()
206 | otherwise -> fail $ "Path is not exptected: " <> show p
208combinationsSpec :: Spec
210 describe "inElem" $ do
211 describe "succeeds" $ do
212 describe "simple" $ do
213 let parser = inElem "a" textFromDom
214 specParserEq "docSimple" docSimple "content" parser
215 specParserEq "docMultiple" docMultiple "content1" parser
217 let parser = inElem "a" $ inElem "b" textFromDom
218 specParserEq "docDeep" docDeep "content" parser
219 specParserEq "docDeepMultiple1" docDeepMultiple1 "content1" parser
220 specParserEq "docDeepWithContent" docDeepWithContent "content" parser
221 describe "fails" $ do
222 describe "simple" $ do
223 let parser = inElem "a" textFromDom
224 specParserFailed "docNone" docNone parser
225 specParserFailed "docSingleEmpty" docSingleEmpty parser
227 let parser = inElem "a" $ inElem "b" textFromDom
228 specParserFailedPath "docDeepMultiple2" docDeepMultiple2
229 (DomPath ["root", "a", "b"]) parser
230 -- should fail here because first tag "a" does not contains
231 -- tag "b" which is expected by parser @inElem "b"@
233 describe "parseAttribute" $ do
234 describe "succeeds" $ do
235 specParserEq "docSimpleAttr" docSimpleAttr "content"
236 $ inElem "a" $ parseAttribute "attr" Right
237 let res = ["content1", "content2", "content3"]
238 specParserEq "docMultipleAttr" docMultipleAttr res
239 $ inElemAll "a" $ parseAttribute "attr" Right
240 describe "fails" $ do
241 specParserFailed "docNone" docNone $ parseAttribute "attr" Right
243 describe "inElemAll" $ do
244 let parser = inElemAll "a" textFromDom
245 describe "succeeds" $ do
246 specParserEq "docNone" docNone [] parser
247 specParserEq "docSimple" docSimple ["content"] parser
248 specParserEq "docMultiple" docMultiple
249 ["content1", "content2", "content3"] parser
250 describe "fails" $ do
251 specParserFailed "docSingleEmpty" docSingleEmpty parser
253 describe "inElemMay" $ do
254 let parser = inElemMay "a" textFromDom
255 describe "succeeds" $ do
256 specParserEq "docNone" docNone Nothing parser
257 specParserEq "docSimple" docSimple (Just "content") parser
258 specParserEq "docMultiple" docMultiple (Just "content1") parser
259 describe "fails" $ do
260 specParserFailed "docSingleEmpty" docSingleEmpty parser
262 describe "inElemNe" $ do
263 let parser = inElemNe "a" textFromDom
264 describe "succeeds" $ do
265 specParserEq "docSimple" docSimple (pure "content") parser
266 specParserEq "docMultiple" docMultiple
267 (NE.fromList ["content1", "content2", "content3"]) parser
268 describe "fails" $ do
269 specParserFailed "docNone" docNone parser
270 specParserFailed "docSingleEmpty" docSingleEmpty parser
272 describe "diveElem" $ do
273 describe "single element" $ do
274 let parser = diveElem "a" $ inElem "b" textFromDom
275 describe "succeeds" $ do
276 specParserEq "docDeepMultiple1" docDeepMultiple1 "content1" parser
277 specParserEq "docDeepMultiple2" docDeepMultiple2 "content1" parser
278 describe "fails" $ do
279 specParserFailedPath "docSimple" docSimple (DomPath ["root", "a", "b"]) parser
280 describe "multiple elements" $ do
282 parser = diveElem "a" $ inElemAll "b" textFromDom
283 result = ["content1", "content2", "content3"]
284 describe "succeeds" $ do
285 specParserEq "docDeepMultiple1" docDeepMultiple1 result parser
286 specParserEq "docDeepMultiple2" docDeepMultiple2 result parser
287 specParserEq "docSimple" docSimple [] parser
289 describe "ignoreEmpty" $ do
290 describe "mandatory element" $ do
291 let parser = inElem "a" $ ignoreEmpty textFromDom
292 describe "succeeds" $ do
293 specParserEq "docSingleEmpty" docSingleEmpty Nothing parser
294 specParserEq "docSimple" docSimple (Just "content") parser
295 specParserEq "docMultiple" docMultiple (Just "content1") parser
296 describe "fails" $ do
297 specParserFailed "docNone" docNone parser
298 describe "optional element" $ do
299 let parser = fmap join $ inElemMay "a" $ ignoreEmpty textFromDom
300 describe "succeeds" $ do
301 specParserEq "docNone" docNone Nothing parser
302 specParserEq "docSingleEmpty" docSingleEmpty Nothing parser
303 specParserEq "docSimple" docSimple (Just "content") parser
304 specParserEq "docMultiple" docMultiple (Just "content1") parser
306 describe "checkCurrentName" $ do
307 describe "succeeded" $ do
308 specParserEq "root element" docSimple () $ do
309 checkCurrentName "root"
310 specParserEq "inner element" docSimple () $ do
313 describe "fails" $ do
314 specParserFailedPath "root element" docSimple (DomPath ["toor"]) $ do
315 checkCurrentName "toor"
316 specParserFailedPath "inner element" docSimple (DomPath ["root", "b"]) $ do
317 inElem "a" $ checkCurrentName "b"
321 describe "fails if inner element found" $ do
322 specParserFailed "docDeep" docDeep $ do
323 inElem "a" $ textFromDom
324 specParserFailed "docDeepWithContent" docDeepWithContent $ do
325 inElem "a" $ textFromDom
329 describe "succeeds" $ do
330 describe "dom structure" $ do
332 result = TestStructure
335 , tsBools = pure True }
336 specParserEq "docStruct" docStruct result testStructureFromDom
337 describe "attribute structure" $ do
339 result = TestStructure
340 { tsName = "structure"
342 , tsBools = pure True }
343 specParserEq "docAttrStruct" docAttrStruct result testStructureAttributes
344 describe "fails" $ do
345 describe "dom structure" $ do
346 specParserFailed "docSimple" docSimple testStructureFromDom
347 describe "attr structure" $ do
348 specParserFailed "docNone" docNone testStructureAttributes
352 describe "combinators" $ do
354 describe "content parsing" $ do
356 describe "expected struct" $ do
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list