Browse Source

More tests and code improvements.

pull/481/head
Sebastian 6 years ago
parent
commit
42842e1b81
  1. 2
      backend/extensions/Squidex.Extensions/APM/Datadog/DatadogPlugin.cs
  2. 9
      backend/src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs
  3. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/FieldConverters.cs
  4. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ValueReferencesConverter.cs
  5. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/ContentSchemaBuilder.cs
  6. 24
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentEntity.cs
  7. 11
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs
  8. 20
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs
  9. 1
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/Adapt.cs
  10. 3
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/Extensions.cs
  11. 2
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryContentsByQuery.cs
  12. 19
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryIdsAsync.cs
  13. 2
      backend/src/Squidex.Domain.Apps.Entities/Apps/DefaultAppLogStore.cs
  14. 4
      backend/src/Squidex.Domain.Apps.Entities/Comments/CommentsGrain.cs
  15. 2
      backend/src/Squidex.Domain.Apps.Entities/Comments/ICommentsGrain.cs
  16. 2
      backend/src/Squidex.Domain.Apps.Entities/Contents/ContentHistoryEventsCreator.cs
  17. 2
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLExecutionContext.cs
  18. 2
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AllTypes.cs
  19. 2
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AssetGraphType.cs
  20. 2
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentEnricher.cs
  21. 2
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/ResolveAssets.cs
  22. 8
      backend/src/Squidex.Infrastructure.Azure/EventSourcing/FilterBuilder.cs
  23. 2
      backend/src/Squidex.Infrastructure.MongoDb/Log/MongoRequestLogRepository.cs
  24. 1
      backend/src/Squidex.Infrastructure/Commands/CustomCommandMiddlewareRunner.cs
  25. 4
      backend/src/Squidex.Infrastructure/Commands/DomainObject.cs
  26. 1
      backend/src/Squidex.Infrastructure/Commands/InMemoryCommandBus.cs
  27. 4
      backend/src/Squidex.Infrastructure/Commands/LogSnapshotDomainObject.cs
  28. 4
      backend/src/Squidex.Infrastructure/Commands/Rebuilder.cs
  29. 2
      backend/src/Squidex.Infrastructure/Security/OpenIdClaims.cs
  30. 6
      backend/src/Squidex.Web/ApiExceptionConverter.cs
  31. 2
      backend/src/Squidex.Web/Json/TypedJsonInheritanceConverter.cs
  32. 2
      backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorsDto.cs
  33. 3
      backend/src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs
  34. 3
      backend/src/Squidex/Config/Domain/StoreServices.cs
  35. 4
      backend/src/Squidex/Config/Web/WebExtensions.cs
  36. 2
      backend/src/Squidex/Pipeline/Plugins/PluginExtensions.cs
  37. 6
      backend/src/Squidex/wwwroot/scripts/combined-editor.html
  38. 2
      backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientsTests.cs
  39. 2
      backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppContributorsTests.cs
  40. 4
      backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/LanguagesConfigJsonTests.cs
  41. 2
      backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/RolesTests.cs
  42. 2
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/BackupAppsTests.cs
  43. 2
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsIndexTests.cs
  44. 2
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Templates/TemplatesTests.cs
  45. 4
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs
  46. 1
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/MongoDb/MongoDbQueryTests.cs
  47. 87
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ConvertDataTests.cs
  48. 10
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/EnrichForCachingTests.cs
  49. 18
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/EnrichWithSchemaTests.cs
  50. 32
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/EnrichWithWorkflowsTests.cs
  51. 38
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ResolveAssetsTests.cs
  52. 46
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ResolveReferencesTests.cs
  53. 2
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/DocValuesTests.cs
  54. 2
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Rules/BackupRulesTests.cs
  55. 4
      backend/tests/Squidex.Infrastructure.Tests/Commands/LogCommandMiddlewareTests.cs
  56. 2
      backend/tests/Squidex.Infrastructure.Tests/Orleans/Indexes/UniqueNameIndexGrainTests.cs
  57. 8
      backend/tests/Squidex.Infrastructure.Tests/Queries/QueryJsonConversionTests.cs
  58. 6
      backend/tests/Squidex.Infrastructure.Tests/Reflection/SimpleEqualsTests.cs
  59. 4
      backend/tests/Squidex.Web.Tests/ApiExceptionFilterAttributeTests.cs
  60. 4
      backend/tests/Squidex.Web.Tests/Pipeline/ETagFilterTests.cs
  61. 62
      backend/tools/TestSuite/TestSuite.ApiTests/ContentCleanupTests.cs
  62. 1
      backend/tools/TestSuite/TestSuite.ApiTests/LanguagesTests.cs
  63. 30
      backend/tools/TestSuite/TestSuite.Shared/Fixtures/ContentFixture.cs
  64. 32
      backend/tools/TestSuite/TestSuite.Shared/Model/TestEntity.cs
  65. 47
      backend/tools/TestSuite/TestSuite.Shared/Model/TestEntityWithReferences.cs

2
backend/extensions/Squidex.Extensions/APM/Datadog/DatadogPlugin.cs

@ -64,7 +64,7 @@ namespace Squidex.Extensions.APM.Datadoq
private static void SetupProfiler() private static void SetupProfiler()
{ {
Profiler.SpanStarted += (session) => Profiler.SpanStarted += session =>
{ {
session.Listen(Tracer.Instance.StartActive(session.Key)); session.Listen(Tracer.Instance.StartActive(session.Key));
}; };

9
backend/src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs

@ -66,9 +66,10 @@ namespace Squidex.Domain.Apps.Core.Apps
{ {
Guard.NotNull(language); Guard.NotNull(language);
var newLanguages = new Dictionary<string, LanguageConfig>(languages); var newLanguages = new Dictionary<string, LanguageConfig>(languages)
{
newLanguages[language] = new LanguageConfig(isOptional, fallbacks); [language] = new LanguageConfig(isOptional, fallbacks)
};
return Build(newLanguages, master); return Build(newLanguages, master);
} }
@ -189,7 +190,7 @@ namespace Squidex.Domain.Apps.Core.Apps
yield return fallback; yield return fallback;
} }
if (!config.Fallbacks.Any(x => x.Iso2Code == Master)) if (config.Fallbacks.All(x => x.Iso2Code != Master))
{ {
yield return Master; yield return Master;
} }

2
backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/FieldConverters.cs

