2022-04-10 07:47:15 +03:00
|
|
|
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
|
2022-06-08 18:31:28 +03:00
|
|
|
import Data.Aeson.KeyMap qualified as KeyMap
|
2022-04-10 07:47:15 +03:00
|
|
|
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
|
2022-05-02 08:03:12 +03:00
|
|
|
import Hasura.Backends.DataConnector.API
|
2022-04-10 07:47:15 +03:00
|
|
|
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
|
|
|
|
|
2022-06-02 08:22:44 +03:00
|
|
|
spec :: Client IO (NamedRoutes Routes) -> SourceName -> Config -> Spec
|
|
|
|
spec api sourceName config = describe "Relationship Queries" $ do
|
2022-04-10 07:47:15 +03:00
|
|
|
it "perform a many to one query by joining artist to albums" $ do
|
|
|
|
let query = albumsWithArtistQuery id
|
2022-06-13 23:58:44 +03:00
|
|
|
receivedAlbums <- (Data.sortBy "ArtistId" . getQueryResponse) <$> (api // _query) sourceName config query
|
2022-04-10 07:47:15 +03:00
|
|
|
|
|
|
|
let joinInArtist (album :: Object) =
|
2022-06-13 23:58:44 +03:00
|
|
|
let artist = (album ^? ix "ArtistId" . _Number) >>= \artistId -> Data.artistsAsJsonById ^? ix artistId
|
|
|
|
artistPropVal = maybe J.Null Object artist
|
|
|
|
in KeyMap.insert "Artist" artistPropVal album
|
|
|
|
let removeArtistId = KeyMap.delete "ArtistId"
|
2022-04-10 07:47:15 +03:00
|
|
|
|
|
|
|
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
|
2022-06-13 23:58:44 +03:00
|
|
|
receivedArtists <- (Data.sortBy "ArtistId" . getQueryResponse) <$> (api // _query) sourceName config query
|
2022-04-10 07:47:15 +03:00
|
|
|
|
|
|
|
let joinInAlbums (artist :: Object) =
|
2022-06-13 23:58:44 +03:00
|
|
|
let artistId = artist ^? ix "ArtistId" . _Number
|
|
|
|
albumFilter artistId' album = album ^? ix "ArtistId" . _Number == Just artistId'
|
2022-06-02 05:06:45 +03:00
|
|
|
albums = maybe [] (\artistId' -> filter (albumFilter artistId') Data.albumsAsJson) artistId
|
2022-06-13 23:58:44 +03:00
|
|
|
albums' = Object . KeyMap.delete "ArtistId" <$> albums
|
|
|
|
in KeyMap.insert "Albums" (Array . Vector.fromList $ albums') artist
|
2022-04-10 07:47:15 +03:00
|
|
|
|
|
|
|
let expectedAlbums = joinInAlbums <$> Data.artistsAsJson
|
|
|
|
receivedArtists `shouldBe` expectedAlbums
|
|
|
|
|
|
|
|
albumsWithArtistQuery :: (Query -> Query) -> Query
|
|
|
|
albumsWithArtistQuery modifySubquery =
|
|
|
|
let joinFieldMapping =
|
|
|
|
HashMap.fromList
|
2022-06-13 23:58:44 +03:00
|
|
|
[ (PrimaryKey $ ColumnName "ArtistId", ForeignKey $ ColumnName "ArtistId")
|
2022-04-10 07:47:15 +03:00
|
|
|
]
|
|
|
|
artistsSubquery = modifySubquery artistsQuery
|
|
|
|
fields =
|
2022-06-08 18:31:28 +03:00
|
|
|
KeyMap.fromList
|
2022-06-13 23:58:44 +03:00
|
|
|
[ ("AlbumId", columnField "AlbumId"),
|
|
|
|
("Title", columnField "Title"),
|
|
|
|
("Artist", RelationshipField $ RelField joinFieldMapping ObjectRelationship artistsSubquery)
|
2022-04-10 07:47:15 +03:00
|
|
|
]
|
|
|
|
in albumsQuery {fields}
|
|
|
|
|
|
|
|
artistsWithAlbumsQuery :: (Query -> Query) -> Query
|
|
|
|
artistsWithAlbumsQuery modifySubquery =
|
|
|
|
let joinFieldMapping =
|
|
|
|
HashMap.fromList
|
2022-06-13 23:58:44 +03:00
|
|
|
[ (PrimaryKey $ ColumnName "ArtistId", ForeignKey $ ColumnName "ArtistId")
|
2022-04-10 07:47:15 +03:00
|
|
|
]
|
2022-06-13 23:58:44 +03:00
|
|
|
albumFields = KeyMap.fromList [("AlbumId", columnField "AlbumId"), ("Title", columnField "Title")]
|
|
|
|
albumsSort = OrderBy (ColumnName "AlbumId") Ascending :| []
|
2022-04-10 07:47:15 +03:00
|
|
|
albumsSubquery = modifySubquery (albumsQuery {fields = albumFields, orderBy = Just albumsSort})
|
|
|
|
fields =
|
2022-06-08 18:31:28 +03:00
|
|
|
KeyMap.fromList
|
2022-06-13 23:58:44 +03:00
|
|
|
[ ("ArtistId", columnField "ArtistId"),
|
|
|
|
("Name", columnField "Name"),
|
|
|
|
("Albums", RelationshipField $ RelField joinFieldMapping ArrayRelationship albumsSubquery)
|
2022-04-10 07:47:15 +03:00
|
|
|
]
|
|
|
|
in artistsQuery {fields}
|
|
|
|
|
|
|
|
artistsQuery :: Query
|
|
|
|
artistsQuery =
|
2022-06-13 23:58:44 +03:00
|
|
|
let fields = KeyMap.fromList [("ArtistId", columnField "ArtistId"), ("Name", columnField "Name")]
|
|
|
|
tableName = TableName "Artist"
|
2022-04-10 07:47:15 +03:00
|
|
|
in Query fields tableName Nothing Nothing Nothing Nothing
|
|
|
|
|
|
|
|
albumsQuery :: Query
|
|
|
|
albumsQuery =
|
2022-06-13 23:58:44 +03:00
|
|
|
let fields = KeyMap.fromList [("AlbumId", columnField "AlbumId"), ("ArtistId", columnField "ArtistId"), ("Title", columnField "Title")]
|
|
|
|
tableName = TableName "Album"
|
2022-04-10 07:47:15 +03:00
|
|
|
in Query fields tableName Nothing Nothing Nothing Nothing
|
|
|
|
|
|
|
|
columnField :: Text -> Field
|
|
|
|
columnField = ColumnField . ValueWrapper . ColumnName
|