iso8601-duration-0.1.1.0: test/Data/Time/ISO8601/IntervalSpec.hs
{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE OverloadedStrings #-}
module Data.Time.ISO8601.IntervalSpec (main, spec) where
-- For Duration Arbitrary instances
import Data.Time.ISO8601.DurationSpec ()
import Data.Time.ISO8601.Interval
import Data.Time
import qualified Data.ByteString.Char8 as BS8
import Data.Either (isLeft)
import Test.Hspec
import Test.Hspec.QuickCheck (prop)
import Test.QuickCheck
import Test.QuickCheck.Instances ()
main :: IO ()
main = hspec spec
spec :: Spec
spec = do
prop "format/parse is idempotent" $ \(int :: Interval) ->
counterexample (BS8.unpack (formatInterval int)) $
parseInterval (formatInterval int) === Right int
describe "hand picked examples" $ do
parseFormatIdempotent "P3Y6M4DT12H30M5S"
parseFormatIdempotent "P6M4D"
parseShouldSatisfy "20080229/P6M4D" $ \i ->
case i of
Interval (StartDuration t _) -> t == datetime 2008 2 29 0 0 0
_ -> False
shouldParse "R/2014-12T20/P1W"
shouldNotParse "R/201412T20/P1W"
shouldParse "R/2014/P1W"
shouldParse "R1000/2014/P1W"
shouldParse "R/2014-W01-1T19:00:00/P1W"
shouldNotParse "R/2014-W1-1T19:00:00/P1W"
shouldNotParse "R/2014-W01-8T19:00:00/P1W"
shouldNotParse "R/2014-W54-1T19:00:00/P1W"
datetime :: Integer -> Int -> Int -> Int -> Int -> Int -> UTCTime
datetime y m d h m' s = UTCTime (fromGregorian y m d) (fromIntegral (h*3600+m'*60+s))
parseShouldSatisfy :: BS8.ByteString -> (Interval -> Bool) -> SpecWith (Arg Expectation)
parseShouldSatisfy str fun = it ("parses " ++ BS8.unpack str) $
parseInterval str `shouldSatisfy` either (const False) fun
shouldParse :: BS8.ByteString -> SpecWith (Arg Expectation)
shouldParse str = parseShouldSatisfy str (const True)
shouldNotParse :: BS8.ByteString -> SpecWith (Arg Expectation)
shouldNotParse str = it ("does not parse " ++ BS8.unpack str) $
parseInterval str `shouldSatisfy` isLeft
parseFormatIdempotent :: BS8.ByteString -> SpecWith (Arg Expectation)
parseFormatIdempotent str = it ("parse/format idempotent on " ++ BS8.unpack str) $
fmap formatInterval (parseInterval str) `shouldBe` Right str
instance Arbitrary Interval where
arbitrary = oneof [ Interval <$> arbitrary
, RecurringInterval <$> arbitrary <*> (fmap getPositive <$> arbitrary)
]
instance Arbitrary IntervalSpec where
arbitrary = oneof [ StartEnd <$> arbitrary <*> arbitrary
, StartDuration <$> arbitrary <*> arbitrary
, DurationEnd <$> arbitrary <*> arbitrary
, JustDuration <$> arbitrary
]