@ -225,8 +225,6 @@ namespace Squidex.Domain.Apps.Core.ConvertContent
public static FieldConverter ResolveFallbackLanguages(LanguagesConfig languages) public static FieldConverter ResolveFallbackLanguages(LanguagesConfig languages)
{ {
var master = languages.Master;
return (data, field) => return (data, field) =>
{ {
if (field.Partitioning.Equals(Partitioning.Language)) if (field.Partitioning.Equals(Partitioning.Language))

2
backend/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ValueReferencesConverter.cs

@ -16,7 +16,7 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds
{ {
public static ValueConverter CleanReferences(HashSet<Guid>? validIds = null) public static ValueConverter CleanReferences(HashSet<Guid>? validIds = null)
{ {
if (validIds == null || validIds.Count == 0) if (validIds == null)
{ {
return (value, field) => value; return (value, field) => value;
} }

2
backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/ContentSchemaBuilder.cs

@ -26,7 +26,7 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
{ {
["id"] = Builder.GuidProperty($"The id of the {schemaName} content.", true), ["id"] = Builder.GuidProperty($"The id of the {schemaName} content.", true),
["data"] = Builder.ObjectProperty(dataSchema, $"The data of the {schemaName}.", true), ["data"] = Builder.ObjectProperty(dataSchema, $"The data of the {schemaName}.", true),
["dataDraft"] = Builder.ObjectProperty(dataSchema, $"The draft data of the {schemaName}.", false), ["dataDraft"] = Builder.ObjectProperty(dataSchema, $"The draft data of the {schemaName}."),
["version"] = Builder.NumberProperty($"The version of the {schemaName}.", true), ["version"] = Builder.NumberProperty($"The version of the {schemaName}.", true),
["created"] = Builder.DateTimeProperty($"The date and time when the {schemaName} content has been created.", true), ["created"] = Builder.DateTimeProperty($"The date and time when the {schemaName} content has been created.", true),
["createdBy"] = Builder.StringProperty($"The user that has created the {schemaName} content.", true), ["createdBy"] = Builder.StringProperty($"The user that has created the {schemaName} content.", true),

24
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentEntity.cs

@ -11,8 +11,11 @@ using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Attributes;
using NodaTime; using NodaTime;
using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.ExtractReferenceIds;
using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Contents; using Squidex.Domain.Apps.Entities.Contents;
using Squidex.Domain.Apps.Entities.Contents.State;
using Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Json;
using Squidex.Infrastructure.MongoDb; using Squidex.Infrastructure.MongoDb;
@ -116,9 +119,28 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
get { return dataDraft; } get { return dataDraft; }
} }
public void LoadData(ContentState value, Schema schema, IJsonSerializer serializer)
{
ReferencedIds = value.Data.GetReferencedIds(schema);
DataByIds = value.Data.ToMongoModel(schema, serializer);
if (!ReferenceEquals(value.Data, value.DataDraft))
{
DataDraftByIds = value.DataDraft.ToMongoModel(schema, serializer);
}
else
{
DataDraftByIds = DataByIds;
}
}
public void ParseData(Schema schema, IJsonSerializer serializer) public void ParseData(Schema schema, IJsonSerializer serializer)
{ {
data = DataByIds?.FromMongoModel(schema, serializer); if (DataByIds != null)
{
data = DataByIds.FromMongoModel(schema, serializer);
}
if (DataDraftByIds != null) if (DataDraftByIds != null)
{ {

11
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs

@ -19,14 +19,11 @@ using Squidex.Domain.Apps.Entities.Contents.Repositories;
using Squidex.Domain.Apps.Entities.Contents.Text; using Squidex.Domain.Apps.Entities.Contents.Text;
using Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations; using Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations;
using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Domain.Apps.Events.Assets;
using Squidex.Domain.Apps.Events.Contents;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Json;
using Squidex.Infrastructure.Log; using Squidex.Infrastructure.Log;
using Squidex.Infrastructure.MongoDb; using Squidex.Infrastructure.MongoDb;
using Squidex.Infrastructure.Queries; using Squidex.Infrastructure.Queries;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Domain.Apps.Entities.MongoDb.Contents namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
{ {
@ -34,8 +31,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
{ {
private readonly IAppProvider appProvider; private readonly IAppProvider appProvider;
private readonly IJsonSerializer serializer; private readonly IJsonSerializer serializer;
private readonly string typeAssetDeleted;
private readonly string typeContentDeleted;
private readonly QueryContent queryContentAsync; private readonly QueryContent queryContentAsync;
private readonly QueryContentsByIds queryContentsById; private readonly QueryContentsByIds queryContentsById;
private readonly QueryContentsByQuery queryContentsByQuery; private readonly QueryContentsByQuery queryContentsByQuery;
@ -47,12 +42,11 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
StatusSerializer.Register(); StatusSerializer.Register();
} }
public MongoContentRepository(IMongoDatabase database, IAppProvider appProvider, IJsonSerializer serializer, ITextIndexer indexer, TypeNameRegistry typeNameRegistry) public MongoContentRepository(IMongoDatabase database, IAppProvider appProvider, IJsonSerializer serializer, ITextIndexer indexer)
: base(database) : base(database)
{ {
Guard.NotNull(appProvider); Guard.NotNull(appProvider);
Guard.NotNull(serializer); Guard.NotNull(serializer);
Guard.NotNull(typeNameRegistry);
this.appProvider = appProvider; this.appProvider = appProvider;
@ -63,9 +57,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
queryContentsByQuery = new QueryContentsByQuery(serializer, indexer); queryContentsByQuery = new QueryContentsByQuery(serializer, indexer);
queryIdsAsync = new QueryIdsAsync(appProvider); queryIdsAsync = new QueryIdsAsync(appProvider);
queryScheduledItems = new QueryScheduledContents(); queryScheduledItems = new QueryScheduledContents();
typeAssetDeleted = typeNameRegistry.GetName<AssetDeleted>();
typeContentDeleted = typeNameRegistry.GetName<ContentDeleted>();
} }
protected override async Task SetupCollectionAsync(IMongoCollection<MongoContentEntity> collection, CancellationToken ct = default) protected override async Task SetupCollectionAsync(IMongoCollection<MongoContentEntity> collection, CancellationToken ct = default)

20
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs

@ -9,7 +9,6 @@ using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MongoDB.Driver; using MongoDB.Driver;
using Squidex.Domain.Apps.Core.ExtractReferenceIds;
using Squidex.Domain.Apps.Entities.Contents.State; using Squidex.Domain.Apps.Entities.Contents.State;
using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure; using Squidex.Infrastructure;
@ -67,26 +66,21 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
var schema = await GetSchemaAsync(value.AppId.Id, value.SchemaId.Id); var schema = await GetSchemaAsync(value.AppId.Id, value.SchemaId.Id);
var idData = value.Data.ToMongoModel(schema.SchemaDef, serializer);
var idDraftData = idData;
if (!ReferenceEquals(value.Data, value.DataDraft))
{
idDraftData = value.DataDraft.ToMongoModel(schema.SchemaDef, serializer);
}
var content = SimpleMapper.Map(value, new MongoContentEntity var content = SimpleMapper.Map(value, new MongoContentEntity
{ {
DataByIds = idData,
DataDraftByIds = idDraftData,
IsDeleted = value.IsDeleted, IsDeleted = value.IsDeleted,
IndexedAppId = value.AppId.Id, IndexedAppId = value.AppId.Id,
IndexedSchemaId = value.SchemaId.Id, IndexedSchemaId = value.SchemaId.Id,
ReferencedIds = value.Data.GetReferencedIds(schema.SchemaDef),
ScheduledAt = value.ScheduleJob?.DueTime,
Version = newVersion Version = newVersion
}); });
content.LoadData(value, schema.SchemaDef, serializer);
if (value.ScheduleJob != null)
{
content.ScheduledAt = value.ScheduleJob.DueTime;
}
await Collection.UpsertVersionedAsync(content.Id, oldVersion, content); await Collection.UpsertVersionedAsync(content.Id, oldVersion, content);
} }
} }

1
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/Adapt.cs

@ -10,7 +10,6 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
using Squidex.Domain.Apps.Core.GenerateEdmSchema; using Squidex.Domain.Apps.Core.GenerateEdmSchema;
using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure.Queries; using Squidex.Infrastructure.Queries;

3
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/Extensions.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Linq; using System.Linq;
using MongoDB.Driver; using MongoDB.Driver;
using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Contents;
@ -14,7 +13,7 @@ using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Json;
using Squidex.Infrastructure.MongoDb; using Squidex.Infrastructure.MongoDb;
namespace Squidex.Domain.Apps.Entities.MongoDb.Contents namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
{ {
public static class Extensions public static class Extensions
{ {

2
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryContentsByQuery.cs

@ -53,7 +53,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
.Ascending(x => x.Status) .Ascending(x => x.Status)
.Descending(x => x.LastModified)); .Descending(x => x.LastModified));
return Collection.Indexes.CreateManyAsync(new[] { index1, index2, }, ct); return Collection.Indexes.CreateManyAsync(new[] { index1, index2 }, ct);
} }
public async Task<IResultList<IContentEntity>> DoAsync(IAppEntity app, ISchemaEntity schema, ClrQuery query, Status[]? status, bool inDraft, bool includeDraft = true) public async Task<IResultList<IContentEntity>> DoAsync(IAppEntity app, ISchemaEntity schema, ClrQuery query, Status[]? status, bool inDraft, bool includeDraft = true)

19
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryIdsAsync.cs

@ -33,19 +33,26 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
new CreateIndexModel<MongoContentEntity>(Index new CreateIndexModel<MongoContentEntity>(Index
.Ascending(x => x.IndexedAppId) .Ascending(x => x.IndexedAppId)
.Ascending(x => x.Id) .Ascending(x => x.Id)
.Ascending(x => x.ReferencedIds)); .Ascending(x => x.IsDeleted));
var index2 = var index2 =
new CreateIndexModel<MongoContentEntity>(Index new CreateIndexModel<MongoContentEntity>(Index
.Ascending(x => x.IndexedSchemaId)); .Ascending(x => x.IndexedSchemaId)
.Ascending(x => x.IsDeleted));
return Collection.Indexes.CreateManyAsync(new[] { index1, index2, }, ct); return Collection.Indexes.CreateManyAsync(new[] { index1, index2 }, ct);
} }
public async Task<IReadOnlyList<(Guid SchemaId, Guid Id)>> DoAsync(Guid appId, HashSet<Guid> ids) public async Task<IReadOnlyList<(Guid SchemaId, Guid Id)>> DoAsync(Guid appId, HashSet<Guid> ids)
{ {
var filter =
Filter.And(
Filter.Eq(x => x.IndexedAppId, appId),
Filter.In(x => x.Id, ids),
Filter.Ne(x => x.IsDeleted, true));
var contentEntities = var contentEntities =
await Collection.Find(Filter.And(Filter.Eq(x => x.IndexedAppId, appId), Filter.In(x => x.Id, ids))).Only(x => x.Id, x => x.IndexedSchemaId) await Collection.Find(filter).Only(x => x.Id, x => x.IndexedSchemaId)
.ToListAsync(); .ToListAsync();
return contentEntities.Select(x => (Guid.Parse(x["_si"].AsString), Guid.Parse(x["_id"].AsString))).ToList(); return contentEntities.Select(x => (Guid.Parse(x["_si"].AsString), Guid.Parse(x["_id"].AsString))).ToList();
@ -74,7 +81,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
var filters = new List<FilterDefinition<MongoContentEntity>> var filters = new List<FilterDefinition<MongoContentEntity>>
{ {
Filter.Eq(x => x.IndexedSchemaId, schemaId), Filter.Eq(x => x.IndexedSchemaId, schemaId),
Filter.Ne(x => x.IsDeleted, true), Filter.Ne(x => x.IsDeleted, true)
}; };
if (filterNode != null) if (filterNode != null)
@ -85,4 +92,4 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
return Filter.And(filters); return Filter.And(filters);
} }
} }
} }

2
backend/src/Squidex.Domain.Apps.Entities/Apps/DefaultAppLogStore.cs

@ -46,7 +46,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
Key = appId.ToString(), Key = appId.ToString(),
Properties = new Dictionary<string, string> Properties = new Dictionary<string, string>
{ {
[FieldCosts] = costs.ToString() [FieldCosts] = costs.ToString(CultureInfo.InvariantCulture)
}, },
Timestamp = timestamp Timestamp = timestamp
}; };

4
backend/src/Squidex.Domain.Apps.Entities/Comments/CommentsGrain.cs

@ -173,9 +173,9 @@ namespace Squidex.Domain.Apps.Entities.Comments
return uncommittedEvents; return uncommittedEvents;
} }
public Task<CommentsResult> GetCommentsAsync(long version = EtagVersion.Any) public Task<CommentsResult> GetCommentsAsync(long sinceVersion = EtagVersion.Any)
{ {
return Task.FromResult(CommentsResult.FromEvents(events, Version, (int)version)); return Task.FromResult(CommentsResult.FromEvents(events, Version, (int)sinceVersion));
} }
} }
} }

2
backend/src/Squidex.Domain.Apps.Entities/Comments/ICommentsGrain.cs

@ -17,6 +17,6 @@ namespace Squidex.Domain.Apps.Entities.Comments
{ {
Task<J<object>> ExecuteAsync(J<CommentsCommand> command); Task<J<object>> ExecuteAsync(J<CommentsCommand> command);
Task<CommentsResult> GetCommentsAsync(long version = EtagVersion.Any); Task<CommentsResult> GetCommentsAsync(long sinceVersion = EtagVersion.Any);
} }
} }

2
backend/src/Squidex.Domain.Apps.Entities/Contents/ContentHistoryEventsCreator.cs

