File: SharedPrimaryKeySpec.hs

package info (click to toggle)
haskell-persistent 2.13.3.5-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,080 kB
  • sloc: haskell: 12,098; makefile: 3
file content (155 lines) | stat: -rw-r--r-- 4,478 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
{-# LANGUAGE TypeApplications, DeriveGeneric #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE DataKinds, FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE StandaloneDeriving #-}

module Database.Persist.TH.SharedPrimaryKeySpec where

import TemplateTestImports

import Data.Time
import Data.Proxy
import Test.Hspec
import Database.Persist
import Database.Persist.EntityDef
import Database.Persist.Sql
import Database.Persist.Sql.Util
import Database.Persist.TH

share [ mkPersist sqlSettings ] [persistLowerCase|

User
    name    String

Profile
    Id      UserId
    email   String

Profile2
    Id      (Key User)
    email   String

DayKeyTable
    Id Day
    name Text

RefDayKey
    dayKey DayKeyTableId

|]

spec :: Spec
spec = describe "Shared Primary Keys" $ do
    let
        getSqlType :: PersistEntity a => Proxy a -> SqlType
        getSqlType p =
            case getEntityId (entityDef p) of
                EntityIdField fd ->
                    fieldSqlType fd
                _ ->
                    SqlOther "Composite Key"

        keyProxy :: Proxy a -> Proxy (Key a)
        keyProxy _ = Proxy

        sqlTypeEquivalent
            :: (PersistFieldSql (Key a), PersistEntity a)
            => Proxy a
            -> Expectation
        sqlTypeEquivalent proxy =
            sqlType (keyProxy proxy) `shouldBe` getSqlType proxy

        testSqlTypeEquivalent
            :: (PersistFieldSql (Key a), PersistEntity a)
            => Proxy a
            -> Spec
        testSqlTypeEquivalent prxy =
            it "has equivalent SqlType from sqlType and entityId" $
                sqlTypeEquivalent prxy
    describe "PersistFieldSql" $ do
        it "should match underlying key" $ do
            sqlType (Proxy @UserId)
                `shouldBe`
                    sqlType (Proxy @ProfileId)

    describe "User" $ do
        it "has default ID key, SqlInt64" $ do
            sqlType (Proxy @UserId)
                `shouldBe`
                    SqlInt64

        testSqlTypeEquivalent (Proxy @User)

    describe "Profile"  $ do
        it "has same ID key type as User" $ do
            sqlType (Proxy @ProfileId)
                `shouldBe`
                    sqlType (Proxy @UserId)
        testSqlTypeEquivalent(Proxy @Profile)

    describe "Profile2" $ do
        it "has same ID key type as User" $ do
            sqlType (Proxy @Profile2Id)
                `shouldBe`
                    sqlType (Proxy @UserId)
        testSqlTypeEquivalent (Proxy @Profile2)

    describe "getEntityId FieldDef" $ do
        it "should match underlying primary key" $ do
            getSqlType (Proxy @User)
                `shouldBe`
                    getSqlType (Proxy @Profile)

    describe "DayKeyTable" $ do
        testSqlTypeEquivalent (Proxy @DayKeyTable)

        it "sqlType has Day type" $ do
            sqlType (Proxy @Day)
                `shouldBe`
                    sqlType (Proxy @DayKeyTableId)

        it "getSqlType has Day type" $ do
            sqlType (Proxy @Day)
                `shouldBe`
                    getSqlType (Proxy @DayKeyTable)

    describe "RefDayKey" $ do
        let
            [dayKeyField] =
                getEntityFields (entityDef (Proxy @RefDayKey))
        testSqlTypeEquivalent (Proxy @RefDayKey)

        it "has same sqltype as underlying" $ do
            fieldSqlType dayKeyField
                `shouldBe`
                    sqlType (Proxy @Day)

        it "has the right fieldType" $ do
            fieldType dayKeyField
                `shouldBe`
                    FTTypeCon Nothing "DayKeyTableId"

        it "has the right type" $ do
            let
                _ =
                    refDayKeyDayKey
                        :: RefDayKey -> DayKeyTableId
                _ =
                    RefDayKeyDayKey
                        :: EntityField RefDayKey DayKeyTableId
            True `shouldBe` True

        it "has a foreign ref" $ do
            case fieldReference dayKeyField of
                ForeignRef refName -> do
                    refName `shouldBe` EntityNameHS "DayKeyTable"
                other ->
                    fail $ "expected foreign ref, got: " <> show other