diff --git a/server/lib/dc-api/test/Test/Data.hs b/server/lib/dc-api/test/Test/Data.hs index ec265630332..0df3a0fbf66 100644 --- a/server/lib/dc-api/test/Test/Data.hs +++ b/server/lib/dc-api/test/Test/Data.hs @@ -25,6 +25,7 @@ module Test.Data _ColumnFieldNumber, _ColumnFieldString, _ColumnFieldBoolean, + _RelationshipFieldRows, orderByColumn, guardQueryResponse, guardedQuery, @@ -38,7 +39,7 @@ where import Codec.Compression.GZip qualified as GZip import Command (NameCasing (..), TestConfig (..)) import Control.Arrow (first, (>>>)) -import Control.Lens (Index, IxValue, Ixed, Traversal', ix, lens, (%~), (&), (^.), (^..), (^?)) +import Control.Lens (Index, IxValue, Ixed, Traversal', ix, lens, (%~), (&), (^.), (^..), (^?), _Just) import Data.Aeson (eitherDecodeStrict) import Data.Aeson qualified as J import Data.Aeson.Lens (_Bool, _Number, _String) @@ -516,6 +517,9 @@ _ColumnFieldString = API._ColumnFieldValue . _String _ColumnFieldBoolean :: Traversal' API.FieldValue Bool _ColumnFieldBoolean = API._ColumnFieldValue . _Bool +_RelationshipFieldRows :: Traversal' API.FieldValue [HashMap API.FieldName API.FieldValue] +_RelationshipFieldRows = API._RelationshipFieldValue . API.qrRows . _Just + columnField :: Text -> API.ScalarType -> API.Field columnField name scalarType = API.ColumnField (API.ColumnName name) scalarType diff --git a/server/lib/dc-api/test/Test/QuerySpec/AggregatesSpec.hs b/server/lib/dc-api/test/Test/QuerySpec/AggregatesSpec.hs index 64321d9be46..94c03bbf070 100644 --- a/server/lib/dc-api/test/Test/QuerySpec/AggregatesSpec.hs +++ b/server/lib/dc-api/test/Test/QuerySpec/AggregatesSpec.hs @@ -297,12 +297,19 @@ spec TestData {..} api sourceName config relationshipCapabilities = describe "Ag let aggregates = Data.mkFieldsMap [("count", Number . fromIntegral $ length albums)] pure $ Data.insertField "Albums" (mkSubqueryResponse (Just albums) (Just aggregates)) artist + let sortAlbums (artistRows :: [HashMap FieldName FieldValue]) = + artistRows & traverse . Data.field "Albums" . Data._RelationshipFieldRows %~ sortOn (^? Data.field "AlbumId") + let expectedArtists = _tdArtistsRows & take 5 & fmap joinInAlbums + & sortAlbums - Data.responseRows receivedArtists `rowsShouldBe` expectedArtists + -- Ignore the sort order of the related albums by sorting them in the response and the expected data + let receivedArtistRows = sortAlbums $ Data.responseRows receivedArtists + + receivedArtistRows `rowsShouldBe` expectedArtists Data.responseAggregates receivedArtists `jsonShouldBe` mempty it "can query with many nested relationships, with aggregates at multiple levels, with filtering, pagination and ordering" $ do diff --git a/server/lib/dc-api/test/Test/QuerySpec/OrderBySpec.hs b/server/lib/dc-api/test/Test/QuerySpec/OrderBySpec.hs index 22b59ac66ed..1efc7454e47 100644 --- a/server/lib/dc-api/test/Test/QuerySpec/OrderBySpec.hs +++ b/server/lib/dc-api/test/Test/QuerySpec/OrderBySpec.hs @@ -1,6 +1,5 @@ module Test.QuerySpec.OrderBySpec (spec) where -import Control.Arrow ((>>>)) import Control.Lens (ix, (&), (.~), (?~), (^.), (^?), _1, _2, _3, _Just) import Control.Monad (when) import Data.Aeson (Value (..)) @@ -54,7 +53,12 @@ spec TestData {..} api sourceName config Capabilities {..} = describe "Order By when (isJust _cRelationships) . describe "involving relationships" $ do it "can order results by a column in a related table" $ do let orderByRelations = HashMap.fromList [(_tdArtistRelationshipName, OrderByRelation Nothing mempty)] - let orderBy = OrderBy orderByRelations $ _tdOrderByColumn [_tdArtistRelationshipName] "Name" Ascending :| [] + let orderBy = + OrderBy orderByRelations $ + NonEmpty.fromList + [ _tdOrderByColumn [_tdArtistRelationshipName] "Name" Ascending, + _tdOrderByColumn [] "AlbumId" Ascending + ] let query = albumsQueryRequest & qrQuery . qOrderBy ?~ orderBy @@ -67,7 +71,7 @@ spec TestData {..} api sourceName config Capabilities {..} = describe "Order By let expectedAlbums = _tdAlbumsRows & fmap (\album -> (album, getRelatedArtist album)) - & sortOn ((^? _2 . _Just . Data.field "Name")) + & sortOn (\row -> (row ^? _2 . _Just . Data.field "Name", row ^? _1 . Data.field "AlbumId")) & fmap fst Data.responseRows receivedAlbums `rowsShouldBe` expectedAlbums @@ -76,7 +80,12 @@ spec TestData {..} api sourceName config Capabilities {..} = describe "Order By it "can order results by a column in a related table where the related table is filtered" $ do let artistTableFilter = ApplyBinaryComparisonOperator GreaterThan (_tdCurrentComparisonColumn "Name" _tdStringType) (ScalarValue (String "N") _tdStringType) let orderByRelations = HashMap.fromList [(_tdArtistRelationshipName, OrderByRelation (Just artistTableFilter) mempty)] - let orderBy = OrderBy orderByRelations $ _tdOrderByColumn [_tdArtistRelationshipName] "Name" Ascending :| [] + let orderBy = + OrderBy orderByRelations $ + NonEmpty.fromList + [ _tdOrderByColumn [_tdArtistRelationshipName] "Name" Ascending, + _tdOrderByColumn [] "AlbumId" Ascending + ] let query = albumsQueryRequest & qrQuery . qOrderBy ?~ orderBy @@ -92,7 +101,7 @@ spec TestData {..} api sourceName config Capabilities {..} = describe "Order By let expectedAlbums = _tdAlbumsRows & fmap (\album -> (album, getRelatedArtist album)) - & sortOn ((^? _2 . _Just . Data.field "Name") >>> toNullsLastOrdering) + & sortOn (\row -> (row ^? _2 . _Just . Data.field "Name" & toNullsLastOrdering, row ^? _1 . Data.field "AlbumId")) & fmap fst Data.responseRows receivedAlbums `rowsShouldBe` expectedAlbums @@ -118,7 +127,8 @@ spec TestData {..} api sourceName config Capabilities {..} = describe "Order By OrderBy orderByRelations $ NonEmpty.fromList [ _tdOrderByColumn [_tdAlbumRelationshipName, _tdArtistRelationshipName] "Name" Descending, - _tdOrderByColumn [] "Name" Ascending + _tdOrderByColumn [] "Name" Ascending, + _tdOrderByColumn [] "TrackId" Ascending ] let query = tracksQueryRequest @@ -137,8 +147,8 @@ spec TestData {..} api sourceName config Capabilities {..} = describe "Order By let expectedTracks = _tdTracksRows - & fmap (\track -> (Data.filterColumnsByQueryFields (_qrQuery tracksQueryRequest) track, getRelatedArtist track, track ^? Data.field "Name")) - & sortOn (\row -> (Down (row ^? _2 . _Just . Data.field "Name"), row ^. _3)) + & fmap (\track -> (Data.filterColumnsByQueryFields (_qrQuery tracksQueryRequest) track, getRelatedArtist track, track)) + & sortOn (\row -> (Down (row ^? _2 . _Just . Data.field "Name"), row ^? _3 . Data.field "Name", row ^? _3 . Data.field "TrackId")) & fmap (^. _1) Data.responseRows receivedTracks `rowsShouldBe` expectedTracks @@ -146,7 +156,12 @@ spec TestData {..} api sourceName config Capabilities {..} = describe "Order By it "can order results by an aggregate of a related table" $ do let orderByRelations = HashMap.fromList [(_tdAlbumsRelationshipName, OrderByRelation Nothing mempty)] - let orderBy = OrderBy orderByRelations $ OrderByElement [_tdAlbumsRelationshipName] OrderByStarCountAggregate Descending :| [] + let orderBy = + OrderBy orderByRelations $ + NonEmpty.fromList + [ OrderByElement [_tdAlbumsRelationshipName] OrderByStarCountAggregate Descending, + _tdOrderByColumn [] "Name" Ascending + ] let query = artistsQueryRequest & qrQuery . qOrderBy ?~ orderBy @@ -161,7 +176,7 @@ spec TestData {..} api sourceName config Capabilities {..} = describe "Order By let expectedArtists = _tdArtistsRows & fmap (\artist -> (artist, getAlbumsCount artist)) - & sortOn (Down . (^. _2)) + & sortOn (\row -> (Down (row ^. _2), row ^? _1 . Data.field "Name")) & fmap fst Data.responseRows receivedArtists `rowsShouldBe` expectedArtists @@ -170,7 +185,12 @@ spec TestData {..} api sourceName config Capabilities {..} = describe "Order By it "can order results by an aggregate of a related table where the related table is filtered" $ do let albumTableFilter = ApplyBinaryComparisonOperator GreaterThan (_tdCurrentComparisonColumn "Title" _tdStringType) (ScalarValue (String "N") _tdStringType) let orderByRelations = HashMap.fromList [(_tdAlbumsRelationshipName, OrderByRelation (Just albumTableFilter) mempty)] - let orderBy = OrderBy orderByRelations $ OrderByElement [_tdAlbumsRelationshipName] OrderByStarCountAggregate Descending :| [] + let orderBy = + OrderBy orderByRelations $ + NonEmpty.fromList + [ OrderByElement [_tdAlbumsRelationshipName] OrderByStarCountAggregate Descending, + _tdOrderByColumn [] "Name" Ascending + ] let query = artistsQueryRequest & qrQuery . qOrderBy ?~ orderBy @@ -185,7 +205,7 @@ spec TestData {..} api sourceName config Capabilities {..} = describe "Order By let expectedArtists = _tdArtistsRows & fmap (\artist -> (artist, getAlbumsCount artist)) - & sortOn (Down . (^. _2)) + & sortOn (\row -> (Down (row ^. _2), row ^? _1 . Data.field "Name")) & fmap fst Data.responseRows receivedArtists `rowsShouldBe` expectedArtists