@ -51,7 +51,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
{ {
var channel = $"contents.{@event.Headers.AggregateId()}"; var channel = $"contents.{@event.Headers.AggregateId()}";
HistoryEvent? result = ForEvent(@event.Payload, channel); var result = ForEvent(@event.Payload, channel);
if (@event.Payload is SchemaEvent schemaEvent) if (@event.Payload is SchemaEvent schemaEvent)
{ {

2
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLExecutionContext.cs

@ -108,7 +108,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
private IDataLoader<Guid, IContentEntity> GetContentsLoader() private IDataLoader<Guid, IContentEntity> GetContentsLoader()
{ {
return dataLoaderContextAccessor.Context.GetOrAddBatchLoader<Guid, IContentEntity>($"References", return dataLoaderContextAccessor.Context.GetOrAddBatchLoader<Guid, IContentEntity>("References",
async batch => async batch =>
{ {
var result = await GetReferencedContentsAsync(new List<Guid>(batch)); var result = await GetReferencedContentsAsync(new List<Guid>(batch));

2
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AllTypes.cs

@ -67,7 +67,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types
public static readonly QueryArguments PathArguments = new QueryArguments(new QueryArgument(None) public static readonly QueryArguments PathArguments = new QueryArguments(new QueryArgument(None)
{ {
Name = PathName, Name = PathName,
Description = $"The path to the json value", Description = "The path to the json value",
DefaultValue = null, DefaultValue = null,
ResolvedType = String ResolvedType = String
}); });

2
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AssetGraphType.cs

@ -206,7 +206,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types
Arguments = AllTypes.PathArguments, Arguments = AllTypes.PathArguments,
ResolvedType = AllTypes.NoopJson, ResolvedType = AllTypes.NoopJson,
Resolver = ResolveMetadata(), Resolver = ResolveMetadata(),
Description = "The asset metadata.", Description = "The asset metadata."
}); });
if (model.CanGenerateAssetSourceUrl) if (model.CanGenerateAssetSourceUrl)

2
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentEnricher.cs

@ -50,8 +50,6 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
Guard.NotNull(contents); Guard.NotNull(contents);
Guard.NotNull(context); Guard.NotNull(context);
var app = context.App;
using (Profiler.TraceMethod<ContentEnricher>()) using (Profiler.TraceMethod<ContentEnricher>())
{ {
var results = new List<ContentEntity>(); var results = new List<ContentEntity>();

2
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/ResolveAssets.cs

@ -63,8 +63,6 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
private void ResolveAssetsUrls(ISchemaEntity schema, IGrouping<Guid, ContentEntity> contents, ILookup<Guid, IEnrichedAssetEntity> assets) private void ResolveAssetsUrls(ISchemaEntity schema, IGrouping<Guid, ContentEntity> contents, ILookup<Guid, IEnrichedAssetEntity> assets)
{ {
var temp = new HashSet<Guid>();
foreach (var field in schema.SchemaDef.ResolvingAssets()) foreach (var field in schema.SchemaDef.ResolvingAssets())
{ {
foreach (var content in contents) foreach (var content in contents)

8
backend/src/Squidex.Infrastructure.Azure/EventSourcing/FilterBuilder.cs

@ -131,11 +131,11 @@ namespace Squidex.Infrastructure.EventSourcing
{ {
if (streamFilter.Contains("^")) if (streamFilter.Contains("^"))
{ {
filters.Add($"STARTSWITH(e.eventStream, @filter)"); filters.Add("STARTSWITH(e.eventStream, @filter)");
} }
else else
{ {
filters.Add($"e.eventStream = @filter"); filters.Add("e.eventStream = @filter");
} }
parameters.Add(new SqlParameter("@filter", streamFilter)); parameters.Add(new SqlParameter("@filter", streamFilter));
@ -146,11 +146,11 @@ namespace Squidex.Infrastructure.EventSourcing
{ {
if (streamPosition.IsEndOfCommit) if (streamPosition.IsEndOfCommit)
{ {
filters.Add($"e.timestamp > @time"); filters.Add("e.timestamp > @time");
} }
else else
{ {
filters.Add($"e.timestamp >= @time"); filters.Add("e.timestamp >= @time");
} }
parameters.Add(new SqlParameter("@time", streamPosition.Timestamp)); parameters.Add(new SqlParameter("@time", streamPosition.Timestamp));

2
backend/src/Squidex.Infrastructure.MongoDb/Log/MongoRequestLogRepository.cs

@ -50,7 +50,7 @@ namespace Squidex.Infrastructure.Log
new CreateIndexOptions new CreateIndexOptions
{ {
ExpireAfter = TimeSpan.FromDays(options.StoreRetentionInDays) ExpireAfter = TimeSpan.FromDays(options.StoreRetentionInDays)
}), })
}, ct); }, ct);
} }

1
backend/src/Squidex.Infrastructure/Commands/CustomCommandMiddlewareRunner.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;

4
backend/src/Squidex.Infrastructure/Commands/DomainObject.cs

@ -73,7 +73,7 @@ namespace Squidex.Infrastructure.Commands
} }
} }
protected async sealed override Task ReadAsync() protected sealed override async Task ReadAsync()
{ {
if (persistence != null) if (persistence != null)
{ {
@ -81,7 +81,7 @@ namespace Squidex.Infrastructure.Commands
} }
} }
public async sealed override Task RebuildStateAsync() public sealed override async Task RebuildStateAsync()
{ {
await EnsureLoadedAsync(); await EnsureLoadedAsync();

1
backend/src/Squidex.Infrastructure/Commands/InMemoryCommandBus.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;

4
backend/src/Squidex.Infrastructure/Commands/LogSnapshotDomainObject.cs

@ -87,7 +87,7 @@ namespace Squidex.Infrastructure.Commands
} }
} }
protected async sealed override Task ReadAsync() protected sealed override async Task ReadAsync()
{ {
if (persistence != null) if (persistence != null)
{ {
@ -95,7 +95,7 @@ namespace Squidex.Infrastructure.Commands
} }
} }
public async sealed override Task RebuildStateAsync() public sealed override async Task RebuildStateAsync()
{ {
await EnsureLoadedAsync(); await EnsureLoadedAsync();

4
backend/src/Squidex.Infrastructure/Commands/Rebuilder.cs

@ -91,13 +91,13 @@ namespace Squidex.Infrastructure.Commands
using (localCache.StartContext()) using (localCache.StartContext())
{ {
await source(new Func<Guid, Task>(async id => await source(async id =>
{ {
if (handledIds.Add(id)) if (handledIds.Add(id))
{ {
await worker.SendAsync(id, ct); await worker.SendAsync(id, ct);
} }
})); });
worker.Complete(); worker.Complete();

2
backend/src/Squidex.Infrastructure/Security/OpenIdClaims.cs

@ -30,7 +30,7 @@ namespace Squidex.Infrastructure.Security
public static readonly string NickName = "nickname"; public static readonly string NickName = "nickname";
/// <summary> /// <summary>
/// Shorthand name by which the End-User wishes to be referred to at the /// Shorthand name by which the End-User wishes to be referred to.
/// </summary> /// </summary>
public static readonly string PreferredUserName = "preferred_username"; public static readonly string PreferredUserName = "preferred_username";

6
backend/src/Squidex.Web/ApiExceptionConverter.cs

@ -31,7 +31,7 @@ namespace Squidex.Web
[412] = "https://tools.ietf.org/html/rfc7231#section-6.5.10", [412] = "https://tools.ietf.org/html/rfc7231#section-6.5.10",
[415] = "https://tools.ietf.org/html/rfc7231#section-6.5.13", [415] = "https://tools.ietf.org/html/rfc7231#section-6.5.13",
[422] = "https://tools.ietf.org/html/rfc4918#section-11.2", [422] = "https://tools.ietf.org/html/rfc4918#section-11.2",
[500] = "https://tools.ietf.org/html/rfc7231#section-6.6.1", [500] = "https://tools.ietf.org/html/rfc7231#section-6.6.1"
}; };
private static void AddHandler<T>(Func<T, ErrorDto> handler) where T : Exception private static void AddHandler<T>(Func<T, ErrorDto> handler) where T : Exception
@ -54,11 +54,9 @@ namespace Squidex.Web
{ {
Guard.NotNull(exception); Guard.NotNull(exception);
ErrorDto? result = null;
foreach (var handler in Handlers) foreach (var handler in Handlers)
{ {
result = handler(exception); var result = handler(exception);
if (result != null) if (result != null)
{ {

2
backend/src/Squidex.Web/Json/TypedJsonInheritanceConverter.cs

@ -79,7 +79,7 @@ namespace Squidex.Web.Json
public TypedJsonInheritanceConverter(string discriminator, IReadOnlyDictionary<string, Type> mapping) public TypedJsonInheritanceConverter(string discriminator, IReadOnlyDictionary<string, Type> mapping)
: base(typeof(T), discriminator) : base(typeof(T), discriminator)
{ {
this.mapping = mapping ?? TypedJsonInheritanceConverter<T>.DefaultMapping.Value; this.mapping = mapping ?? DefaultMapping.Value;
} }
protected override Type GetDiscriminatorType(JObject jObject, Type objectType, string discriminatorValue) protected override Type GetDiscriminatorType(JObject jObject, Type objectType, string discriminatorValue)

2
backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorsDto.cs

@ -68,7 +68,7 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models
{ {
Metadata = new ContributorsMetadata Metadata = new ContributorsMetadata
{ {
IsInvited = isInvited.ToString() IsInvited = "true"
}; };
} }
} }

3
backend/src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs

@ -38,19 +38,16 @@ namespace Squidex.Areas.Api.Controllers.Assets
private readonly IAppPlansProvider appPlansProvider; private readonly IAppPlansProvider appPlansProvider;
private readonly MyContentsControllerOptions controllerOptions; private readonly MyContentsControllerOptions controllerOptions;
private readonly ITagService tagService; private readonly ITagService tagService;
private readonly AssetOptions assetOptions;
public AssetsController( public AssetsController(
ICommandBus commandBus, ICommandBus commandBus,
IAssetQueryService assetQuery, IAssetQueryService assetQuery,
IAssetUsageTracker assetStatsRepository, IAssetUsageTracker assetStatsRepository,
IAppPlansProvider appPlansProvider, IAppPlansProvider appPlansProvider,
IOptions<AssetOptions> assetOptions,
IOptions<MyContentsControllerOptions> controllerOptions, IOptions<MyContentsControllerOptions> controllerOptions,
ITagService tagService) ITagService tagService)
: base(commandBus) : base(commandBus)
{ {
this.assetOptions = assetOptions.Value;
this.assetQuery = assetQuery; this.assetQuery = assetQuery;
this.assetStatsRepository = assetStatsRepository; this.assetStatsRepository = assetStatsRepository;
this.appPlansProvider = appPlansProvider; this.appPlansProvider = appPlansProvider;

3
backend/src/Squidex/Config/Domain/StoreServices.cs

@ -118,8 +118,7 @@ namespace Squidex.Config.Domain
c.GetRequiredService<IMongoClient>().GetDatabase(mongoContentDatabaseName), c.GetRequiredService<IMongoClient>().GetDatabase(mongoContentDatabaseName),
c.GetRequiredService<IAppProvider>(), c.GetRequiredService<IAppProvider>(),
c.GetRequiredService<IJsonSerializer>(), c.GetRequiredService<IJsonSerializer>(),
c.GetRequiredService<ITextIndexer>(), c.GetRequiredService<ITextIndexer>()))
c.GetRequiredService<TypeNameRegistry>()))
.As<IContentRepository>() .As<IContentRepository>()
.As<ISnapshotStore<ContentState, Guid>>() .As<ISnapshotStore<ContentState, Guid>>()
.As<IEventConsumer>(); .As<IEventConsumer>();

4
backend/src/Squidex/Config/Web/WebExtensions.cs

@ -121,7 +121,7 @@ namespace Squidex.Config.Web
if (!string.IsNullOrWhiteSpace(urlsOptions.BaseUrl) && urlsOptions.EnableXForwardedHost) if (!string.IsNullOrWhiteSpace(urlsOptions.BaseUrl) && urlsOptions.EnableXForwardedHost)
{ {
return new ForwardedHeadersOptions() return new ForwardedHeadersOptions
{ {
AllowedHosts = new List<string> { new Uri(urlsOptions.BaseUrl).Host }, AllowedHosts = new List<string> { new Uri(urlsOptions.BaseUrl).Host },
ForwardedHeaders = ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost, ForwardedHeaders = ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost,
@ -131,7 +131,7 @@ namespace Squidex.Config.Web
} }
else else
{ {
return new ForwardedHeadersOptions() return new ForwardedHeadersOptions
{ {
ForwardedHeaders = ForwardedHeaders.XForwardedProto, ForwardedHeaders = ForwardedHeaders.XForwardedProto,
ForwardLimit = null, ForwardLimit = null,

2
backend/src/Squidex/Pipeline/Plugins/PluginExtensions.cs

@ -23,7 +23,7 @@ namespace Squidex.Pipeline.Plugins
{ {
public static class PluginExtensions public static class PluginExtensions
{ {
private static readonly AssemblyName[] SharedAssemblies = new Type[] private static readonly AssemblyName[] SharedAssemblies = new[]
{ {
typeof(IPlugin), typeof(IPlugin),
typeof(SquidexCoreModel), typeof(SquidexCoreModel),

6
backend/src/Squidex/wwwroot/scripts/combined-editor.html

@ -27,13 +27,13 @@
element.disabled = disabled; element.disabled = disabled;
}); });
field.onFormValueChanged(function (value) { field.onFormValueChanged(function(value) {
if (value.a && value.a.iv && value.b && value.b.iv) { if (value.a && value.a.iv && value.b && value.b.iv) {
element.value = value.a.iv + value.b.iv; element.value = value.a.iv + value.b.iv;
field.valueChanged(element.value); field.valueChanged(element.value);
} }
}) });
</script> </script>
</body> </body>

2
backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientsTests.cs

@ -97,7 +97,7 @@ namespace Squidex.Domain.Apps.Core.Model.Apps
var clients_2 = clients_1.Add("3", "secret3"); var clients_2 = clients_1.Add("3", "secret3");
var clients_3 = clients_2.Revoke("2"); var clients_3 = clients_2.Revoke("2");
Assert.Equal(new string[] { "1", "3" }, clients_3.Keys); Assert.Equal(new[] { "1", "3" }, clients_3.Keys);
} }
[Fact] [Fact]

2
backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppContributorsTests.cs

@ -52,7 +52,7 @@ namespace Squidex.Domain.Apps.Core.Model.Apps
var contributors_3 = contributors_2.Assign("3", Role.Developer); var contributors_3 = contributors_2.Assign("3", Role.Developer);
var contributors_4 = contributors_3.Remove("2"); var contributors_4 = contributors_3.Remove("2");
Assert.Equal(new string[] { "1", "3" }, contributors_4.Keys); Assert.Equal(new[] { "1", "3" }, contributors_4.Keys);
} }
[Fact] [Fact]

4
backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/LanguagesConfigJsonTests.cs

@ -20,8 +20,8 @@ namespace Squidex.Domain.Apps.Core.Model.Apps
var languages = var languages =
LanguagesConfig.English LanguagesConfig.English
.Set(Language.FR) .Set(Language.FR)
.Set(Language.IT, false) .Set(Language.IT)
.Set(Language.DE, true, new Language[] { Language.IT }) .Set(Language.DE, true, Language.IT)
.MakeMaster(Language.FR); .MakeMaster(Language.FR);
var serialized = languages.SerializeAndDeserialize(); var serialized = languages.SerializeAndDeserialize();

2
backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/RolesTests.cs

@ -91,7 +91,7 @@ namespace Squidex.Domain.Apps.Core.Model.Apps
var roles_2 = roles_1.Add("role2"); var roles_2 = roles_1.Add("role2");
var roles_3 = roles_2.Remove(firstRole); var roles_3 = roles_2.Remove(firstRole);
Assert.Equal(new string[] { "role1", "role2" }, roles_3.Custom.Select(x => x.Name)); Assert.Equal(new[] { "role1", "role2" }, roles_3.Custom.Select(x => x.Name));
} }
[Fact] [Fact]

2
backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/BackupAppsTests.cs

@ -330,7 +330,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
Assert.Equal(new HashSet<string> Assert.Equal(new HashSet<string>
{ {
"found1_mapped", "found1_mapped",
"found2_mapped", "found2_mapped"
}, newIndex); }, newIndex);
} }

2
backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsIndexTests.cs

@ -49,7 +49,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
{ {
var expected = SetupApp(0, false); var expected = SetupApp(0, false);
A.CallTo(() => indexByName.GetIdsAsync(A<string[]>.That.IsSameSequenceAs(new string[] { appId.Name }))) A.CallTo(() => indexByName.GetIdsAsync(A<string[]>.That.IsSameSequenceAs(new[] { appId.Name })))
.Returns(new List<Guid> { appId.Id }); .Returns(new List<Guid> { appId.Id });
var actual = await sut.GetAppsForUserAsync(userId, new PermissionSet($"squidex.apps.{appId.Name}")); var actual = await sut.GetAppsForUserAsync(userId, new PermissionSet($"squidex.apps.{appId.Name}"));

2
backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Templates/TemplatesTests.cs

@ -20,7 +20,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
{ {
private readonly ICommandBus commandBus = A.Fake<ICommandBus>(); private readonly ICommandBus commandBus = A.Fake<ICommandBus>();
public static readonly IEnumerable<object[]> TemplateTests = new object[][] public static readonly IEnumerable<object[]> TemplateTests = new[]
{ {
new object[] { new CreateBlogCommandMiddleware(), "blog" }, new object[] { new CreateBlogCommandMiddleware(), "blog" },
new object[] { new CreateIdentityCommandMiddleware(), "identity" }, new object[] { new CreateIdentityCommandMiddleware(), "identity" },

4
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs

@ -199,7 +199,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
metadata = new metadata = new
{ {
pixelWidth = 800, pixelWidth = 800,
pixelHeight = 600, pixelHeight = 600
}, },
tags = new[] tags = new[]
{ {
@ -295,7 +295,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
metadata = new metadata = new
{ {
pixelWidth = 800, pixelWidth = 800,
pixelHeight = 600, pixelHeight = 600
}, },
tags = new[] tags = new[]
{ {

1
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/MongoDb/MongoDbQueryTests.cs

@ -16,7 +16,6 @@ using Squidex.Domain.Apps.Core;
using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Apps;
using Squidex.Domain.Apps.Entities.MongoDb.Assets.Visitors;
using Squidex.Domain.Apps.Entities.MongoDb.Contents; using Squidex.Domain.Apps.Entities.MongoDb.Contents;
using Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations; using Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations;
using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Domain.Apps.Entities.Schemas;

87
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ConvertDataTests.cs

@ -57,25 +57,25 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
[Fact] [Fact]
public async Task Should_convert_data_only() public async Task Should_convert_data_only()
{ {
var source = PublishedContent(); var content = PublishedContent(new NamedContentData());
await sut.EnrichAsync(requestContext, Enumerable.Repeat(source, 1), schemaProvider); await sut.EnrichAsync(requestContext, Enumerable.Repeat(content, 1), schemaProvider);
Assert.NotNull(source.Data); Assert.NotNull(content.Data);
Assert.Null(source.DataDraft); Assert.Null(content.DataDraft);
} }
[Fact] [Fact]
public async Task Should_convert_data_and_data_draft_when_frontend_user() public async Task Should_convert_data_and_data_draft_when_frontend_user()
{ {
var source = PublishedContent(); var content = PublishedContent(new NamedContentData());
var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId)); var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId));
await sut.EnrichAsync(ctx, Enumerable.Repeat(source, 1), schemaProvider); await sut.EnrichAsync(ctx, Enumerable.Repeat(content, 1), schemaProvider);
Assert.NotNull(source.Data); Assert.NotNull(content.Data);
Assert.NotNull(source.DataDraft); Assert.NotNull(content.DataDraft);
} }
[Fact] [Fact]
@ -84,26 +84,54 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var id1 = Guid.NewGuid(); var id1 = Guid.NewGuid();
var id2 = Guid.NewGuid(); var id2 = Guid.NewGuid();
var source = var source = BuildTestData(id1, id2);
var content = PublishedContent(source);
var expected =
new NamedContentData() new NamedContentData()
.AddField("references", .AddField("references",
new ContentFieldData() new ContentFieldData()
.AddJsonValue(JsonValue.Array(id1, id2))) .AddJsonValue(JsonValue.Array(id2)))
.AddField("assets", .AddField("assets",
new ContentFieldData() new ContentFieldData()
.AddJsonValue(JsonValue.Array(id1))) .AddJsonValue(JsonValue.Array()))
.AddField("array", .AddField("array",
new ContentFieldData() new ContentFieldData()
.AddJsonValue( .AddJsonValue(
JsonValue.Array( JsonValue.Array(
JsonValue.Object() JsonValue.Object()
.Add("nested", JsonValue.Array(id1, id2))))); .Add("nested", JsonValue.Array(id2)))));
A.CallTo(() => assetRepository.QueryIdsAsync(appId.Id, A<HashSet<Guid>>.That.Is(id1, id2)))
.Returns(new List<Guid> { id2 });
A.CallTo(() => contentRepository.QueryIdsAsync(appId.Id, A<HashSet<Guid>>.That.Is(id1, id2)))
.Returns(new List<(Guid, Guid)> { (id2, id2) });
var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId));
await sut.EnrichAsync(ctx, Enumerable.Repeat(content, 1), schemaProvider);
Assert.Equal(expected, content.Data);
Assert.Equal(expected, content.DataDraft);
}
[Fact]
public async Task Should_cleanup_references_when_everything_deleted()
{
var id1 = Guid.NewGuid();
var id2 = Guid.NewGuid();
var source = BuildTestData(id1, id2);
var content = PublishedContent(source);
var expected = var expected =
new NamedContentData() new NamedContentData()
.AddField("references", .AddField("references",
new ContentFieldData() new ContentFieldData()
.AddJsonValue(JsonValue.Array(id2))) .AddJsonValue(JsonValue.Array()))
.AddField("assets", .AddField("assets",
new ContentFieldData() new ContentFieldData()
.AddJsonValue(JsonValue.Array())) .AddJsonValue(JsonValue.Array()))
@ -112,17 +140,13 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
.AddJsonValue( .AddJsonValue(
JsonValue.Array( JsonValue.Array(
JsonValue.Object() JsonValue.Object()
.Add("nested", JsonValue.Array(id2))))); .Add("nested", JsonValue.Array()))));
var content = PublishedContent();
content.Data = source;
content.DataDraft = source;
A.CallTo(() => assetRepository.QueryIdsAsync(appId.Id, A<HashSet<Guid>>.That.Is(id1, id2))) A.CallTo(() => assetRepository.QueryIdsAsync(appId.Id, A<HashSet<Guid>>.That.Is(id1, id2)))
.Returns(new List<Guid> { id2 }); .Returns(new List<Guid>());
A.CallTo(() => contentRepository.QueryIdsAsync(appId.Id, A<HashSet<Guid>>.That.Is(id1, id2))) A.CallTo(() => contentRepository.QueryIdsAsync(appId.Id, A<HashSet<Guid>>.That.Is(id1, id2)))
.Returns(new List<(Guid, Guid)> { (id2, id2) }); .Returns(new List<(Guid, Guid)>());
var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId)); var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId));
@ -132,13 +156,30 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
Assert.Equal(expected, content.DataDraft); Assert.Equal(expected, content.DataDraft);
} }
private ContentEntity PublishedContent() private static NamedContentData BuildTestData(Guid id1, Guid id2)
{
return new NamedContentData()
.AddField("references",
new ContentFieldData()
.AddJsonValue(JsonValue.Array(id1, id2)))
.AddField("assets",
new ContentFieldData()
.AddJsonValue(JsonValue.Array(id1)))
.AddField("array",
new ContentFieldData()
.AddJsonValue(
JsonValue.Array(
JsonValue.Object()
.Add("nested", JsonValue.Array(id1, id2)))));
}
private ContentEntity PublishedContent(NamedContentData data)
{ {
return new ContentEntity return new ContentEntity
{ {
Status = Status.Published, Status = Status.Published,
Data = new NamedContentData(), Data = data,
DataDraft = new NamedContentData(), DataDraft = data,
SchemaId = schemaId SchemaId = schemaId
}; };
} }

10
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/EnrichForCachingTests.cs

@ -39,14 +39,14 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
[Fact] [Fact]
public async Task Should_add_app_version_and_schema_as_dependency() public async Task Should_add_app_version_and_schema_as_dependency()
{ {
var source = PublishedContent(); var content = PublishedContent();
await sut.EnrichAsync(requestContext, Enumerable.Repeat(source, 1), schemaProvider); await sut.EnrichAsync(requestContext, Enumerable.Repeat(content, 1), schemaProvider);
Assert.Contains(requestContext.App.Version, source.CacheDependencies); Assert.Contains(requestContext.App.Version, content.CacheDependencies);
Assert.Contains(schema.Id, source.CacheDependencies); Assert.Contains(schema.Id, content.CacheDependencies);
Assert.Contains(schema.Version, source.CacheDependencies); Assert.Contains(schema.Version, content.CacheDependencies);
} }
private ContentEntity PublishedContent() private ContentEntity PublishedContent()

18
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/EnrichWithSchemaTests.cs

@ -39,13 +39,13 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
[Fact] [Fact]
public async Task Should_enrich_with_reference_fields() public async Task Should_enrich_with_reference_fields()
{ {
var ctx = new Context(Mocks.FrontendUser(), requestContext.App); var content = PublishedContent();
var source = PublishedContent(); var ctx = new Context(Mocks.FrontendUser(), requestContext.App);
await sut.EnrichAsync(ctx, Enumerable.Repeat(source, 1), schemaProvider); await sut.EnrichAsync(ctx, Enumerable.Repeat(content, 1), schemaProvider);
Assert.NotNull(source.ReferenceFields); Assert.NotNull(content.ReferenceFields);
} }
[Fact] [Fact]
@ -61,14 +61,12 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
[Fact] [Fact]
public async Task Should_enrich_with_schema_names() public async Task Should_enrich_with_schema_names()
{ {
var ctx = new Context(Mocks.FrontendUser(), requestContext.App); var content = PublishedContent();
var source = PublishedContent(); await sut.EnrichAsync(requestContext, Enumerable.Repeat(content, 1), schemaProvider);
await sut.EnrichAsync(requestContext, Enumerable.Repeat(source, 1), schemaProvider);
Assert.Equal("my-schema", source.SchemaName); Assert.Equal("my-schema", content.SchemaName);
Assert.Equal("my-schema", source.SchemaDisplayName); Assert.Equal("my-schema", content.SchemaDisplayName);
} }
private ContentEntity PublishedContent() private ContentEntity PublishedContent()

32
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/EnrichWithWorkflowsTests.cs

@ -44,44 +44,44 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
[Fact] [Fact]
public async Task Should_enrich_content_with_status_color() public async Task Should_enrich_content_with_status_color()
{ {
var source = PublishedContent(); var content = PublishedContent();
A.CallTo(() => contentWorkflow.GetInfoAsync(source)) A.CallTo(() => contentWorkflow.GetInfoAsync(content))
.Returns(new StatusInfo(Status.Published, StatusColors.Published)); .Returns(new StatusInfo(Status.Published, StatusColors.Published));
await sut.EnrichAsync(requestContext, new[] { source }, schemaProvider); await sut.EnrichAsync(requestContext, new[] { content }, schemaProvider);
Assert.Equal(StatusColors.Published, source.StatusColor); Assert.Equal(StatusColors.Published, content.StatusColor);
} }
[Fact] [Fact]
public async Task Should_enrich_content_with_default_color_if_not_found() public async Task Should_enrich_content_with_default_color_if_not_found()
{ {
var source = PublishedContent(); var content = PublishedContent();
A.CallTo(() => contentWorkflow.GetInfoAsync(source)) A.CallTo(() => contentWorkflow.GetInfoAsync(content))
.Returns(Task.FromResult<StatusInfo>(null!)); .Returns(Task.FromResult<StatusInfo>(null!));
var ctx = requestContext.WithResolveFlow(true); var ctx = requestContext.WithResolveFlow(true);
await sut.EnrichAsync(ctx, new[] { source }, schemaProvider); await sut.EnrichAsync(ctx, new[] { content }, schemaProvider);
Assert.Equal(StatusColors.Draft, source.StatusColor); Assert.Equal(StatusColors.Draft, content.StatusColor);
} }
[Fact] [Fact]
public async Task Should_enrich_content_with_can_update() public async Task Should_enrich_content_with_can_update()
{ {
var source = new ContentEntity { SchemaId = schemaId }; var content = new ContentEntity { SchemaId = schemaId };
A.CallTo(() => contentWorkflow.CanUpdateAsync(source, requestContext.User)) A.CallTo(() => contentWorkflow.CanUpdateAsync(content, requestContext.User))
.Returns(true); .Returns(true);
var ctx = requestContext.WithResolveFlow(true); var ctx = requestContext.WithResolveFlow(true);
await sut.EnrichAsync(ctx, new[] { source }, schemaProvider); await sut.EnrichAsync(ctx, new[] { content }, schemaProvider);
Assert.True(source.CanUpdate); Assert.True(content.CanUpdate);
} }
[Fact] [Fact]
@ -89,15 +89,15 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
{ {
requestContext.WithResolveFlow(false); requestContext.WithResolveFlow(false);
var source = new ContentEntity { SchemaId = schemaId }; var content = new ContentEntity { SchemaId = schemaId };
var ctx = requestContext.WithResolveFlow(false); var ctx = requestContext.WithResolveFlow(false);
await sut.EnrichAsync(ctx, new[] { source }, schemaProvider); await sut.EnrichAsync(ctx, new[] { content }, schemaProvider);
Assert.False(source.CanUpdate); Assert.False(content.CanUpdate);
A.CallTo(() => contentWorkflow.CanUpdateAsync(source, requestContext.User)) A.CallTo(() => contentWorkflow.CanUpdateAsync(content, requestContext.User))
.MustNotHaveHappened(); .MustNotHaveHappened();
} }

38
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ResolveAssetsTests.cs

@ -81,7 +81,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var document1 = CreateAsset(Guid.NewGuid(), 3, AssetType.Unknown); var document1 = CreateAsset(Guid.NewGuid(), 3, AssetType.Unknown);
var document2 = CreateAsset(Guid.NewGuid(), 4, AssetType.Unknown); var document2 = CreateAsset(Guid.NewGuid(), 4, AssetType.Unknown);
var source = new[] var contents = new[]
{ {
CreateContent( CreateContent(
new[] { document1.Id, image1.Id }, new[] { document1.Id, image1.Id },
@ -94,14 +94,14 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
A.CallTo(() => assetQuery.QueryAsync(A<Context>.That.Matches(x => !x.ShouldEnrichAsset()), null, A<Q>.That.Matches(x => x.Ids.Count == 4))) A.CallTo(() => assetQuery.QueryAsync(A<Context>.That.Matches(x => !x.ShouldEnrichAsset()), null, A<Q>.That.Matches(x => x.Ids.Count == 4)))
.Returns(ResultList.CreateFrom(4, image1, image2, document1, document2)); .Returns(ResultList.CreateFrom(4, image1, image2, document1, document2));
await sut.EnrichAsync(requestContext, source, schemaProvider); await sut.EnrichAsync(requestContext, contents, schemaProvider);
var enriched1 = source[0]; var enriched1 = contents[0];
Assert.Contains(image1.Id, enriched1.CacheDependencies); Assert.Contains(image1.Id, enriched1.CacheDependencies);
Assert.Contains(image1.Version, enriched1.CacheDependencies); Assert.Contains(image1.Version, enriched1.CacheDependencies);
var enriched2 = source[1]; var enriched2 = contents[1];
Assert.Contains(image2.Id, enriched2.CacheDependencies); Assert.Contains(image2.Id, enriched2.CacheDependencies);
Assert.Contains(image2.Version, enriched2.CacheDependencies); Assert.Contains(image2.Version, enriched2.CacheDependencies);
@ -116,7 +116,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var document1 = CreateAsset(Guid.NewGuid(), 3, AssetType.Unknown); var document1 = CreateAsset(Guid.NewGuid(), 3, AssetType.Unknown);
var document2 = CreateAsset(Guid.NewGuid(), 4, AssetType.Unknown); var document2 = CreateAsset(Guid.NewGuid(), 4, AssetType.Unknown);
var source = new[] var contents = new[]
{ {
CreateContent( CreateContent(
new[] { document1.Id, image1.Id }, new[] { document1.Id, image1.Id },
@ -129,7 +129,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
A.CallTo(() => assetQuery.QueryAsync(A<Context>.That.Matches(x => !x.ShouldEnrichAsset()), null, A<Q>.That.Matches(x => x.Ids.Count == 4))) A.CallTo(() => assetQuery.QueryAsync(A<Context>.That.Matches(x => !x.ShouldEnrichAsset()), null, A<Q>.That.Matches(x => x.Ids.Count == 4)))
.Returns(ResultList.CreateFrom(4, image1, image2, document1, document2)); .Returns(ResultList.CreateFrom(4, image1, image2, document1, document2));
await sut.EnrichAsync(requestContext, source, schemaProvider); await sut.EnrichAsync(requestContext, contents, schemaProvider);
Assert.Equal( Assert.Equal(
new NamedContentData() new NamedContentData()
@ -138,7 +138,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
.AddValue("iv", $"url/to/{image1.Id}")) .AddValue("iv", $"url/to/{image1.Id}"))
.AddField("asset2", .AddField("asset2",
new ContentFieldData()), new ContentFieldData()),
source[0].ReferenceData); contents[0].ReferenceData);
Assert.Equal( Assert.Equal(
new NamedContentData() new NamedContentData()
@ -147,22 +147,22 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
.AddField("asset2", .AddField("asset2",
new ContentFieldData() new ContentFieldData()
.AddValue("en", $"url/to/{image2.Id}")), .AddValue("en", $"url/to/{image2.Id}")),
source[1].ReferenceData); contents[1].ReferenceData);
} }
[Fact] [Fact]
public async Task Should_not_enrich_references_if_not_api_user() public async Task Should_not_enrich_references_if_not_api_user()
{ {
var source = new[] var contents = new[]
{ {
CreateContent(new Guid[] { Guid.NewGuid() }, new Guid[0]) CreateContent(new[] { Guid.NewGuid() }, new Guid[0])
}; };
var ctx = new Context(Mocks.ApiUser(), Mocks.App(appId)); var ctx = new Context(Mocks.ApiUser(), Mocks.App(appId));
await sut.EnrichAsync(ctx, source, schemaProvider); await sut.EnrichAsync(ctx, contents, schemaProvider);
Assert.Null(source[0].ReferenceData); Assert.Null(contents[0].ReferenceData);
A.CallTo(() => assetQuery.QueryAsync(A<Context>.Ignored, null, A<Q>.Ignored)) A.CallTo(() => assetQuery.QueryAsync(A<Context>.Ignored, null, A<Q>.Ignored))
.MustNotHaveHappened(); .MustNotHaveHappened();
@ -171,16 +171,16 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
[Fact] [Fact]
public async Task Should_not_enrich_references_if_disabled() public async Task Should_not_enrich_references_if_disabled()
{ {
var source = new[] var contents = new[]
{ {
CreateContent(new Guid[] { Guid.NewGuid() }, new Guid[0]) CreateContent(new[] { Guid.NewGuid() }, new Guid[0])
}; };
var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId)).WithoutContentEnrichment(true); var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId)).WithoutContentEnrichment(true);
await sut.EnrichAsync(ctx, source, schemaProvider); await sut.EnrichAsync(ctx, contents, schemaProvider);
Assert.Null(source[0].ReferenceData); Assert.Null(contents[0].ReferenceData);
A.CallTo(() => assetQuery.QueryAsync(A<Context>.Ignored, null, A<Q>.Ignored)) A.CallTo(() => assetQuery.QueryAsync(A<Context>.Ignored, null, A<Q>.Ignored))
.MustNotHaveHappened(); .MustNotHaveHappened();
@ -189,14 +189,14 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
[Fact] [Fact]
public async Task Should_not_invoke_query_service_if_no_assets_found() public async Task Should_not_invoke_query_service_if_no_assets_found()
{ {
var source = new[] var contents = new[]
{ {
CreateContent(new Guid[0], new Guid[0]) CreateContent(new Guid[0], new Guid[0])
}; };
await sut.EnrichAsync(requestContext, source, schemaProvider); await sut.EnrichAsync(requestContext, contents, schemaProvider);
Assert.NotNull(source[0].ReferenceData); Assert.NotNull(contents[0].ReferenceData);
A.CallTo(() => assetQuery.QueryAsync(A<Context>.Ignored, null, A<Q>.Ignored)) A.CallTo(() => assetQuery.QueryAsync(A<Context>.Ignored, null, A<Q>.Ignored))
.MustNotHaveHappened(); .MustNotHaveHappened();

46
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ResolveReferencesTests.cs

@ -94,7 +94,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var ref2_1 = CreateRefContent(Guid.NewGuid(), 3, "ref2_1", 23, refSchemaId2); var ref2_1 = CreateRefContent(Guid.NewGuid(), 3, "ref2_1", 23, refSchemaId2);
var ref2_2 = CreateRefContent(Guid.NewGuid(), 4, "ref2_2", 29, refSchemaId2); var ref2_2 = CreateRefContent(Guid.NewGuid(), 4, "ref2_2", 29, refSchemaId2);
var source = new[] var contents = new[]
{ {
CreateContent(new[] { ref1_1.Id }, new[] { ref2_1.Id }), CreateContent(new[] { ref1_1.Id }, new[] { ref2_1.Id }),
CreateContent(new[] { ref1_2.Id }, new[] { ref2_2.Id }) CreateContent(new[] { ref1_2.Id }, new[] { ref2_2.Id })
@ -103,9 +103,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
A.CallTo(() => contentQuery.QueryAsync(A<Context>.Ignored, A<IReadOnlyList<Guid>>.That.Matches(x => x.Count == 4))) A.CallTo(() => contentQuery.QueryAsync(A<Context>.Ignored, A<IReadOnlyList<Guid>>.That.Matches(x => x.Count == 4)))
.Returns(ResultList.CreateFrom(4, ref1_1, ref1_2, ref2_1, ref2_2)); .Returns(ResultList.CreateFrom(4, ref1_1, ref1_2, ref2_1, ref2_2));
await sut.EnrichAsync(requestContext, source, schemaProvider); await sut.EnrichAsync(requestContext, contents, schemaProvider);
var enriched1 = source[0]; var enriched1 = contents[0];
Assert.Contains(refSchemaId1.Id, enriched1.CacheDependencies); Assert.Contains(refSchemaId1.Id, enriched1.CacheDependencies);
Assert.Contains(refSchemaId2.Id, enriched1.CacheDependencies); Assert.Contains(refSchemaId2.Id, enriched1.CacheDependencies);
@ -116,7 +116,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
Assert.Contains(ref2_1.Id, enriched1.CacheDependencies); Assert.Contains(ref2_1.Id, enriched1.CacheDependencies);
Assert.Contains(ref2_1.Version, enriched1.CacheDependencies); Assert.Contains(ref2_1.Version, enriched1.CacheDependencies);
var enriched2 = source[1]; var enriched2 = contents[1];
Assert.Contains(refSchemaId1.Id, enriched2.CacheDependencies); Assert.Contains(refSchemaId1.Id, enriched2.CacheDependencies);
Assert.Contains(refSchemaId2.Id, enriched2.CacheDependencies); Assert.Contains(refSchemaId2.Id, enriched2.CacheDependencies);
@ -136,7 +136,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var ref2_1 = CreateRefContent(Guid.NewGuid(), 3, "ref2_1", 23, refSchemaId2); var ref2_1 = CreateRefContent(Guid.NewGuid(), 3, "ref2_1", 23, refSchemaId2);
var ref2_2 = CreateRefContent(Guid.NewGuid(), 3, "ref2_2", 29, refSchemaId2); var ref2_2 = CreateRefContent(Guid.NewGuid(), 3, "ref2_2", 29, refSchemaId2);
var source = new[] var contents = new[]
{ {
CreateContent(new[] { ref1_1.Id }, new[] { ref2_1.Id }), CreateContent(new[] { ref1_1.Id }, new[] { ref2_1.Id }),
CreateContent(new[] { ref1_2.Id }, new[] { ref2_2.Id }) CreateContent(new[] { ref1_2.Id }, new[] { ref2_2.Id })
@ -145,7 +145,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
A.CallTo(() => contentQuery.QueryAsync(A<Context>.That.Matches(x => !x.ShouldEnrichContent()), A<IReadOnlyList<Guid>>.That.Matches(x => x.Count == 4))) A.CallTo(() => contentQuery.QueryAsync(A<Context>.That.Matches(x => !x.ShouldEnrichContent()), A<IReadOnlyList<Guid>>.That.Matches(x => x.Count == 4)))
.Returns(ResultList.CreateFrom(4, ref1_1, ref1_2, ref2_1, ref2_2)); .Returns(ResultList.CreateFrom(4, ref1_1, ref1_2, ref2_1, ref2_2));
await sut.EnrichAsync(requestContext, source, schemaProvider); await sut.EnrichAsync(requestContext, contents, schemaProvider);
Assert.Equal( Assert.Equal(
new NamedContentData() new NamedContentData()
@ -161,7 +161,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
JsonValue.Object() JsonValue.Object()
.Add("en", "ref2_1, 23") .Add("en", "ref2_1, 23")
.Add("de", "ref2_1, 23"))), .Add("de", "ref2_1, 23"))),
source[0].ReferenceData); contents[0].ReferenceData);
Assert.Equal( Assert.Equal(
new NamedContentData() new NamedContentData()
@ -177,7 +177,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
JsonValue.Object() JsonValue.Object()
.Add("en", "ref2_2, 29") .Add("en", "ref2_2, 29")
.Add("de", "ref2_2, 29"))), .Add("de", "ref2_2, 29"))),
source[1].ReferenceData); contents[1].ReferenceData);
} }
[Fact] [Fact]
@ -188,7 +188,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var ref2_1 = CreateRefContent(Guid.NewGuid(), 3, "ref2_1", 23, refSchemaId2); var ref2_1 = CreateRefContent(Guid.NewGuid(), 3, "ref2_1", 23, refSchemaId2);
var ref2_2 = CreateRefContent(Guid.NewGuid(), 4, "ref2_2", 29, refSchemaId2); var ref2_2 = CreateRefContent(Guid.NewGuid(), 4, "ref2_2", 29, refSchemaId2);
var source = new[] var contents = new[]
{ {
CreateContent(new[] { ref1_1.Id }, new[] { ref2_1.Id, ref2_2.Id }), CreateContent(new[] { ref1_1.Id }, new[] { ref2_1.Id, ref2_2.Id }),
CreateContent(new[] { ref1_2.Id }, new[] { ref2_1.Id, ref2_2.Id }) CreateContent(new[] { ref1_2.Id }, new[] { ref2_1.Id, ref2_2.Id })
@ -197,7 +197,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
A.CallTo(() => contentQuery.QueryAsync(A<Context>.That.Matches(x => !x.ShouldEnrichContent()), A<IReadOnlyList<Guid>>.That.Matches(x => x.Count == 4))) A.CallTo(() => contentQuery.QueryAsync(A<Context>.That.Matches(x => !x.ShouldEnrichContent()), A<IReadOnlyList<Guid>>.That.Matches(x => x.Count == 4)))
.Returns(ResultList.CreateFrom(4, ref1_1, ref1_2, ref2_1, ref2_2)); .Returns(ResultList.CreateFrom(4, ref1_1, ref1_2, ref2_1, ref2_2));
await sut.EnrichAsync(requestContext, source, schemaProvider); await sut.EnrichAsync(requestContext, contents, schemaProvider);
Assert.Equal( Assert.Equal(
new NamedContentData() new NamedContentData()
@ -213,7 +213,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
JsonValue.Object() JsonValue.Object()
.Add("en", "2 Reference(s)") .Add("en", "2 Reference(s)")
.Add("de", "2 Reference(s)"))), .Add("de", "2 Reference(s)"))),
source[0].ReferenceData); contents[0].ReferenceData);
Assert.Equal( Assert.Equal(
new NamedContentData() new NamedContentData()
@ -229,22 +229,22 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
JsonValue.Object() JsonValue.Object()
.Add("en", "2 Reference(s)") .Add("en", "2 Reference(s)")
.Add("de", "2 Reference(s)"))), .Add("de", "2 Reference(s)"))),
source[1].ReferenceData); contents[1].ReferenceData);
} }
[Fact] [Fact]
public async Task Should_not_enrich_references_if_not_api_user() public async Task Should_not_enrich_references_if_not_api_user()
{ {
var source = new[] var contents = new[]
{ {
CreateContent(new Guid[] { Guid.NewGuid() }, new Guid[0]) CreateContent(new[] { Guid.NewGuid() }, new Guid[0])
}; };
var ctx = new Context(Mocks.ApiUser(), Mocks.App(appId)); var ctx = new Context(Mocks.ApiUser(), Mocks.App(appId));
await sut.EnrichAsync(ctx, source, schemaProvider); await sut.EnrichAsync(ctx, contents, schemaProvider);
Assert.Null(source[0].ReferenceData); Assert.Null(contents[0].ReferenceData);
A.CallTo(() => contentQuery.QueryAsync(A<Context>.Ignored, A<List<Guid>>.Ignored)) A.CallTo(() => contentQuery.QueryAsync(A<Context>.Ignored, A<List<Guid>>.Ignored))
.MustNotHaveHappened(); .MustNotHaveHappened();
@ -253,16 +253,16 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
[Fact] [Fact]
public async Task Should_not_enrich_references_if_disabled() public async Task Should_not_enrich_references_if_disabled()
{ {
var source = new[] var contents = new[]
{ {
CreateContent(new Guid[] { Guid.NewGuid() }, new Guid[0]) CreateContent(new[] { Guid.NewGuid() }, new Guid[0])
}; };
var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId)).WithoutContentEnrichment(true); var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId)).WithoutContentEnrichment(true);
await sut.EnrichAsync(ctx, source, schemaProvider); await sut.EnrichAsync(ctx, contents, schemaProvider);
Assert.Null(source[0].ReferenceData); Assert.Null(contents[0].ReferenceData);
A.CallTo(() => contentQuery.QueryAsync(A<Context>.Ignored, A<List<Guid>>.Ignored)) A.CallTo(() => contentQuery.QueryAsync(A<Context>.Ignored, A<List<Guid>>.Ignored))
.MustNotHaveHappened(); .MustNotHaveHappened();
@ -271,14 +271,14 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
[Fact] [Fact]
public async Task Should_not_invoke_query_service_if_no_references_found() public async Task Should_not_invoke_query_service_if_no_references_found()
{ {
var source = new[] var contents = new[]
{ {
CreateContent(new Guid[0], new Guid[0]) CreateContent(new Guid[0], new Guid[0])
}; };
await sut.EnrichAsync(requestContext, source, schemaProvider); await sut.EnrichAsync(requestContext, contents, schemaProvider);
Assert.NotNull(source[0].ReferenceData); Assert.NotNull(contents[0].ReferenceData);
A.CallTo(() => contentQuery.QueryAsync(A<Context>.Ignored, A<List<Guid>>.Ignored)) A.CallTo(() => contentQuery.QueryAsync(A<Context>.Ignored, A<List<Guid>>.Ignored))
.MustNotHaveHappened(); .MustNotHaveHappened();

2
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/DocValuesTests.cs

@ -31,7 +31,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Text
{ {
var document = new Document(); var document = new Document();
document.AddBinaryDocValuesField("field", new BytesRef(new byte[] { i })); document.AddBinaryDocValuesField("field", new BytesRef(new[] { i }));
indexWriter.AddDocument(document); indexWriter.AddDocument(document);
} }

2
backend/tests/Squidex.Domain.Apps.Entities.Tests/Rules/BackupRulesTests.cs

@ -75,7 +75,7 @@ namespace Squidex.Domain.Apps.Entities.Rules
Assert.Equal(new HashSet<Guid> Assert.Equal(new HashSet<Guid>
{ {
ruleId1, ruleId1,
ruleId2, ruleId2
}, newIndex); }, newIndex);
} }
} }

