epub-metadata-3.0: testsuite/OpfParse.hs
-- Copyright: 2010-2013 Dino Morelli
-- License: BSD3 (see LICENSE)
-- Author: Dino Morelli <dino@ui3.info>
module OpfParse
( tests )
where
import Control.Monad.Error
import System.FilePath
import Test.HUnit
import Codec.Epub2.IO
import Codec.Epub2.Opf.Package
import Codec.Epub2.Opf.Parse
tests :: Test
tests = TestList
[ testFull
, testMinimal
, testMissingAll
, testDamagedZip
, testIllegalCharsBeforeDecl
]
{- A fairly comprehensive test containing all possible things
Not complete at this time because the library can't parse it all yet!
-}
testFull :: Test
testFull = TestCase $ do
xmlString <- readFile $ "testsuite" </> "testFull.opf"
actual <- runErrorT $ parseXmlToOpf xmlString
let expected =
Right Package
{ opVersion = "2.0"
, opUniqueId = "isbn"
, opMeta = Metadata
{ metaTitles =
[ Title Nothing "Title Of This Book"
, Title (Just "fr") "Titre De Ce Livre"
]
, metaCreators =
[ Creator
(Just "aut")
(Just "Wiggins, Josephine B.")
"Josephine B. Wiggins"
, Creator
(Just "aut")
Nothing
"Horatio Cromwell"
, Creator
Nothing
Nothing
"Natalia Jenkins"
]
, metaContributors =
[ Creator
(Just "ill")
(Just "Knickerbocker, Reginald Q.")
"Reginald Q. Knickerbocker"
, Creator
(Just "edt")
Nothing "Beverly Abercrombie"
]
, metaSubjects = ["Fiction","Science Fiction"]
, metaDescriptions =
[ Description Nothing "This document is a stub used for unit testing. It is missing the rest of the tags that normally occur after metadata."
, Description Nothing "An additional description"
]
, metaPublishers =
[ "Fictional Books Ltd."
, "An additional publisher"
]
, metaDates =
[ Date (Just "published") "2010"
, Date (Just "created") "2010-05-07"
, Date (Just "modified") "2010-05-08T10:20:57"
, Date Nothing "2009"
]
, metaTypes =
[ "test OPF Package Document"
, "an additional type"
]
, metaFormats =
[ "ePub publication"
, "an additional format"
]
, metaIds =
[ Identifier "isbn" (Just "ISBN") "1-82057-821-9"
, Identifier "other" Nothing "1386506873266"
]
, metaSources =
[ "document source"
, "an additional source"
]
, metaLangs = ["en-US", "en-UK"]
, metaRelations =
[ "document relation"
, "an additional relation"
]
, metaCoverages =
[ "coverage information"
, "an additional coverage"
]
, metaRights =
[ "Copyright: 2010 Dino Morelli, License: BSD3"
, "an additional rights"
]
}
, opManifest =
[ ManifestItem
{ mfiId = "ncx"
, mfiHref = "toc.ncx"
, mfiMediaType = "application/x-dtbncx+xml"
}
, ManifestItem
{ mfiId = "titlePage"
, mfiHref = "content/titlePage.html"
, mfiMediaType = "application/xhtml+xml"
}
, ManifestItem
{ mfiId = "someContent"
, mfiHref = "content/someContent.html"
, mfiMediaType = "application/xhtml+xml"
}
]
, opSpine = Spine
{ spineToc = "ncx"
, spineItemrefs =
[ SpineItemref {siIdRef = "titlePage", siLinear = Nothing}
, SpineItemref {siIdRef = "someContent", siLinear = Nothing}
]
}
, opGuide =
[ GuideRef
{ grType = "title-page"
, grTitle = Just "Title page"
, grHref = "content/titlePage.html"
}
, GuideRef
{ grType = "text"
, grTitle = Just "Title Of This Book"
, grHref = "content/someContent.html"
}
]
}
assertEqual "very full" expected actual
{- Test the absolute minimum set of fields allowed while remaining
compliant with the spec
-}
testMinimal :: Test
testMinimal = TestCase $ do
xmlString <- liftIO $ readFile $ "testsuite" </> "testMinimal.opf"
actual <- runErrorT $ parseXmlToOpf xmlString
let expected =
Right Package
{ opVersion = "2.0"
, opUniqueId = "isbn"
, opMeta = Metadata
{ metaTitles = [Title Nothing "Title Of This Book"]
, metaCreators = []
, metaContributors = []
, metaSubjects = []
, metaDescriptions = []
, metaPublishers = []
, metaDates = []
, metaTypes = []
, metaFormats = []
, metaIds = [Identifier "isbn" (Just "ISBN") "1-82057-821-9"]
, metaSources = []
, metaLangs = ["en-us"]
, metaRelations = []
, metaCoverages = []
, metaRights = []
}
, opManifest =
[ ManifestItem
{ mfiId = "ncx"
, mfiHref = "toc.ncx"
, mfiMediaType = "application/x-dtbncx+xml"
}
]
, opSpine = Spine {spineToc = "ncx", spineItemrefs = []}
, opGuide = []
}
assertEqual "minimal" expected actual
{- Test data missing everything important: package version and
unique-identifier attributes, title, identifier and language tags
-}
testMissingAll :: Test
testMissingAll = TestCase $ do
xmlString <- readFile $ "testsuite" </> "testMissingAll.opf"
actual <- runErrorT $ parseXmlToOpf xmlString
let expected =
Right Package
{ opVersion = ""
, opUniqueId = ""
, opMeta = emptyMetadata
, opManifest = []
, opSpine = Spine {spineToc = "", spineItemrefs = []}
, opGuide = []
}
assertEqual "missing all" expected actual
{- Occasionally epub zip files come along that are damaged in this
way. It's not fatal to the UNIX zip utility or to book readers, but had
to be specially handled in the Haskell zip-archive library or it causes
a fatal exception.
-}
testDamagedZip :: Test
testDamagedZip = TestLabel "damaged zip" $ TestCase $ do
actual <- runErrorT $ opfContentsFromZip $ "testsuite"
</> "damagedZipCentralDir.epub"
actual @?= Left "Did not find end of central directory signature. Failed reading at byte position 138"
{- Found books coming from Barnes & Noble (for their NOOK reader) to
contain illegal characters before the XML declaration. This is
strictly not allowed by the XML specification. I am very
disappointed with Barnes & Noble for selling garbage like this.
-}
testIllegalCharsBeforeDecl :: Test
testIllegalCharsBeforeDecl = TestCase $ do
xmlString <- readFile $
"testsuite" </> "testIllegalCharsBeforeDecl.opf"
actual <- runErrorT $ parseXmlToOpf xmlString
let expected =
Right Package
{ opVersion = "2.0"
, opUniqueId = "uuid_id"
, opMeta = Metadata
{ metaTitles = [Title Nothing "Foo Bar Baz"]
, metaCreators = []
, metaContributors = []
, metaSubjects = []
, metaDescriptions = []
, metaPublishers = []
, metaDates = []
, metaTypes = []
, metaFormats = []
, metaIds = [Identifier "uuid_id" (Just "uuid") "1122334455"]
, metaSources = []
, metaLangs = ["en"]
, metaRelations = []
, metaCoverages = []
, metaRights = []}
, opManifest =
[ ManifestItem
{ mfiId = "ncx"
, mfiHref = "toc.ncx"
, mfiMediaType = "application/x-dtbncx+xml"
}
]
, opSpine = Spine {spineToc = "ncx", spineItemrefs = []}
, opGuide = []
}
assertEqual "illegal chars before XML declaration" expected actual