|
Packit |
899799 |
{-# LANGUAGE DeriveDataTypeable #-}
|
|
Packit |
899799 |
{-# LANGUAGE OverloadedStrings #-}
|
|
Packit |
899799 |
|
|
Packit |
899799 |
import Control.Exception (Exception, toException)
|
|
Packit |
899799 |
import Control.Monad.IO.Class (liftIO)
|
|
Packit |
899799 |
import qualified Data.ByteString.Char8 as S
|
|
Packit |
899799 |
import qualified Data.ByteString.Lazy.Char8 as L
|
|
Packit |
899799 |
import Data.Typeable (Typeable)
|
|
Packit |
899799 |
import Data.XML.Types
|
|
Packit |
899799 |
import Test.Hspec
|
|
Packit |
899799 |
import Test.HUnit hiding (Test)
|
|
Packit |
899799 |
import qualified Text.XML as Res
|
|
Packit |
899799 |
import qualified Text.XML.Cursor as Cu
|
|
Packit |
899799 |
import Text.XML.Stream.Parse (def)
|
|
Packit |
899799 |
import qualified Text.XML.Stream.Parse as P
|
|
Packit |
899799 |
import qualified Text.XML.Unresolved as D
|
|
Packit |
899799 |
|
|
Packit |
899799 |
import Control.Applicative ((<$>))
|
|
Packit |
899799 |
import Control.Monad
|
|
Packit |
899799 |
import Control.Monad.Trans.Class (lift)
|
|
Packit |
899799 |
import qualified Data.Set as Set
|
|
Packit |
899799 |
import Data.Text (Text)
|
|
Packit |
899799 |
import qualified Data.Text as T
|
|
Packit |
899799 |
import Text.XML.Cursor (($.//), ($/), ($//), ($|),
|
|
Packit |
899799 |
(&.//), (&/), (&//))
|
|
Packit |
899799 |
|
|
Packit |
899799 |
import Control.Monad.Trans.Resource (runResourceT)
|
|
Packit |
899799 |
import qualified Control.Monad.Trans.Resource as C
|
|
Packit |
899799 |
import Data.Conduit ((=$=))
|
|
Packit |
899799 |
import qualified Data.Conduit as C
|
|
Packit |
899799 |
import qualified Data.Conduit.List as CL
|
|
Packit |
899799 |
import qualified Data.Map as Map
|
|
Packit |
899799 |
import Text.Blaze (toMarkup)
|
|
Packit |
899799 |
import Text.Blaze.Renderer.String (renderMarkup)
|
|
Packit |
899799 |
|
|
Packit |
899799 |
main :: IO ()
|
|
Packit |
899799 |
main = hspec $ do
|
|
Packit |
899799 |
describe "XML parsing and rendering" $ do
|
|
Packit |
899799 |
it "is idempotent to parse and render a document" documentParseRender
|
|
Packit |
899799 |
it "has valid parser combinators" combinators
|
|
Packit |
899799 |
context "has working choose function" testChoose
|
|
Packit |
899799 |
it "has working many function" testMany
|
|
Packit |
899799 |
it "has working many' function" testMany'
|
|
Packit |
899799 |
it "has working manyYield function" testManyYield
|
|
Packit |
899799 |
it "has working takeContent function" testTakeContent
|
|
Packit |
899799 |
it "has working takeTree function" testTakeTree
|
|
Packit |
899799 |
it "has working takeAnyTreeContent function" testTakeAnyTreeContent
|
|
Packit |
899799 |
it "has working orE" testOrE
|
|
Packit |
899799 |
it "is idempotent to parse and pretty render a document" documentParsePrettyRender
|
|
Packit |
899799 |
it "ignores the BOM" parseIgnoreBOM
|
|
Packit |
899799 |
it "strips duplicated attributes" stripDuplicateAttributes
|
|
Packit |
899799 |
it "displays comments" testRenderComments
|
|
Packit |
899799 |
it "conduit parser" testConduitParser
|
|
Packit |
899799 |
it "can omit the XML declaration" omitXMLDeclaration
|
|
Packit |
899799 |
context "correctly parses hexadecimal entities" hexEntityParsing
|
|
Packit |
899799 |
describe "XML Cursors" $ do
|
|
Packit |
899799 |
it "has correct parent" cursorParent
|
|
Packit |
899799 |
it "has correct ancestor" cursorAncestor
|
|
Packit |
899799 |
it "has correct orSelf" cursorOrSelf
|
|
Packit |
899799 |
it "has correct preceding" cursorPreceding
|
|
Packit |
899799 |
it "has correct following" cursorFollowing
|
|
Packit |
899799 |
it "has correct precedingSibling" cursorPrecedingSib
|
|
Packit |
899799 |
it "has correct followingSibling" cursorFollowingSib
|
|
Packit |
899799 |
it "has correct descendant" cursorDescendant
|
|
Packit |
899799 |
it "has correct check" cursorCheck
|
|
Packit |
899799 |
it "has correct check with lists" cursorPredicate
|
|
Packit |
899799 |
it "has correct checkNode" cursorCheckNode
|
|
Packit |
899799 |
it "has correct checkElement" cursorCheckElement
|
|
Packit |
899799 |
it "has correct checkName" cursorCheckName
|
|
Packit |
899799 |
it "has correct anyElement" cursorAnyElement
|
|
Packit |
899799 |
it "has correct element" cursorElement
|
|
Packit |
899799 |
it "has correct laxElement" cursorLaxElement
|
|
Packit |
899799 |
it "has correct content" cursorContent
|
|
Packit |
899799 |
it "has correct attribute" cursorAttribute
|
|
Packit |
899799 |
it "has correct laxAttribute" cursorLaxAttribute
|
|
Packit |
899799 |
it "has correct &* and $* operators" cursorDeep
|
|
Packit |
899799 |
it "has correct force" cursorForce
|
|
Packit |
899799 |
it "has correct forceM" cursorForceM
|
|
Packit |
899799 |
it "has correct hasAttribute" cursorHasAttribute
|
|
Packit |
899799 |
it "has correct attributeIs" cursorAttributeIs
|
|
Packit |
899799 |
describe "resolved" $ do
|
|
Packit |
899799 |
it "identifies unresolved entities" resolvedIdentifies
|
|
Packit |
899799 |
it "decodeHtmlEntities" testHtmlEntities
|
|
Packit |
899799 |
it "works for resolvable entities" resolvedAllGood
|
|
Packit |
899799 |
it "merges adjacent content nodes" resolvedMergeContent
|
|
Packit |
899799 |
it "understands inline entity declarations" resolvedInline
|
|
Packit |
899799 |
describe "pretty" $ do
|
|
Packit |
899799 |
it "works" casePretty
|
|
Packit |
899799 |
describe "top level namespaces" $ do
|
|
Packit |
899799 |
it "works" caseTopLevelNamespace
|
|
Packit |
899799 |
it "works with prefix" caseTopLevelNamespacePrefix
|
|
Packit |
899799 |
it "handles conflicts" caseTLNConflict
|
|
Packit |
899799 |
describe "blaze-html instances" $ do
|
|
Packit |
899799 |
it "works" caseBlazeHtml
|
|
Packit |
899799 |
describe "attribute reordering" $ do
|
|
Packit |
899799 |
it "works" caseAttrReorder
|
|
Packit |
899799 |
describe "ordering attributes explicitly" $ do
|
|
Packit |
899799 |
it "works" caseOrderAttrs
|
|
Packit |
899799 |
it "parsing CDATA" caseParseCdata
|
|
Packit |
899799 |
it "retains namespaces when asked" caseRetainNamespaces
|
|
Packit |
899799 |
it "handles iso-8859-1" caseIso8859_1
|
|
Packit |
899799 |
it "renders CDATA when asked" caseRenderCDATA
|
|
Packit |
899799 |
it "escapes CDATA closing tag in CDATA" caseEscapesCDATA
|
|
Packit |
899799 |
|
|
Packit |
899799 |
documentParseRender :: IO ()
|
|
Packit |
899799 |
documentParseRender =
|
|
Packit |
899799 |
mapM_ go docs
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
go x = x @=? D.parseLBS_ def (D.renderLBS def x)
|
|
Packit |
899799 |
docs =
|
|
Packit |
899799 |
[ Document (Prologue [] Nothing [])
|
|
Packit |
899799 |
(Element "foo" [] [])
|
|
Packit |
899799 |
[]
|
|
Packit |
899799 |
, D.parseLBS_ def
|
|
Packit |
899799 |
"\n<foo/>"
|
|
Packit |
899799 |
, D.parseLBS_ def
|
|
Packit |
899799 |
"\n<foo><nested>&ignore;</nested></foo>"
|
|
Packit |
899799 |
, D.parseLBS_ def
|
|
Packit |
899799 |
"<foo>]]></foo>"
|
|
Packit |
899799 |
, D.parseLBS_ def
|
|
Packit |
899799 |
"<foo bar='baz&bin'/>"
|
|
Packit |
899799 |
, D.parseLBS_ def
|
|
Packit |
899799 |
"<foo></foo>"
|
|
Packit |
899799 |
, D.parseLBS_ def
|
|
Packit |
899799 |
"<foo></foo>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
documentParsePrettyRender :: IO ()
|
|
Packit |
899799 |
documentParsePrettyRender =
|
|
Packit |
899799 |
L.unpack (D.renderLBS def { D.rsPretty = True } (D.parseLBS_ def doc)) @?= L.unpack doc
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
doc = L.unlines
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "<foo>"
|
|
Packit |
899799 |
, " "
|
|
Packit |
899799 |
, " text"
|
|
Packit |
899799 |
, " "
|
|
Packit |
899799 |
, "</foo>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
combinators :: Assertion
|
|
Packit |
899799 |
combinators = runResourceT $ P.parseLBS def input C.$$ do
|
|
Packit |
899799 |
P.force "need hello" $ P.tag' "hello" (P.requireAttr "world") $ \world -> do
|
|
Packit |
899799 |
liftIO $ world @?= "true"
|
|
Packit |
899799 |
P.force "need child1" $ P.tagNoAttr "{mynamespace}child1" $ return ()
|
|
Packit |
899799 |
P.force "need child2" $ P.tagNoAttr "child2" $ return ()
|
|
Packit |
899799 |
P.force "need child3" $ P.tagNoAttr "child3" $ do
|
|
Packit |
899799 |
x <- P.contentMaybe
|
|
Packit |
899799 |
liftIO $ x @?= Just "combine <all> &content"
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<hello world='true'>"
|
|
Packit |
899799 |
, ""
|
|
Packit |
899799 |
, "<child1 xmlns='mynamespace'/>"
|
|
Packit |
899799 |
, ""
|
|
Packit |
899799 |
, "<child2> </child2>"
|
|
Packit |
899799 |
, "<child3>combine <all> </child3>\n"
|
|
Packit |
899799 |
, "</hello>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testChoose :: Spec
|
|
Packit |
899799 |
testChoose = do
|
|
Packit |
899799 |
it "can choose between elements"
|
|
Packit |
899799 |
testChooseEitherElem
|
|
Packit |
899799 |
it "can choose between elements and text, returning text"
|
|
Packit |
899799 |
testChooseElemOrTextIsText
|
|
Packit |
899799 |
it "can choose between elements and text, returning elements"
|
|
Packit |
899799 |
testChooseElemOrTextIsElem
|
|
Packit |
899799 |
it "can choose between text and elements, returning text"
|
|
Packit |
899799 |
testChooseTextOrElemIsText
|
|
Packit |
899799 |
it "can choose between text and elements, returning elements"
|
|
Packit |
899799 |
testChooseTextOrElemIsElem
|
|
Packit |
899799 |
it "can choose between text and elements, when the text is encoded"
|
|
Packit |
899799 |
testChooseElemOrTextIsEncoded
|
|
Packit |
899799 |
it "can choose between text and elements, when the text is encoded, NBSP"
|
|
Packit |
899799 |
testChooseElemOrTextIsEncodedNBSP
|
|
Packit |
899799 |
it "can choose between elements and text, when the text is whitespace"
|
|
Packit |
899799 |
testChooseElemOrTextIsWhiteSpace
|
|
Packit |
899799 |
it "can choose between text and elements, when the text is whitespace"
|
|
Packit |
899799 |
testChooseTextOrElemIsWhiteSpace
|
|
Packit |
899799 |
it "can choose between text and elements, when the whitespace is both literal and encoded"
|
|
Packit |
899799 |
testChooseElemOrTextIsChunkedText
|
|
Packit |
899799 |
it "can choose between text and elements, when the text is chunked the other way"
|
|
Packit |
899799 |
testChooseElemOrTextIsChunkedText2
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testChooseElemOrTextIsText :: Assertion
|
|
Packit |
899799 |
testChooseElemOrTextIsText = runResourceT $ P.parseLBS def input C.$$ do
|
|
Packit |
899799 |
P.force "need hello" $ P.tagNoAttr "hello" $ do
|
|
Packit |
899799 |
x <- P.choose
|
|
Packit |
899799 |
[ P.tagNoAttr "failure" $ return "boom"
|
|
Packit |
899799 |
, P.contentMaybe
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
liftIO $ x @?= Just " something "
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<hello>"
|
|
Packit |
899799 |
, " something "
|
|
Packit |
899799 |
, "</hello>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testChooseElemOrTextIsEncoded :: Assertion
|
|
Packit |
899799 |
testChooseElemOrTextIsEncoded = runResourceT $ P.parseLBS def input C.$$ do
|
|
Packit |
899799 |
P.force "need hello" $ P.tagNoAttr "hello" $ do
|
|
Packit |
899799 |
x <- P.choose
|
|
Packit |
899799 |
[ P.tagNoAttr "failure" $ return "boom"
|
|
Packit |
899799 |
, P.contentMaybe
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
liftIO $ x @?= Just "\x20something\x20"
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<hello>"
|
|
Packit |
899799 |
, " something "
|
|
Packit |
899799 |
, "</hello>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testChooseElemOrTextIsEncodedNBSP :: Assertion
|
|
Packit |
899799 |
testChooseElemOrTextIsEncodedNBSP = runResourceT $ P.parseLBS def input C.$$ do
|
|
Packit |
899799 |
P.force "need hello" $ P.tagNoAttr "hello" $ do
|
|
Packit |
899799 |
x <- P.choose
|
|
Packit |
899799 |
[ P.tagNoAttr "failure" $ return "boom"
|
|
Packit |
899799 |
, P.contentMaybe
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
liftIO $ x @?= Just "\160something\160"
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<hello>"
|
|
Packit |
899799 |
, " something "
|
|
Packit |
899799 |
, "</hello>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testChooseElemOrTextIsWhiteSpace :: Assertion
|
|
Packit |
899799 |
testChooseElemOrTextIsWhiteSpace = runResourceT $ P.parseLBS def input C.$$ do
|
|
Packit |
899799 |
P.force "need hello" $ P.tagNoAttr "hello" $ do
|
|
Packit |
899799 |
x <- P.choose
|
|
Packit |
899799 |
[ P.tagNoAttr "failure" $ return "boom"
|
|
Packit |
899799 |
, P.contentMaybe
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
liftIO $ x @?= Just "\x20\x20\x20"
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<hello> </hello>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testChooseTextOrElemIsWhiteSpace :: Assertion
|
|
Packit |
899799 |
testChooseTextOrElemIsWhiteSpace = runResourceT $ P.parseLBS def input C.$$ do
|
|
Packit |
899799 |
P.force "need hello" $ P.tagNoAttr "hello" $ do
|
|
Packit |
899799 |
x <- P.choose
|
|
Packit |
899799 |
[ P.contentMaybe
|
|
Packit |
899799 |
, P.tagNoAttr "failure" $ return "boom"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
liftIO $ x @?= Just "\x20\x20\x20"
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<hello> </hello>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testChooseElemOrTextIsChunkedText :: Assertion
|
|
Packit |
899799 |
testChooseElemOrTextIsChunkedText = runResourceT $ P.parseLBS def input C.$$ do
|
|
Packit |
899799 |
P.force "need hello" $ P.tagNoAttr "hello" $ do
|
|
Packit |
899799 |
x <- P.choose
|
|
Packit |
899799 |
[ P.tagNoAttr "failure" $ return "boom"
|
|
Packit |
899799 |
, P.contentMaybe
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
liftIO $ x @?= Just "\x20\x20\x20"
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<hello> </hello>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testChooseElemOrTextIsChunkedText2 :: Assertion
|
|
Packit |
899799 |
testChooseElemOrTextIsChunkedText2 = runResourceT $ P.parseLBS def input C.$$ do
|
|
Packit |
899799 |
P.force "need hello" $ P.tagNoAttr "hello" $ do
|
|
Packit |
899799 |
x <- P.choose
|
|
Packit |
899799 |
[ P.tagNoAttr "failure" $ return "boom"
|
|
Packit |
899799 |
, P.contentMaybe
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
liftIO $ x @?= Just "\x20\x20\x20"
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<hello> </hello>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testChooseElemOrTextIsElem :: Assertion
|
|
Packit |
899799 |
testChooseElemOrTextIsElem = runResourceT $ P.parseLBS def input C.$$ do
|
|
Packit |
899799 |
P.force "need hello" $ P.tagNoAttr "hello" $ do
|
|
Packit |
899799 |
x <- P.choose
|
|
Packit |
899799 |
[ P.tagNoAttr "success" $ return "success"
|
|
Packit |
899799 |
, P.contentMaybe
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
liftIO $ x @?= Just "success"
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<hello>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "</hello>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testChooseTextOrElemIsText :: Assertion
|
|
Packit |
899799 |
testChooseTextOrElemIsText = runResourceT $ P.parseLBS def input C.$$ do
|
|
Packit |
899799 |
P.force "need hello" $ P.tagNoAttr "hello" $ do
|
|
Packit |
899799 |
x <- P.choose
|
|
Packit |
899799 |
[ P.contentMaybe
|
|
Packit |
899799 |
, P.tagNoAttr "failure" $ return "boom"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
liftIO $ x @?= Just " something "
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<hello>"
|
|
Packit |
899799 |
, " something "
|
|
Packit |
899799 |
, "</hello>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testChooseTextOrElemIsElem :: Assertion
|
|
Packit |
899799 |
testChooseTextOrElemIsElem = runResourceT $ P.parseLBS def input C.$$ do
|
|
Packit |
899799 |
P.force "need hello" $ P.tagNoAttr "hello" $ do
|
|
Packit |
899799 |
x <- P.choose
|
|
Packit |
899799 |
[ P.contentMaybe
|
|
Packit |
899799 |
, P.tagNoAttr "success" $ return "success"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
liftIO $ x @?= Just "success"
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<hello>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "</hello>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testChooseEitherElem :: Assertion
|
|
Packit |
899799 |
testChooseEitherElem = runResourceT $ P.parseLBS def input C.$$ do
|
|
Packit |
899799 |
P.force "need hello" $ P.tagNoAttr "hello" $ do
|
|
Packit |
899799 |
x <- P.choose
|
|
Packit |
899799 |
[ P.tagNoAttr "failure" $ return 1
|
|
Packit |
899799 |
, P.tagNoAttr "success" $ return 2
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
liftIO $ x @?= Just (2 :: Int)
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<hello>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "</hello>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testManyYield :: Assertion
|
|
Packit |
899799 |
testManyYield = do
|
|
Packit |
899799 |
-- Basically the same as testMany, but consume the streamed result
|
|
Packit |
899799 |
result <- runResourceT $
|
|
Packit |
899799 |
P.parseLBS def input C.$$ helloParser
|
|
Packit |
899799 |
=$= CL.consume
|
|
Packit |
899799 |
length result @?= 5
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
helloParser = void $ P.tagNoAttr "hello" $ P.manyYield successParser
|
|
Packit |
899799 |
successParser = P.tagNoAttr "success" $ return ()
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<hello>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "</hello>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testTakeContent :: Assertion
|
|
Packit |
899799 |
testTakeContent = do
|
|
Packit |
899799 |
result <- runResourceT $ P.parseLBS def input C.$$ rootParser
|
|
Packit |
899799 |
result @?= Just
|
|
Packit |
899799 |
[ EventContent (ContentText "Hello world !")
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
rootParser = P.tagNoAttr "root" $ void (P.takeContent >> P.takeContent) =$= CL.consume
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<root>"
|
|
Packit |
899799 |
, "Hello world !"
|
|
Packit |
899799 |
, "</root>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testTakeTree :: Assertion
|
|
Packit |
899799 |
testTakeTree = do
|
|
Packit |
899799 |
result <- runResourceT $ P.parseLBS def input C.$$ rootParser
|
|
Packit |
899799 |
result @?=
|
|
Packit |
899799 |
[ EventBeginDocument
|
|
Packit |
899799 |
, EventBeginDoctype "foo" Nothing
|
|
Packit |
899799 |
, EventEndDoctype
|
|
Packit |
899799 |
, EventBeginElement "a" []
|
|
Packit |
899799 |
, EventBeginElement "em" []
|
|
Packit |
899799 |
, EventContent (ContentText "Hello world !")
|
|
Packit |
899799 |
, EventEndElement "em"
|
|
Packit |
899799 |
, EventEndElement "a"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
rootParser = void (P.takeTree "a" P.ignoreAttrs) =$= CL.consume
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, ""
|
|
Packit |
899799 |
, "Hello world !"
|
|
Packit |
899799 |
, ""
|
|
Packit |
899799 |
, ""
|
|
Packit |
899799 |
, ""
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testTakeAnyTreeContent :: Assertion
|
|
Packit |
899799 |
testTakeAnyTreeContent = do
|
|
Packit |
899799 |
result <- runResourceT $ P.parseLBS def input C.$$ rootParser
|
|
Packit |
899799 |
result @?= Just
|
|
Packit |
899799 |
[ EventBeginElement "b" []
|
|
Packit |
899799 |
, EventContent (ContentText "Hello ")
|
|
Packit |
899799 |
, EventBeginElement "em" []
|
|
Packit |
899799 |
, EventContent (ContentText "world")
|
|
Packit |
899799 |
, EventEndElement "em"
|
|
Packit |
899799 |
, EventContent (ContentText " !")
|
|
Packit |
899799 |
, EventEndElement "b"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
rootParser = P.tagNoAttr "root" $ (P.takeAnyTreeContent >> void P.ignoreAnyTreeContent) =$= CL.consume
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<root>"
|
|
Packit |
899799 |
, "Hello world ! Welcome !"
|
|
Packit |
899799 |
, "</root>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testMany :: Assertion
|
|
Packit |
899799 |
testMany = runResourceT $ P.parseLBS def input C.$$ do
|
|
Packit |
899799 |
P.force "need hello" $ P.tagNoAttr "hello" $ do
|
|
Packit |
899799 |
x <- P.many $ P.tagNoAttr "success" $ return ()
|
|
Packit |
899799 |
liftIO $ length x @?= 5
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<hello>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "</hello>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testMany' :: Assertion
|
|
Packit |
899799 |
testMany' = runResourceT $ P.parseLBS def input C.$$ do
|
|
Packit |
899799 |
P.force "need hello" $ P.tagNoAttr "hello" $ do
|
|
Packit |
899799 |
x <- P.many' $ P.tagNoAttr "success" $ return ()
|
|
Packit |
899799 |
liftIO $ length x @?= 5
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<hello>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "<foobar/>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "<foo><bar attr=\"1\">some content</bar></foo>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "</hello>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testOrE :: IO ()
|
|
Packit |
899799 |
testOrE = runResourceT $ P.parseLBS def input C.$$ do
|
|
Packit |
899799 |
P.force "need hello" $ P.tagNoAttr "hello" $ do
|
|
Packit |
899799 |
x <- P.tagNoAttr "failure" (return 1) `P.orE`
|
|
Packit |
899799 |
P.tagNoAttr "success" (return 2)
|
|
Packit |
899799 |
y <- P.tag' "success" (P.requireAttr "failure") (const $ return 1) `P.orE`
|
|
Packit |
899799 |
P.tag' "success" (P.requireAttr "success") (const $ return 2)
|
|
Packit |
899799 |
liftIO $ x @?= Just (2 :: Int)
|
|
Packit |
899799 |
liftIO $ y @?= Just (2 :: Int)
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<hello>"
|
|
Packit |
899799 |
, "<success/>"
|
|
Packit |
899799 |
, "<success success=\"0\"/>"
|
|
Packit |
899799 |
, "</hello>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testConduitParser :: Assertion
|
|
Packit |
899799 |
testConduitParser = runResourceT $ do
|
|
Packit |
899799 |
x <- P.parseLBS def input
|
|
Packit |
899799 |
C.$$ (P.force "need hello" $ P.tagNoAttr "hello" f)
|
|
Packit |
899799 |
=$= CL.consume
|
|
Packit |
899799 |
liftIO $ x @?= [1, 1, 1]
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "\n"
|
|
Packit |
899799 |
, "<hello>"
|
|
Packit |
899799 |
, "<item/>"
|
|
Packit |
899799 |
, "<item/>"
|
|
Packit |
899799 |
, "<item/>"
|
|
Packit |
899799 |
, "</hello>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
f :: C.MonadThrow m => C.Conduit Event m Int
|
|
Packit |
899799 |
f = do
|
|
Packit |
899799 |
ma <- P.tagNoAttr "item" (return 1)
|
|
Packit |
899799 |
maybe (return ()) (\a -> C.yield a >> f) ma
|
|
Packit |
899799 |
|
|
Packit |
899799 |
omitXMLDeclaration :: Assertion
|
|
Packit |
899799 |
omitXMLDeclaration = Res.renderLBS settings input @?= spec
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
settings = def { Res.rsXMLDeclaration = False }
|
|
Packit |
899799 |
input = Res.Document (Prologue [] Nothing [])
|
|
Packit |
899799 |
(Res.Element "foo" Map.empty [Res.NodeContent "bar"])
|
|
Packit |
899799 |
[]
|
|
Packit |
899799 |
spec = "<foo>bar</foo>"
|
|
Packit |
899799 |
|
|
Packit |
899799 |
hexEntityParsing :: Spec
|
|
Packit |
899799 |
hexEntityParsing = do
|
|
Packit |
899799 |
it "rejects leading 0x" $
|
|
Packit |
899799 |
go "<foo>�xff;</foo>" @?= Nothing
|
|
Packit |
899799 |
it "rejects leading 0X" $
|
|
Packit |
899799 |
go "<foo>�Xff;</foo>" @?= Nothing
|
|
Packit |
899799 |
it "accepts lowercase hex digits" $
|
|
Packit |
899799 |
go "<foo>ÿ</foo>" @?= Just spec
|
|
Packit |
899799 |
it "accepts uppercase hex digits" $
|
|
Packit |
899799 |
go "<foo>ÿ</foo>" @?= Just spec
|
|
Packit |
899799 |
--Note: this must be rejected, because, according to the XML spec, a
|
|
Packit |
899799 |
--legal EntityRef's entity matches Name, which can't start with a
|
|
Packit |
899799 |
--hash.
|
|
Packit |
899799 |
it "rejects trailing junk" $
|
|
Packit |
899799 |
go "<foo>ÿhello;</foo>" @?= Nothing
|
|
Packit |
899799 |
--Some of these next tests are XML 1.0 specific (i.e., they would
|
|
Packit |
899799 |
--differ for XML 1.1), but approximately no-one uses XML 1.1.
|
|
Packit |
899799 |
it "rejects illegal character #x0" $
|
|
Packit |
899799 |
go "<foo></foo>" @?= Nothing
|
|
Packit |
899799 |
it "rejects illegal character #xFFFE" $
|
|
Packit |
899799 |
go "<foo></foo>" @?= Nothing
|
|
Packit |
899799 |
it "rejects illegal character #xFFFF" $
|
|
Packit |
899799 |
go "<foo></foo>" @?= Nothing
|
|
Packit |
899799 |
it "rejects illegal character #xD900" $
|
|
Packit |
899799 |
go "<foo></foo>" @?= Nothing
|
|
Packit |
899799 |
it "rejects illegal character #xC" $
|
|
Packit |
899799 |
go "<foo></foo>" @?= Nothing
|
|
Packit |
899799 |
it "rejects illegal character #x1F" $
|
|
Packit |
899799 |
go "<foo></foo>" @?= Nothing
|
|
Packit |
899799 |
it "accepts astral plane character" $
|
|
Packit |
899799 |
go "<foo></foo>" @?= Just astralSpec
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
spec = Document (Prologue [] Nothing [])
|
|
Packit |
899799 |
(Element "foo" [] [NodeContent (ContentText "\xff")])
|
|
Packit |
899799 |
[]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
astralSpec = Document (Prologue [] Nothing [])
|
|
Packit |
899799 |
(Element "foo" [] [NodeContent (ContentText "\x1006ff")])
|
|
Packit |
899799 |
[]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
go = either (const Nothing) Just . D.parseLBS def
|
|
Packit |
899799 |
|
|
Packit |
899799 |
name :: [Cu.Cursor] -> [Text]
|
|
Packit |
899799 |
name [] = []
|
|
Packit |
899799 |
name (c:cs) = ($ name cs) $ case Cu.node c of
|
|
Packit |
899799 |
Res.NodeElement e -> ((Res.nameLocalName $ Res.elementName e) :)
|
|
Packit |
899799 |
_ -> id
|
|
Packit |
899799 |
|
|
Packit |
899799 |
cursor :: Cu.Cursor
|
|
Packit |
899799 |
cursor =
|
|
Packit |
899799 |
Cu.fromDocument $ Res.parseLBS_ def input
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
input = L.concat
|
|
Packit |
899799 |
[ "<foo attr=\"x\">"
|
|
Packit |
899799 |
, "<bar1/>"
|
|
Packit |
899799 |
, "<bar2>"
|
|
Packit |
899799 |
, "<baz1/>"
|
|
Packit |
899799 |
, "<baz2 attr=\"y\"/>"
|
|
Packit |
899799 |
, "<baz3>a</baz3>"
|
|
Packit |
899799 |
, "</bar2>"
|
|
Packit |
899799 |
, "<bar3>"
|
|
Packit |
899799 |
, "<bin1/>"
|
|
Packit |
899799 |
, "b"
|
|
Packit |
899799 |
, "<bin2/>"
|
|
Packit |
899799 |
, "<bin3/>"
|
|
Packit |
899799 |
, "</bar3>"
|
|
Packit |
899799 |
, "<Bar1 xmlns=\"http://example.com\" Attr=\"q\"/>"
|
|
Packit |
899799 |
, "</foo>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
bar2, baz2, bar3, bin2 :: Cu.Cursor
|
|
Packit |
899799 |
bar2 = Cu.child cursor !! 1
|
|
Packit |
899799 |
baz2 = Cu.child bar2 !! 1
|
|
Packit |
899799 |
|
|
Packit |
899799 |
bar3 = Cu.child cursor !! 2
|
|
Packit |
899799 |
bin2 = Cu.child bar3 !! 1
|
|
Packit |
899799 |
|
|
Packit |
899799 |
cursorParent, cursorAncestor, cursorOrSelf, cursorPreceding, cursorFollowing,
|
|
Packit |
899799 |
cursorPrecedingSib, cursorFollowingSib, cursorDescendant, cursorCheck,
|
|
Packit |
899799 |
cursorPredicate, cursorCheckNode, cursorCheckElement, cursorCheckName,
|
|
Packit |
899799 |
cursorAnyElement, cursorElement, cursorLaxElement, cursorContent,
|
|
Packit |
899799 |
cursorAttribute, cursorLaxAttribute, cursorHasAttribute,
|
|
Packit |
899799 |
cursorAttributeIs, cursorDeep, cursorForce, cursorForceM,
|
|
Packit |
899799 |
resolvedIdentifies, resolvedAllGood, resolvedMergeContent,
|
|
Packit |
899799 |
testHtmlEntities
|
|
Packit |
899799 |
:: Assertion
|
|
Packit |
899799 |
cursorParent = name (Cu.parent bar2) @?= ["foo"]
|
|
Packit |
899799 |
cursorAncestor = name (Cu.ancestor baz2) @?= ["bar2", "foo"]
|
|
Packit |
899799 |
cursorOrSelf = name (Cu.orSelf Cu.ancestor baz2) @?= ["baz2", "bar2", "foo"]
|
|
Packit |
899799 |
cursorPreceding = do
|
|
Packit |
899799 |
name (Cu.preceding baz2) @?= ["baz1", "bar1"]
|
|
Packit |
899799 |
name (Cu.preceding bin2) @?= ["bin1", "baz3", "baz2", "baz1", "bar2", "bar1"]
|
|
Packit |
899799 |
cursorFollowing = do
|
|
Packit |
899799 |
name (Cu.following baz2) @?= ["baz3", "bar3", "bin1", "bin2", "bin3", "Bar1"]
|
|
Packit |
899799 |
name (Cu.following bar2) @?= ["bar3", "bin1", "bin2", "bin3", "Bar1"]
|
|
Packit |
899799 |
cursorPrecedingSib = name (Cu.precedingSibling baz2) @?= ["baz1"]
|
|
Packit |
899799 |
cursorFollowingSib = name (Cu.followingSibling baz2) @?= ["baz3"]
|
|
Packit |
899799 |
cursorDescendant = (name $ Cu.descendant cursor) @?= T.words "bar1 bar2 baz1 baz2 baz3 bar3 bin1 bin2 bin3 Bar1"
|
|
Packit |
899799 |
cursorCheck = null (cursor $.// Cu.check (const False)) @?= True
|
|
Packit |
899799 |
cursorPredicate = (name $ cursor $.// Cu.check Cu.descendant) @?= T.words "foo bar2 baz3 bar3"
|
|
Packit |
899799 |
cursorCheckNode = (name $ cursor $// Cu.checkNode f) @?= T.words "bar1 bar2 bar3"
|
|
Packit |
899799 |
where f (Res.NodeElement e) = "bar" `T.isPrefixOf` Res.nameLocalName (Res.elementName e)
|
|
Packit |
899799 |
f _ = False
|
|
Packit |
899799 |
cursorCheckElement = (name $ cursor $// Cu.checkElement f) @?= T.words "bar1 bar2 bar3"
|
|
Packit |
899799 |
where f e = "bar" `T.isPrefixOf` Res.nameLocalName (Res.elementName e)
|
|
Packit |
899799 |
cursorCheckName = (name $ cursor $// Cu.checkName f) @?= T.words "bar1 bar2 bar3"
|
|
Packit |
899799 |
where f n = "bar" `T.isPrefixOf` nameLocalName n
|
|
Packit |
899799 |
cursorAnyElement = (name $ cursor $// Cu.anyElement) @?= T.words "bar1 bar2 baz1 baz2 baz3 bar3 bin1 bin2 bin3 Bar1"
|
|
Packit |
899799 |
cursorElement = (name $ cursor $// Cu.element "bar1") @?= ["bar1"]
|
|
Packit |
899799 |
cursorLaxElement = (name $ cursor $// Cu.laxElement "bar1") @?= ["bar1", "Bar1"]
|
|
Packit |
899799 |
cursorContent = do
|
|
Packit |
899799 |
Cu.content cursor @?= []
|
|
Packit |
899799 |
(cursor $.// Cu.content) @?= ["a", "b"]
|
|
Packit |
899799 |
cursorAttribute = Cu.attribute "attr" cursor @?= ["x"]
|
|
Packit |
899799 |
cursorLaxAttribute = (cursor $.// Cu.laxAttribute "Attr") @?= ["x", "y", "q"]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
cursorHasAttribute = (length $ cursor $.// Cu.hasAttribute "attr") @?= 2
|
|
Packit |
899799 |
cursorAttributeIs = (length $ cursor $.// Cu.attributeIs "attr" "y") @?= 1
|
|
Packit |
899799 |
|
|
Packit |
899799 |
cursorDeep = do
|
|
Packit |
899799 |
(Cu.element "foo" &/ Cu.element "bar2" &// Cu.attribute "attr") cursor @?= ["y"]
|
|
Packit |
899799 |
(return &.// Cu.attribute "attr") cursor @?= ["x", "y"]
|
|
Packit |
899799 |
(cursor $.// Cu.attribute "attr") @?= ["x", "y"]
|
|
Packit |
899799 |
(cursor $/ Cu.element "bar2" &// Cu.attribute "attr") @?= ["y"]
|
|
Packit |
899799 |
(cursor $/ Cu.element "bar2" &/ Cu.element "baz2" >=> Cu.attribute "attr") @?= ["y"]
|
|
Packit |
899799 |
null (cursor $| Cu.element "foo") @?= False
|
|
Packit |
899799 |
cursorForce = do
|
|
Packit |
899799 |
Cu.force DummyEx [] @?= (Nothing :: Maybe Integer)
|
|
Packit |
899799 |
Cu.force DummyEx [1] @?= Just (1 :: Int)
|
|
Packit |
899799 |
Cu.force DummyEx [1,2] @?= Just (1 :: Int)
|
|
Packit |
899799 |
cursorForceM = do
|
|
Packit |
899799 |
Cu.forceM DummyEx [] @?= (Nothing :: Maybe Integer)
|
|
Packit |
899799 |
Cu.forceM DummyEx [Just 1, Nothing] @?= Just (1 :: Int)
|
|
Packit |
899799 |
Cu.forceM DummyEx [Nothing, Just (1 :: Int)] @?= Nothing
|
|
Packit |
899799 |
|
|
Packit |
899799 |
data DummyEx = DummyEx
|
|
Packit |
899799 |
deriving (Show, Typeable)
|
|
Packit |
899799 |
instance Exception DummyEx
|
|
Packit |
899799 |
|
|
Packit |
899799 |
showEq :: (Show a, Show b) => Either a b -> Either a b -> Assertion
|
|
Packit |
899799 |
showEq x y = show x @=? show y
|
|
Packit |
899799 |
|
|
Packit |
899799 |
resolvedIdentifies =
|
|
Packit |
899799 |
Left (toException $ Res.UnresolvedEntityException $ Set.fromList ["foo", "bar", "baz"]) `showEq`
|
|
Packit |
899799 |
Res.parseLBS def
|
|
Packit |
899799 |
"<root attr='&bar;'>&foo; --- &baz; &foo;</root>"
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testHtmlEntities =
|
|
Packit |
899799 |
Res.parseLBS_ def
|
|
Packit |
899799 |
{ P.psDecodeEntities = P.decodeHtmlEntities
|
|
Packit |
899799 |
} xml1 @=? Res.parseLBS_ def xml2
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
xml1 = "<root> </root>"
|
|
Packit |
899799 |
xml2 = "<root> </root>"
|
|
Packit |
899799 |
|
|
Packit |
899799 |
resolvedAllGood =
|
|
Packit |
899799 |
D.parseLBS_ def xml @=?
|
|
Packit |
899799 |
Res.toXMLDocument (Res.parseLBS_ def xml)
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
xml = "<foo><bar/><baz/></foo>"
|
|
Packit |
899799 |
|
|
Packit |
899799 |
resolvedMergeContent =
|
|
Packit |
899799 |
Res.documentRoot (Res.parseLBS_ def xml) @=?
|
|
Packit |
899799 |
Res.Element "foo" Map.empty [Res.NodeContent "bar&baz"]
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
xml = "<foo>bar&baz</foo>"
|
|
Packit |
899799 |
|
|
Packit |
899799 |
parseIgnoreBOM :: Assertion
|
|
Packit |
899799 |
parseIgnoreBOM = do
|
|
Packit |
899799 |
either (const $ Left (1 :: Int)) Right (Res.parseText Res.def "\xfeef<foo/>") @?=
|
|
Packit |
899799 |
either (const $ Left (2 :: Int)) Right (Res.parseText Res.def "<foo/>")
|
|
Packit |
899799 |
|
|
Packit |
899799 |
stripDuplicateAttributes :: Assertion
|
|
Packit |
899799 |
stripDuplicateAttributes = do
|
|
Packit |
899799 |
"<foo bar=\"baz\"/>" @=?
|
|
Packit |
899799 |
D.renderLBS def (Document (Prologue [] Nothing []) (Element "foo" [("bar", [ContentText "baz"]), ("bar", [ContentText "bin"])] []) [])
|
|
Packit |
899799 |
"<foo x:bar=\"baz\" xmlns:x=\"namespace\"/>" @=?
|
|
Packit |
899799 |
D.renderLBS def (Document (Prologue [] Nothing []) (Element "foo"
|
|
Packit |
899799 |
[ ("x:bar", [ContentText "baz"])
|
|
Packit |
899799 |
, (Name "bar" (Just "namespace") (Just "x"), [ContentText "bin"])
|
|
Packit |
899799 |
] []) [])
|
|
Packit |
899799 |
|
|
Packit |
899799 |
testRenderComments :: Assertion
|
|
Packit |
899799 |
testRenderComments =do
|
|
Packit |
899799 |
"<foo></foo>"
|
|
Packit |
899799 |
@=? D.renderLBS def (Document (Prologue [] Nothing [])
|
|
Packit |
899799 |
(Element "foo" [] [NodeComment "comment"]) [])
|
|
Packit |
899799 |
|
|
Packit |
899799 |
resolvedInline :: Assertion
|
|
Packit |
899799 |
resolvedInline = do
|
|
Packit |
899799 |
Res.Document _ root _ <- return $ Res.parseLBS_ Res.def "]><foo>&bar;</foo>"
|
|
Packit |
899799 |
root @?= Res.Element "foo" Map.empty [Res.NodeContent "baz"]
|
|
Packit |
899799 |
Res.Document _ root2 _ <- return $ Res.parseLBS_ Res.def "]><foo bar='&bar;'/>"
|
|
Packit |
899799 |
root2 @?= Res.Element "foo" (Map.singleton "bar" "baz") []
|
|
Packit |
899799 |
|
|
Packit |
899799 |
casePretty :: Assertion
|
|
Packit |
899799 |
casePretty = do
|
|
Packit |
899799 |
let pretty = S.unlines
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, ""
|
|
Packit |
899799 |
, "<foo bar=\"bar\" baz=\"baz\">"
|
|
Packit |
899799 |
, "
|
|
Packit |
899799 |
, " bar=\"bar\""
|
|
Packit |
899799 |
, " baz=\"baz\""
|
|
Packit |
899799 |
, " bin=\"bin\">"
|
|
Packit |
899799 |
, " Hello World"
|
|
Packit |
899799 |
, " </foo>"
|
|
Packit |
899799 |
, " <foo/>"
|
|
Packit |
899799 |
, " "
|
|
Packit |
899799 |
, " "
|
|
Packit |
899799 |
, " <bar>"
|
|
Packit |
899799 |
, " bar content"
|
|
Packit |
899799 |
, " </bar>"
|
|
Packit |
899799 |
, "</foo>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
doctype = Res.Doctype "foo" Nothing
|
|
Packit |
899799 |
doc = Res.Document (Res.Prologue [] (Just doctype) []) root []
|
|
Packit |
899799 |
root = Res.Element "foo" (Map.fromList [("bar", "bar"), ("baz", "baz")])
|
|
Packit |
899799 |
[ Res.NodeElement $ Res.Element "foo" (Map.fromList [("bar", "bar"), ("baz", "baz"), ("bin", "bin")])
|
|
Packit |
899799 |
[ Res.NodeContent " Hello World\n\n"
|
|
Packit |
899799 |
, Res.NodeContent " "
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
, Res.NodeElement $ Res.Element "foo" Map.empty []
|
|
Packit |
899799 |
, Res.NodeInstruction $ Res.Instruction "foo" "bar"
|
|
Packit |
899799 |
, Res.NodeComment "foo bar\n\r\nbaz \tbin "
|
|
Packit |
899799 |
, Res.NodeElement $ Res.Element "bar" Map.empty [Res.NodeContent "bar content"]
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
pretty @=? S.concat (L.toChunks $ Res.renderLBS def { D.rsPretty = True } doc)
|
|
Packit |
899799 |
|
|
Packit |
899799 |
caseTopLevelNamespace :: Assertion
|
|
Packit |
899799 |
caseTopLevelNamespace = do
|
|
Packit |
899799 |
let lbs = S.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "<foo xmlns:bar=\"baz\">"
|
|
Packit |
899799 |
, "<subfoo bar:bin=\"\"/>"
|
|
Packit |
899799 |
, "</foo>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
rs = def { D.rsNamespaces = [("bar", "baz")] }
|
|
Packit |
899799 |
doc = Res.Document (Res.Prologue [] Nothing [])
|
|
Packit |
899799 |
(Res.Element "foo" Map.empty
|
|
Packit |
899799 |
[ Res.NodeElement
|
|
Packit |
899799 |
$ Res.Element "subfoo" (Map.singleton "{baz}bin" "") []
|
|
Packit |
899799 |
])
|
|
Packit |
899799 |
[]
|
|
Packit |
899799 |
lbs @=? S.concat (L.toChunks $ Res.renderLBS rs doc)
|
|
Packit |
899799 |
|
|
Packit |
899799 |
caseTopLevelNamespacePrefix :: Assertion
|
|
Packit |
899799 |
caseTopLevelNamespacePrefix = do
|
|
Packit |
899799 |
let lbs = S.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "<foo xmlns:bar=\"baz\">"
|
|
Packit |
899799 |
, "<subfoo bar:bin=\"\"/>"
|
|
Packit |
899799 |
, "</foo>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
rs = def { D.rsNamespaces = [("bar", "baz")] }
|
|
Packit |
899799 |
doc = Res.Document (Res.Prologue [] Nothing [])
|
|
Packit |
899799 |
(Res.Element "foo" Map.empty
|
|
Packit |
899799 |
[ Res.NodeElement
|
|
Packit |
899799 |
$ Res.Element "subfoo" (Map.fromList [(Name "bin" (Just "baz") (Just "bar"), "")]) []
|
|
Packit |
899799 |
])
|
|
Packit |
899799 |
[]
|
|
Packit |
899799 |
lbs @=? S.concat (L.toChunks $ Res.renderLBS rs doc)
|
|
Packit |
899799 |
|
|
Packit |
899799 |
caseTLNConflict :: Assertion
|
|
Packit |
899799 |
caseTLNConflict = do
|
|
Packit |
899799 |
let lbs = S.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "<foo xmlns:bar=\"something\" bar:x=\"y\">"
|
|
Packit |
899799 |
, "<subfoo xmlns:bar_=\"baz\" bar_:bin=\"\"/>"
|
|
Packit |
899799 |
, "</foo>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
rs = def { D.rsNamespaces = [("bar", "baz")] }
|
|
Packit |
899799 |
doc = Res.Document (Res.Prologue [] Nothing [])
|
|
Packit |
899799 |
(Res.Element "foo" (Map.fromList [(Name "x" (Just "something") (Just "bar"), "y")])
|
|
Packit |
899799 |
[ Res.NodeElement
|
|
Packit |
899799 |
$ Res.Element "subfoo" (Map.fromList [(Name "bin" (Just "baz") (Just "bar"), "")]) []
|
|
Packit |
899799 |
])
|
|
Packit |
899799 |
[]
|
|
Packit |
899799 |
lbs @=? S.concat (L.toChunks $ Res.renderLBS rs doc)
|
|
Packit |
899799 |
|
|
Packit |
899799 |
caseBlazeHtml :: Assertion
|
|
Packit |
899799 |
caseBlazeHtml =
|
|
Packit |
899799 |
expected @=? str
|
|
Packit |
899799 |
where
|
|
Packit |
899799 |
str = renderMarkup $ toMarkup $ Res.Document (Res.Prologue [] Nothing []) root []
|
|
Packit |
899799 |
root :: Res.Element
|
|
Packit |
899799 |
root = Res.Element "html" Map.empty
|
|
Packit |
899799 |
[ Res.NodeElement $ Res.Element "head" Map.empty
|
|
Packit |
899799 |
[ Res.NodeElement $ Res.Element "title" Map.empty [Res.NodeContent "Test"]
|
|
Packit |
899799 |
, Res.NodeElement $ Res.Element "script" Map.empty
|
|
Packit |
899799 |
[Res.NodeContent "if (5 < 6 || 8 > 9) alert('Hello World!');"]
|
|
Packit |
899799 |
, Res.NodeElement $ Res.Element "{http://www.snoyman.com/xml2html}ie-cond" (Map.singleton "cond" "lt IE 7")
|
|
Packit |
899799 |
[Res.NodeElement $ Res.Element "link" (Map.singleton "href" "ie6.css") []]
|
|
Packit |
899799 |
, Res.NodeElement $ Res.Element "style" Map.empty
|
|
Packit |
899799 |
[Res.NodeContent "body > h1 { color: red }"]
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
, Res.NodeElement $ Res.Element "body" Map.empty
|
|
Packit |
899799 |
[ Res.NodeElement $ Res.Element "h1" Map.empty [Res.NodeContent "Hello World!"]
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
expected :: String
|
|
Packit |
899799 |
expected = concat
|
|
Packit |
899799 |
[ "\n"
|
|
Packit |
899799 |
, "<html><head><title>Test</title><script>if (5 < 6 || 8 > 9) alert('Hello World!');</script>"
|
|
Packit |
899799 |
, ""
|
|
Packit |
899799 |
, "<style>body > h1 { color: red }</style>"
|
|
Packit |
899799 |
, "</head>"
|
|
Packit |
899799 |
, "<body>Hello World!</body></html>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
caseAttrReorder :: Assertion
|
|
Packit |
899799 |
caseAttrReorder = do
|
|
Packit |
899799 |
let lbs = S.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "<foo c=\"c\" b=\"b\" a=\"a\">"
|
|
Packit |
899799 |
, "<bar a=\"a\" b=\"b\" c=\"c\"/>"
|
|
Packit |
899799 |
, "</foo>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
rs = def { Res.rsAttrOrder = \name m ->
|
|
Packit |
899799 |
case name of
|
|
Packit |
899799 |
"foo" -> reverse $ Map.toAscList m
|
|
Packit |
899799 |
_ -> Map.toAscList m
|
|
Packit |
899799 |
}
|
|
Packit |
899799 |
attrs = Map.fromList [("a", "a"), ("b", "b"), ("c", "c")]
|
|
Packit |
899799 |
doc = Res.Document (Res.Prologue [] Nothing [])
|
|
Packit |
899799 |
(Res.Element "foo" attrs
|
|
Packit |
899799 |
[ Res.NodeElement
|
|
Packit |
899799 |
$ Res.Element "bar" attrs []
|
|
Packit |
899799 |
])
|
|
Packit |
899799 |
[]
|
|
Packit |
899799 |
lbs @=? S.concat (L.toChunks $ Res.renderLBS rs doc)
|
|
Packit |
899799 |
|
|
Packit |
899799 |
caseOrderAttrs :: Assertion
|
|
Packit |
899799 |
caseOrderAttrs = do
|
|
Packit |
899799 |
let lbs = S.concat
|
|
Packit |
899799 |
[ ""
|
|
Packit |
899799 |
, "<foo c=\"c\" b=\"b\" a=\"a\">"
|
|
Packit |
899799 |
, "<bar a=\"a\" b=\"b\" c=\"c\"/>"
|
|
Packit |
899799 |
, "</foo>"
|
|
Packit |
899799 |
]
|
|
Packit |
899799 |
rs = def { Res.rsAttrOrder = Res.orderAttrs
|
|
Packit |
899799 |
[("foo", ["c", "b"])]
|
|
Packit |
899799 |
}
|
|
Packit |
899799 |
attrs = Map.fromList [("a", "a"), ("b", "b"), ("c", "c")]
|
|
Packit |
899799 |
doc = Res.Document (Res.Prologue [] Nothing [])
|
|
Packit |
899799 |
(Res.Element "foo" attrs
|
|
Packit |
899799 |
[ Res.NodeElement
|
|
Packit |
899799 |
$ Res.Element "bar" attrs []
|
|
Packit |
899799 |
])
|
|
Packit |
899799 |
[]
|
|
Packit |
899799 |
lbs @=? S.concat (L.toChunks $ Res.renderLBS rs doc)
|
|
Packit |
899799 |
|
|
Packit |
899799 |
caseParseCdata :: Assertion
|
|
Packit |
899799 |
caseParseCdata = do
|
|
Packit |
899799 |
let lbs = ""
|
|
Packit |
899799 |
doc = Res.Document (Res.Prologue [] Nothing [])
|
|
Packit |
899799 |
(Res.Element "a" Map.empty
|
|
Packit |
899799 |
[ Res.NodeContent "www.google.com"
|
|
Packit |
899799 |
])
|
|
Packit |
899799 |
[]
|
|
Packit |
899799 |
Res.parseLBS_ def lbs @?= doc
|
|
Packit |
899799 |
|
|
Packit |
899799 |
caseRetainNamespaces :: Assertion
|
|
Packit |
899799 |
caseRetainNamespaces = do
|
|
Packit |
899799 |
let lbs = "<foo xmlns:bar='baz'><bar:bin/><bin3 xmlns='bin4'></bin3></foo>"
|
|
Packit |
899799 |
doc = Res.parseLBS_ def { Res.psRetainNamespaces = True } lbs
|
|
Packit |
899799 |
doc `shouldBe` Res.Document
|
|
Packit |
899799 |
(Res.Prologue [] Nothing [])
|
|
Packit |
899799 |
(Res.Element
|
|
Packit |
899799 |
"foo"
|
|
Packit |
899799 |
(Map.singleton "xmlns:bar" "baz")
|
|
Packit |
899799 |
[ Res.NodeElement $ Res.Element
|
|
Packit |
899799 |
"{baz}bin"
|
|
Packit |
899799 |
Map.empty
|
|
Packit |
899799 |
[]
|
|
Packit |
899799 |
, Res.NodeElement $ Res.Element
|
|
Packit |
899799 |
"{bin4}bin3"
|
|
Packit |
899799 |
(Map.singleton "xmlns" "bin4")
|
|
Packit |
899799 |
[]
|
|
Packit |
899799 |
])
|
|
Packit |
899799 |
[]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
caseIso8859_1 :: Assertion
|
|
Packit |
899799 |
caseIso8859_1 = do
|
|
Packit |
899799 |
let lbs = "<foo>\232</foo>"
|
|
Packit |
899799 |
doc = Res.parseLBS_ def lbs
|
|
Packit |
899799 |
doc `shouldBe` Res.Document
|
|
Packit |
899799 |
(Res.Prologue [] Nothing [])
|
|
Packit |
899799 |
(Res.Element
|
|
Packit |
899799 |
"foo"
|
|
Packit |
899799 |
Map.empty
|
|
Packit |
899799 |
[Res.NodeContent "\232"])
|
|
Packit |
899799 |
[]
|
|
Packit |
899799 |
|
|
Packit |
899799 |
caseRenderCDATA :: Assertion
|
|
Packit |
899799 |
caseRenderCDATA = do
|
|
Packit |
899799 |
let doc = Res.Document (Res.Prologue [] Nothing [])
|
|
Packit |
899799 |
(Res.Element "a" Map.empty
|
|
Packit |
899799 |
[ Res.NodeContent "www.google.com"
|
|
Packit |
899799 |
])
|
|
Packit |
899799 |
[]
|
|
Packit |
899799 |
withoutCDATA = Res.renderLBS def doc
|
|
Packit |
899799 |
withCDATA = Res.renderLBS (def { Res.rsUseCDATA = const True }) doc
|
|
Packit |
899799 |
withCDATA `shouldBe` ""
|
|
Packit |
899799 |
withoutCDATA `shouldBe` "www.google.com"
|
|
Packit |
899799 |
|
|
Packit |
899799 |
caseEscapesCDATA :: Assertion
|
|
Packit |
899799 |
caseEscapesCDATA = do
|
|
Packit |
899799 |
let doc = Res.Document (Res.Prologue [] Nothing [])
|
|
Packit |
899799 |
(Res.Element "a" Map.empty
|
|
Packit |
899799 |
[ Res.NodeContent "]]>"
|
|
Packit |
899799 |
])
|
|
Packit |
899799 |
[]
|
|
Packit |
899799 |
result = Res.renderLBS (def { Res.rsUseCDATA = const True }) doc
|
|
Packit |
899799 |
result `shouldBe` "]]>"
|