File: ForeignRefSpec.hs

package info (click to toggle)
haskell-persistent 2.14.6.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,120 kB
  • sloc: haskell: 12,767; makefile: 3
file content (178 lines) | stat: -rw-r--r-- 5,781 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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
--
-- DeriveAnyClass is not actually used by persistent-template
-- But a long standing bug was that if it was enabled, it was used to derive instead of GeneralizedNewtypeDeriving
-- This was fixed by using DerivingStrategies to specify newtype deriving should be used.
-- This pragma is left here as a "test" that deriving works when DeriveAnyClass is enabled.
-- See https://github.com/yesodweb/persistent/issues/578
{-# LANGUAGE DeriveAnyClass #-}

module Database.Persist.TH.ForeignRefSpec where

import Control.Applicative (Const(..))
import Data.Aeson
import Data.ByteString.Lazy.Char8 ()
import Data.Coerce
import Data.Functor.Identity (Identity(..))
import Data.Int
import qualified Data.List as List
import Data.Proxy
import Data.Text (Text, pack)
import GHC.Generics (Generic)
import Test.Hspec
import Test.Hspec.QuickCheck
import Test.QuickCheck.Arbitrary
import Test.QuickCheck.Gen (Gen)

import Database.Persist
import Database.Persist.EntityDef.Internal
import Database.Persist.Sql
import Database.Persist.Sql.Util
import Database.Persist.TH
import TemplateTestImports

mkPersist sqlSettings [persistLowerCase|

HasCustomName sql=custom_name
    name Text

ForeignTarget
    name Text
    deriving Eq Show

ForeignSource
    name Text
    foreignTargetId ForeignTargetId
    Foreign ForeignTarget fk_s_t foreignTargetId

ForeignPrimary
    name Text
    Primary name
    deriving Eq Show

ForeignPrimarySource
    name Text
    Foreign ForeignPrimary fk_name_target name

NullableRef
    name Text Maybe
    Foreign ForeignPrimary fk_nullable_ref name

ParentImplicit
    name Text

ChildImplicit
    name Text
    parent ParentImplicitId OnDeleteCascade OnUpdateCascade

ParentExplicit
    name Text
    Primary name

ChildExplicit
    name Text
    Foreign ParentExplicit OnDeleteCascade OnUpdateCascade fkparent name
|]

spec :: Spec
spec = describe "ForeignRefSpec" $ do
    describe "HasCustomName" $ do
        let
            edef =
                entityDef $ Proxy @HasCustomName
        it "should have a custom db name" $ do
            entityDB edef
                `shouldBe`
                    EntityNameDB "custom_name"

    it "should compile" $ do
        True `shouldBe` True

    describe "ForeignPrimarySource" $ do
        let
            fpsDef =
                entityDef $ Proxy @ForeignPrimarySource
            [foreignDef] =
                entityForeigns fpsDef
        it "has the right type" $ do
            foreignPrimarySourceFk_name_target (ForeignPrimarySource "asdf")
                `shouldBe`
                    ForeignPrimaryKey "asdf"

    describe "Cascade" $ do
        describe "Explicit" $ do
            let
                parentDef =
                    entityDef $ Proxy @ParentExplicit
                childDef =
                    entityDef $ Proxy @ChildExplicit
                childForeigns =
                    entityForeigns childDef
            it "should have a single foreign reference defined" $ do
                    case entityForeigns childDef of
                        [a] ->
                            pure ()
                        as ->
                            expectationFailure . mconcat $
                                [ "Expected one foreign reference on childDef, "
                                , "got: "
                                , show as
                                ]
            let
                [ForeignDef {..}] =
                    childForeigns

            describe "ChildExplicit" $ do
                it "should have the right target table" $ do
                    foreignRefTableHaskell `shouldBe`
                        EntityNameHS "ParentExplicit"
                    foreignRefTableDBName `shouldBe`
                        EntityNameDB "parent_explicit"
                it "should have the right cascade behavior" $ do
                    foreignFieldCascade
                        `shouldBe`
                            FieldCascade
                                { fcOnUpdate =
                                    Just Cascade
                                , fcOnDelete =
                                    Just Cascade
                                }
                it "is not nullable" $ do
                    foreignNullable `shouldBe` False
                it "is to the Primary key" $ do
                    foreignToPrimary `shouldBe` True

        describe "Implicit" $ do
            let
                parentDef =
                    entityDef $ Proxy @ParentImplicit
                childDef =
                    entityDef $ Proxy @ChildImplicit
                childFields =
                    entityFields childDef
            describe "ChildImplicit" $ do
                case childFields of
                    [nameField, parentIdField] -> do
                        it "parentId has reference" $ do
                            fieldReference parentIdField `shouldBe`
                                ForeignRef (EntityNameHS "ParentImplicit")
                    as ->
                        error . mconcat $
                            [ "Expected one foreign reference on childDef, "
                            , "got: "
                            , show as
                            ]