packages feed

opml-conduit-0.2.0.1: test/Main.hs

{-# LANGUAGE OverloadedLists   #-}
{-# LANGUAGE OverloadedStrings #-}
import           Control.Lens.Fold
import           Control.Lens.Getter
import           Control.Monad.Catch.Pure
import           Control.Monad.Identity
import           Control.Monad.Trans.Resource

import           Data.Conduit
import           Data.Conduit.Combinators     as Conduit hiding (length, map,
                                                          null)
import           Data.String
import           Data.Tree
import           Data.Version

import           Paths_opml_conduit

import qualified Language.Haskell.HLint       as HLint (hlint)
import           Test.Tasty
import           Test.Tasty.HUnit
import           Test.Tasty.QuickCheck
import           Text.OPML.Arbitrary          ()
import           Text.OPML.Stream.Parse
import           Text.OPML.Stream.Render
import           Text.OPML.Types
import           Text.XML.Stream.Parse        as XML


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 ^. opmlVersion_) @?= Version [2,0] []
  (result ^. head_ . opmlTitle_) @?= "Illustrating the category attribute"
  show (result ^. head_ . opmlCreated_) @?= "Just 2005-10-31 19:23:00 UTC"
  length (result ^.. outlines_ . traverse . traverse . _OpmlOutlineGeneric) @?= 1
  map (map length .levels) (result ^. outlines_) @?= [[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 ^. opmlVersion_) @?= Version [2,0] []
  (result ^. head_ . opmlTitle_) @?= "scriptingNewsDirectory.opml"
  show (result ^. head_ . opmlCreated_) @?= "Just 2005-10-13 15:34:07 UTC"
  show (result ^. head_ . modified_) @?= "Just 2005-10-25 21:33:57 UTC"
  (result ^. head_ . ownerName_) @?= "Dave Winer"
  (result ^. head_ . ownerEmail_) @?= "dwiner@yahoo.com"
  (result ^. head_ . expansionState_) @?= []
  (result ^. head_ . vertScrollState_) @?= Just 1
  (result ^. head_ . window_) @?= [(Top',105), (Left',466), (Bottom',386), (Right',964)]
  length (result ^.. outlines_ . traverse . traverse . _OpmlOutlineLink) @?= 8
  map (map length .levels) (result ^. outlines_) @?= [[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 ^. opmlVersion_) @?= Version [2,0] []
  (result ^. head_ . opmlTitle_) @?= "placesLived.opml"
  show (result ^. head_ . opmlCreated_) @?= "Just 2006-02-27 12:09:48 UTC"
  show (result ^. head_ . modified_) @?= "Just 2006-02-27 12:11:44 UTC"
  (result ^. head_ . ownerName_) @?= "Dave Winer"
  show (result ^. head_ . ownerId_) @?= "Just http://www.opml.org/profiles/sendMail?usernum=1"
  (result ^. head_ . expansionState_) @?= [1,2,5,10,13,15]
  (result ^. head_ . vertScrollState_) @?= Just 1
  (result ^. head_ . window_) @?= [(Top',242), (Left',329), (Bottom',665), (Right',547)]
  length (result ^.. outlines_ . traverse . traverse . _OpmlOutlineGeneric) @?= 18
  length (result ^.. outlines_ . traverse . traverse . _OpmlOutlineLink) @?= 1
  map (map length .levels) (result ^. outlines_) @?= [[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 ^. opmlVersion_) @?= Version [2,0] []
  (result ^. head_ . opmlTitle_) @?= "workspace.userlandsamples.doSomeUpstreaming"
  show (result ^. head_ . opmlCreated_) @?= "Just 2002-02-11 22:48:02 UTC"
  show (result ^. head_ . modified_) @?= "Just 2005-10-30 03:30:17 UTC"
  (result ^. head_ . ownerName_) @?= "Dave Winer"
  (result ^. head_ . ownerEmail_) @?= "dwiner@yahoo.com"
  (result ^. head_ . expansionState_) @?= [1, 2, 4]
  (result ^. head_ . vertScrollState_) @?= Just 1
  (result ^. head_ . window_) @?= [(Top', 74), (Left', 41), (Bottom', 314), (Right', 475)]
  length (result ^.. outlines_ . traverse . traverse . _OpmlOutlineGeneric) @?= 11
  map (map length .levels) (result ^. outlines_) @?= [[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 ^. opmlVersion_) @?= Version [2,0] []
  (result ^. head_ . opmlTitle_) @?= "states.opml"
  show (result ^. head_ . opmlCreated_) @?= "Just 2005-03-15 16:35:45 UTC"
  show (result ^. head_ . modified_) @?= "Just 2005-07-14 23:41:05 UTC"
  (result ^. head_ . ownerName_) @?= "Dave Winer"
  (result ^. head_ . ownerEmail_) @?= "dave@scripting.com"
  (result ^. head_ . expansionState_) @?= [1, 6, 13, 16, 18, 20]
  (result ^. head_ . vertScrollState_) @?= Just 1
  (result ^. head_ . window_) @?= [(Top', 106), (Left', 106), (Bottom', 558), (Right', 479)]
  length (result ^.. outlines_ . traverse . traverse . _OpmlOutlineGeneric) @?= 63
  map (map length .levels) (result ^. outlines_) @?= [[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 ^. opmlVersion_) @?= Version [2,0] []
  (result ^. head_ . opmlTitle_) @?= "mySubscriptions.opml"
  show (result ^. head_ . opmlCreated_) @?= "Just 2005-06-18 12:11:52 UTC"
  show (result ^. head_ . modified_) @?= "Just 2005-08-02 21:42:48 UTC"
  (result ^. head_ . ownerName_) @?= "Dave Winer"
  (result ^. head_ . ownerEmail_) @?= "dave@scripting.com"
  (result ^. head_ . vertScrollState_) @?= Just 1
  (result ^. head_ . window_) @?= [(Top', 61), (Left', 304), (Bottom', 562), (Right',842)]
  length (result ^.. outlines_ . traverse . traverse . _OpmlOutlineSubscription) @?= 13

inverseHeadProperty :: TestTree
inverseHeadProperty = testProperty "parse . render = id (on OpmlHead)" $ \opmlHead -> either (const False) (opmlHead ==) (runIdentity . runCatchT . runConduit $ renderOpmlHead opmlHead =$= force "Invalid OPML head" parseOpmlHead)

inverseProperty :: TestTree
inverseProperty = testProperty "parse . render = id" $ \opml -> either (const False) (opml ==) (runIdentity . runCatchT . runConduit $ renderOpml opml =$= force "Invalid OPML" parseOpml)