graphql-engine/server/tests-dc-api/Test/QuerySpec/RelationshipsSpec.hs
Solomon 01f56735ac Feature/gdw 113
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4620
GitOrigin-RevId: f732fff4f3f2449ebc97f76522ee6ad11bcfbc68
2022-06-07 01:35:38 +00:00

95 lines
4.0 KiB
Haskell

module Test.QuerySpec.RelationshipsSpec (spec) where
import Autodocodec.Extended (ValueWrapper (..))
import Control.Lens (ix, (^?))
import Data.Aeson (Object, Value (..))
import Data.Aeson qualified as J
import Data.Aeson.Lens (_Number)
import Data.HashMap.Strict qualified as HashMap
import Data.List.NonEmpty (NonEmpty (..))
import Data.Text (Text)
import Data.Vector qualified as Vector
import Hasura.Backends.DataConnector.API
import Servant.API (NamedRoutes)
import Servant.Client (Client, (//))
import Test.Data qualified as Data
import Test.Hspec (Spec, describe, it)
import Test.Hspec.Expectations.Pretty (shouldBe)
import Prelude
spec :: Client IO (NamedRoutes Routes) -> SourceName -> Config -> Spec
spec api sourceName config = describe "Relationship Queries" $ do
it "perform a many to one query by joining artist to albums" $ do
let query = albumsWithArtistQuery id
receivedAlbums <- (Data.sortBy "id" . getQueryResponse) <$> (api // _query) sourceName config query
let joinInArtist (album :: Object) =
let artist = (album ^? ix "artist_id" . _Number) >>= \artistId -> Data.artistsAsJsonById ^? ix artistId
artistPropVal = maybe J.Null (Array . Vector.singleton . Object) artist
in HashMap.insert "artist" artistPropVal album
let removeArtistId = HashMap.delete "artist_id"
let expectedAlbums = (removeArtistId . joinInArtist) <$> Data.albumsAsJson
receivedAlbums `shouldBe` expectedAlbums
it "perform a one to many query by joining albums to artists" $ do
let query = artistsWithAlbumsQuery id
receivedArtists <- (Data.sortBy "id" . getQueryResponse) <$> (api // _query) sourceName config query
let joinInAlbums (artist :: Object) =
let artistId = artist ^? ix "id" . _Number
albumFilter artistId' album = album ^? ix "artist_id" . _Number == Just artistId'
albums = maybe [] (\artistId' -> filter (albumFilter artistId') Data.albumsAsJson) artistId
albums' = Object . HashMap.delete "artist_id" <$> albums
in HashMap.insert "albums" (Array . Vector.fromList $ albums') artist
let expectedAlbums = joinInAlbums <$> Data.artistsAsJson
receivedArtists `shouldBe` expectedAlbums
albumsWithArtistQuery :: (Query -> Query) -> Query
albumsWithArtistQuery modifySubquery =
let joinFieldMapping =
HashMap.fromList
[ (PrimaryKey $ ColumnName "artist_id", ForeignKey $ ColumnName "id")
]
artistsSubquery = modifySubquery artistsQuery
fields =
HashMap.fromList
[ ("id", columnField "id"),
("title", columnField "title"),
("artist", RelationshipField $ RelField joinFieldMapping ObjectRelationship artistsSubquery)
]
in albumsQuery {fields}
artistsWithAlbumsQuery :: (Query -> Query) -> Query
artistsWithAlbumsQuery modifySubquery =
let joinFieldMapping =
HashMap.fromList
[ (PrimaryKey $ ColumnName "id", ForeignKey $ ColumnName "artist_id")
]
albumFields = HashMap.fromList [("id", columnField "id"), ("title", columnField "title")]
albumsSort = OrderBy (ColumnName "id") Ascending :| []
albumsSubquery = modifySubquery (albumsQuery {fields = albumFields, orderBy = Just albumsSort})
fields =
HashMap.fromList
[ ("id", columnField "id"),
("name", columnField "name"),
("albums", RelationshipField $ RelField joinFieldMapping ArrayRelationship albumsSubquery)
]
in artistsQuery {fields}
artistsQuery :: Query
artistsQuery =
let fields = HashMap.fromList [("id", columnField "id"), ("name", columnField "name")]
tableName = TableName "artists"
in Query fields tableName Nothing Nothing Nothing Nothing
albumsQuery :: Query
albumsQuery =
let fields = HashMap.fromList [("id", columnField "id"), ("artist_id", columnField "artist_id"), ("title", columnField "title")]
tableName = TableName "albums"
in Query fields tableName Nothing Nothing Nothing Nothing
columnField :: Text -> Field
columnField = ColumnField . ValueWrapper . ColumnName