module Saturn.Unstable.Type.HourSpec where

import qualified Data.Maybe as Maybe
import qualified Data.Text.Lazy.Builder as Builder
import qualified Data.Word as Word
import qualified Saturn.Unstable.Type.FieldSpec as FieldSpec
import qualified Saturn.Unstable.Type.Hour as Hour
import qualified Test.Hspec as Hspec
import qualified Test.QuickCheck as QuickCheck
import qualified Text.Parsec as Parsec

spec :: Hspec.Spec
spec :: Spec
spec = String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
Hspec.describe String
"Saturn.Unstable.Type.Hour" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
  String -> Property -> SpecWith (Arg Property)
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
Hspec.it String
"round trips"
    (Property -> Spec)
-> ((Hour -> Expectation) -> Property)
-> (Hour -> Expectation)
-> Spec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Gen Hour -> (Hour -> [Hour]) -> (Hour -> Expectation) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> [a]) -> (a -> prop) -> Property
QuickCheck.forAllShrink Gen Hour
arbitrary Hour -> [Hour]
shrink
    ((Hour -> Expectation) -> Spec) -> (Hour -> Expectation) -> Spec
forall a b. (a -> b) -> a -> b
$ \Hour
x -> do
      Parsec Text () Hour -> String -> Text -> Either ParseError Hour
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
Parsec.parse Parsec Text () Hour
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Hour
Hour.parsec String
"" (Builder -> Text
Builder.toLazyText (Builder -> Text) -> Builder -> Text
forall a b. (a -> b) -> a -> b
$ Hour -> Builder
Hour.toBuilder Hour
x)
        Either ParseError Hour -> Either ParseError Hour -> Expectation
forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
`Hspec.shouldBe` Hour -> Either ParseError Hour
forall a b. b -> Either a b
Right Hour
x

arbitrary :: QuickCheck.Gen Hour.Hour
arbitrary :: Gen Hour
arbitrary = Gen Field -> (Field -> Maybe Hour) -> Gen Hour
forall a b. Gen a -> (a -> Maybe b) -> Gen b
QuickCheck.suchThatMap Gen Field
FieldSpec.arbitrary Field -> Maybe Hour
Hour.fromField

shrink :: Hour.Hour -> [Hour.Hour]
shrink :: Hour -> [Hour]
shrink = (Field -> Maybe Hour) -> [Field] -> [Hour]
forall a b. (a -> Maybe b) -> [a] -> [b]
Maybe.mapMaybe Field -> Maybe Hour
Hour.fromField ([Field] -> [Hour]) -> (Hour -> [Field]) -> Hour -> [Hour]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Field -> [Field]
FieldSpec.shrink (Field -> [Field]) -> (Hour -> Field) -> Hour -> [Field]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Hour -> Field
Hour.toField

new :: (MonadFail m) => [[Word.Word8]] -> m Hour.Hour
new :: forall (m :: * -> *). MonadFail m => [[Word8]] -> m Hour
new [[Word8]]
xs = do
  Field
field <- [[Word8]] -> m Field
forall (m :: * -> *). MonadFail m => [[Word8]] -> m Field
FieldSpec.new [[Word8]]
xs
  m Hour -> (Hour -> m Hour) -> Maybe Hour -> m Hour
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> m Hour
forall a. String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> m Hour) -> String -> m Hour
forall a b. (a -> b) -> a -> b
$ String
"invalid Hour: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> [[Word8]] -> String
forall a. Show a => a -> String
show [[Word8]]
xs) Hour -> m Hour
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe Hour -> m Hour) -> Maybe Hour -> m Hour
forall a b. (a -> b) -> a -> b
$ Field -> Maybe Hour
Hour.fromField Field
field