packages feed

opml-conduit-0.6.0.0: test/Main.hs

{-# 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)