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()
{
Profiler.SpanStarted += (session) =>
Profiler.SpanStarted += session =>
{
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);
var newLanguages = new Dictionary<string, LanguageConfig>(languages);
newLanguages[language] = new LanguageConfig(isOptional, fallbacks);
var newLanguages = new Dictionary<string, LanguageConfig>(languages)
{
[language] = new LanguageConfig(isOptional, fallbacks)
};
return Build(newLanguages, master);
}
@ -189,7 +190,7 @@ namespace Squidex.Domain.Apps.Core.Apps
yield return fallback;
}
if (!config.Fallbacks.Any(x => x.Iso2Code == Master))
if (config.Fallbacks.All(x => x.Iso2Code != 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)
{
var master = languages.Master;
return (data, field) =>
{
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)
{
if (validIds == null || validIds.Count == 0)
if (validIds == null)
{
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),
["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),
["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),

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

@ -11,8 +11,11 @@ using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using NodaTime;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.ExtractReferenceIds;
using Squidex.Domain.Apps.Core.Schemas;
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.Json;
using Squidex.Infrastructure.MongoDb;
@ -116,9 +119,28 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
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)
{
data = DataByIds?.FromMongoModel(schema, serializer);
if (DataByIds != null)
{
data = DataByIds.FromMongoModel(schema, serializer);
}
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.MongoDb.Contents.Operations;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Domain.Apps.Events.Assets;
using Squidex.Domain.Apps.Events.Contents;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json;
using Squidex.Infrastructure.Log;
using Squidex.Infrastructure.MongoDb;
using Squidex.Infrastructure.Queries;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
{
@ -34,8 +31,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
{
private readonly IAppProvider appProvider;
private readonly IJsonSerializer serializer;
private readonly string typeAssetDeleted;
private readonly string typeContentDeleted;
private readonly QueryContent queryContentAsync;
private readonly QueryContentsByIds queryContentsById;
private readonly QueryContentsByQuery queryContentsByQuery;
@ -47,12 +42,11 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
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)
{
Guard.NotNull(appProvider);
Guard.NotNull(serializer);
Guard.NotNull(typeNameRegistry);
this.appProvider = appProvider;
@ -63,9 +57,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
queryContentsByQuery = new QueryContentsByQuery(serializer, indexer);
queryIdsAsync = new QueryIdsAsync(appProvider);
queryScheduledItems = new QueryScheduledContents();
typeAssetDeleted = typeNameRegistry.GetName<AssetDeleted>();
typeContentDeleted = typeNameRegistry.GetName<ContentDeleted>();
}
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.Tasks;
using MongoDB.Driver;
using Squidex.Domain.Apps.Core.ExtractReferenceIds;
using Squidex.Domain.Apps.Entities.Contents.State;
using Squidex.Domain.Apps.Entities.Schemas;
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 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
{
DataByIds = idData,
DataDraftByIds = idDraftData,
IsDeleted = value.IsDeleted,
IndexedAppId = value.AppId.Id,
IndexedSchemaId = value.SchemaId.Id,
ReferencedIds = value.Data.GetReferencedIds(schema.SchemaDef),
ScheduledAt = value.ScheduleJob?.DueTime,
Version = newVersion
});
content.LoadData(value, schema.SchemaDef, serializer);
if (value.ScheduleJob != null)
{
content.ScheduledAt = value.ScheduleJob.DueTime;
}
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.Reflection;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
using Squidex.Domain.Apps.Core.GenerateEdmSchema;
using Squidex.Domain.Apps.Core.Schemas;
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.
// ==========================================================================
using System;
using System.Linq;
using MongoDB.Driver;
using Squidex.Domain.Apps.Core.Contents;
@ -14,7 +13,7 @@ using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure.Json;
using Squidex.Infrastructure.MongoDb;
namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
{
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)
.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)

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
.Ascending(x => x.IndexedAppId)
.Ascending(x => x.Id)
.Ascending(x => x.ReferencedIds));
.Ascending(x => x.IsDeleted));
var index2 =
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)
{
var filter =
Filter.And(
Filter.Eq(x => x.IndexedAppId, appId),
Filter.In(x => x.Id, ids),
Filter.Ne(x => x.IsDeleted, true));
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();
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>>
{
Filter.Eq(x => x.IndexedSchemaId, schemaId),
Filter.Ne(x => x.IsDeleted, true),
Filter.Ne(x => x.IsDeleted, true)
};
if (filterNode != null)
@ -85,4 +92,4 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
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(),
Properties = new Dictionary<string, string>
{
[FieldCosts] = costs.ToString()
[FieldCosts] = costs.ToString(CultureInfo.InvariantCulture)
},
Timestamp = timestamp
};

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

@ -173,9 +173,9 @@ namespace Squidex.Domain.Apps.Entities.Comments
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<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()}";
HistoryEvent? result = ForEvent(@event.Payload, channel);
var result = ForEvent(@event.Payload, channel);
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()
{
return dataLoaderContextAccessor.Context.GetOrAddBatchLoader<Guid, IContentEntity>($"References",
return dataLoaderContextAccessor.Context.GetOrAddBatchLoader<Guid, IContentEntity>("References",
async 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)
{
Name = PathName,
Description = $"The path to the json value",
Description = "The path to the json value",
DefaultValue = null,
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,
ResolvedType = AllTypes.NoopJson,
Resolver = ResolveMetadata(),
Description = "The asset metadata.",
Description = "The asset metadata."
});
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(context);
var app = context.App;
using (Profiler.TraceMethod<ContentEnricher>())
{
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)
{
var temp = new HashSet<Guid>();
foreach (var field in schema.SchemaDef.ResolvingAssets())
{
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("^"))
{
filters.Add($"STARTSWITH(e.eventStream, @filter)");
filters.Add("STARTSWITH(e.eventStream, @filter)");
}
else
{
filters.Add($"e.eventStream = @filter");
filters.Add("e.eventStream = @filter");
}
parameters.Add(new SqlParameter("@filter", streamFilter));
@ -146,11 +146,11 @@ namespace Squidex.Infrastructure.EventSourcing
{
if (streamPosition.IsEndOfCommit)
{
filters.Add($"e.timestamp > @time");
filters.Add("e.timestamp > @time");
}
else
{
filters.Add($"e.timestamp >= @time");
filters.Add("e.timestamp >= @time");
}
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
{
ExpireAfter = TimeSpan.FromDays(options.StoreRetentionInDays)
}),
})
}, ct);
}

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

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Linq;
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)
{
@ -81,7 +81,7 @@ namespace Squidex.Infrastructure.Commands
}
}
public async sealed override Task RebuildStateAsync()
public sealed override async Task RebuildStateAsync()
{
await EnsureLoadedAsync();

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

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Linq;
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)
{
@ -95,7 +95,7 @@ namespace Squidex.Infrastructure.Commands
}
}
public async sealed override Task RebuildStateAsync()
public sealed override async Task RebuildStateAsync()
{
await EnsureLoadedAsync();

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

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

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

@ -30,7 +30,7 @@ namespace Squidex.Infrastructure.Security
public static readonly string NickName = "nickname";
/// <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>
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",
[415] = "https://tools.ietf.org/html/rfc7231#section-6.5.13",
[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
@ -54,11 +54,9 @@ namespace Squidex.Web
{
Guard.NotNull(exception);
ErrorDto? result = null;
foreach (var handler in Handlers)
{
result = handler(exception);
var result = handler(exception);
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)
: 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)

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
{
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 MyContentsControllerOptions controllerOptions;
private readonly ITagService tagService;
private readonly AssetOptions assetOptions;
public AssetsController(
ICommandBus commandBus,
IAssetQueryService assetQuery,
IAssetUsageTracker assetStatsRepository,
IAppPlansProvider appPlansProvider,
IOptions<AssetOptions> assetOptions,
IOptions<MyContentsControllerOptions> controllerOptions,
ITagService tagService)
: base(commandBus)
{
this.assetOptions = assetOptions.Value;
this.assetQuery = assetQuery;
this.assetStatsRepository = assetStatsRepository;
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<IAppProvider>(),
c.GetRequiredService<IJsonSerializer>(),
c.GetRequiredService<ITextIndexer>(),
c.GetRequiredService<TypeNameRegistry>()))
c.GetRequiredService<ITextIndexer>()))
.As<IContentRepository>()
.As<ISnapshotStore<ContentState, Guid>>()
.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)
{
return new ForwardedHeadersOptions()
return new ForwardedHeadersOptions
{
AllowedHosts = new List<string> { new Uri(urlsOptions.BaseUrl).Host },
ForwardedHeaders = ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost,
@ -131,7 +131,7 @@ namespace Squidex.Config.Web
}
else
{
return new ForwardedHeadersOptions()
return new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedProto,
ForwardLimit = null,

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

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

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

@ -27,13 +27,13 @@
element.disabled = disabled;
});
field.onFormValueChanged(function (value) {
field.onFormValueChanged(function(value) {
if (value.a && value.a.iv && value.b && value.b.iv) {
element.value = value.a.iv + value.b.iv;
field.valueChanged(element.value);
}
})
});
</script>
</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_3 = clients_2.Revoke("2");
Assert.Equal(new string[] { "1", "3" }, clients_3.Keys);
Assert.Equal(new[] { "1", "3" }, clients_3.Keys);
}
[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_4 = contributors_3.Remove("2");
Assert.Equal(new string[] { "1", "3" }, contributors_4.Keys);
Assert.Equal(new[] { "1", "3" }, contributors_4.Keys);
}
[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 =
LanguagesConfig.English
.Set(Language.FR)
.Set(Language.IT, false)
.Set(Language.DE, true, new Language[] { Language.IT })
.Set(Language.IT)
.Set(Language.DE, true, Language.IT)
.MakeMaster(Language.FR);
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_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]

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>
{
"found1_mapped",
"found2_mapped",
"found2_mapped"
}, 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);
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 });
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>();
public static readonly IEnumerable<object[]> TemplateTests = new object[][]
public static readonly IEnumerable<object[]> TemplateTests = new[]
{
new object[] { new CreateBlogCommandMiddleware(), "blog" },
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
{
pixelWidth = 800,
pixelHeight = 600,
pixelHeight = 600
},
tags = new[]
{
@ -295,7 +295,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
metadata = new
{
pixelWidth = 800,
pixelHeight = 600,
pixelHeight = 600
},
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.Schemas;
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.Operations;
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]
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.Null(source.DataDraft);
Assert.NotNull(content.Data);
Assert.Null(content.DataDraft);
}
[Fact]
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));
await sut.EnrichAsync(ctx, Enumerable.Repeat(source, 1), schemaProvider);
await sut.EnrichAsync(ctx, Enumerable.Repeat(content, 1), schemaProvider);
Assert.NotNull(source.Data);
Assert.NotNull(source.DataDraft);
Assert.NotNull(content.Data);
Assert.NotNull(content.DataDraft);
}
[Fact]
@ -84,26 +84,54 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var id1 = Guid.NewGuid();
var id2 = Guid.NewGuid();
var source =
var source = BuildTestData(id1, id2);
var content = PublishedContent(source);
var expected =
new NamedContentData()
.AddField("references",
new ContentFieldData()
.AddJsonValue(JsonValue.Array(id1, id2)))
.AddJsonValue(JsonValue.Array(id2)))
.AddField("assets",
new ContentFieldData()
.AddJsonValue(JsonValue.Array(id1)))
.AddJsonValue(JsonValue.Array()))
.AddField("array",
new ContentFieldData()
.AddJsonValue(
JsonValue.Array(
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 =
new NamedContentData()
.AddField("references",
new ContentFieldData()
.AddJsonValue(JsonValue.Array(id2)))
.AddJsonValue(JsonValue.Array()))
.AddField("assets",
new ContentFieldData()
.AddJsonValue(JsonValue.Array()))
@ -112,17 +140,13 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
.AddJsonValue(
JsonValue.Array(
JsonValue.Object()
.Add("nested", JsonValue.Array(id2)))));
var content = PublishedContent();
content.Data = source;
content.DataDraft = source;
.Add("nested", JsonValue.Array()))));
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)))
.Returns(new List<(Guid, Guid)> { (id2, id2) });
.Returns(new List<(Guid, Guid)>());
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);
}
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
{
Status = Status.Published,
Data = new NamedContentData(),
DataDraft = new NamedContentData(),
Data = data,
DataDraft = data,
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]
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.Version, source.CacheDependencies);
Assert.Contains(schema.Id, content.CacheDependencies);
Assert.Contains(schema.Version, content.CacheDependencies);
}
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]
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]
@ -61,14 +61,12 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
[Fact]
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(source, 1), schemaProvider);
await sut.EnrichAsync(requestContext, Enumerable.Repeat(content, 1), schemaProvider);
Assert.Equal("my-schema", source.SchemaName);
Assert.Equal("my-schema", source.SchemaDisplayName);
Assert.Equal("my-schema", content.SchemaName);
Assert.Equal("my-schema", content.SchemaDisplayName);
}
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]
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));
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]
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!));
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]
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);
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]
@ -89,15 +89,15 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
{
requestContext.WithResolveFlow(false);
var source = new ContentEntity { SchemaId = schemaId };
var content = new ContentEntity { SchemaId = schemaId };
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();
}

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 document2 = CreateAsset(Guid.NewGuid(), 4, AssetType.Unknown);
var source = new[]
var contents = new[]
{
CreateContent(
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)))
.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.Version, enriched1.CacheDependencies);
var enriched2 = source[1];
var enriched2 = contents[1];
Assert.Contains(image2.Id, 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 document2 = CreateAsset(Guid.NewGuid(), 4, AssetType.Unknown);
var source = new[]
var contents = new[]
{
CreateContent(
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)))
.Returns(ResultList.CreateFrom(4, image1, image2, document1, document2));
await sut.EnrichAsync(requestContext, source, schemaProvider);
await sut.EnrichAsync(requestContext, contents, schemaProvider);
Assert.Equal(
new NamedContentData()
@ -138,7 +138,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
.AddValue("iv", $"url/to/{image1.Id}"))
.AddField("asset2",
new ContentFieldData()),
source[0].ReferenceData);
contents[0].ReferenceData);
Assert.Equal(
new NamedContentData()
@ -147,22 +147,22 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
.AddField("asset2",
new ContentFieldData()
.AddValue("en", $"url/to/{image2.Id}")),
source[1].ReferenceData);
contents[1].ReferenceData);
}
[Fact]
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));
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))
.MustNotHaveHappened();
@ -171,16 +171,16 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
[Fact]
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);
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))
.MustNotHaveHappened();
@ -189,14 +189,14 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
[Fact]
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])
};
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))
.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_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_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)))
.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(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.Version, enriched1.CacheDependencies);
var enriched2 = source[1];
var enriched2 = contents[1];
Assert.Contains(refSchemaId1.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_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_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)))
.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(
new NamedContentData()
@ -161,7 +161,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
JsonValue.Object()
.Add("en", "ref2_1, 23")
.Add("de", "ref2_1, 23"))),
source[0].ReferenceData);
contents[0].ReferenceData);
Assert.Equal(
new NamedContentData()
@ -177,7 +177,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
JsonValue.Object()
.Add("en", "ref2_2, 29")
.Add("de", "ref2_2, 29"))),
source[1].ReferenceData);
contents[1].ReferenceData);
}
[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_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_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)))
.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(
new NamedContentData()
@ -213,7 +213,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
JsonValue.Object()
.Add("en", "2 Reference(s)")
.Add("de", "2 Reference(s)"))),
source[0].ReferenceData);
contents[0].ReferenceData);
Assert.Equal(
new NamedContentData()
@ -229,22 +229,22 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
JsonValue.Object()
.Add("en", "2 Reference(s)")
.Add("de", "2 Reference(s)"))),
source[1].ReferenceData);
contents[1].ReferenceData);
}
[Fact]
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));
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))
.MustNotHaveHappened();
@ -253,16 +253,16 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
[Fact]
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);
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))
.MustNotHaveHappened();
@ -271,14 +271,14 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
[Fact]
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])
};
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))
.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();
document.AddBinaryDocValuesField("field", new BytesRef(new byte[] { i }));
document.AddBinaryDocValuesField("field", new BytesRef(new[] { i }));
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>
{
ruleId1,
ruleId2,
ruleId2
}, newIndex);
}
}

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