4
backend/tests/Squidex.Infrastructure.Tests/Commands/LogCommandMiddlewareTests.cs

@ -75,7 +75,7 @@ namespace Squidex.Infrastructure.Commands
{ {
[SemanticLogLevel.Debug] = 1, [SemanticLogLevel.Debug] = 1,
[SemanticLogLevel.Information] = 1, [SemanticLogLevel.Information] = 1,
[SemanticLogLevel.Error] = 1, [SemanticLogLevel.Error] = 1
}); });
} }
@ -90,7 +90,7 @@ namespace Squidex.Infrastructure.Commands
{ {
[SemanticLogLevel.Debug] = 1, [SemanticLogLevel.Debug] = 1,
[SemanticLogLevel.Information] = 2, [SemanticLogLevel.Information] = 2,
[SemanticLogLevel.Fatal] = 1, [SemanticLogLevel.Fatal] = 1
}); });
} }
} }

2
backend/tests/Squidex.Infrastructure.Tests/Orleans/Indexes/UniqueNameIndexGrainTests.cs

@ -182,7 +182,7 @@ namespace Squidex.Infrastructure.Orleans.Indexes
await AddAsync(id1); await AddAsync(id1);
await AddAsync(id2); await AddAsync(id2);
var result = await sut.GetIdsAsync(new string[] { id1.Name, id2.Name, "not-found" }); var result = await sut.GetIdsAsync(new[] { id1.Name, id2.Name, "not-found" });
Assert.Equal(new List<Guid> { id1.Id, id2.Id }, result); Assert.Equal(new List<Guid> { id1.Id, id2.Id }, result);
} }

