{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedStrings #-}
-- {{{ Imports
import Arbitrary ()
import Control.Monad.Trans.Resource
import Data.Conduit
import Data.Conduit.Combinators as Conduit (sourceFile)
import Data.Default
import Data.String
import Data.Text.Encoding
import Data.Tree
import Data.Version
import Paths_opml_conduit
import qualified Language.Haskell.HLint as HLint (hlint)
import Lens.Simple
import Test.Tasty
import Test.Tasty.HUnit
import Test.Tasty.QuickCheck
import Text.OPML.Conduit.Parse
import Text.OPML.Conduit.Render
import Text.OPML.Lens
import Text.XML.Stream.Parse as XML
import URI.ByteString
-- }}}
main :: IO ()
main = defaultMain $ testGroup "Tests"
[ unitTests
, properties
, hlint
]
unitTests :: TestTree
unitTests = testGroup "Unit tests"
[ categoriesCase
, directoryCase
, placesCase
, scriptCase
, statesCase
, subscriptionsCase
]
properties :: TestTree
properties = testGroup "Properties"
[ inverseHeadProperty
-- , inverseProperty
]
hlint :: TestTree
hlint = testCase "HLint check" $ do
result <- HLint.hlint [ "test/", "Text/" ]
null result @?= True
categoriesCase :: TestTree
categoriesCase = testCase "Parse categories list" $ do
dataFile <- fromString <$> getDataFileName "data/category.opml"
result <- runResourceT . runConduit $ sourceFile dataFile =$= XML.parseBytes def =$= force "Invalid OPML" parseOpml
(result ^. opmlVersionL) @?= Version [2,0] []
(result ^. opmlHeadL . opmlTitleL) @?= "Illustrating the category attribute"
show (result ^. opmlHeadL . opmlCreatedL) @?= "Just 2005-10-31 19:23:00 UTC"
length (result ^.. opmlOutlinesL . traverse . traverse . _OpmlOutlineGeneric) @?= 1
map (map length .levels) (result ^. opmlOutlinesL) @?= [[1]]
directoryCase :: TestTree
directoryCase = testCase "Parse directory tree" $ do
dataFile <- fromString <$> getDataFileName "data/directory.opml"
result <- runResourceT . runConduit $ sourceFile dataFile =$= XML.parseBytes def =$= force "Invalid OPML" parseOpml
(result ^. opmlVersionL) @?= Version [2,0] []
(result ^. opmlHeadL . opmlTitleL) @?= "scriptingNewsDirectory.opml"
show (result ^. opmlHeadL . opmlCreatedL) @?= "Just 2005-10-13 15:34:07 UTC"
show (result ^. opmlHeadL . modifiedL) @?= "Just 2005-10-25 21:33:57 UTC"
(result ^. opmlHeadL . ownerNameL) @?= "Dave Winer"
(result ^. opmlHeadL . ownerEmailL) @?= "dwiner@yahoo.com"
(result ^.. opmlHeadL . expansionStateL) @?= []
(result ^. opmlHeadL . vertScrollStateL) @?= Just 1
(result ^. opmlHeadL . windowBottomL) @?= Just 386
(result ^. opmlHeadL . windowLeftL) @?= Just 466
(result ^. opmlHeadL . windowRightL) @?= Just 964
(result ^. opmlHeadL . windowTopL) @?= Just 105
length (result ^.. opmlOutlinesL . traverse . traverse . _OpmlOutlineLink) @?= 8
map (map length .levels) (result ^. opmlOutlinesL) @?= [[1], [1], [1], [1], [1], [1], [1], [1]]
placesCase :: TestTree
placesCase = testCase "Parse places list" $ do
dataFile <- fromString <$> getDataFileName "data/placesLived.opml"
result <- runResourceT . runConduit $ sourceFile dataFile =$= XML.parseBytes def =$= force "Invalid OPML" parseOpml
(result ^. opmlVersionL) @?= Version [2,0] []
(result ^. opmlHeadL . opmlTitleL) @?= "placesLived.opml"
show (result ^. opmlHeadL . opmlCreatedL) @?= "Just 2006-02-27 12:09:48 UTC"
show (result ^. opmlHeadL . modifiedL) @?= "Just 2006-02-27 12:11:44 UTC"
(result ^. opmlHeadL . ownerNameL) @?= "Dave Winer"
fmap (decodeUtf8 . serializeURIRef') (result ^. opmlHeadL . ownerIdL) @?= Just "http://www.opml.org/profiles/sendMail?usernum=1"
(result ^.. opmlHeadL . expansionStateL) @?= [1,2,5,10,13,15]
(result ^. opmlHeadL . vertScrollStateL) @?= Just 1
(result ^. opmlHeadL . windowBottomL) @?= Just 665
(result ^. opmlHeadL . windowLeftL) @?= Just 329
(result ^. opmlHeadL . windowRightL) @?= Just 547
(result ^. opmlHeadL . windowTopL) @?= Just 242
length (result ^.. opmlOutlinesL . traverse . traverse . _OpmlOutlineGeneric) @?= 18
length (result ^.. opmlOutlinesL . traverse . traverse . _OpmlOutlineLink) @?= 1
map (map length .levels) (result ^. opmlOutlinesL) @?= [[1,6,12]]
scriptCase :: TestTree
scriptCase = testCase "Parse script" $ do
dataFile <- fromString <$> getDataFileName "data/simpleScript.opml"
result <- runResourceT . runConduit $ sourceFile dataFile =$= XML.parseBytes def =$= force "Invalid OPML" parseOpml
(result ^. opmlVersionL) @?= Version [2,0] []
(result ^. opmlHeadL . opmlTitleL) @?= "workspace.userlandsamples.doSomeUpstreaming"
show (result ^. opmlHeadL . opmlCreatedL) @?= "Just 2002-02-11 22:48:02 UTC"
show (result ^. opmlHeadL . modifiedL) @?= "Just 2005-10-30 03:30:17 UTC"
(result ^. opmlHeadL . ownerNameL) @?= "Dave Winer"
(result ^. opmlHeadL . ownerEmailL) @?= "dwiner@yahoo.com"
(result ^.. opmlHeadL . expansionStateL) @?= [1, 2, 4]
(result ^. opmlHeadL . vertScrollStateL) @?= Just 1
(result ^. opmlHeadL . windowBottomL) @?= Just 314
(result ^. opmlHeadL . windowLeftL) @?= Just 41
(result ^. opmlHeadL . windowRightL) @?= Just 475
(result ^. opmlHeadL . windowTopL) @?= Just 74
length (result ^.. opmlOutlinesL . traverse . traverse . _OpmlOutlineGeneric) @?= 11
map (map length .levels) (result ^. opmlOutlinesL) @?= [[1,2,2], [1,2], [1], [1,1]]
statesCase :: TestTree
statesCase = testCase "Parse states list" $ do
dataFile <- fromString <$> getDataFileName "data/states.opml"
result <- runResourceT . runConduit $ sourceFile dataFile =$= XML.parseBytes def =$= force "Invalid OPML" parseOpml
(result ^. opmlVersionL) @?= Version [2,0] []
(result ^. opmlHeadL . opmlTitleL) @?= "states.opml"
show (result ^. opmlHeadL . opmlCreatedL) @?= "Just 2005-03-15 16:35:45 UTC"
show (result ^. opmlHeadL . modifiedL) @?= "Just 2005-07-14 23:41:05 UTC"
(result ^. opmlHeadL . ownerNameL) @?= "Dave Winer"
(result ^. opmlHeadL . ownerEmailL) @?= "dave@scripting.com"
(result ^.. opmlHeadL . expansionStateL) @?= [1, 6, 13, 16, 18, 20]
(result ^. opmlHeadL . vertScrollStateL) @?= Just 1
(result ^. opmlHeadL . windowBottomL) @?= Just 558
(result ^. opmlHeadL . windowLeftL) @?= Just 106
(result ^. opmlHeadL . windowRightL) @?= Just 479
(result ^. opmlHeadL . windowTopL) @?= Just 106
length (result ^.. opmlOutlinesL . traverse . traverse . _OpmlOutlineGeneric) @?= 63
map (map length .levels) (result ^. opmlOutlinesL) @?= [[1, 8, 50, 4]]
subscriptionsCase :: TestTree
subscriptionsCase = testCase "Parse subscriptions list" $ do
dataFile <- fromString <$> getDataFileName "data/subscriptionList.opml"
result <- runResourceT . runConduit $ sourceFile dataFile =$= XML.parseBytes def =$= force "Invalid OPML" parseOpml
(result ^. opmlVersionL) @?= Version [2,0] []
(result ^. opmlHeadL . opmlTitleL) @?= "mySubscriptions.opml"
show (result ^. opmlHeadL . opmlCreatedL) @?= "Just 2005-06-18 12:11:52 UTC"
show (result ^. opmlHeadL . modifiedL) @?= "Just 2005-08-02 21:42:48 UTC"
(result ^. opmlHeadL . ownerNameL) @?= "Dave Winer"
(result ^. opmlHeadL . ownerEmailL) @?= "dave@scripting.com"
(result ^. opmlHeadL . vertScrollStateL) @?= Just 1
(result ^. opmlHeadL . windowBottomL) @?= Just 562
(result ^. opmlHeadL . windowLeftL) @?= Just 304
(result ^. opmlHeadL . windowRightL) @?= Just 842
(result ^. opmlHeadL . windowTopL) @?= Just 61
length (result ^.. opmlOutlinesL . traverse . traverse . _OpmlOutlineSubscription) @?= 13
inverseHeadProperty :: TestTree
inverseHeadProperty = testProperty "parse . render = id (on OpmlHead)" $ \opmlHead -> either (const False) (opmlHead ==) (runConduit $ renderOpmlHead opmlHead =$= force "Invalid <head>" parseOpmlHead)
-- inverseProperty :: TestTree
-- inverseProperty = testProperty "parse . render = id" $ \opml -> either (const False) (opml ==) (runIdentity . runCatchT . runConduit $ renderOpml opml =$= force "Invalid OPML" parseOpml)