@ -75,7 +75,7 @@ namespace Squidex.Infrastructure.Commands
{
[SemanticLogLevel.Debug] = 1,
[SemanticLogLevel.Information] = 1,
[SemanticLogLevel.Error] = 1,
[SemanticLogLevel.Error] = 1
});
}
@ -90,7 +90,7 @@ namespace Squidex.Infrastructure.Commands
{
[SemanticLogLevel.Debug] = 1,
[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(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);
}

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

@ -30,7 +30,7 @@ namespace Squidex.Infrastructure.Queries
("le", "$FIELD <= $VALUE"),
("lt", "$FIELD < $VALUE"),
("ne", "$FIELD != $VALUE"),
("startswith", "startsWith($FIELD, $VALUE)"),
("startswith", "startsWith($FIELD, $VALUE)")
};
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)
{
var fields = new string[]
var fields = new[]
{
$"{field}",
$"json.{field}",
@ -451,7 +451,7 @@ namespace Squidex.Infrastructure.Queries
{
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("$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[]
{
Guid.NewGuid(),
Guid.NewGuid(),
Guid.NewGuid()
};
yield return new object[]
@ -118,7 +118,7 @@ namespace Squidex.Infrastructure.Reflection
public void Should_compare_equal_strings()
{
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_2));
@ -128,7 +128,7 @@ namespace Squidex.Infrastructure.Reflection
public void Should_compare_non_equal_strings()
{
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, 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.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]

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

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

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

@ -6,10 +6,8 @@
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Squidex.ClientLibrary.Management;
using TestSuite.Fixtures;
using TestSuite.Model;
using Xunit;
@ -34,33 +32,11 @@ namespace TestSuite.ApiTests
var schemaName = $"schema-{DateTime.UtcNow.Ticks}";
// STEP 1: Create a schema.
var schema = await _.Schemas.PostSchemaAsync(_.AppName, new CreateSchemaDto
{
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 schema = await TestEntity.CreateSchemaAsync(_.Schemas, _.AppName, schemaName);
var contents = _.ClientManager.GetClient<TestEntity, TestEntityData>(schemaName);
// STEP 2: Create a content for this schema.
var data = new TestEntityData { Number = 12, String = "hello" };
@ -79,5 +55,39 @@ namespace TestSuite.ApiTests
// Should not return deleted field.
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.
// ==========================================================================
using System;
using System.Threading.Tasks;
using TestSuite.Fixtures;
using Xunit;

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

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

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

@ -5,13 +5,45 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Collections.Generic;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Squidex.ClientLibrary;
using Squidex.ClientLibrary.Management;
namespace TestSuite.Model
{
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

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