8
backend/tests/Squidex.Infrastructure.Tests/Queries/QueryJsonConversionTests.cs

@ -30,7 +30,7 @@ namespace Squidex.Infrastructure.Queries
("le", "$FIELD <= $VALUE"), ("le", "$FIELD <= $VALUE"),
("lt", "$FIELD < $VALUE"), ("lt", "$FIELD < $VALUE"),
("ne", "$FIELD != $VALUE"), ("ne", "$FIELD != $VALUE"),
("startswith", "startsWith($FIELD, $VALUE)"), ("startswith", "startsWith($FIELD, $VALUE)")
}; };
private readonly List<string> errors = new List<string>(); private readonly List<string> errors = new List<string>();
@ -440,7 +440,7 @@ namespace Squidex.Infrastructure.Queries
public static IEnumerable<object[]> BuildInTests(string field, object value, string valueString) public static IEnumerable<object[]> BuildInTests(string field, object value, string valueString)
{ {
var fields = new string[] var fields = new[]
{ {
$"{field}", $"{field}",
$"json.{field}", $"json.{field}",
@ -451,7 +451,7 @@ namespace Squidex.Infrastructure.Queries
{ {
var expected = $"{f} in [{valueString}]"; var expected = $"{f} in [{valueString}]";
yield return new object[] { f, value, expected }; yield return new[] { f, value, expected };
} }
} }
@ -473,7 +473,7 @@ namespace Squidex.Infrastructure.Queries
.Replace("$FIELD", f) .Replace("$FIELD", f)
.Replace("$VALUE", valueString); .Replace("$VALUE", valueString);
yield return new object[] { f, op.Operator, value, expected }; yield return new[] { f, op.Operator, value, expected };
} }
} }
} }

