diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs index 8eed38bd8..d3e85b6e8 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs @@ -70,7 +70,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets await Task.WhenAll(contentItems, contentCount); - return ResultList.Create(contentItems.Result, contentCount.Result); + return ResultList.Create(contentCount.Result, contentItems.Result); } catch (NotSupportedException) { @@ -105,7 +105,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets await Task.WhenAll(assetItems, assetCount); - return ResultList.Create(assetItems.Result.OfType().ToList(), assetCount.Result); + return ResultList.Create(assetCount.Result, assetItems.Result.OfType()); } } diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs index 1195376f5..ad6854d8b 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs @@ -66,7 +66,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents entity.ParseData(schema.SchemaDef); } - return ResultList.Create(contentItems.Result, contentCount.Result); + return ResultList.Create(contentCount.Result, contentItems.Result); } catch (NotSupportedException) { @@ -106,7 +106,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents entity.ParseData(schema.SchemaDef); } - return ResultList.Create(contentItems.Result, contentCount.Result); + return ResultList.Create(contentCount.Result, contentItems.Result); } public Task CleanupAsync(Guid id) diff --git a/src/Squidex.Domain.Apps.Entities/Assets/AssetQueryService.cs b/src/Squidex.Domain.Apps.Entities/Assets/AssetQueryService.cs index 4faf3dffc..739b70cff 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/AssetQueryService.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/AssetQueryService.cs @@ -70,7 +70,7 @@ namespace Squidex.Domain.Apps.Entities.Assets { var sorted = ids.Select(id => assets.FirstOrDefault(x => x.Id == id)).Where(x => x != null); - return ResultList.Create(sorted, assets.Total); + return ResultList.Create(assets.Total, sorted); } private async Task DenormalizeTagsAsync(Guid appId, IEnumerable assets) diff --git a/src/Squidex.Domain.Apps.Entities/Contents/ContentQueryService.cs b/src/Squidex.Domain.Apps.Entities/Contents/ContentQueryService.cs index 39492d884..032ab7c36 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/ContentQueryService.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/ContentQueryService.cs @@ -123,14 +123,14 @@ namespace Squidex.Domain.Apps.Entities.Contents { var transformed = Transform(context, schema, checkType, (IEnumerable)contents); - return ResultList.Create(transformed, contents.Total); + return ResultList.Create(contents.Total, transformed); } private IResultList Sort(IResultList contents, IList ids) { var sorted = ids.Select(id => contents.FirstOrDefault(x => x.Id == id)).Where(x => x != null); - return ResultList.Create(sorted, contents.Total); + return ResultList.Create(contents.Total, sorted); } private IEnumerable Transform(QueryContext context, ISchemaEntity schema, bool checkType, IEnumerable contents) diff --git a/src/Squidex.Infrastructure/ResultList.cs b/src/Squidex.Infrastructure/ResultList.cs index 07d80e75b..957ecc48b 100644 --- a/src/Squidex.Infrastructure/ResultList.cs +++ b/src/Squidex.Infrastructure/ResultList.cs @@ -22,7 +22,12 @@ namespace Squidex.Infrastructure } } - public static IResultList Create(IEnumerable items, long total) + public static IResultList Create(long total, IEnumerable items) + { + return new Impl(items, total); + } + + public static IResultList Create(long total, params T[] items) { return new Impl(items, total); } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetQueryServiceTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetQueryServiceTests.cs new file mode 100644 index 000000000..f60022bb3 --- /dev/null +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetQueryServiceTests.cs @@ -0,0 +1,117 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschränkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Collections.Generic; +using System.Security.Claims; +using System.Threading.Tasks; +using FakeItEasy; +using Squidex.Domain.Apps.Core.Apps; +using Squidex.Domain.Apps.Entities.Apps; +using Squidex.Domain.Apps.Entities.Assets.Repositories; +using Squidex.Domain.Apps.Entities.Tags; +using Squidex.Infrastructure; +using Xunit; + +namespace Squidex.Domain.Apps.Entities.Assets +{ + public class AssetQueryServiceTests + { + private readonly ITagService tagService = A.Fake(); + private readonly IAssetRepository assetRepository = A.Fake(); + private readonly IAppEntity app = A.Fake(); + private readonly Guid appId = Guid.NewGuid(); + private readonly string appName = "my-app"; + private readonly ClaimsPrincipal user; + private readonly ClaimsIdentity identity = new ClaimsIdentity(); + private readonly QueryContext context; + private readonly AssetQueryService sut; + + public AssetQueryServiceTests() + { + user = new ClaimsPrincipal(identity); + + A.CallTo(() => app.Id).Returns(appId); + A.CallTo(() => app.Name).Returns(appName); + A.CallTo(() => app.LanguagesConfig).Returns(LanguagesConfig.English); + + context = QueryContext.Create(app, user); + + A.CallTo(() => tagService.DenormalizeTagsAsync(appId, TagGroups.Assets, A>.That.IsSameSequenceAs("id1", "id2", "id3"))) + .Returns(new Dictionary + { + ["id1"] = "name1", + ["id2"] = "name2", + ["id3"] = "name3" + }); + + sut = new AssetQueryService(tagService, assetRepository); + } + + [Fact] + public async Task Should_find_asset_by_id_and_resolve_tags() + { + var id = Guid.NewGuid(); + + A.CallTo(() => assetRepository.FindAssetAsync(id)) + .Returns(CreateAsset(id, "id1", "id2", "id3")); + + var result = await sut.FindAssetAsync(context, id); + + Assert.Equal(HashSet.Of("name1", "name2", "name3"), result.Tags); + } + + [Fact] + public async Task Should_load_assets_from_ids_and_resolve_tags() + { + var id1 = Guid.NewGuid(); + var id2 = Guid.NewGuid(); + + var ids = HashSet.Of(id1, id2); + + A.CallTo(() => assetRepository.QueryAsync(appId, A>.That.IsSameSequenceAs(ids))) + .Returns(ResultList.Create(8, + CreateAsset(id1, "id1", "id2", "id3"), + CreateAsset(id2))); + + var result = await sut.QueryAsync(context, Query.Empty.WithIds(ids)); + + Assert.Equal(8, result.Total); + Assert.Equal(2, result.Count); + + Assert.Equal(HashSet.Of("name1", "name2", "name3"), result[0].Tags); + Assert.Empty(result[1].Tags); + } + + [Fact] + public async Task Should_load_assets_with_query_and_resolve_tags() + { + A.CallTo(() => assetRepository.QueryAsync(appId, "my-query")) + .Returns(ResultList.Create(8, + CreateAsset(Guid.NewGuid(), "id1", "id2"), + CreateAsset(Guid.NewGuid(), "id2", "id3"))); + + var result = await sut.QueryAsync(context, Query.Empty.WithODataQuery("my-query")); + + Assert.Equal(8, result.Total); + Assert.Equal(2, result.Count); + + Assert.Equal(HashSet.Of("name1", "name2"), result[0].Tags); + Assert.Equal(HashSet.Of("name2", "name3"), result[1].Tags); + } + + private IAssetEntity CreateAsset(Guid id, params string[] tags) + { + var asset = A.Fake(); + + A.CallTo(() => asset.Id).Returns(id); + A.CallTo(() => asset.Tags).Returns(HashSet.Of(tags)); + + return asset; + } + } +} \ No newline at end of file diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs index 02d6b9b6d..c772d4aaf 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs @@ -185,7 +185,7 @@ namespace Squidex.Domain.Apps.Entities.Contents .Returns(schema); A.CallTo(() => contentRepository.QueryAsync(app, schema, A.That.IsSameSequenceAs(status), A.Ignored)) - .Returns(ResultList.Create(Enumerable.Repeat(content, count), total)); + .Returns(ResultList.Create(total, Enumerable.Repeat(content, count))); var result = await sut.QueryAsync(context.WithSchemaId(schemaId).WithArchived(archive), Query.Empty); @@ -239,7 +239,7 @@ namespace Squidex.Domain.Apps.Entities.Contents .Returns(schema); A.CallTo(() => contentRepository.QueryAsync(app, schema, A.That.IsSameSequenceAs(status), A>.Ignored)) - .Returns(ResultList.Create(ids.Select(x => CreateContent(x)).Shuffle(), total)); + .Returns(ResultList.Create(total, ids.Select(x => CreateContent(x)).Shuffle())); var result = await sut.QueryAsync(context.WithSchemaId(schemaId).WithArchived(archive), Query.Empty.WithIds(ids)); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs index 52d6141ee..8d4e96402 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs @@ -63,10 +63,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL var asset = CreateAsset(Guid.NewGuid()); - var assets = new List { asset }; - A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), A.That.Matches(x => x.ODataQuery == "?$take=30&$skip=5&$search=my-query"))) - .Returns(ResultList.Create(assets, 0)); + .Returns(ResultList.Create(0, asset)); var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); @@ -132,10 +130,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL var asset = CreateAsset(Guid.NewGuid()); - var assets = new List { asset }; - A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), A.That.Matches(x => x.ODataQuery == "?$take=30&$skip=5&$search=my-query"))) - .Returns(ResultList.Create(assets, 10)); + .Returns(ResultList.Create(10, asset)); var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); @@ -285,10 +281,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL var content = CreateContent(Guid.NewGuid(), Guid.Empty, Guid.Empty); - var contents = new List { content }; - A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5"))) - .Returns(ResultList.Create(contents, 0)); + .Returns(ResultList.Create(0, content)); var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); @@ -419,10 +413,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL var content = CreateContent(Guid.NewGuid(), Guid.Empty, Guid.Empty); - var contents = new List { content }; - A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5"))) - .Returns(ResultList.Create(contents, 10)); + .Returns(ResultList.Create(10, content)); var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); @@ -630,13 +622,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL }} }}"; - var refContents = new List { contentRef }; - A.CallTo(() => contentQuery.FindContentAsync(MatchsContentContext(), contentId, EtagVersion.Any)) .Returns(content); A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A.Ignored)) - .Returns(ResultList.Create(refContents, 0)); + .Returns(ResultList.Create(0, contentRef)); var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); @@ -690,13 +680,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL }} }}"; - var refAssets = new List { assetRef }; - A.CallTo(() => contentQuery.FindContentAsync(MatchsContentContext(), contentId, EtagVersion.Any)) .Returns(content); A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), A.Ignored)) - .Returns(ResultList.Create(refAssets, 0)); + .Returns(ResultList.Create(0, assetRef)); var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query });