iso8601-duration-0.1.1.0: test/Data/Time/ISO8601/DurationSpec.hs
{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE OverloadedStrings #-}
module Data.Time.ISO8601.DurationSpec (main, spec) where
import Data.Time.ISO8601.Duration
import Data.Time
import qualified Data.ByteString.Char8 as BS8
import Data.String
import Test.Hspec
import Test.Hspec.QuickCheck (prop)
import Test.QuickCheck
main :: IO ()
main = hspec spec
spec :: Spec
spec = do
describe "format/parse" $ do
prop "is idempotent" $ \(dur :: Duration) ->
counterexample (BS8.unpack (formatDuration dur)) $
parseDuration (formatDuration dur) === Right dur
describe "works on hand picked examples" $ do
tryExample "P3Y6M4DT12H30M5S"
tryExample "P6M4D"
describe "addDuration" $ do
itAddsDuration "P6D" (datetime 2016 11 22 13 14 0) (datetime 2016 11 28 13 14 0)
itAddsDuration "P6DT5H4M" (datetime 2016 11 22 13 14 0) (datetime 2016 11 28 18 18 0)
itAddsDuration "P6DT5H4M61S" (datetime 2016 11 22 13 14 0) (datetime 2016 11 28 18 19 1)
itAddsDuration "P8W" (datetime 2016 11 22 13 14 0) (datetime 2017 1 17 13 14 0)
itAddsDuration :: Duration -> UTCTime -> UTCTime -> SpecWith (Arg Expectation)
itAddsDuration d t e = it msg $ d `addDuration` t `shouldBe` e where
msg = show (formatDuration d) ++ " `addDuration` " ++ show t ++ " == " ++ show e
unsafeParseDuration :: BS8.ByteString -> Duration
unsafeParseDuration = either (const (error "unparsable")) id . parseDuration
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))
instance IsString Duration where
fromString = unsafeParseDuration . fromString
tryExample :: BS8.ByteString -> SpecWith (Arg Expectation)
tryExample str = it ("parses " ++ BS8.unpack str) $
fmap formatDuration (parseDuration str) `shouldBe` Right str
instance Arbitrary DurSecond where arbitrary = DurSecond <$> (getPositive <$> arbitrary)
instance Arbitrary DurMinute where arbitrary = DurMinute <$> (getPositive <$> arbitrary) <*> arbitrary
instance Arbitrary DurHour where arbitrary = DurHour <$> (getPositive <$> arbitrary) <*> arbitrary
instance Arbitrary DurTime where arbitrary = oneof [ DurTimeHour <$> arbitrary
, DurTimeMinute <$> arbitrary
, DurTimeSecond <$> arbitrary
]
instance Arbitrary DurDay where arbitrary = DurDay <$> (getPositive <$> arbitrary)
instance Arbitrary DurWeek where arbitrary = DurWeek <$> (getPositive <$> arbitrary)
instance Arbitrary DurMonth where arbitrary = DurMonth <$> (getPositive <$> arbitrary) <*> arbitrary
instance Arbitrary DurYear where arbitrary = DurYear <$> (getPositive <$> arbitrary) <*> arbitrary
instance Arbitrary DurDate where arbitrary = oneof [ DurDateDay <$> arbitrary <*> arbitrary
, DurDateMonth <$> arbitrary <*> arbitrary
, DurDateYear <$> arbitrary <*> arbitrary
]
instance Arbitrary Duration where arbitrary = oneof [ DurationDate <$> arbitrary
, DurationTime <$> arbitrary
, DurationWeek <$> arbitrary
]