6
backend/tests/Squidex.Infrastructure.Tests/Reflection/SimpleEqualsTests.cs

@ -64,7 +64,7 @@ namespace Squidex.Infrastructure.Reflection
yield return new object[] yield return new object[]
{ {
Guid.NewGuid(), Guid.NewGuid(),
Guid.NewGuid(), Guid.NewGuid()
}; };
yield return new object[] yield return new object[]
@ -118,7 +118,7 @@ namespace Squidex.Infrastructure.Reflection
public void Should_compare_equal_strings() public void Should_compare_equal_strings()
{ {
var stringA_1 = "a"; var stringA_1 = "a";
var stringA_2 = new string(new char[] { 'a' }); var stringA_2 = new string(new[] { 'a' });
Assert.True(SimpleEquals.IsEquals(stringA_1, stringA_1)); Assert.True(SimpleEquals.IsEquals(stringA_1, stringA_1));
Assert.True(SimpleEquals.IsEquals(stringA_1, stringA_2)); Assert.True(SimpleEquals.IsEquals(stringA_1, stringA_2));
@ -128,7 +128,7 @@ namespace Squidex.Infrastructure.Reflection
public void Should_compare_non_equal_strings() public void Should_compare_non_equal_strings()
{ {
var stringA_1 = "a"; var stringA_1 = "a";
var stringB_2 = new string(new char[] { 'b' }); var stringB_2 = new string(new[] { 'b' });
Assert.False(SimpleEquals.IsEquals(stringA_1, stringB_2)); Assert.False(SimpleEquals.IsEquals(stringA_1, stringB_2));
Assert.False(SimpleEquals.IsEquals(stringA_1, null!)); Assert.False(SimpleEquals.IsEquals(stringA_1, null!));

4
backend/tests/Squidex.Web.Tests/ApiExceptionFilterAttributeTests.cs

@ -51,9 +51,9 @@ namespace Squidex.Web
Assert.Equal(400, result.StatusCode); Assert.Equal(400, result.StatusCode);
Assert.Equal(400, (result.Value as ErrorDto)?.StatusCode); Assert.Equal(400, (result.Value as ErrorDto)?.StatusCode);
Assert.Equal(ex.Summary, (result.Value as ErrorDto)!.Message); Assert.Equal(ex.Summary, ((ErrorDto)result.Value).Message);
Assert.Equal(new[] { "Error1", "P: Error2", "P1, P2: Error3" }, (result.Value as ErrorDto)!.Details); Assert.Equal(new[] { "Error1", "P: Error2", "P1, P2: Error3" }, ((ErrorDto)result.Value).Details);
} }
[Fact] [Fact]

4
backend/tests/Squidex.Web.Tests/Pipeline/ETagFilterTests.cs

@ -78,7 +78,7 @@ namespace Squidex.Web.Pipeline
await sut.OnActionExecutionAsync(executingContext, Next()); await sut.OnActionExecutionAsync(executingContext, Next());
Assert.Equal(304, (executedContext.Result as StatusCodeResult)!.StatusCode); Assert.Equal(304, ((StatusCodeResult)executedContext.Result).StatusCode);
} }
[Fact] [Fact]
@ -91,7 +91,7 @@ namespace Squidex.Web.Pipeline
await sut.OnActionExecutionAsync(executingContext, Next()); await sut.OnActionExecutionAsync(executingContext, Next());
Assert.Equal(200, (executedContext.Result as StatusCodeResult)!.StatusCode); Assert.Equal(200, ((StatusCodeResult)executedContext.Result).StatusCode);
} }
private ActionExecutionDelegate Next() private ActionExecutionDelegate Next()

