packages feed

cassava-th-0.1.0.0: test/Data/Csv/THSpec.hs

{-# LANGUAGE TemplateHaskell #-}

module Data.Csv.THSpec where

import Data.Csv hiding (record)
import Data.Text (Text)
import Data.ByteString (ByteString)
import Data.Csv.TH
import GHC.Generics
import Test.Hspec

data Foo = Foo
  { fooName :: Text
  , fooAge :: Int
  }
  deriving stock (Show, Eq, Generic)

$(deriveNamedRecord csvDefaultOptions ''Foo)
$(deriveToAndFromRecord ''Foo)

newtype GenericCsv a = GenericCsv a
  deriving stock (Show, Eq)

instance (Generic a, GToRecord (Rep a) (ByteString, ByteString)) => ToNamedRecord (GenericCsv a) where
  toNamedRecord (GenericCsv a) = genericToNamedRecord defaultOptions a

instance (Generic a, GToRecord (Rep a) ByteString) => ToRecord (GenericCsv a) where
  toRecord (GenericCsv a) = genericToRecord defaultOptions a

instance (Generic a, GFromNamedRecord (Rep a)) => FromNamedRecord (GenericCsv a) where
  parseNamedRecord rec = GenericCsv <$> genericParseNamedRecord defaultOptions rec

instance (Generic a, GFromRecord (Rep a)) => FromRecord (GenericCsv a) where
  parseRecord rec = GenericCsv <$> genericParseRecord defaultOptions rec

spec :: Spec
spec = do
  let foo = Foo "hello" 50
  describe "deriveToNamedRecord" do
    it "is equivalent to the generic" do
      toNamedRecord foo
        `shouldBe` toNamedRecord (GenericCsv foo)
  describe "deriveToRecord" do
    it "is equivalent to the generic" do
      toRecord foo
        `shouldBe` toRecord (GenericCsv foo)
  describe "deriveFromNamedRecord" do
    it "is equivalent to the generic" do
      let record = toNamedRecord foo
          recordG = toNamedRecord (GenericCsv foo)
      runParser (parseNamedRecord record)
        `shouldBe` pure foo
      runParser (parseNamedRecord recordG)
        `shouldBe` pure foo
      runParser (parseNamedRecord record)
        `shouldBe` pure (GenericCsv foo)
      runParser (parseNamedRecord recordG)
        `shouldBe` pure (GenericCsv foo)
  describe "deriveFromRecord" do
    it "is equivalent to the Generic" do
      let record = toRecord foo
          recordG = toRecord (GenericCsv foo)
      runParser (parseRecord record)
        `shouldBe` Right foo
      runParser (parseRecord record)
        `shouldBe` Right (GenericCsv foo)
      runParser (parseRecord recordG)
        `shouldBe` Right foo
      runParser (parseRecord recordG)
        `shouldBe` pure (GenericCsv foo)