Browse Source

Get contents by ids only.

pull/351/head
Sebastian 7 years ago
parent
commit
e0e9abb26b
  1. 34
      src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs
  2. 9
      src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentDraftCollection.cs
  3. 18
      src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentPublishedCollection.cs
  4. 19
      src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs
  5. 92
      src/Squidex.Domain.Apps.Entities/Contents/ContentQueryService.cs
  6. 3
      src/Squidex.Domain.Apps.Entities/Contents/IContentQueryService.cs
  7. 2
      src/Squidex.Domain.Apps.Entities/Contents/Repositories/IContentRepository.cs
  8. 41
      src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs
  9. 88
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs

34
src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs

@ -25,15 +25,18 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
{ {
internal class MongoContentCollection : MongoRepositoryBase<MongoContentEntity> internal class MongoContentCollection : MongoRepositoryBase<MongoContentEntity>
{ {
private readonly IAppProvider appProvider;
private readonly string collectionName; private readonly string collectionName;
protected IJsonSerializer Serializer { get; } protected IJsonSerializer Serializer { get; }
public MongoContentCollection(IMongoDatabase database, IJsonSerializer serializer, string collectionName) public MongoContentCollection(IMongoDatabase database, IJsonSerializer serializer, IAppProvider appProvider, string collectionName)
: base(database) : base(database)
{ {
this.collectionName = collectionName; this.collectionName = collectionName;
this.appProvider = appProvider;
Serializer = serializer; Serializer = serializer;
} }
@ -87,6 +90,35 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
} }
} }
public async Task<List<(IContentEntity Content, ISchemaEntity Schema)>> QueryAsync(IAppEntity app, HashSet<Guid> ids, Status[] status = null)
{
var find =
status != null && status.Length > 0 ?
Collection.Find(x => x.IndexedAppId == app.Id && ids.Contains(x.Id) && x.IsDeleted != true && status.Contains(x.Status)) :
Collection.Find(x => x.IndexedAppId == app.Id && ids.Contains(x.Id));
var contentItems = await find.Not(x => x.DataText).ToListAsync();
var schemaIds = contentItems.Select(x => x.IndexedSchemaId).ToList();
var schemas = await Task.WhenAll(schemaIds.Select(x => appProvider.GetSchemaAsync(app.Id, x)));
var result = new List<(IContentEntity Content, ISchemaEntity Schema)>();
foreach (var entity in contentItems)
{
var schema = schemas.FirstOrDefault(x => x.Id == entity.IndexedSchemaId);
if (schema != null)
{
entity.ParseData(schema.SchemaDef, Serializer);
result.Add((entity, schema));
}
}
return result;
}
public async Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, ISchemaEntity schema, HashSet<Guid> ids, Status[] status = null) public async Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, ISchemaEntity schema, HashSet<Guid> ids, Status[] status = null)
{ {
var find = var find =

9
src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentDraftCollection.cs

@ -29,8 +29,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
{ {
internal sealed class MongoContentDraftCollection : MongoContentCollection internal sealed class MongoContentDraftCollection : MongoContentCollection
{ {
public MongoContentDraftCollection(IMongoDatabase database, IJsonSerializer serializer) public MongoContentDraftCollection(IMongoDatabase database, IJsonSerializer serializer, IAppProvider appProvider)
: base(database, serializer, "State_Content_Draft") : base(database, serializer, appProvider, "State_Content_Draft")
{ {
} }
@ -39,6 +39,11 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
await collection.Indexes.CreateManyAsync( await collection.Indexes.CreateManyAsync(
new[] new[]
{ {
new CreateIndexModel<MongoContentEntity>(
Index
.Ascending(x => x.IndexedAppId)
.Ascending(x => x.Id)
.Ascending(x => x.IsDeleted)),
new CreateIndexModel<MongoContentEntity>( new CreateIndexModel<MongoContentEntity>(
Index Index
.Ascending(x => x.IndexedSchemaId) .Ascending(x => x.IndexedSchemaId)

18
src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentPublishedCollection.cs

@ -20,8 +20,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
{ {
internal sealed class MongoContentPublishedCollection : MongoContentCollection internal sealed class MongoContentPublishedCollection : MongoContentCollection
{ {
public MongoContentPublishedCollection(IMongoDatabase database, IJsonSerializer serializer) public MongoContentPublishedCollection(IMongoDatabase database, IJsonSerializer serializer, IAppProvider appProvider)
: base(database, serializer, "State_Content_Published") : base(database, serializer, appProvider, "State_Content_Published")
{ {
} }
@ -30,8 +30,18 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
await collection.Indexes.CreateManyAsync( await collection.Indexes.CreateManyAsync(
new[] new[]
{ {
new CreateIndexModel<MongoContentEntity>(Index.Text(x => x.DataText).Ascending(x => x.IndexedSchemaId)), new CreateIndexModel<MongoContentEntity>(
new CreateIndexModel<MongoContentEntity>(Index.Ascending(x => x.IndexedSchemaId).Ascending(x => x.Id)) Index
.Ascending(x => x.IndexedAppId)
.Ascending(x => x.Id)),
new CreateIndexModel<MongoContentEntity>(
Index
.Ascending(x => x.IndexedSchemaId)
.Ascending(x => x.Id)),
new CreateIndexModel<MongoContentEntity>(
Index
.Text(x => x.DataText)
.Ascending(x => x.IndexedSchemaId))
}, ct); }, ct);
await base.SetupCollectionAsync(collection, ct); await base.SetupCollectionAsync(collection, ct);

19
src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs

@ -40,8 +40,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
this.serializer = serializer; this.serializer = serializer;
contentsDraft = new MongoContentDraftCollection(database, serializer); contentsDraft = new MongoContentDraftCollection(database, serializer, appProvider);
contentsPublished = new MongoContentPublishedCollection(database, serializer); contentsPublished = new MongoContentPublishedCollection(database, serializer, appProvider);
this.database = database; this.database = database;
} }
@ -81,6 +81,21 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
} }
} }
public async Task<List<(IContentEntity Content, ISchemaEntity Schema)>> QueryAsync(IAppEntity app, Status[] status, HashSet<Guid> ids)
{
using (Profiler.TraceMethod<MongoContentRepository>("QueryAsyncByIdsWithoutSchema"))
{
if (RequiresPublished(status))
{
return await contentsPublished.QueryAsync(app, ids);
}
else
{
return await contentsDraft.QueryAsync(app, ids, status);
}
}
}
public async Task<IContentEntity> FindContentAsync(IAppEntity app, ISchemaEntity schema, Status[] status, Guid id) public async Task<IContentEntity> FindContentAsync(IAppEntity app, ISchemaEntity schema, Status[] status, Guid id)
{ {
using (Profiler.TraceMethod<MongoContentRepository>()) using (Profiler.TraceMethod<MongoContentRepository>())

92
src/Squidex.Domain.Apps.Entities/Contents/ContentQueryService.cs

@ -23,6 +23,7 @@ using Squidex.Infrastructure.Log;
using Squidex.Infrastructure.Queries; using Squidex.Infrastructure.Queries;
using Squidex.Infrastructure.Queries.OData; using Squidex.Infrastructure.Queries.OData;
using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Reflection;
using Squidex.Infrastructure.Security;
using Squidex.Shared; using Squidex.Shared;
using Squidex.Shared.Identity; using Squidex.Shared.Identity;
@ -81,7 +82,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
var schema = await GetSchemaAsync(context, schemaIdOrName); var schema = await GetSchemaAsync(context, schemaIdOrName);
CheckPermission(schema, context.User); CheckPermission(context.User, schema);
using (Profiler.TraceMethod<ContentQueryService>()) using (Profiler.TraceMethod<ContentQueryService>())
{ {
@ -99,7 +100,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
throw new DomainObjectNotFoundException(id.ToString(), typeof(IContentEntity)); throw new DomainObjectNotFoundException(id.ToString(), typeof(IContentEntity));
} }
return Transform(context, schema, true, content); return Transform(context, schema, content);
} }
} }
@ -109,7 +110,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
var schema = await GetSchemaAsync(context, schemaIdOrName); var schema = await GetSchemaAsync(context, schemaIdOrName);
CheckPermission(schema, context.User); CheckPermission(context.User, schema);
using (Profiler.TraceMethod<ContentQueryService>()) using (Profiler.TraceMethod<ContentQueryService>())
{ {
@ -120,7 +121,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
if (query.Ids?.Count > 0) if (query.Ids?.Count > 0)
{ {
contents = await contentRepository.QueryAsync(context.App, schema, status, new HashSet<Guid>(query.Ids)); contents = await contentRepository.QueryAsync(context.App, schema, status, new HashSet<Guid>(query.Ids));
contents = Sort(contents, query.Ids); contents = SortSet(contents, query.Ids);
} }
else else
{ {
@ -129,34 +130,67 @@ namespace Squidex.Domain.Apps.Entities.Contents
contents = await contentRepository.QueryAsync(context.App, schema, status, parsedQuery); contents = await contentRepository.QueryAsync(context.App, schema, status, parsedQuery);
} }
return Transform(context, schema, true, contents); return Transform(context, schema, contents);
} }
} }
private IContentEntity Transform(QueryContext context, ISchemaEntity schema, bool checkType, IContentEntity content) public async Task<IList<IContentEntity>> QueryAsync(QueryContext context, IReadOnlyList<Guid> ids)
{ {
return TransformCore(context, schema, checkType, Enumerable.Repeat(content, 1)).FirstOrDefault(); Guard.NotNull(context, nameof(context));
using (Profiler.TraceMethod<ContentQueryService>())
{
var status = GetQueryStatus(context);
List<IContentEntity> result;
if (ids?.Count > 0)
{
var contents = await contentRepository.QueryAsync(context.App, status, new HashSet<Guid>(ids));
var permissions = context.User.Permissions();
contents = contents.Where(x => HasPermission(permissions, x.Schema)).ToList();
result = contents.Select(x => Transform(context, x.Schema, x.Content)).ToList();
result = SortList(result, ids).ToList();
}
else
{
result = new List<IContentEntity>();
}
return result;
}
} }
private IResultList<IContentEntity> Transform(QueryContext context, ISchemaEntity schema, bool checkType, IResultList<IContentEntity> contents) private IResultList<IContentEntity> Transform(QueryContext context, ISchemaEntity schema, IResultList<IContentEntity> contents)
{ {
var transformed = TransformCore(context, schema, checkType, contents); var transformed = TransformCore(context, schema, contents);
return ResultList.Create(contents.Total, transformed); return ResultList.Create(contents.Total, transformed);
} }
private static IResultList<IContentEntity> Sort(IResultList<IContentEntity> contents, IReadOnlyList<Guid> ids) private IContentEntity Transform(QueryContext context, ISchemaEntity schema, IContentEntity content)
{ {
var sorted = ids.Select(id => contents.FirstOrDefault(x => x.Id == id)).Where(x => x != null); return TransformCore(context, schema, Enumerable.Repeat(content, 1)).FirstOrDefault();
}
private static IResultList<IContentEntity> SortSet(IResultList<IContentEntity> contents, IReadOnlyList<Guid> ids)
{
return ResultList.Create(contents.Total, SortList(contents, ids));
}
return ResultList.Create(contents.Total, sorted); private static IEnumerable<IContentEntity> SortList(IEnumerable<IContentEntity> contents, IReadOnlyList<Guid> ids)
{
return ids.Select(id => contents.FirstOrDefault(x => x.Id == id)).Where(x => x != null);
} }
private IEnumerable<IContentEntity> TransformCore(QueryContext context, ISchemaEntity schema, bool checkType, IEnumerable<IContentEntity> contents) private IEnumerable<IContentEntity> TransformCore(QueryContext context, ISchemaEntity schema, IEnumerable<IContentEntity> contents)
{ {
using (Profiler.TraceMethod<ContentQueryService>()) using (Profiler.TraceMethod<ContentQueryService>())
{ {
var converters = GenerateConverters(context, checkType).ToArray(); var converters = GenerateConverters(context).ToArray();
var scriptText = schema.SchemaDef.Scripts.Query; var scriptText = schema.SchemaDef.Scripts.Query;
@ -170,7 +204,9 @@ namespace Squidex.Domain.Apps.Entities.Contents
{ {
if (!context.IsFrontendClient && isScripting) if (!context.IsFrontendClient && isScripting)
{ {
result.Data = scriptEngine.Transform(new ScriptContext { User = context.User, Data = content.Data, ContentId = content.Id }, scriptText); var ctx = new ScriptContext { User = context.User, Data = content.Data, ContentId = content.Id };
result.Data = scriptEngine.Transform(ctx, scriptText);
} }
result.Data = result.Data.ConvertName2Name(schema.SchemaDef, converters); result.Data = result.Data.ConvertName2Name(schema.SchemaDef, converters);
@ -186,7 +222,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
} }
} }
private IEnumerable<FieldConverter> GenerateConverters(QueryContext context, bool checkType) private IEnumerable<FieldConverter> GenerateConverters(QueryContext context)
{ {
if (!context.IsFrontendClient) if (!context.IsFrontendClient)
{ {
@ -194,11 +230,8 @@ namespace Squidex.Domain.Apps.Entities.Contents
yield return FieldConverters.ForNestedName2Name(ValueConverters.ExcludeHidden()); yield return FieldConverters.ForNestedName2Name(ValueConverters.ExcludeHidden());
} }
if (checkType) yield return FieldConverters.ExcludeChangedTypes();
{ yield return FieldConverters.ForNestedName2Name(ValueConverters.ExcludeChangedTypes());
yield return FieldConverters.ExcludeChangedTypes();
yield return FieldConverters.ForNestedName2Name(ValueConverters.ExcludeChangedTypes());
}
yield return FieldConverters.ResolveInvariant(context.App.LanguagesConfig); yield return FieldConverters.ResolveInvariant(context.App.LanguagesConfig);
yield return FieldConverters.ResolveLanguages(context.App.LanguagesConfig); yield return FieldConverters.ResolveLanguages(context.App.LanguagesConfig);
@ -274,17 +307,26 @@ namespace Squidex.Domain.Apps.Entities.Contents
return schema; return schema;
} }
private static void CheckPermission(ISchemaEntity schema, ClaimsPrincipal user) private static void CheckPermission(ClaimsPrincipal user, params ISchemaEntity[] schemas)
{ {
var permissions = user.Permissions(); var permissions = user.Permissions();
var permission = Permissions.ForApp(Permissions.AppContentsRead, schema.AppId.Name, schema.SchemaDef.Name);
if (!permissions.Allows(permission)) foreach (var schema in schemas)
{ {
throw new DomainForbiddenException("You do not have permission for this schema."); if (!HasPermission(permissions, schema))
{
throw new DomainForbiddenException("You do not have permission for this schema.");
}
} }
} }
private static bool HasPermission(PermissionSet permissions, ISchemaEntity schema)
{
var permission = Permissions.ForApp(Permissions.AppContentsRead, schema.AppId.Name, schema.SchemaDef.Name);
return permissions.Allows(permission);
}
private static Status[] GetFindStatus(QueryContext context) private static Status[] GetFindStatus(QueryContext context)
{ {
if (context.IsFrontendClient) if (context.IsFrontendClient)

3
src/Squidex.Domain.Apps.Entities/Contents/IContentQueryService.cs

@ -6,6 +6,7 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Squidex.Infrastructure; using Squidex.Infrastructure;
@ -13,6 +14,8 @@ namespace Squidex.Domain.Apps.Entities.Contents
{ {
public interface IContentQueryService public interface IContentQueryService
{ {
Task<IList<IContentEntity>> QueryAsync(QueryContext context, IReadOnlyList<Guid> ids);
Task<IResultList<IContentEntity>> QueryAsync(QueryContext context, string schemaIdOrName, Q query); Task<IResultList<IContentEntity>> QueryAsync(QueryContext context, string schemaIdOrName, Q query);
Task<IContentEntity> FindContentAsync(QueryContext context, string schemaIdOrName, Guid id, long version = EtagVersion.Any); Task<IContentEntity> FindContentAsync(QueryContext context, string schemaIdOrName, Guid id, long version = EtagVersion.Any);

2
src/Squidex.Domain.Apps.Entities/Contents/Repositories/IContentRepository.cs

@ -19,6 +19,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Repositories
{ {
public interface IContentRepository public interface IContentRepository
{ {
Task<List<(IContentEntity Content, ISchemaEntity Schema)>> QueryAsync(IAppEntity app, Status[] status, HashSet<Guid> ids);
Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, ISchemaEntity schema, Status[] status, HashSet<Guid> ids); Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, ISchemaEntity schema, Status[] status, HashSet<Guid> ids);
Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, ISchemaEntity schema, Status[] status, Query query); Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, ISchemaEntity schema, Status[] status, Query query);

41
src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs

@ -106,6 +106,45 @@ namespace Squidex.Areas.Api.Controllers.Contents
} }
} }
/// <summary>
/// Queries contents.
/// </summary>
/// <param name="app">The name of the app.</param>
/// <param name="ids">The optional ids of the content to fetch.</param>
/// <param name="archived">Indicates whether to query content items from the archive.</param>
/// <returns>
/// 200 => Contents retrieved.
/// 404 => App not found.
/// </returns>
/// <remarks>
/// You can read the generated documentation for your app at /api/content/{appName}/docs
/// </remarks>
[HttpGet]
[Route("content/{app}/")]
[ApiPermission]
[ApiCosts(1)]
public async Task<IActionResult> GetAllContents(string app, [FromQuery] string ids, [FromQuery] bool archived = false)
{
var context = Context().WithArchived(archived);
var result = await contentQuery.QueryAsync(context, Q.Empty.WithIds(ids).Ids);
var response = new ContentsDto
{
Total = result.Count,
Items = result.Take(200).Select(x => ContentDto.FromContent(x, context)).ToArray()
};
if (controllerOptions.Value.EnableSurrogateKeys && response.Items.Length <= controllerOptions.Value.MaxItemsForSurrogateKeys)
{
Response.Headers["Surrogate-Key"] = response.Items.ToSurrogateKeys();
}
Response.Headers[HeaderNames.ETag] = response.Items.ToManyEtag();
return Ok(response);
}
/// <summary> /// <summary>
/// Queries contents. /// Queries contents.
/// </summary> /// </summary>
@ -124,7 +163,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[Route("content/{app}/{name}/")] [Route("content/{app}/{name}/")]
[ApiPermission] [ApiPermission]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> GetContents(string app, string name, [FromQuery] bool archived = false, [FromQuery] string ids = null) public async Task<IActionResult> GetContents(string app, string name, [FromQuery] string ids = null, [FromQuery] bool archived = false)
{ {
var context = Context().WithArchived(archived); var context = Context().WithArchived(archived);

88
tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs

@ -358,7 +358,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
[Theory] [Theory]
[MemberData(nameof(ManyIdDataApi))] [MemberData(nameof(ManyIdDataApi))]
public async Task Should_query_contents_by_id_from_repository_and_transform(bool archive, bool unpublished, params Status[] status) public async Task Should_query_contents_by_id_for_api_and_transform(bool archive, bool unpublished, params Status[] status)
{ {
const int count = 5, total = 200; const int count = 5, total = 200;
@ -380,6 +380,86 @@ namespace Squidex.Domain.Apps.Entities.Contents
.MustHaveHappened(count, Times.Exactly); .MustHaveHappened(count, Times.Exactly);
} }
[Theory]
[MemberData(nameof(ManyIdDataFrontend))]
public async Task Should_query_all_contents_by_id_for_frontend_and_transform(bool archive, bool unpublished, params Status[] status)
{
const int count = 5;
var ids = Enumerable.Range(0, count).Select(x => Guid.NewGuid()).ToList();
SetupClaims(true);
SetupSchema();
SetupScripting(ids.ToArray());
SetupContents(status, ids);
var ctx = context.WithArchived(archive).WithUnpublished(unpublished);
var result = await sut.QueryAsync(ctx, ids);
Assert.Equal(ids, result.Select(x => x.Id).ToList());
A.CallTo(() => scriptEngine.Transform(A<ScriptContext>.Ignored, A<string>.Ignored))
.MustNotHaveHappened();
}
[Theory]
[MemberData(nameof(ManyIdDataApi))]
public async Task Should_query_all_contents_by_id_for_api_and_transform(bool archive, bool unpublished, params Status[] status)
{
const int count = 5;
var ids = Enumerable.Range(0, count).Select(x => Guid.NewGuid()).ToList();
SetupClaims();
SetupSchema();
SetupScripting(ids.ToArray());
SetupContents(status, ids);
var ctx = context.WithArchived(archive).WithUnpublished(unpublished);
var result = await sut.QueryAsync(ctx, ids);
Assert.Equal(ids, result.Select(x => x.Id).ToList());
A.CallTo(() => scriptEngine.Transform(A<ScriptContext>.Ignored, A<string>.Ignored))
.MustHaveHappened(count, Times.Exactly);
}
[Fact]
public async Task Should_skip_contents_when_user_has_no_permission()
{
var ids = Enumerable.Range(0, 1).Select(x => Guid.NewGuid()).ToList();
SetupClaims(false, false);
SetupSchema();
SetupContents(new Status[0], ids);
var ctx = context;
var result = await sut.QueryAsync(ctx, ids);
Assert.Empty(result);
}
[Fact]
public async Task Should_not_call_repository_if_no_id_defined()
{
var ids = new List<Guid>();
SetupClaims(false, false);
SetupSchema();
var ctx = context;
var result = await sut.QueryAsync(ctx, ids);
Assert.Empty(result);
A.CallTo(() => contentRepository.QueryAsync(app, A<Status[]>.Ignored, A<HashSet<Guid>>.Ignored))
.MustNotHaveHappened();
}
private void SetupClaims(bool isFrontend = false, bool allowSchema = true) private void SetupClaims(bool isFrontend = false, bool allowSchema = true)
{ {
if (isFrontend) if (isFrontend)
@ -414,6 +494,12 @@ namespace Squidex.Domain.Apps.Entities.Contents
.Returns(ResultList.Create(total, ids.Select(x => CreateContent(x)).Shuffle())); .Returns(ResultList.Create(total, ids.Select(x => CreateContent(x)).Shuffle()));
} }
private void SetupContents(Status[] status, List<Guid> ids)
{
A.CallTo(() => contentRepository.QueryAsync(app, A<Status[]>.That.IsSameSequenceAs(status), A<HashSet<Guid>>.Ignored))
.Returns(ids.Select(x => (CreateContent(x), schema)).ToList());
}
private void SetupSchema() private void SetupSchema()
{ {
A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, schemaId.Name)) A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, schemaId.Name))

Loading…
Cancel
Save