62
backend/tools/TestSuite/TestSuite.ApiTests/ContentCleanupTests.cs

@ -6,10 +6,8 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Squidex.ClientLibrary.Management;
using TestSuite.Fixtures; using TestSuite.Fixtures;
using TestSuite.Model; using TestSuite.Model;
using Xunit; using Xunit;
@ -34,33 +32,11 @@ namespace TestSuite.ApiTests
var schemaName = $"schema-{DateTime.UtcNow.Ticks}"; var schemaName = $"schema-{DateTime.UtcNow.Ticks}";
// STEP 1: Create a schema. // STEP 1: Create a schema.
var schema = await _.Schemas.PostSchemaAsync(_.AppName, new CreateSchemaDto var schema = await TestEntity.CreateSchemaAsync(_.Schemas, _.AppName, schemaName);
{
Name = schemaName,
Fields = new List<UpsertSchemaFieldDto>
{
new UpsertSchemaFieldDto
{
Name = "number",
Properties = new NumberFieldPropertiesDto
{
IsRequired = true
}
},
new UpsertSchemaFieldDto
{
Name = "string",
Properties = new StringFieldPropertiesDto
{
IsRequired = false
}
}
},
IsPublished = true
});
var contents = _.ClientManager.GetClient<TestEntity, TestEntityData>(schemaName); var contents = _.ClientManager.GetClient<TestEntity, TestEntityData>(schemaName);
// STEP 2: Create a content for this schema. // STEP 2: Create a content for this schema.
var data = new TestEntityData { Number = 12, String = "hello" }; var data = new TestEntityData { Number = 12, String = "hello" };
@ -79,5 +55,39 @@ namespace TestSuite.ApiTests
// Should not return deleted field. // Should not return deleted field.
Assert.Null(content_2.Data.String); Assert.Null(content_2.Data.String);
} }
[Fact]
public async Task Should_cleanup_old_references()
{
var schemaName = $"schema-{DateTime.UtcNow.Ticks}";
// STEP 1: Create a schema.
await TestEntityWithReferences.CreateSchemaAsync(_.Schemas, _.AppName, schemaName);
var contents = _.ClientManager.GetClient<TestEntityWithReferences, TestEntityWithReferencesData>(schemaName);
// STEP 2: Create a referenced content.
var dataA = new TestEntityWithReferencesData();
var contentA_1 = await contents.CreateAsync(dataA);
// STEP 3: Create a content with a reference.
var dataB = new TestEntityWithReferencesData { References = new[] { Guid.Parse(contentA_1.Id) } };
var contentB_1 = await contents.CreateAsync(dataB);
// STEP 3: Delete a reference
await contents.DeleteAsync(contentA_1.Id);
// STEP 4: Make any update.
var contentB_2 = await contents.ChangeStatusAsync(contentB_1.Id, "Published");
// Should not return deleted field.
Assert.Empty(contentB_2.Data.References);
}
} }
} }

