main.hs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. {-# LANGUAGE ExistentialQuantification #-}
  2. {-# LANGUAGE FlexibleInstances #-}
  3. {-# LANGUAGE GeneralizedNewtypeDeriving #-}
  4. {-# LANGUAGE MultiParamTypeClasses #-}
  5. {-# LANGUAGE OverloadedStrings #-}
  6. {-# LANGUAGE QuasiQuotes #-}
  7. {-# LANGUAGE TemplateHaskell #-}
  8. {-# LANGUAGE TypeFamilies #-}
  9. {-# LANGUAGE UndecidableInstances #-}
  10. module Main
  11. (
  12. -- avoid unused ident warnings
  13. module Main
  14. ) where
  15. import Control.Applicative (Const (..))
  16. import Data.Aeson
  17. import Data.ByteString.Lazy.Char8 ()
  18. import Data.Functor.Identity (Identity (..))
  19. import Data.Text (Text, pack)
  20. import Test.Hspec
  21. import Test.Hspec.QuickCheck
  22. import Test.QuickCheck.Arbitrary
  23. import Test.QuickCheck.Gen (Gen)
  24. import Database.Persist
  25. import Database.Persist.TH
  26. import TemplateTestImports
  27. share [mkPersist sqlSettings { mpsGeneric = False }, mkDeleteCascade sqlSettings { mpsGeneric = False }] [persistUpperCase|
  28. Person json
  29. name Text
  30. age Int Maybe
  31. foo Foo
  32. address Address
  33. deriving Show Eq
  34. Address json
  35. street Text
  36. city Text
  37. zip Int Maybe
  38. deriving Show Eq
  39. NoJson
  40. foo Text
  41. deriving Show Eq
  42. |]
  43. share [mkPersist sqlSettings { mpsGeneric = False, mpsGenerateLenses = True }] [persistLowerCase|
  44. Lperson json
  45. name Text
  46. age Int Maybe
  47. address Laddress
  48. deriving Show Eq
  49. Laddress json
  50. street Text
  51. city Text
  52. zip Int Maybe
  53. deriving Show Eq
  54. |]
  55. arbitraryT :: Gen Text
  56. arbitraryT = pack <$> arbitrary
  57. instance Arbitrary Person where
  58. arbitrary = Person <$> arbitraryT <*> arbitrary <*> arbitrary <*> arbitrary
  59. instance Arbitrary Address where
  60. arbitrary = Address <$> arbitraryT <*> arbitraryT <*> arbitrary
  61. main :: IO ()
  62. main = hspec $ do
  63. describe "JSON serialization" $ do
  64. prop "to/from is idempotent" $ \person ->
  65. decode (encode person) == Just (person :: Person)
  66. it "decode" $
  67. decode "{\"name\":\"Michael\",\"age\":27,\"foo\":\"Bar\",\"address\":{\"street\":\"Narkis\",\"city\":\"Maalot\"}}" `shouldBe` Just
  68. (Person "Michael" (Just 27) Bar $ Address "Narkis" "Maalot" Nothing)
  69. describe "JSON serialization for Entity" $ do
  70. let key = PersonKey 0
  71. prop "to/from is idempotent" $ \person ->
  72. decode (encode (Entity key person)) == Just (Entity key (person :: Person))
  73. it "decode" $
  74. decode "{\"id\": 0, \"name\":\"Michael\",\"age\":27,\"foo\":\"Bar\",\"address\":{\"street\":\"Narkis\",\"city\":\"Maalot\"}}" `shouldBe` Just
  75. (Entity key (Person "Michael" (Just 27) Bar $ Address "Narkis" "Maalot" Nothing))
  76. it "lens operations" $ do
  77. let street1 = "street1"
  78. city1 = "city1"
  79. city2 = "city2"
  80. zip1 = Just 12345
  81. address1 = Laddress street1 city1 zip1
  82. address2 = Laddress street1 city2 zip1
  83. name1 = "name1"
  84. age1 = Just 27
  85. person1 = Lperson name1 age1 address1
  86. person2 = Lperson name1 age1 address2
  87. (person1 ^. lpersonAddress) `shouldBe` address1
  88. (person1 ^. (lpersonAddress . laddressCity)) `shouldBe` city1
  89. (person1 & ((lpersonAddress . laddressCity) .~ city2)) `shouldBe` person2
  90. (&) :: a -> (a -> b) -> b
  91. x & f = f x
  92. (^.) :: s
  93. -> ((a -> Const a b) -> (s -> Const a t))
  94. -> a
  95. x ^. lens = getConst $ lens Const x
  96. (.~) :: ((a -> Identity b) -> (s -> Identity t))
  97. -> b
  98. -> s
  99. -> t
  100. lens .~ val = runIdentity . lens (\_ -> Identity val)