1
backend/tools/TestSuite/TestSuite.ApiTests/LanguagesTests.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using TestSuite.Fixtures; using TestSuite.Fixtures;
using Xunit; using Xunit;

30
backend/tools/TestSuite/TestSuite.Shared/Fixtures/ContentFixture.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Squidex.ClientLibrary; using Squidex.ClientLibrary;
using Squidex.ClientLibrary.Management; using Squidex.ClientLibrary.Management;
@ -19,10 +18,6 @@ namespace TestSuite.Fixtures
public string SchemaName { get; } public string SchemaName { get; }
public string FieldNumber { get; } = "number";
public string FieldString { get; } = "string";
public ContentFixture() public ContentFixture()
: this("my-writes") : this("my-writes")
{ {
@ -36,30 +31,7 @@ namespace TestSuite.Fixtures
{ {
try try
{ {
await Schemas.PostSchemaAsync(AppName, new CreateSchemaDto await TestEntity.CreateSchemaAsync(Schemas, AppName, schemaName);
{
Name = SchemaName,
Fields = new List<UpsertSchemaFieldDto>
{
new UpsertSchemaFieldDto
{
Name = FieldNumber,
Properties = new NumberFieldPropertiesDto
{
IsRequired = true
}
},
new UpsertSchemaFieldDto
{
Name = FieldString,
Properties = new StringFieldPropertiesDto
{
IsRequired = false
}
}
},
IsPublished = true
});
} }
catch (SquidexManagementException ex) catch (SquidexManagementException ex)
{ {

32
backend/tools/TestSuite/TestSuite.Shared/Model/TestEntity.cs

@ -5,13 +5,45 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System.Collections.Generic;
using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using Squidex.ClientLibrary; using Squidex.ClientLibrary;
using Squidex.ClientLibrary.Management;
namespace TestSuite.Model namespace TestSuite.Model
{ {
public sealed class TestEntity : SquidexEntityBase<TestEntityData> public sealed class TestEntity : SquidexEntityBase<TestEntityData>
{ {
public static async Task<SchemaDetailsDto> CreateSchemaAsync(ISchemasClient schemas, string appName, string name)
{
var schema = await schemas.PostSchemaAsync(appName, new CreateSchemaDto
{
Name = name,
Fields = new List<UpsertSchemaFieldDto>
{
new UpsertSchemaFieldDto
{
Name = nameof(TestEntityData.Number).ToLowerInvariant(),
Properties = new NumberFieldPropertiesDto
{
IsRequired = true
}
},
new UpsertSchemaFieldDto
{
Name = nameof(TestEntityData.String).ToLowerInvariant(),
Properties = new StringFieldPropertiesDto
{
IsRequired = false
}
}
},
IsPublished = true
});
return schema;
}
} }
public sealed class TestEntityData public sealed class TestEntityData

47
backend/tools/TestSuite/TestSuite.Shared/Model/TestEntityWithReferences.cs

@ -0,0 +1,47 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Squidex.ClientLibrary;
using Squidex.ClientLibrary.Management;
namespace TestSuite.Model
{
public sealed class TestEntityWithReferences : SquidexEntityBase<TestEntityWithReferencesData>
{
public static async Task<SchemaDetailsDto> CreateSchemaAsync(ISchemasClient schemas, string appName, string name)
{
var schema = await schemas.PostSchemaAsync(appName, new CreateSchemaDto
{
Name = name,
Fields = new List<UpsertSchemaFieldDto>
{
new UpsertSchemaFieldDto
{
Name = nameof(TestEntityWithReferencesData.References).ToLowerInvariant(),
Properties = new ReferencesFieldPropertiesDto
{
IsRequired = false
}
}
},
IsPublished = true
});
return schema;
}
}
public sealed class TestEntityWithReferencesData
{
[JsonConverter(typeof(InvariantConverter))]
public Guid[] References { get; set; }
}
}
Loading…
Cancel
Save