From 7c5345d3ded446636b7005092ea7c903a26ca91a Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 23 Jul 2019 17:09:34 +0200 Subject: [PATCH] Tests fixed and improved. --- .../Schemas/ReferencesFieldProperties.cs | 2 + .../Schemas/SchemaExtensions.cs | 12 + .../ContentReferencesExtensions.cs | 22 +- .../Contents/Extensions.cs | 2 +- .../Contents/ContentEnricher.cs | 69 ++++-- .../Guards/FieldPropertiesValidator.cs | 7 + .../Fields/ReferencesFieldPropertiesDto.cs | 5 + src/Squidex/Config/Domain/EntitiesServices.cs | 8 +- .../pages/content/content-page.component.ts | 2 + .../forms/field-form-common.component.ts | 4 +- .../schema/types/references-ui.component.html | 17 +- .../schema/types/references-ui.component.ts | 3 + .../app/shared/services/schemas.types.ts | 1 + .../app/shared/state/contents.forms.ts | 28 +-- .../ReferenceExtractionTests.cs | 19 +- .../AppsByUserIndexCommandMiddlewareTests.cs | 23 +- .../InviteUserCommandMiddlewareTests.cs | 11 +- .../Apps/RolePermissionsProviderTests.cs | 21 +- .../Assets/AssetQueryServiceTests.cs | 28 +-- .../ContentEnricherReferencesTests.cs | 215 ++++++++++++++++++ .../Contents/ContentEnricherTests.cs | 8 +- .../Contents/ContentGrainTests.cs | 23 +- .../Contents/ContentQueryServiceTests.cs | 131 ++++++----- .../DefaultWorkflowsValidatorTests.cs | 6 +- .../Contents/DynamicContentWorkflowTests.cs | 61 ++--- .../Contents/GraphQL/GraphQLQueriesTests.cs | 52 ++--- .../Contents/GraphQL/GraphQLTestBase.cs | 34 ++- .../Contents/Guard/GuardContentTests.cs | 57 +++-- .../Queries/FilterTagTransformerTests.cs | 31 +-- .../Contents/Text/GrainTextIndexerTests.cs | 25 +- .../Rules/Guards/GuardRuleTests.cs | 6 +- .../Triggers/ContentChangedTriggerTests.cs | 29 +-- .../ReferencesFieldPropertiesTests.cs | 14 ++ ...SchemasByAppIndexCommandMiddlewareTests.cs | 31 ++- .../TestHelpers/HandlerTestBase.cs | 2 +- .../TestHelpers/Mocks.cs | 67 ++++++ ...nrichWithSchemaIdCommandMiddlewareTests.cs | 2 - 37 files changed, 722 insertions(+), 356 deletions(-) create mode 100644 tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentEnricherReferencesTests.cs create mode 100644 tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/Mocks.cs diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs index b23ee085e..3f6013f9e 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs @@ -15,6 +15,8 @@ namespace Squidex.Domain.Apps.Core.Schemas public int? MaxItems { get; set; } + public bool ResolveReference { get; set; } + public bool AllowDuplicates { get; set; } public ReferencesFieldEditor Editor { get; set; } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/SchemaExtensions.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/SchemaExtensions.cs index 23989053a..0e2274691 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/SchemaExtensions.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/SchemaExtensions.cs @@ -6,6 +6,8 @@ // ========================================================================== using System; +using System.Collections.Generic; +using System.Linq; using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Core.Schemas @@ -51,5 +53,15 @@ namespace Squidex.Domain.Apps.Core.Schemas { return schema.Properties.Label.WithFallback(schema.TypeName()); } + + public static IEnumerable> ResolvingReferences(this Schema schema) + { + return schema.Fields.OfType>() + .Where(x => + x.Properties.SchemaId != Guid.Empty && + x.Properties.ResolveReference && + x.Properties.MaxItems == 1 && + (x.Properties.IsListField || schema.Fields.Count == 1)); + } } } diff --git a/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ContentReferencesExtensions.cs b/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ContentReferencesExtensions.cs index 4d157cd78..6fb83a936 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ContentReferencesExtensions.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ContentReferencesExtensions.cs @@ -23,18 +23,13 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds { Guard.NotNull(schema, nameof(schema)); - var foundReferences = new HashSet(); - foreach (var field in schema.Fields) { var ids = source.GetReferencedIds(field, strategy); foreach (var id in ids) { - if (foundReferences.Add(id)) - { - yield return id; - } + yield return id; } } } @@ -57,6 +52,21 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds } } + public static IEnumerable GetReferencedIds(this NamedContentData source, Schema schema, Ids strategy = Ids.All) + { + Guard.NotNull(schema, nameof(schema)); + + foreach (var field in schema.Fields) + { + var ids = source.GetReferencedIds(field, strategy); + + foreach (var id in ids) + { + yield return id; + } + } + } + public static IEnumerable GetReferencedIds(this NamedContentData source, IField field, Ids strategy = Ids.All) { Guard.NotNull(field, nameof(field)); diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Extensions.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Extensions.cs index c677386a6..e28b1e9de 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Extensions.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Extensions.cs @@ -20,7 +20,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents { public static List ToReferencedIds(this IdContentData data, Schema schema) { - return data.GetReferencedIds(schema).ToList(); + return data.GetReferencedIds(schema).Distinct().ToList(); } public static NamedContentData FromMongoModel(this IdContentData result, Schema schema, List deletedIds, IJsonSerializer serializer) diff --git a/src/Squidex.Domain.Apps.Entities/Contents/ContentEnricher.cs b/src/Squidex.Domain.Apps.Entities/Contents/ContentEnricher.cs index c07d90cb8..5228024db 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/ContentEnricher.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/ContentEnricher.cs @@ -12,6 +12,7 @@ using System.Threading.Tasks; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.ExtractReferenceIds; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Infrastructure; using Squidex.Infrastructure.Json.Objects; using Squidex.Infrastructure.Log; @@ -22,7 +23,7 @@ namespace Squidex.Domain.Apps.Entities.Contents public sealed class ContentEnricher : IContentEnricher { private const string DefaultColor = StatusColors.Draft; - private static readonly Dictionary EmptyReferences = new Dictionary(); + private static readonly ILookup EmptyReferences = Enumerable.Empty().ToLookup(x => x.Id); private readonly Lazy contentQuery; private readonly IContentWorkflow contentWorkflow; @@ -92,25 +93,21 @@ namespace Squidex.Domain.Apps.Entities.Contents private async Task ResolveReferencesAsync(Guid schemaId, IEnumerable contents, Context context) { - var appId = contents.First().AppId.Id; - var schema = await ContentQuery.GetSchemaOrThrowAsync(context, schemaId.ToString()); - var referenceFields = - schema.SchemaDef.Fields.OfType>() - .Where(x => - x.Properties.SchemaId != Guid.Empty && - x.Properties.MinItems == 1 && - x.Properties.MaxItems == 1 && - x.Properties.IsListField); + var references = await GetReferencesAsync(schema, contents, context); - var formatted = new Dictionary(); + var formatted = new Dictionary(); - foreach (var field in referenceFields) + foreach (var field in schema.SchemaDef.ResolvingReferences()) { foreach (var content in contents) { - content.ReferenceData = new NamedContentData(); + if (content.ReferenceData == null) + { + content.ReferenceData = new NamedContentData(); + } + content.ReferenceData.GetOrAddNew(field.Name); } @@ -119,25 +116,33 @@ namespace Squidex.Domain.Apps.Entities.Contents var referencedSchemaId = field.Properties.SchemaId; var referencedSchema = await ContentQuery.GetSchemaOrThrowAsync(context, referencedSchemaId.ToString()); - var references = await GetReferencesAsync(referencedSchemaId, contents, field, context); - foreach (var content in contents) { var fieldReference = content.ReferenceData[field.Name]; if (content.DataDraft.TryGetValue(field.Name, out var fieldData)) { - foreach (var partition in fieldData) + foreach (var partitionValue in fieldData) { - var id = field.GetReferencedIds(partition.Value, Ids.ContentOnly).FirstOrDefault(); + var referencedContents = + field.GetReferencedIds(partitionValue.Value, Ids.ContentOnly) + .Select(x => references[x]) + .SelectMany(x => x) + .ToList(); - if (references.TryGetValue(id, out var reference)) + if (referencedContents.Count == 1) { var value = - formatted.GetOrAdd(id, - _ => reference.DataDraft.FormatReferences(referencedSchema.SchemaDef, context.App.LanguagesConfig)); + formatted.GetOrAdd(referencedContents[0], + x => x.DataDraft.FormatReferences(referencedSchema.SchemaDef, context.App.LanguagesConfig)); + + fieldReference.AddJsonValue(partitionValue.Key, value); + } + else if (referencedContents.Count > 1) + { + var value = CreateFallback(context, referencedContents); - fieldReference[partition.Key] = JsonValue.Create(value); + fieldReference.AddJsonValue(partitionValue.Key, value); } } } @@ -150,20 +155,34 @@ namespace Squidex.Domain.Apps.Entities.Contents } } - private async Task> GetReferencesAsync(Guid schemaId, IEnumerable contents, IField field, Context context) + private static JsonObject CreateFallback(Context context, List referencedContents) + { + var text = $"{referencedContents.Count} Reference(s)"; + + var value = JsonValue.Object(); + + foreach (var language in context.App.LanguagesConfig) + { + value.Add(language.Key, text); + } + + return value; + } + + private async Task> GetReferencesAsync(ISchemaEntity schema, IEnumerable contents, Context context) { var ids = new HashSet(); foreach (var content in contents) { - ids.AddRange(content.DataDraft.GetReferencedIds(field, Ids.ContentOnly)); + ids.AddRange(content.DataDraft.GetReferencedIds(schema.SchemaDef, Ids.ContentOnly)); } if (ids.Count > 0) { - var references = await ContentQuery.QueryAsync(context.Clone().WithNoEnrichment(true), schemaId.ToString(), Q.Empty.WithIds(ids)); + var references = await ContentQuery.QueryAsync(context.Clone().WithNoEnrichment(true), ids.ToList()); - return references.ToDictionary(x => x.Id); + return references.ToLookup(x => x.Id); } else { diff --git a/src/Squidex.Domain.Apps.Entities/Schemas/Guards/FieldPropertiesValidator.cs b/src/Squidex.Domain.Apps.Entities/Schemas/Guards/FieldPropertiesValidator.cs index aeb29743e..2a4a384b9 100644 --- a/src/Squidex.Domain.Apps.Entities/Schemas/Guards/FieldPropertiesValidator.cs +++ b/src/Squidex.Domain.Apps.Entities/Schemas/Guards/FieldPropertiesValidator.cs @@ -218,6 +218,13 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards nameof(properties.MinItems), nameof(properties.MaxItems)); } + + if (properties.ResolveReference && properties.MaxItems != 1) + { + yield return new ValidationError("Can only resolve references when MaxItems is 1.", + nameof(properties.ResolveReference), + nameof(properties.MaxItems)); + } } public IEnumerable Visit(StringFieldProperties properties) diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ReferencesFieldPropertiesDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ReferencesFieldPropertiesDto.cs index 0b5bd9042..8f144931c 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ReferencesFieldPropertiesDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ReferencesFieldPropertiesDto.cs @@ -28,6 +28,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields /// public bool AllowDuplicates { get; set; } + /// + /// True to resolve references in the content list. + /// + public bool ResolveReference { get; set; } + /// /// The editor that is used to manage this field. /// diff --git a/src/Squidex/Config/Domain/EntitiesServices.cs b/src/Squidex/Config/Domain/EntitiesServices.cs index 1b480e088..d122a072a 100644 --- a/src/Squidex/Config/Domain/EntitiesServices.cs +++ b/src/Squidex/Config/Domain/EntitiesServices.cs @@ -99,13 +99,13 @@ namespace Squidex.Config.Domain services.AddSingletonAs() .As(); - services.AddSingletonAs() - .As(); - services.AddSingletonAs() .As(); - services.AddSingletonAs(c => new Lazy(() => c.GetRequiredService())) + services.AddSingletonAs() + .As(); + + services.AddSingletonAs(c => new Lazy(() => c.GetRequiredService())) .AsSelf(); services.AddSingletonAs() diff --git a/src/Squidex/app/features/content/pages/content/content-page.component.ts b/src/Squidex/app/features/content/pages/content/content-page.component.ts index 08b7c4e56..879c5790a 100644 --- a/src/Squidex/app/features/content/pages/content/content-page.component.ts +++ b/src/Squidex/app/features/content/pages/content/content-page.component.ts @@ -169,6 +169,8 @@ export class ContentPageComponent extends ResourceOwner implements CanComponentD this.contentsState.create(value, publish) .subscribe(() => { + this.contentForm.submitCompleted({ noReset: true }); + this.back(); }, error => { this.contentForm.submitFailed(error); diff --git a/src/Squidex/app/features/schemas/pages/schema/forms/field-form-common.component.ts b/src/Squidex/app/features/schemas/pages/schema/forms/field-form-common.component.ts index 4e813eb43..58ff319ac 100644 --- a/src/Squidex/app/features/schemas/pages/schema/forms/field-form-common.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/forms/field-form-common.component.ts @@ -55,7 +55,7 @@ import { FieldDto } from '@app/shared';
-
+
-
+
-
+
+ +
+
+
+ + +
+ + + If check the reference is resolved for the content list.
Can only be checken when the MaxItems field in the validation tab is set to 1. +
+
+
\ No newline at end of file diff --git a/src/Squidex/app/features/schemas/pages/schema/types/references-ui.component.ts b/src/Squidex/app/features/schemas/pages/schema/types/references-ui.component.ts index 8f3ee4acd..775dd7ea1 100644 --- a/src/Squidex/app/features/schemas/pages/schema/types/references-ui.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/types/references-ui.component.ts @@ -30,5 +30,8 @@ export class ReferencesUIComponent implements OnInit { new FormControl(this.properties.editor, [ Validators.required ])); + + this.editForm.setControl('resolveReference', + new FormControl(this.properties.resolveReference)); } } \ No newline at end of file diff --git a/src/Squidex/app/shared/services/schemas.types.ts b/src/Squidex/app/shared/services/schemas.types.ts index cb5059939..10fd41334 100644 --- a/src/Squidex/app/shared/services/schemas.types.ts +++ b/src/Squidex/app/shared/services/schemas.types.ts @@ -327,6 +327,7 @@ export class ReferencesFieldPropertiesDto extends FieldPropertiesDto { public readonly maxItems?: number; public readonly editor: string; public readonly schemaId?: string; + public readonly resolveReference?: boolean; public readonly allowDuplicates?: boolean; public get isSortable() { diff --git a/src/Squidex/app/shared/state/contents.forms.ts b/src/Squidex/app/shared/state/contents.forms.ts index 31745c6d8..7ad42e608 100644 --- a/src/Squidex/app/shared/state/contents.forms.ts +++ b/src/Squidex/app/shared/state/contents.forms.ts @@ -61,24 +61,26 @@ export class SaveQueryForm extends Form { export type FieldValue = string | HtmlValue; export function getContentValue(content: ContentDto, language: LanguageDto, field: RootFieldDto, allowHtml = true): { value: any, formatted: FieldValue } { - const reference = content.referenceData[field.name]; + if (content.referenceData) { + const reference = content.referenceData[field.name]; - if (reference) { - let fieldValue: ContentReferencesValue; + if (reference) { + let fieldValue: ContentReferencesValue; - if (field.isLocalizable) { - fieldValue = reference[language.iso2Code]; - } else { - fieldValue = reference[fieldInvariant]; - } + if (field.isLocalizable) { + fieldValue = reference[language.iso2Code]; + } else { + fieldValue = reference[fieldInvariant]; + } - let value = ''; + let value = ''; - if (fieldValue) { - value = fieldValue[language.iso2Code] || ''; - } + if (fieldValue) { + value = fieldValue[language.iso2Code] || ''; + } - return { value, formatted: value }; + return { value, formatted: value }; + } } const contentField = content.dataDraft[field.name]; diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs index 4fa3ef5f9..7573a5194 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs @@ -40,7 +40,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds } [Fact] - public void Should_remove_ids() + public void Should_get_ids_from_id_data() { var id1 = Guid.NewGuid(); var id2 = Guid.NewGuid(); @@ -56,6 +56,23 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds Assert.Equal(new[] { id1, id2 }, ids); } + [Fact] + public void Should_get_ids_from_name_data() + { + var id1 = Guid.NewGuid(); + var id2 = Guid.NewGuid(); + + var input = + new NamedContentData() + .AddField("assets1", + new ContentFieldData() + .AddValue("iv", JsonValue.Array(id1.ToString(), id2.ToString()))); + + var ids = input.GetReferencedIds(schema).ToArray(); + + Assert.Equal(new[] { id1, id2 }, ids); + } + [Fact] public void Should_cleanup_deleted_ids() { diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsByUserIndexCommandMiddlewareTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsByUserIndexCommandMiddlewareTests.cs index 6d164d38e..ab1b64e64 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsByUserIndexCommandMiddlewareTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsByUserIndexCommandMiddlewareTests.cs @@ -11,6 +11,7 @@ using FakeItEasy; using Orleans; using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Entities.Apps.Commands; +using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Infrastructure; using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.Orleans; @@ -23,7 +24,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes private readonly IGrainFactory grainFactory = A.Fake(); private readonly ICommandBus commandBus = A.Fake(); private readonly IAppsByUserIndex index = A.Fake(); - private readonly Guid appId = Guid.NewGuid(); + private readonly NamedId appId = NamedId.Of(Guid.NewGuid(), "my-app"); private readonly string userId = "123"; private readonly AppsByUserIndexCommandMiddleware sut; @@ -39,12 +40,12 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes public async Task Should_add_app_to_index_on_create() { var context = - new CommandContext(new CreateApp { AppId = appId, Actor = new RefToken("user", userId) }, commandBus) + new CommandContext(new CreateApp { AppId = appId.Id, Actor = new RefToken("user", userId) }, commandBus) .Complete(); await sut.HandleAsync(context); - A.CallTo(() => index.AddAppAsync(appId)) + A.CallTo(() => index.AddAppAsync(appId.Id)) .MustHaveHappened(); } @@ -52,12 +53,12 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes public async Task Should_add_app_to_index_on_assign_of_contributor() { var context = - new CommandContext(new AssignContributor { AppId = appId, ContributorId = userId }, commandBus) + new CommandContext(new AssignContributor { AppId = appId.Id, ContributorId = userId }, commandBus) .Complete(); await sut.HandleAsync(context); - A.CallTo(() => index.AddAppAsync(appId)) + A.CallTo(() => index.AddAppAsync(appId.Id)) .MustHaveHappened(); } @@ -65,12 +66,12 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes public async Task Should_add_app_to_index_on_remove_of_contributor() { var context = - new CommandContext(new RemoveContributor { AppId = appId, ContributorId = userId }, commandBus) + new CommandContext(new RemoveContributor { AppId = appId.Id, ContributorId = userId }, commandBus) .Complete(); await sut.HandleAsync(context); - A.CallTo(() => index.RemoveAppAsync(appId)) + A.CallTo(() => index.RemoveAppAsync(appId.Id)) .MustHaveHappened(); } @@ -78,9 +79,9 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes public async Task Should_remove_app_from_index_on_archive() { var appGrain = A.Fake(); - var appState = A.Fake(); + var appState = Mocks.App(appId); - A.CallTo(() => grainFactory.GetGrain(appId, null)) + A.CallTo(() => grainFactory.GetGrain(appId.Id, null)) .Returns(appGrain); A.CallTo(() => appGrain.GetStateAsync()) @@ -90,12 +91,12 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes .Returns(AppContributors.Empty.Assign(userId, Role.Owner)); var context = - new CommandContext(new ArchiveApp { AppId = appId }, commandBus) + new CommandContext(new ArchiveApp { AppId = appId.Id }, commandBus) .Complete(); await sut.HandleAsync(context); - A.CallTo(() => index.RemoveAppAsync(appId)) + A.CallTo(() => index.RemoveAppAsync(appId.Id)) .MustHaveHappened(); } } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Invitation/InviteUserCommandMiddlewareTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Invitation/InviteUserCommandMiddlewareTests.cs index 43070abf8..2f504edc3 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Invitation/InviteUserCommandMiddlewareTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Invitation/InviteUserCommandMiddlewareTests.cs @@ -5,9 +5,12 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System; using System.Threading.Tasks; using FakeItEasy; using Squidex.Domain.Apps.Entities.Apps.Commands; +using Squidex.Domain.Apps.Entities.TestHelpers; +using Squidex.Infrastructure; using Squidex.Infrastructure.Commands; using Squidex.Shared.Users; using Xunit; @@ -34,13 +37,13 @@ namespace Squidex.Domain.Apps.Entities.Apps.Invitation A.CallTo(() => userResolver.CreateUserIfNotExists("me@email.com", true)) .Returns(true); - var app = A.Fake(); + var result = Mocks.App(NamedId.Of(Guid.NewGuid(), "my-app")); - context.Complete(app); + context.Complete(result); await sut.HandleAsync(context); - Assert.Same(context.Result().App, app); + Assert.Same(context.Result().App, result); A.CallTo(() => userResolver.CreateUserIfNotExists("me@email.com", true)) .MustHaveHappened(); @@ -55,7 +58,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Invitation A.CallTo(() => userResolver.CreateUserIfNotExists("me@email.com", true)) .Returns(false); - var result = A.Fake(); + var result = Mocks.App(NamedId.Of(Guid.NewGuid(), "my-app")); context.Complete(result); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Apps/RolePermissionsProviderTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Apps/RolePermissionsProviderTests.cs index fa7fe1d98..ff03efb5a 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Apps/RolePermissionsProviderTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Apps/RolePermissionsProviderTests.cs @@ -9,8 +9,9 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using FakeItEasy; -using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Entities.Schemas; +using Squidex.Domain.Apps.Entities.TestHelpers; +using Squidex.Infrastructure; using Xunit; #pragma warning disable xUnit2017 // Do not use Contains() to check if a value exists in a collection @@ -19,13 +20,14 @@ namespace Squidex.Domain.Apps.Entities.Apps { public class RolePermissionsProviderTests { + private readonly IAppEntity app; private readonly IAppProvider appProvider = A.Fake(); - private readonly IAppEntity app = A.Fake(); + private readonly NamedId appId = NamedId.Of(Guid.NewGuid(), "my-app"); private readonly RolePermissionsProvider sut; public RolePermissionsProviderTests() { - A.CallTo(() => app.Name).Returns("my-app"); + app = Mocks.App(appId); sut = new RolePermissionsProvider(appProvider); } @@ -36,8 +38,8 @@ namespace Squidex.Domain.Apps.Entities.Apps A.CallTo(() => appProvider.GetSchemasAsync(A.Ignored)) .Returns(new List { - CreateSchema("schema1"), - CreateSchema("schema2") + Mocks.Schema(appId, NamedId.Of(Guid.NewGuid(), "schema1")), + Mocks.Schema(appId, NamedId.Of(Guid.NewGuid(), "schema2")), }); var result = await sut.GetPermissionsAsync(app); @@ -48,14 +50,5 @@ namespace Squidex.Domain.Apps.Entities.Apps Assert.True(result.Contains("schemas.schema1.update")); Assert.True(result.Contains("schemas.schema2.update")); } - - private static ISchemaEntity CreateSchema(string name) - { - var schema = A.Fake(); - - A.CallTo(() => schema.SchemaDef).Returns(new Schema(name)); - - return schema; - } } } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetQueryServiceTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetQueryServiceTests.cs index be9ad655e..2ca9007f0 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetQueryServiceTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetQueryServiceTests.cs @@ -8,13 +8,10 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Security.Claims; using System.Threading.Tasks; using FakeItEasy; using Microsoft.Extensions.Options; -using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Tags; -using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Assets.Repositories; using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Infrastructure; @@ -25,23 +22,16 @@ namespace Squidex.Domain.Apps.Entities.Assets { public class AssetQueryServiceTests { - private readonly ITagService tagService = A.Fake(); private readonly IAssetEnricher assetEnricher = A.Fake(); private readonly IAssetRepository assetRepository = A.Fake(); - private readonly IAppEntity app = A.Fake(); + private readonly ITagService tagService = A.Fake(); private readonly NamedId appId = NamedId.Of(Guid.NewGuid(), "my-app"); - private readonly Context context; + private readonly Context requestContext; private readonly AssetQueryService sut; public AssetQueryServiceTests() { - var user = new ClaimsPrincipal(new ClaimsIdentity()); - - A.CallTo(() => app.Id).Returns(appId.Id); - A.CallTo(() => app.Name).Returns(appId.Name); - A.CallTo(() => app.LanguagesConfig).Returns(LanguagesConfig.English); - - context = new Context(user, app); + requestContext = new Context(Mocks.FrontendUser(), Mocks.App(appId)); var options = Options.Create(new AssetOptions { DefaultPageSize = 30 }); @@ -109,7 +99,7 @@ namespace Squidex.Domain.Apps.Entities.Assets A.CallTo(() => assetEnricher.EnrichAsync(A>.That.IsSameSequenceAs(found1, found2))) .Returns(new List { enriched1, enriched2 }); - var result = await sut.QueryAsync(context, Q.Empty.WithIds(ids)); + var result = await sut.QueryAsync(requestContext, Q.Empty.WithIds(ids)); Assert.Equal(8, result.Total); @@ -131,7 +121,7 @@ namespace Squidex.Domain.Apps.Entities.Assets A.CallTo(() => assetEnricher.EnrichAsync(A>.That.IsSameSequenceAs(found1, found2))) .Returns(new List { enriched1, enriched2 }); - var result = await sut.QueryAsync(context, Q.Empty); + var result = await sut.QueryAsync(requestContext, Q.Empty); Assert.Equal(8, result.Total); @@ -143,7 +133,7 @@ namespace Squidex.Domain.Apps.Entities.Assets { var query = Q.Empty.WithODataQuery("$top=100&$orderby=fileName asc&$search=Hello World"); - await sut.QueryAsync(context, query); + await sut.QueryAsync(requestContext, query); A.CallTo(() => assetRepository.QueryAsync(appId.Id, A.That.Is("FullText: 'Hello World'; Take: 100; Sort: fileName Ascending"))) .MustHaveHappened(); @@ -154,7 +144,7 @@ namespace Squidex.Domain.Apps.Entities.Assets { var query = Q.Empty.WithODataQuery("$top=200&$filter=fileName eq 'ABC'"); - await sut.QueryAsync(context, query); + await sut.QueryAsync(requestContext, query); A.CallTo(() => assetRepository.QueryAsync(appId.Id, A.That.Is("Filter: fileName == 'ABC'; Take: 200; Sort: lastModified Descending"))) .MustHaveHappened(); @@ -165,7 +155,7 @@ namespace Squidex.Domain.Apps.Entities.Assets { var query = Q.Empty; - await sut.QueryAsync(context, query); + await sut.QueryAsync(requestContext, query); A.CallTo(() => assetRepository.QueryAsync(appId.Id, A.That.Is("Take: 30; Sort: lastModified Descending"))) .MustHaveHappened(); @@ -176,7 +166,7 @@ namespace Squidex.Domain.Apps.Entities.Assets { var query = Q.Empty.WithODataQuery("$top=300&$skip=20"); - await sut.QueryAsync(context, query); + await sut.QueryAsync(requestContext, query); A.CallTo(() => assetRepository.QueryAsync(appId.Id, A.That.Is("Skip: 20; Take: 200; Sort: lastModified Descending"))) .MustHaveHappened(); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentEnricherReferencesTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentEnricherReferencesTests.cs new file mode 100644 index 000000000..22ddb944d --- /dev/null +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentEnricherReferencesTests.cs @@ -0,0 +1,215 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using FakeItEasy; +using Squidex.Domain.Apps.Core; +using Squidex.Domain.Apps.Core.Contents; +using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Domain.Apps.Entities.TestHelpers; +using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; +using Xunit; + +namespace Squidex.Domain.Apps.Entities.Contents +{ + public class ContentEnricherReferencesTests + { + private readonly IContentWorkflow contentWorkflow = A.Fake(); + private readonly IContentQueryService contentQuery = A.Fake(); + private readonly NamedId appId = NamedId.Of(Guid.NewGuid(), "my-app"); + private readonly NamedId refSchemaId1 = NamedId.Of(Guid.NewGuid(), "my-ref1"); + private readonly NamedId refSchemaId2 = NamedId.Of(Guid.NewGuid(), "my-ref2"); + private readonly NamedId schemaId = NamedId.Of(Guid.NewGuid(), "my-schema"); + private readonly Context requestContext; + private readonly ContentEnricher sut; + + public ContentEnricherReferencesTests() + { + requestContext = new Context(Mocks.FrontendUser(), Mocks.App(appId, Language.DE)); + + var refSchemaDef = + new Schema("my-ref") + .AddString(1, "name", Partitioning.Invariant, + new StringFieldProperties { IsReferenceField = true }) + .AddNumber(2, "number", Partitioning.Invariant, + new NumberFieldProperties { IsReferenceField = true }); + + var schemaDef = + new Schema(schemaId.Name) + .AddReferences(1, "ref1", Partitioning.Invariant, new ReferencesFieldProperties + { + ResolveReference = true, + IsListField = true, + MinItems = 1, + MaxItems = 1, + SchemaId = refSchemaId1.Id + }) + .AddReferences(2, "ref2", Partitioning.Invariant, new ReferencesFieldProperties + { + ResolveReference = true, + IsListField = true, + MinItems = 1, + MaxItems = 1, + SchemaId = refSchemaId2.Id + }); + + void SetupSchema(NamedId id, Schema def) + { + var schemaEntity = Mocks.Schema(appId, id, def); + + A.CallTo(() => contentQuery.GetSchemaOrThrowAsync(requestContext, id.Id.ToString())) + .Returns(schemaEntity); + } + + SetupSchema(schemaId, schemaDef); + SetupSchema(refSchemaId1, refSchemaDef); + SetupSchema(refSchemaId2, refSchemaDef); + + sut = new ContentEnricher(new Lazy(() => contentQuery), contentWorkflow); + } + + [Fact] + public async Task Should_enrich_with_reference_data() + { + var ref1_1 = CreateRefContent(Guid.NewGuid(), "ref1_1", 13); + var ref1_2 = CreateRefContent(Guid.NewGuid(), "ref1_2", 17); + var ref2_1 = CreateRefContent(Guid.NewGuid(), "ref2_1", 23); + var ref2_2 = CreateRefContent(Guid.NewGuid(), "ref2_2", 29); + + var source = new IContentEntity[] + { + CreateContent(new Guid[] { ref1_1.Id }, new Guid[] { ref2_1.Id }), + CreateContent(new Guid[] { ref1_2.Id }, new Guid[] { ref2_2.Id }) + }; + + A.CallTo(() => contentQuery.QueryAsync(A.Ignored, A>.That.Matches(x => x.Count == 4))) + .Returns(ResultList.CreateFrom(4, ref1_1, ref1_2, ref2_1, ref2_2)); + + var enriched = await sut.EnrichAsync(source, requestContext); + + Assert.Equal( + new NamedContentData() + .AddField("ref1", + new ContentFieldData() + .AddJsonValue("iv", + JsonValue.Object() + .Add("en", "ref1_1, 13") + .Add("de", "ref1_1, 13"))) + .AddField("ref2", + new ContentFieldData() + .AddJsonValue("iv", + JsonValue.Object() + .Add("en", "ref2_1, 23") + .Add("de", "ref2_1, 23"))), + enriched.ElementAt(0).ReferenceData); + + Assert.Equal( + new NamedContentData() + .AddField("ref1", + new ContentFieldData() + .AddJsonValue("iv", + JsonValue.Object() + .Add("en", "ref1_2, 17") + .Add("de", "ref1_2, 17"))) + .AddField("ref2", + new ContentFieldData() + .AddJsonValue("iv", + JsonValue.Object() + .Add("en", "ref2_2, 29") + .Add("de", "ref2_2, 29"))), + enriched.ElementAt(1).ReferenceData); + } + + [Fact] + public async Task Should_not_enrich_when_content_has_more_items() + { + var ref1_1 = CreateRefContent(Guid.NewGuid(), "ref1_1", 13); + var ref1_2 = CreateRefContent(Guid.NewGuid(), "ref1_2", 17); + var ref2_1 = CreateRefContent(Guid.NewGuid(), "ref2_1", 23); + var ref2_2 = CreateRefContent(Guid.NewGuid(), "ref2_2", 29); + + var source = new IContentEntity[] + { + CreateContent(new Guid[] { ref1_1.Id }, new Guid[] { ref2_1.Id, ref2_2.Id }), + CreateContent(new Guid[] { ref1_2.Id }, new Guid[] { ref2_1.Id, ref2_2.Id }) + }; + + A.CallTo(() => contentQuery.QueryAsync(A.Ignored, A>.That.Matches(x => x.Count == 4))) + .Returns(ResultList.CreateFrom(4, ref1_1, ref1_2, ref2_1, ref2_2)); + + var enriched = await sut.EnrichAsync(source, requestContext); + + Assert.Equal( + new NamedContentData() + .AddField("ref1", + new ContentFieldData() + .AddJsonValue("iv", + JsonValue.Object() + .Add("en", "ref1_1, 13") + .Add("de", "ref1_1, 13"))) + .AddField("ref2", + new ContentFieldData() + .AddJsonValue("iv", + JsonValue.Object() + .Add("en", "2 Reference(s)") + .Add("de", "2 Reference(s)"))), + enriched.ElementAt(0).ReferenceData); + + Assert.Equal( + new NamedContentData() + .AddField("ref1", + new ContentFieldData() + .AddJsonValue("iv", + JsonValue.Object() + .Add("en", "ref1_2, 17") + .Add("de", "ref1_2, 17"))) + .AddField("ref2", + new ContentFieldData() + .AddJsonValue("iv", + JsonValue.Object() + .Add("en", "2 Reference(s)") + .Add("de", "2 Reference(s)"))), + enriched.ElementAt(1).ReferenceData); + } + + private IEnrichedContentEntity CreateContent(Guid[] ref1, Guid[] ref2) + { + return new ContentEntity + { + DataDraft = + new NamedContentData() + .AddField("ref1", + new ContentFieldData() + .AddJsonValue("iv", JsonValue.Array(ref1.Select(x => x.ToString()).ToArray()))) + .AddField("ref2", + new ContentFieldData() + .AddJsonValue("iv", JsonValue.Array(ref2.Select(x => x.ToString()).ToArray()))), + SchemaId = schemaId + }; + } + + private IEnrichedContentEntity CreateRefContent(Guid id, string name, int number) + { + return new ContentEntity + { + DataDraft = + new NamedContentData() + .AddField("name", + new ContentFieldData() + .AddValue("iv", name)) + .AddField("number", + new ContentFieldData() + .AddValue("iv", number)), + Id = id + }; + } + } +} diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentEnricherTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentEnricherTests.cs index d795ec571..c8227ef60 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentEnricherTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentEnricherTests.cs @@ -89,10 +89,16 @@ namespace Squidex.Domain.Apps.Entities.Contents var source1 = new ContentEntity { Status = Status.Published, SchemaId = schemaId }; var source2 = new ContentEntity { Status = Status.Published, SchemaId = schemaId }; + var source = new IContentEntity[] + { + source1, + source2 + }; + A.CallTo(() => contentWorkflow.GetInfoAsync(source1)) .Returns(new StatusInfo(Status.Published, StatusColors.Published)); - var result = await sut.EnrichAsync(new[] { source1, source2 }, requestContext); + var result = await sut.EnrichAsync(source, requestContext); Assert.Equal(StatusColors.Published, result[0].StatusColor); Assert.Equal(StatusColors.Published, result[1].StatusColor); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs index c68392509..948971ffb 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs @@ -10,7 +10,6 @@ using System.Threading.Tasks; using FakeItEasy; using NodaTime; using Squidex.Domain.Apps.Core; -using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Scripting; @@ -31,13 +30,13 @@ namespace Squidex.Domain.Apps.Entities.Contents { public class ContentGrainTests : HandlerTestBase { - private readonly ISchemaEntity schema = A.Fake(); - private readonly IScriptEngine scriptEngine = A.Fake(); + private readonly Guid contentId = Guid.NewGuid(); + private readonly IAppEntity app; + private readonly IAppProvider appProvider = A.Fake(); private readonly IContentRepository contentRepository = A.Dummy(); private readonly IContentWorkflow contentWorkflow = A.Fake(x => x.Wrapping(new DefaultContentWorkflow())); - private readonly IAppProvider appProvider = A.Fake(); - private readonly IAppEntity appEntity = A.Fake(); - private readonly LanguagesConfig languagesConfig = LanguagesConfig.Build(Language.DE); + private readonly ISchemaEntity schema; + private readonly IScriptEngine scriptEngine = A.Fake(); private readonly NamedContentData invalidData = new NamedContentData() @@ -66,7 +65,6 @@ namespace Squidex.Domain.Apps.Entities.Contents new ContentFieldData() .AddValue("iv", 2)); private readonly NamedContentData patched; - private readonly Guid contentId = Guid.NewGuid(); private readonly ContentGrain sut; protected override Guid Id @@ -76,6 +74,8 @@ namespace Squidex.Domain.Apps.Entities.Contents public ContentGrainTests() { + app = Mocks.App(AppNamedId, Language.DE); + var scripts = new SchemaScripts { Change = "", @@ -92,12 +92,13 @@ namespace Squidex.Domain.Apps.Entities.Contents new NumberFieldProperties { IsRequired = false }) .ConfigureScripts(scripts); - A.CallTo(() => appEntity.LanguagesConfig).Returns(languagesConfig); + schema = Mocks.Schema(AppNamedId, SchemaNamedId, schemaDef); - A.CallTo(() => appProvider.GetAppAsync(AppName)).Returns(appEntity); - A.CallTo(() => appProvider.GetAppWithSchemaAsync(AppId, SchemaId)).Returns((appEntity, schema)); + A.CallTo(() => appProvider.GetAppAsync(AppName)) + .Returns(app); - A.CallTo(() => schema.SchemaDef).Returns(schemaDef); + A.CallTo(() => appProvider.GetAppWithSchemaAsync(AppId, SchemaId)) + .Returns((app, schema)); A.CallTo(() => scriptEngine.ExecuteAndTransform(A.Ignored, A.Ignored)) .ReturnsLazily(x => x.GetArgument(0).Data); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs index 9c917e4b4..6e4625ccf 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs @@ -13,7 +13,6 @@ using System.Threading.Tasks; using FakeItEasy; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; -using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.ConvertContent; using Squidex.Domain.Apps.Core.Schemas; @@ -37,14 +36,14 @@ namespace Squidex.Domain.Apps.Entities.Contents { public class ContentQueryServiceTests { + private readonly IAppEntity app; + private readonly IAppProvider appProvider = A.Fake(); + private readonly IAssetUrlGenerator urlGenerator = A.Fake(); private readonly IContentEnricher contentEnricher = A.Fake(); private readonly IContentRepository contentRepository = A.Fake(); private readonly IContentVersionLoader contentVersionLoader = A.Fake(); + private readonly ISchemaEntity schema; private readonly IScriptEngine scriptEngine = A.Fake(); - private readonly ISchemaEntity schema = A.Fake(); - private readonly IAppEntity app = A.Fake(); - private readonly IAppProvider appProvider = A.Fake(); - private readonly IAssetUrlGenerator urlGenerator = A.Fake(); private readonly Guid contentId = Guid.NewGuid(); private readonly NamedId appId = NamedId.Of(Guid.NewGuid(), "my-app"); private readonly NamedId schemaId = NamedId.Of(Guid.NewGuid(), "my-schema"); @@ -53,7 +52,7 @@ namespace Squidex.Domain.Apps.Entities.Contents private readonly ClaimsPrincipal user; private readonly ClaimsIdentity identity = new ClaimsIdentity(); private readonly EdmModelBuilder modelBuilder = new EdmModelBuilder(new MemoryCache(Options.Create(new MemoryCacheOptions()))); - private readonly Context context; + private readonly Context requestContext; private readonly ContentQueryService sut; public static IEnumerable ApiStatusTests = new[] @@ -66,22 +65,18 @@ namespace Squidex.Domain.Apps.Entities.Contents { user = new ClaimsPrincipal(identity); - A.CallTo(() => app.Id).Returns(appId.Id); - A.CallTo(() => app.Name).Returns(appId.Name); - A.CallTo(() => app.LanguagesConfig).Returns(LanguagesConfig.English); + app = Mocks.App(appId); + + requestContext = new Context(user, app); var schemaDef = new Schema(schemaId.Name) .ConfigureScripts(new SchemaScripts { Query = "" }); - A.CallTo(() => schema.Id).Returns(schemaId.Id); - A.CallTo(() => schema.AppId).Returns(appId); - A.CallTo(() => schema.SchemaDef).Returns(schemaDef); + schema = Mocks.Schema(appId, schemaId, schemaDef); SetupEnricher(); - context = new Context(user, app); - var options = Options.Create(new ContentOptions { DefaultPageSize = 30 }); sut = new ContentQueryService( @@ -108,7 +103,7 @@ namespace Squidex.Domain.Apps.Entities.Contents { SetupSchemaFound(); - var result = await sut.GetSchemaOrThrowAsync(context, schemaId.Name); + var result = await sut.GetSchemaOrThrowAsync(requestContext, schemaId.Id.ToString()); Assert.Equal(schema, result); } @@ -118,7 +113,7 @@ namespace Squidex.Domain.Apps.Entities.Contents { SetupSchemaFound(); - var result = await sut.GetSchemaOrThrowAsync(context, schemaId.Name); + var result = await sut.GetSchemaOrThrowAsync(requestContext, schemaId.Name); Assert.Equal(schema, result); } @@ -128,7 +123,7 @@ namespace Squidex.Domain.Apps.Entities.Contents { SetupSchemaNotFound(); - var ctx = context; + var ctx = requestContext; await Assert.ThrowsAsync(() => sut.GetSchemaOrThrowAsync(ctx, schemaId.Name)); } @@ -138,7 +133,7 @@ namespace Squidex.Domain.Apps.Entities.Contents { SetupSchemaNotFound(); - var ctx = context; + var ctx = requestContext; await Assert.ThrowsAsync(() => sut.GetSchemaOrThrowAsync(ctx, schemaId.Name)); } @@ -146,14 +141,15 @@ namespace Squidex.Domain.Apps.Entities.Contents [Fact] public async Task Should_apply_default_page_size() { - SetupClaims(isFrontend: false); + SetupUser(isFrontend: false); SetupSchemaFound(); var query = Q.Empty; - await sut.QueryAsync(context, schemaId.Name, query); + await sut.QueryAsync(requestContext, schemaId.Name, query); - A.CallTo(() => contentRepository.QueryAsync(app, schema, A.That.Is(Status.Published), false, A.That.Is("Take: 30; Sort: lastModified Descending"), false)) + A.CallTo(() => contentRepository.QueryAsync(app, schema, A.That.Is(Status.Published), false, + A.That.Is("Take: 30; Sort: lastModified Descending"), false)) .MustHaveHappened(); } @@ -162,24 +158,25 @@ namespace Squidex.Domain.Apps.Entities.Contents { var status = new[] { Status.Published }; - SetupClaims(isFrontend: false); + SetupUser(isFrontend: false); SetupSchemaFound(); var query = Q.Empty.WithODataQuery("$top=300&$skip=20"); - await sut.QueryAsync(context, schemaId.Name, query); + await sut.QueryAsync(requestContext, schemaId.Name, query); - A.CallTo(() => contentRepository.QueryAsync(app, schema, A.That.Is(status), false, A.That.Is("Skip: 20; Take: 200; Sort: lastModified Descending"), false)) + A.CallTo(() => contentRepository.QueryAsync(app, schema, A.That.Is(status), false, + A.That.Is("Skip: 20; Take: 200; Sort: lastModified Descending"), false)) .MustHaveHappened(); } [Fact] public async Task Should_throw_for_single_content_if_no_permission() { - SetupClaims(false, false); + SetupUser(false, false); SetupSchemaFound(); - var ctx = context; + var ctx = requestContext; await Assert.ThrowsAsync(() => sut.FindContentAsync(ctx, schemaId.Name, contentId)); } @@ -189,11 +186,11 @@ namespace Squidex.Domain.Apps.Entities.Contents { var status = new[] { Status.Published }; - SetupClaims(isFrontend: false); + SetupUser(isFrontend: false); SetupSchemaFound(); SetupContent(status, null, includeDraft: false); - var ctx = context; + var ctx = requestContext; await Assert.ThrowsAsync(async () => await sut.FindContentAsync(ctx, schemaId.Name, contentId)); } @@ -203,12 +200,12 @@ namespace Squidex.Domain.Apps.Entities.Contents { var content = CreateContent(contentId); - SetupClaims(isFrontend: true); + SetupUser(isFrontend: true); SetupSchemaFound(); - SetupScripting(contentId); + SetupSchemaScripting(contentId); SetupContent(null, content, includeDraft: true); - var ctx = context; + var ctx = requestContext; var result = await sut.FindContentAsync(ctx, schemaId.Name, contentId); @@ -225,12 +222,12 @@ namespace Squidex.Domain.Apps.Entities.Contents { var content = CreateContent(contentId); - SetupClaims(isFrontend: false); + SetupUser(isFrontend: false); SetupSchemaFound(); - SetupScripting(contentId); + SetupSchemaScripting(contentId); SetupContent(status, content, unpublished == 1); - var ctx = context.WithUnpublished(unpublished == 1); + var ctx = requestContext.WithUnpublished(unpublished == 1); var result = await sut.FindContentAsync(ctx, schemaId.Name, contentId); @@ -246,14 +243,14 @@ namespace Squidex.Domain.Apps.Entities.Contents { var content = CreateContent(contentId); - SetupClaims(true); + SetupUser(true); SetupSchemaFound(); - SetupScripting(contentId); + SetupSchemaScripting(contentId); A.CallTo(() => contentVersionLoader.LoadAsync(contentId, 10)) .Returns(content); - var ctx = context; + var ctx = requestContext; var result = await sut.FindContentAsync(ctx, schemaId.Name, contentId, 10); @@ -264,10 +261,10 @@ namespace Squidex.Domain.Apps.Entities.Contents [Fact] public async Task Should_throw_for_query_if_no_permission() { - SetupClaims(false, false); + SetupUser(false, false); SetupSchemaFound(); - var ctx = context; + var ctx = requestContext; await Assert.ThrowsAsync(() => sut.QueryAsync(ctx, schemaId.Name, Q.Empty)); } @@ -279,12 +276,12 @@ namespace Squidex.Domain.Apps.Entities.Contents var content = CreateContent(contentId); - SetupClaims(isFrontend: true); + SetupUser(isFrontend: true); SetupSchemaFound(); - SetupScripting(contentId); + SetupSchemaScripting(contentId); SetupContents(null, count, total, content, inDraft: true, includeDraft: true); - var ctx = context; + var ctx = requestContext; var result = await sut.QueryAsync(ctx, schemaId.Name, Q.Empty); @@ -305,12 +302,12 @@ namespace Squidex.Domain.Apps.Entities.Contents var content = CreateContent(contentId); - SetupClaims(isFrontend: false); + SetupUser(isFrontend: false); SetupSchemaFound(); - SetupScripting(contentId); + SetupSchemaScripting(contentId); SetupContents(status, count, total, content, inDraft: false, unpublished == 1); - var ctx = context.WithUnpublished(unpublished == 1); + var ctx = requestContext.WithUnpublished(unpublished == 1); var result = await sut.QueryAsync(ctx, schemaId.Name, Q.Empty); @@ -326,12 +323,12 @@ namespace Squidex.Domain.Apps.Entities.Contents [Fact] public async Task Should_throw_if_query_is_invalid() { - SetupClaims(isFrontend: false); + SetupUser(isFrontend: false); SetupSchemaFound(); var query = Q.Empty.WithODataQuery("$filter=invalid"); - await Assert.ThrowsAsync(() => sut.QueryAsync(context, schemaId.Name, query)); + await Assert.ThrowsAsync(() => sut.QueryAsync(requestContext, schemaId.Name, query)); } [Fact] @@ -341,12 +338,12 @@ namespace Squidex.Domain.Apps.Entities.Contents var ids = Enumerable.Range(0, count).Select(x => Guid.NewGuid()).ToList(); - SetupClaims(isFrontend: true); + SetupUser(isFrontend: true); SetupSchemaFound(); - SetupScripting(ids.ToArray()); + SetupSchemaScripting(ids.ToArray()); SetupContents(null, total, ids, includeDraft: true); - var ctx = context; + var ctx = requestContext; var result = await sut.QueryAsync(ctx, schemaId.Name, Q.Empty.WithIds(ids)); @@ -365,12 +362,12 @@ namespace Squidex.Domain.Apps.Entities.Contents var ids = Enumerable.Range(0, count).Select(x => Guid.NewGuid()).ToList(); - SetupClaims(isFrontend: false); + SetupUser(isFrontend: false); SetupSchemaFound(); - SetupScripting(ids.ToArray()); + SetupSchemaScripting(ids.ToArray()); SetupContents(status, total, ids, unpublished == 1); - var ctx = context.WithUnpublished(unpublished == 1); + var ctx = requestContext.WithUnpublished(unpublished == 1); var result = await sut.QueryAsync(ctx, schemaId.Name, Q.Empty.WithIds(ids)); @@ -388,12 +385,12 @@ namespace Squidex.Domain.Apps.Entities.Contents var ids = Enumerable.Range(0, count).Select(x => Guid.NewGuid()).ToList(); - SetupClaims(isFrontend: true); + SetupUser(isFrontend: true); SetupSchemaFound(); - SetupScripting(ids.ToArray()); + SetupSchemaScripting(ids.ToArray()); SetupContents(null, ids, includeDraft: true); - var ctx = context; + var ctx = requestContext; var result = await sut.QueryAsync(ctx, ids); @@ -411,12 +408,12 @@ namespace Squidex.Domain.Apps.Entities.Contents var ids = Enumerable.Range(0, count).Select(x => Guid.NewGuid()).ToList(); - SetupClaims(isFrontend: false); + SetupUser(isFrontend: false); SetupSchemaFound(); - SetupScripting(ids.ToArray()); + SetupSchemaScripting(ids.ToArray()); SetupContents(status, ids, unpublished == 1); - var ctx = context.WithUnpublished(unpublished == 1); + var ctx = requestContext.WithUnpublished(unpublished == 1); var result = await sut.QueryAsync(ctx, ids); @@ -431,12 +428,12 @@ namespace Squidex.Domain.Apps.Entities.Contents { var ids = Enumerable.Range(0, 1).Select(x => Guid.NewGuid()).ToList(); - SetupClaims(isFrontend: false, allowSchema: false); + SetupUser(isFrontend: false, allowSchema: false); SetupSchemaFound(); - SetupScripting(ids.ToArray()); + SetupSchemaScripting(ids.ToArray()); SetupContents(new Status[0], ids, includeDraft: false); - var ctx = context; + var ctx = requestContext; var result = await sut.QueryAsync(ctx, ids); @@ -448,10 +445,10 @@ namespace Squidex.Domain.Apps.Entities.Contents { var ids = new List(); - SetupClaims(isFrontend: false, allowSchema: false); + SetupUser(isFrontend: false, allowSchema: false); SetupSchemaFound(); - var ctx = context; + var ctx = requestContext; var result = await sut.QueryAsync(ctx, ids); @@ -461,7 +458,7 @@ namespace Squidex.Domain.Apps.Entities.Contents .MustNotHaveHappened(); } - private void SetupClaims(bool isFrontend, bool allowSchema = true) + private void SetupUser(bool isFrontend, bool allowSchema = true) { if (isFrontend) { @@ -474,7 +471,7 @@ namespace Squidex.Domain.Apps.Entities.Contents } } - private void SetupScripting(params Guid[] ids) + private void SetupSchemaScripting(params Guid[] ids) { foreach (var id in ids) { @@ -527,7 +524,7 @@ namespace Squidex.Domain.Apps.Entities.Contents private void SetupEnricher() { - A.CallTo(() => contentEnricher.EnrichAsync(A>.Ignored, context)) + A.CallTo(() => contentEnricher.EnrichAsync(A>.Ignored, requestContext)) .ReturnsLazily(x => { var input = (IEnumerable)x.Arguments[0]; diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultWorkflowsValidatorTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultWorkflowsValidatorTests.cs index 9a887a73b..a662ce977 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultWorkflowsValidatorTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultWorkflowsValidatorTests.cs @@ -12,6 +12,7 @@ using FakeItEasy; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Entities.Schemas; +using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Infrastructure; using Xunit; @@ -26,10 +27,7 @@ namespace Squidex.Domain.Apps.Entities.Contents public DefaultWorkflowsValidatorTests() { - var schema = A.Fake(); - - A.CallTo(() => schema.Id).Returns(schemaId.Id); - A.CallTo(() => schema.SchemaDef).Returns(new Schema(schemaId.Name)); + var schema = Mocks.Schema(appId, schemaId, new Schema(schemaId.Name)); A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, A.Ignored, false)) .Returns(Task.FromResult(null)); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DynamicContentWorkflowTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DynamicContentWorkflowTests.cs index 911c756ec..5759c297e 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DynamicContentWorkflowTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DynamicContentWorkflowTests.cs @@ -7,14 +7,13 @@ using System; using System.Collections.Generic; -using System.Security.Claims; using System.Threading.Tasks; using FakeItEasy; using FluentAssertions; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Scripting; using Squidex.Domain.Apps.Entities.Apps; -using Squidex.Domain.Apps.Entities.Schemas; +using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Infrastructure; using Xunit; @@ -22,11 +21,11 @@ namespace Squidex.Domain.Apps.Entities.Contents { public class DynamicContentWorkflowTests { + private readonly IAppEntity app; + private readonly IAppProvider appProvider = A.Fake(); private readonly NamedId appId = NamedId.Of(Guid.NewGuid(), "my-app"); private readonly NamedId schemaId = NamedId.Of(Guid.NewGuid(), "my-schema"); private readonly NamedId simpleSchemaId = NamedId.Of(Guid.NewGuid(), "my-simple-schema"); - private readonly IAppProvider appProvider = A.Fake(); - private readonly IAppEntity appEntity = A.Fake(); private readonly DynamicContentWorkflow sut; private readonly Workflow workflow = new Workflow( @@ -62,6 +61,8 @@ namespace Squidex.Domain.Apps.Entities.Contents public DynamicContentWorkflowTests() { + app = Mocks.App(appId); + simpleWorkflow = new Workflow( Status.Draft, new Dictionary @@ -86,9 +87,9 @@ namespace Squidex.Domain.Apps.Entities.Contents var workflows = Workflows.Empty.Set(workflow).Set(Guid.NewGuid(), simpleWorkflow); A.CallTo(() => appProvider.GetAppAsync(appId.Id)) - .Returns(appEntity); + .Returns(app); - A.CallTo(() => appEntity.Workflows) + A.CallTo(() => app.Workflows) .Returns(workflows); sut = new DynamicContentWorkflow(new JintScriptEngine(), appProvider); @@ -99,7 +100,7 @@ namespace Squidex.Domain.Apps.Entities.Contents { var expected = new StatusInfo(Status.Draft, StatusColors.Draft); - var result = await sut.GetInitialStatusAsync(CreateSchema()); + var result = await sut.GetInitialStatusAsync(Mocks.Schema(appId, schemaId)); result.Should().BeEquivalentTo(expected); } @@ -109,7 +110,7 @@ namespace Squidex.Domain.Apps.Entities.Contents { var content = CreateContent(Status.Draft, 2); - var result = await sut.CanPublishOnCreateAsync(CreateSchema(), content.DataDraft, User("Editor")); + var result = await sut.CanPublishOnCreateAsync(Mocks.Schema(appId, schemaId), content.DataDraft, Mocks.FrontendUser("Editor")); Assert.True(result); } @@ -119,7 +120,7 @@ namespace Squidex.Domain.Apps.Entities.Contents { var content = CreateContent(Status.Draft, 4); - var result = await sut.CanPublishOnCreateAsync(CreateSchema(), content.DataDraft, User("Editor")); + var result = await sut.CanPublishOnCreateAsync(Mocks.Schema(appId, schemaId), content.DataDraft, Mocks.FrontendUser("Editor")); Assert.False(result); } @@ -129,7 +130,7 @@ namespace Squidex.Domain.Apps.Entities.Contents { var content = CreateContent(Status.Draft, 2); - var result = await sut.CanPublishOnCreateAsync(CreateSchema(), content.DataDraft, User("Developer")); + var result = await sut.CanPublishOnCreateAsync(Mocks.Schema(appId, schemaId), content.DataDraft, Mocks.FrontendUser("Developer")); Assert.False(result); } @@ -139,7 +140,7 @@ namespace Squidex.Domain.Apps.Entities.Contents { var content = CreateContent(Status.Draft, 2); - var result = await sut.CanMoveToAsync(content, Status.Published, User("Editor")); + var result = await sut.CanMoveToAsync(content, Status.Published, Mocks.FrontendUser("Editor")); Assert.True(result); } @@ -149,7 +150,7 @@ namespace Squidex.Domain.Apps.Entities.Contents { var content = CreateContent(Status.Draft, 2); - var result = await sut.CanMoveToAsync(content, Status.Published, User("Developer")); + var result = await sut.CanMoveToAsync(content, Status.Published, Mocks.FrontendUser("Developer")); Assert.False(result); } @@ -159,7 +160,7 @@ namespace Squidex.Domain.Apps.Entities.Contents { var content = CreateContent(Status.Draft, 4); - var result = await sut.CanMoveToAsync(content, Status.Published, User("Editor")); + var result = await sut.CanMoveToAsync(content, Status.Published, Mocks.FrontendUser("Editor")); Assert.False(result); } @@ -204,7 +205,7 @@ namespace Squidex.Domain.Apps.Entities.Contents new StatusInfo(Status.Archived, StatusColors.Archived) }; - var result = await sut.GetNextsAsync(content, User("Developer")); + var result = await sut.GetNextsAsync(content, Mocks.FrontendUser("Developer")); result.Should().BeEquivalentTo(expected); } @@ -219,7 +220,7 @@ namespace Squidex.Domain.Apps.Entities.Contents new StatusInfo(Status.Archived, StatusColors.Archived) }; - var result = await sut.GetNextsAsync(content, User("Editor")); + var result = await sut.GetNextsAsync(content, Mocks.FrontendUser("Editor")); result.Should().BeEquivalentTo(expected); } @@ -235,7 +236,7 @@ namespace Squidex.Domain.Apps.Entities.Contents new StatusInfo(Status.Published, StatusColors.Published) }; - var result = await sut.GetNextsAsync(content, User("Editor")); + var result = await sut.GetNextsAsync(content, Mocks.FrontendUser("Editor")); result.Should().BeEquivalentTo(expected); } @@ -281,7 +282,7 @@ namespace Squidex.Domain.Apps.Entities.Contents new StatusInfo(Status.Published, StatusColors.Published) }; - var result = await sut.GetAllAsync(CreateSchema()); + var result = await sut.GetAllAsync(Mocks.Schema(appId, schemaId)); result.Should().BeEquivalentTo(expected); } @@ -295,7 +296,7 @@ namespace Squidex.Domain.Apps.Entities.Contents new StatusInfo(Status.Published, StatusColors.Published) }; - var result = await sut.GetAllAsync(CreateSchema(true)); + var result = await sut.GetAllAsync(Mocks.Schema(appId, simpleSchemaId)); result.Should().BeEquivalentTo(expected); } @@ -303,7 +304,7 @@ namespace Squidex.Domain.Apps.Entities.Contents [Fact] public async Task Should_return_all_statuses_for_default_workflow_when_no_workflow_configured() { - A.CallTo(() => appEntity.Workflows).Returns(Workflows.Empty); + A.CallTo(() => app.Workflows).Returns(Workflows.Empty); var expected = new[] { @@ -312,21 +313,11 @@ namespace Squidex.Domain.Apps.Entities.Contents new StatusInfo(Status.Published, StatusColors.Published) }; - var result = await sut.GetAllAsync(CreateSchema(true)); + var result = await sut.GetAllAsync(Mocks.Schema(appId, simpleSchemaId)); result.Should().BeEquivalentTo(expected); } - private ISchemaEntity CreateSchema(bool simple = false) - { - var schema = A.Fake(); - - A.CallTo(() => schema.AppId).Returns(appId); - A.CallTo(() => schema.Id).Returns(simple ? simpleSchemaId.Id : schemaId.Id); - - return schema; - } - private IContentEntity CreateContent(Status status, int value, bool simple = false) { var content = new ContentEntity { AppId = appId, Status = status }; @@ -348,15 +339,5 @@ namespace Squidex.Domain.Apps.Entities.Contents return content; } - - private ClaimsPrincipal User(string role) - { - var userIdentity = new ClaimsIdentity(); - var userPrincipal = new ClaimsPrincipal(userIdentity); - - userIdentity.AddClaim(new Claim(ClaimTypes.Role, role)); - - return userPrincipal; - } } } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs index f07d13263..22d12e6db 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs @@ -22,7 +22,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL [InlineData(" ")] public async Task Should_return_empty_object_for_empty_query(string query) { - var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); + var result = await sut.QueryAsync(requestContext, new GraphQLQuery { Query = query }); var expected = new { @@ -67,7 +67,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), A.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5&$filter=my-query"))) .Returns(ResultList.CreateFrom(0, asset)); - var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); + var result = await sut.QueryAsync(requestContext, new GraphQLQuery { Query = query }); var expected = new { @@ -140,7 +140,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), A.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5&$filter=my-query"))) .Returns(ResultList.CreateFrom(10, asset)); - var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); + var result = await sut.QueryAsync(requestContext, new GraphQLQuery { Query = query }); var expected = new { @@ -215,7 +215,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), MatchId(assetId))) .Returns(ResultList.CreateFrom(1, asset)); - var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); + var result = await sut.QueryAsync(requestContext, new GraphQLQuery { Query = query }); var expected = new { @@ -301,10 +301,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL var content = CreateContent(Guid.NewGuid(), Guid.Empty, Guid.Empty); - A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), A.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5"))) + A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.Id.ToString(), A.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5"))) .Returns(ResultList.CreateFrom(0, content)); - var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); + var result = await sut.QueryAsync(requestContext, new GraphQLQuery { Query = query }); var expected = new { @@ -442,10 +442,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL var content = CreateContent(Guid.NewGuid(), Guid.Empty, Guid.Empty); - A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), A.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5"))) + A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.Id.ToString(), A.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5"))) .Returns(ResultList.CreateFrom(10, content)); - var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); + var result = await sut.QueryAsync(requestContext, new GraphQLQuery { Query = query }); var expected = new { @@ -548,10 +548,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL } }".Replace("", contentId.ToString()); - A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), MatchId(contentId))) + A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.Id.ToString(), MatchId(contentId))) .Returns(ResultList.CreateFrom(1, content)); - var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); + var result = await sut.QueryAsync(requestContext, new GraphQLQuery { Query = query }); var expected = new { @@ -640,10 +640,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL } }".Replace("", contentId.ToString()); - A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), MatchId(contentId))) + A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.Id.ToString(), MatchId(contentId))) .Returns(ResultList.CreateFrom(1, content)); - var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); + var result = await sut.QueryAsync(requestContext, new GraphQLQuery { Query = query }); var expected = new { @@ -736,13 +736,13 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL } }".Replace("", contentId.ToString()); - A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), A.Ignored)) + A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.Id.ToString(), A.Ignored)) .Returns(ResultList.CreateFrom(0, contentRef)); - A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), MatchId(contentId))) + A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.Id.ToString(), MatchId(contentId))) .Returns(ResultList.CreateFrom(1, content)); - var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); + var result = await sut.QueryAsync(requestContext, new GraphQLQuery { Query = query }); var expected = new { @@ -794,13 +794,13 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL } }".Replace("", contentId.ToString()); - A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), MatchId(contentId))) + A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.Id.ToString(), MatchId(contentId))) .Returns(ResultList.CreateFrom(1, content)); A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), A.Ignored)) .Returns(ResultList.CreateFrom(0, assetRef)); - var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); + var result = await sut.QueryAsync(requestContext, new GraphQLQuery { Query = query }); var expected = new { @@ -856,7 +856,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), MatchId(assetId2))) .Returns(ResultList.CreateFrom(0, asset2)); - var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query1 }, new GraphQLQuery { Query = query2 }); + var result = await sut.QueryAsync(requestContext, new GraphQLQuery { Query = query1 }, new GraphQLQuery { Query = query2 }); var expected = new object[] { @@ -909,10 +909,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL } }".Replace("", contentId.ToString()); - A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), MatchId(contentId))) + A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.Id.ToString(), MatchId(contentId))) .Returns(ResultList.CreateFrom(1, content)); - var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); + var result = await sut.QueryAsync(requestContext, new GraphQLQuery { Query = query }); var json = serializer.Serialize(result); @@ -947,10 +947,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL } }".Replace("", contentId.ToString()); - A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), MatchId(contentId))) + A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.Id.ToString(), MatchId(contentId))) .Returns(ResultList.CreateFrom(1, content)); - var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); + var result = await sut.QueryAsync(requestContext, new GraphQLQuery { Query = query }); var expected = new { @@ -993,10 +993,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL } }".Replace("", contentId.ToString()); - A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), MatchId(contentId))) + A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.Id.ToString(), MatchId(contentId))) .Returns(ResultList.CreateFrom(1, content)); - var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); + var result = await sut.QueryAsync(requestContext, new GraphQLQuery { Query = query }); var expected = new { @@ -1019,12 +1019,12 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL private Context MatchsAssetContext() { - return A.That.Matches(x => x.App == app && x.User == user); + return A.That.Matches(x => x.App == app && x.User == requestContext.User); } private Context MatchsContentContext() { - return A.That.Matches(x => x.App == app && x.User == user); + return A.That.Matches(x => x.App == app && x.User == requestContext.User); } } } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs index d14332136..3817ba7ec 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Generic; -using System.Security.Claims; using FakeItEasy; using GraphQL; using GraphQL.DataLoader; @@ -16,13 +15,13 @@ using Microsoft.Extensions.Options; using Newtonsoft.Json; using NodaTime; using Squidex.Domain.Apps.Core; -using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Assets; using Squidex.Domain.Apps.Entities.Contents.TestData; using Squidex.Domain.Apps.Entities.Schemas; +using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Infrastructure; using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Json.Objects; @@ -36,21 +35,21 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL { public class GraphQLTestBase { - protected readonly Guid schemaId = Guid.NewGuid(); - protected readonly Guid appId = Guid.NewGuid(); - protected readonly string appName = "my-app"; - protected readonly IContentQueryService contentQuery = A.Fake(); + protected readonly IAppEntity app; protected readonly IAssetQueryService assetQuery = A.Fake(); - protected readonly ISchemaEntity schema = A.Fake(); - protected readonly IJsonSerializer serializer = TestUtils.CreateSerializer(TypeNameHandling.None); + protected readonly IContentQueryService contentQuery = A.Fake(); protected readonly IDependencyResolver dependencyResolver; - protected readonly IAppEntity app = A.Dummy(); - protected readonly Context context; - protected readonly ClaimsPrincipal user = new ClaimsPrincipal(); + protected readonly IJsonSerializer serializer = TestUtils.CreateSerializer(TypeNameHandling.None); + protected readonly ISchemaEntity schema; + protected readonly Context requestContext; + protected readonly NamedId appId = NamedId.Of(Guid.NewGuid(), "my-app"); + protected readonly NamedId schemaId = NamedId.Of(Guid.NewGuid(), "my-schema"); protected readonly IGraphQLService sut; public GraphQLTestBase() { + app = Mocks.App(appId, Language.DE, Language.GermanGermany); + var schemaDef = new Schema("my-schema") .AddJson(1, "my-json", Partitioning.Invariant, @@ -68,7 +67,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL .AddDateTime(7, "my-datetime", Partitioning.Invariant, new DateTimeFieldProperties()) .AddReferences(8, "my-references", Partitioning.Invariant, - new ReferencesFieldProperties { SchemaId = schemaId }) + new ReferencesFieldProperties { SchemaId = schemaId.Id }) .AddReferences(9, "my-invalid", Partitioning.Invariant, new ReferencesFieldProperties { SchemaId = Guid.NewGuid() }) .AddGeolocation(10, "my-geolocation", Partitioning.Invariant, @@ -84,14 +83,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL .ConfigureScripts(new SchemaScripts { Query = "" }) .Publish(); - A.CallTo(() => app.Id).Returns(appId); - A.CallTo(() => app.Name).Returns(appName); - A.CallTo(() => app.LanguagesConfig).Returns(LanguagesConfig.Build(Language.DE, Language.GermanGermany)); - - context = new Context(user, app); + schema = Mocks.Schema(appId, schemaId, schemaDef); - A.CallTo(() => schema.Id).Returns(schemaId); - A.CallTo(() => schema.SchemaDef).Returns(schemaDef); + requestContext = new Context(Mocks.FrontendUser(), app); sut = CreateSut(); } @@ -213,7 +207,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL { var appProvider = A.Fake(); - A.CallTo(() => appProvider.GetSchemasAsync(appId)) + A.CallTo(() => appProvider.GetSchemasAsync(appId.Id)) .Returns(new List { schema }); var dataLoaderContext = new DataLoaderContextAccessor(); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Guard/GuardContentTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Guard/GuardContentTests.cs index 8f69ae486..e48fb576f 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Guard/GuardContentTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Guard/GuardContentTests.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System; using System.Security.Claims; using System.Threading.Tasks; using FakeItEasy; @@ -22,19 +23,16 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard { public class GuardContentTests { - private readonly ISchemaEntity schema = A.Fake(); private readonly IContentWorkflow contentWorkflow = A.Fake(); - private readonly ClaimsPrincipal user = new ClaimsPrincipal(); + private readonly NamedId appId = NamedId.Of(Guid.NewGuid(), "my-app"); + private readonly ClaimsPrincipal user = Mocks.FrontendUser(); private readonly Instant dueTimeInPast = SystemClock.Instance.GetCurrentInstant().Minus(Duration.FromHours(1)); - public GuardContentTests() - { - SetupSingleton(false); - } - [Fact] public async Task CanCreate_should_throw_exception_if_data_is_null() { + var schema = CreateSchema(false); + var command = new CreateContent(); await ValidationAssert.ThrowsAsync(() => GuardContent.CanCreate(schema, contentWorkflow, command), @@ -44,7 +42,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard [Fact] public async Task CanCreate_should_throw_exception_if_singleton() { - SetupSingleton(true); + var schema = CreateSchema(true); var command = new CreateContent { Data = new NamedContentData() }; @@ -54,7 +52,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard [Fact] public async Task CanCreate_should_not_throw_exception_if_singleton_and_id_is_schema_id() { - SetupSingleton(true); + var schema = CreateSchema(true); var command = new CreateContent { Data = new NamedContentData(), ContentId = schema.Id }; @@ -64,7 +62,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard [Fact] public async Task CanCreate_should_throw_exception_publish_not_allowed() { - SetupCanCreatePublish(false); + var schema = CreateSchema(false); + + SetupCanCreatePublish(schema, false); var command = new CreateContent { Data = new NamedContentData(), Publish = true }; @@ -74,7 +74,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard [Fact] public async Task CanCreate_should_not_throw_exception_publishing_allowed() { - SetupCanCreatePublish(true); + var schema = CreateSchema(false); + + SetupCanCreatePublish(schema, true); var command = new CreateContent { Data = new NamedContentData(), Publish = true }; @@ -84,6 +86,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard [Fact] public async Task CanCreate_should_not_throw_exception_if_data_is_not_null() { + var schema = CreateSchema(false); + var command = new CreateContent { Data = new NamedContentData() }; await GuardContent.CanCreate(schema, contentWorkflow, command); @@ -92,6 +96,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard [Fact] public async Task CanUpdate_should_throw_exception_if_data_is_null() { + var schema = CreateSchema(false); + SetupCanUpdate(true); var content = CreateContent(Status.Draft, false); @@ -104,6 +110,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard [Fact] public async Task CanUpdate_should_throw_exception_if_workflow_blocks_it() { + var schema = CreateSchema(false); + SetupCanUpdate(false); var content = CreateContent(Status.Draft, false); @@ -126,6 +134,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard [Fact] public async Task CanPatch_should_throw_exception_if_data_is_null() { + var schema = CreateSchema(false); + SetupCanUpdate(true); var content = CreateContent(Status.Draft, false); @@ -138,6 +148,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard [Fact] public async Task CanPatch_should_throw_exception_if_workflow_blocks_it() { + var schema = CreateSchema(false); + SetupCanUpdate(false); var content = CreateContent(Status.Draft, false); @@ -160,6 +172,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard [Fact] public async Task CanChangeStatus_should_throw_exception_if_publishing_without_pending_changes() { + var schema = CreateSchema(false); + var content = CreateContent(Status.Published, false); var command = new ChangeContentStatus { Status = Status.Published }; @@ -170,7 +184,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard [Fact] public async Task CanChangeStatus_should_throw_exception_if_singleton() { - SetupSingleton(true); + var schema = CreateSchema(true); var content = CreateContent(Status.Published, false); var command = new ChangeContentStatus { Status = Status.Draft }; @@ -181,7 +195,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard [Fact] public async Task CanChangeStatus_should_not_throw_exception_if_publishing_with_pending_changes() { - SetupSingleton(true); + var schema = CreateSchema(true); var content = CreateContent(Status.Published, true); var command = new ChangeContentStatus { Status = Status.Published }; @@ -192,6 +206,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard [Fact] public async Task CanChangeStatus_should_throw_exception_if_due_date_in_past() { + var schema = CreateSchema(false); + var content = CreateContent(Status.Draft, false); var command = new ChangeContentStatus { Status = Status.Published, DueTime = dueTimeInPast, User = user }; @@ -205,6 +221,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard [Fact] public async Task CanChangeStatus_should_throw_exception_if_status_flow_not_valid() { + var schema = CreateSchema(false); + var content = CreateContent(Status.Draft, false); var command = new ChangeContentStatus { Status = Status.Published, User = user }; @@ -218,6 +236,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard [Fact] public async Task CanChangeStatus_should_not_throw_exception_if_status_flow_valid() { + var schema = CreateSchema(false); + var content = CreateContent(Status.Draft, false); var command = new ChangeContentStatus { Status = Status.Published, User = user }; @@ -246,7 +266,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard [Fact] public void CanDelete_should_throw_exception_if_singleton() { - SetupSingleton(true); + var schema = CreateSchema(true); var command = new DeleteContent(); @@ -256,6 +276,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard [Fact] public void CanDelete_should_not_throw_exception() { + var schema = CreateSchema(false); + var command = new DeleteContent(); GuardContent.CanDelete(schema, command); @@ -267,16 +289,15 @@ namespace Squidex.Domain.Apps.Entities.Contents.Guard .Returns(canUpdate); } - private void SetupCanCreatePublish(bool canCreate) + private void SetupCanCreatePublish(ISchemaEntity schema, bool canCreate) { A.CallTo(() => contentWorkflow.CanPublishOnCreateAsync(schema, A.Ignored, user)) .Returns(canCreate); } - private void SetupSingleton(bool isSingleton) + private ISchemaEntity CreateSchema(bool isSingleton) { - A.CallTo(() => schema.SchemaDef) - .Returns(new Schema("schema", isSingleton: isSingleton)); + return Mocks.Schema(appId, NamedId.Of(Guid.NewGuid(), "my-schema"), new Schema("schema", isSingleton: isSingleton)); } private IContentEntity CreateContent(Status status, bool isPending) diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/FilterTagTransformerTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/FilterTagTransformerTests.cs index b34a10c33..4d8d0201e 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/FilterTagTransformerTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/FilterTagTransformerTests.cs @@ -12,6 +12,8 @@ using Squidex.Domain.Apps.Core; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Tags; using Squidex.Domain.Apps.Entities.Schemas; +using Squidex.Domain.Apps.Entities.TestHelpers; +using Squidex.Infrastructure; using Squidex.Infrastructure.Queries; using Xunit; @@ -20,9 +22,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries public class FilterTagTransformerTests { private readonly ITagService tagService = A.Fake(); - private readonly ISchemaEntity schema = A.Fake(); - private readonly Guid appId = Guid.NewGuid(); - private readonly Guid schemaId = Guid.NewGuid(); + private readonly ISchemaEntity schema; + private readonly NamedId appId = NamedId.Of(Guid.NewGuid(), "my-app"); + private readonly NamedId schemaId = NamedId.Of(Guid.NewGuid(), "my-schema"); public FilterTagTransformerTests() { @@ -32,18 +34,17 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries .AddTags(2, "tags2", Partitioning.Invariant, new TagsFieldProperties { Normalization = TagsFieldNormalization.Schema }) .AddString(3, "string", Partitioning.Invariant); - A.CallTo(() => schema.Id).Returns(schemaId); - A.CallTo(() => schema.SchemaDef).Returns(schemaDef); + schema = Mocks.Schema(appId, schemaId, schemaDef); } [Fact] public void Should_normalize_tags() { - A.CallTo(() => tagService.GetTagIdsAsync(appId, TagGroups.Schemas(schemaId), A>.That.Contains("name1"))) + A.CallTo(() => tagService.GetTagIdsAsync(appId.Id, TagGroups.Schemas(schemaId.Id), A>.That.Contains("name1"))) .Returns(new Dictionary { ["name1"] = "id1" }); var source = FilterBuilder.Eq("data.tags2.iv", "name1"); - var result = FilterTagTransformer.Transform(source, appId, schema, tagService); + var result = FilterTagTransformer.Transform(source, appId.Id, schema, tagService); Assert.Equal("data.tags2.iv == 'id1'", result.ToString()); } @@ -51,11 +52,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries [Fact] public void Should_not_fail_when_tags_not_found() { - A.CallTo(() => tagService.GetTagIdsAsync(appId, TagGroups.Assets, A>.That.Contains("name1"))) + A.CallTo(() => tagService.GetTagIdsAsync(appId.Id, TagGroups.Assets, A>.That.Contains("name1"))) .Returns(new Dictionary()); var source = FilterBuilder.Eq("data.tags2.iv", "name1"); - var result = FilterTagTransformer.Transform(source, appId, schema, tagService); + var result = FilterTagTransformer.Transform(source, appId.Id, schema, tagService); Assert.Equal("data.tags2.iv == 'name1'", result.ToString()); } @@ -64,11 +65,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries public void Should_not_normalize_other_tags_field() { var source = FilterBuilder.Eq("data.tags1.iv", "value"); - var result = FilterTagTransformer.Transform(source, appId, schema, tagService); + var result = FilterTagTransformer.Transform(source, appId.Id, schema, tagService); Assert.Equal("data.tags1.iv == 'value'", result.ToString()); - A.CallTo(() => tagService.GetTagIdsAsync(appId, A.Ignored, A>.Ignored)) + A.CallTo(() => tagService.GetTagIdsAsync(appId.Id, A.Ignored, A>.Ignored)) .MustNotHaveHappened(); } @@ -76,11 +77,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries public void Should_not_normalize_other_typed_field() { var source = FilterBuilder.Eq("data.string.iv", "value"); - var result = FilterTagTransformer.Transform(source, appId, schema, tagService); + var result = FilterTagTransformer.Transform(source, appId.Id, schema, tagService); Assert.Equal("data.string.iv == 'value'", result.ToString()); - A.CallTo(() => tagService.GetTagIdsAsync(appId, A.Ignored, A>.Ignored)) + A.CallTo(() => tagService.GetTagIdsAsync(appId.Id, A.Ignored, A>.Ignored)) .MustNotHaveHappened(); } @@ -88,11 +89,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries public void Should_not_normalize_non_data_field() { var source = FilterBuilder.Eq("no.data", "value"); - var result = FilterTagTransformer.Transform(source, appId, schema, tagService); + var result = FilterTagTransformer.Transform(source, appId.Id, schema, tagService); Assert.Equal("no.data == 'value'", result.ToString()); - A.CallTo(() => tagService.GetTagIdsAsync(appId, A.Ignored, A>.Ignored)) + A.CallTo(() => tagService.GetTagIdsAsync(appId.Id, A.Ignored, A>.Ignored)) .MustNotHaveHappened(); } } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/GrainTextIndexerTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/GrainTextIndexerTests.cs index af936c260..6b15aa70b 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/GrainTextIndexerTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/GrainTextIndexerTests.cs @@ -10,9 +10,9 @@ using System.Collections.Generic; using System.Threading.Tasks; using FakeItEasy; using Orleans; -using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Entities.Apps; +using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Domain.Apps.Events.Contents; using Squidex.Infrastructure; using Squidex.Infrastructure.EventSourcing; @@ -23,16 +23,20 @@ namespace Squidex.Domain.Apps.Entities.Contents.Text { public class GrainTextIndexerTests { + private readonly IAppEntity app; private readonly IGrainFactory grainFactory = A.Fake(); private readonly ITextIndexerGrain grain = A.Fake(); - private readonly Guid schemaId = Guid.NewGuid(); private readonly Guid contentId = Guid.NewGuid(); + private readonly NamedId appId = NamedId.Of(Guid.NewGuid(), "my-app"); + private readonly NamedId schemaId = NamedId.Of(Guid.NewGuid(), "my-schema"); private readonly NamedContentData data = new NamedContentData(); private readonly GrainTextIndexer sut; public GrainTextIndexerTests() { - A.CallTo(() => grainFactory.GetGrain(schemaId, null)) + app = Mocks.App(appId); + + A.CallTo(() => grainFactory.GetGrain(schemaId.Id, null)) .Returns(grain); sut = new GrainTextIndexer(grainFactory); @@ -109,7 +113,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Text A.CallTo(() => grain.SearchAsync("Search", A.Ignored)) .Returns(foundIds); - var ids = await sut.SearchAsync("Search", GetApp(), schemaId, Scope.Draft); + var ids = await sut.SearchAsync("Search", app, schemaId.Id, Scope.Draft); Assert.Equal(foundIds, ids); } @@ -117,7 +121,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Text [Fact] public async Task Should_not_call_grain_when_input_is_empty() { - var ids = await sut.SearchAsync(string.Empty, GetApp(), schemaId, Scope.Published); + var ids = await sut.SearchAsync(string.Empty, app, schemaId.Id, Scope.Published); Assert.Null(ids); @@ -125,19 +129,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.Text .MustNotHaveHappened(); } - private static IAppEntity GetApp() - { - var app = A.Fake(); - - A.CallTo(() => app.LanguagesConfig).Returns(LanguagesConfig.Build(Language.EN, Language.DE)); - - return app; - } - private Envelope E(ContentEvent contentEvent) { contentEvent.ContentId = contentId; - contentEvent.SchemaId = NamedId.Of(schemaId, "my-schema"); + contentEvent.SchemaId = schemaId; return new Envelope(contentEvent); } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/GuardRuleTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/GuardRuleTests.cs index 50c196f5a..b6a43ff8b 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/GuardRuleTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/GuardRuleTests.cs @@ -11,7 +11,6 @@ using FakeItEasy; using Squidex.Domain.Apps.Core.Rules; using Squidex.Domain.Apps.Core.Rules.Triggers; using Squidex.Domain.Apps.Entities.Rules.Commands; -using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Infrastructure; using Squidex.Infrastructure.Collections; @@ -26,6 +25,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards private readonly Uri validUrl = new Uri("https://squidex.io"); private readonly Rule rule_0 = new Rule(new ContentChangedTriggerV2(), new TestAction()); private readonly NamedId appId = NamedId.Of(Guid.NewGuid(), "my-app"); + private readonly NamedId schemaId = NamedId.Of(Guid.NewGuid(), "my-schema"); private readonly IAppProvider appProvider = A.Fake(); public sealed class TestAction : RuleAction @@ -35,8 +35,8 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards public GuardRuleTests() { - A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, A.Ignored, false)) - .Returns(A.Fake()); + A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, schemaId.Id, false)) + .Returns(Mocks.Schema(appId, schemaId)); } [Fact] diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Triggers/ContentChangedTriggerTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Triggers/ContentChangedTriggerTests.cs index a4eb93efd..e8f8a876f 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Triggers/ContentChangedTriggerTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Triggers/ContentChangedTriggerTests.cs @@ -12,6 +12,7 @@ using FakeItEasy; using FluentAssertions; using Squidex.Domain.Apps.Core.Rules.Triggers; using Squidex.Domain.Apps.Entities.Schemas; +using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Infrastructure; using Squidex.Infrastructure.Collections; using Xunit; @@ -21,8 +22,8 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Triggers public class ContentChangedTriggerTests { private readonly IAppProvider appProvider = A.Fake(); - private readonly Guid appId = Guid.NewGuid(); - private readonly Guid schemaId = Guid.NewGuid(); + private readonly NamedId appId = NamedId.Of(Guid.NewGuid(), "my-app"); + private readonly NamedId schemaId = NamedId.Of(Guid.NewGuid(), "my-schema"); [Fact] public async Task Should_add_error_if_schema_id_is_not_defined() @@ -32,7 +33,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Triggers Schemas = ReadOnlyCollection.Create(new ContentChangedTriggerSchemaV2()) }; - var errors = await RuleTriggerValidator.ValidateAsync(appId, trigger, appProvider); + var errors = await RuleTriggerValidator.ValidateAsync(appId.Id, trigger, appProvider); errors.Should().BeEquivalentTo( new List @@ -40,27 +41,27 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Triggers new ValidationError("Schema id is required.", "Schemas") }); - A.CallTo(() => appProvider.GetSchemaAsync(appId, A.Ignored, false)) + A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, A.Ignored, false)) .MustNotHaveHappened(); } [Fact] public async Task Should_add_error_if_schemas_ids_are_not_valid() { - A.CallTo(() => appProvider.GetSchemaAsync(appId, schemaId, false)) + A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, schemaId.Id, false)) .Returns(Task.FromResult(null)); var trigger = new ContentChangedTriggerV2 { - Schemas = ReadOnlyCollection.Create(new ContentChangedTriggerSchemaV2 { SchemaId = schemaId }) + Schemas = ReadOnlyCollection.Create(new ContentChangedTriggerSchemaV2 { SchemaId = schemaId.Id }) }; - var errors = await RuleTriggerValidator.ValidateAsync(appId, trigger, appProvider); + var errors = await RuleTriggerValidator.ValidateAsync(appId.Id, trigger, appProvider); errors.Should().BeEquivalentTo( new List { - new ValidationError($"Schema {schemaId} does not exist.", "Schemas") + new ValidationError($"Schema {schemaId.Id} does not exist.", "Schemas") }); } @@ -69,7 +70,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Triggers { var trigger = new ContentChangedTriggerV2(); - var errors = await RuleTriggerValidator.ValidateAsync(appId, trigger, appProvider); + var errors = await RuleTriggerValidator.ValidateAsync(appId.Id, trigger, appProvider); Assert.Empty(errors); } @@ -82,7 +83,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Triggers Schemas = ReadOnlyCollection.Empty() }; - var errors = await RuleTriggerValidator.ValidateAsync(appId, trigger, appProvider); + var errors = await RuleTriggerValidator.ValidateAsync(appId.Id, trigger, appProvider); Assert.Empty(errors); } @@ -90,15 +91,15 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Triggers [Fact] public async Task Should_not_add_error_if_schemas_ids_are_valid() { - A.CallTo(() => appProvider.GetSchemaAsync(appId, A.Ignored, false)) - .Returns(A.Fake()); + A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, A.Ignored, false)) + .Returns(Mocks.Schema(appId, schemaId)); var trigger = new ContentChangedTriggerV2 { - Schemas = ReadOnlyCollection.Create(new ContentChangedTriggerSchemaV2 { SchemaId = schemaId }) + Schemas = ReadOnlyCollection.Create(new ContentChangedTriggerSchemaV2 { SchemaId = schemaId.Id }) }; - var errors = await RuleTriggerValidator.ValidateAsync(appId, trigger, appProvider); + var errors = await RuleTriggerValidator.ValidateAsync(appId.Id, trigger, appProvider); Assert.Empty(errors); } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/ReferencesFieldPropertiesTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/ReferencesFieldPropertiesTests.cs index c7b7e1e98..cd702f624 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/ReferencesFieldPropertiesTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/ReferencesFieldPropertiesTests.cs @@ -44,6 +44,20 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards.FieldProperties }); } + [Fact] + public void Should_add_error_if_resolving_references_with_more_than_one_max_items() + { + var sut = new ReferencesFieldProperties { ResolveReference = true, MaxItems = 2 }; + + var errors = FieldPropertiesValidator.Validate(sut).ToList(); + + errors.Should().BeEquivalentTo( + new List + { + new ValidationError("Can only resolve references when MaxItems is 1.", "ResolveReference", "MaxItems") + }); + } + [Fact] public void Should_not_add_error_if_min_items_greater_equals_to_max_items() { diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Indexes/SchemasByAppIndexCommandMiddlewareTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Indexes/SchemasByAppIndexCommandMiddlewareTests.cs index 77892d415..06ddb1d39 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Indexes/SchemasByAppIndexCommandMiddlewareTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Indexes/SchemasByAppIndexCommandMiddlewareTests.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using FakeItEasy; using Orleans; using Squidex.Domain.Apps.Entities.Schemas.Commands; +using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Infrastructure; using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.Orleans; @@ -22,12 +23,13 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes private readonly IGrainFactory grainFactory = A.Fake(); private readonly ICommandBus commandBus = A.Fake(); private readonly ISchemasByAppIndex index = A.Fake(); - private readonly Guid appId = Guid.NewGuid(); + private readonly NamedId appId = NamedId.Of(Guid.NewGuid(), "my-app"); + private readonly NamedId schemaId = NamedId.Of(Guid.NewGuid(), "my-schema"); private readonly SchemasByAppIndexCommandMiddleware sut; public SchemasByAppIndexCommandMiddlewareTests() { - A.CallTo(() => grainFactory.GetGrain(appId, null)) + A.CallTo(() => grainFactory.GetGrain(appId.Id, null)) .Returns(index); sut = new SchemasByAppIndexCommandMiddleware(grainFactory); @@ -36,13 +38,14 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes [Fact] public async Task Should_add_schema_to_index_on_create() { - var context = - new CommandContext(new CreateSchema { SchemaId = appId, Name = "my-schema", AppId = BuildAppId() }, commandBus) - .Complete(); + var command = new CreateSchema { SchemaId = schemaId.Id, Name = schemaId.Name, AppId = appId }; + var context = new CommandContext(command, commandBus); + + context.Complete(); await sut.HandleAsync(context); - A.CallTo(() => index.AddSchemaAsync(appId, "my-schema")) + A.CallTo(() => index.AddSchemaAsync(schemaId.Id, schemaId.Name)) .MustHaveHappened(); } @@ -50,30 +53,22 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes public async Task Should_remove_schema_from_index_on_delete() { var schemaGrain = A.Fake(); - var schemaState = A.Fake(); + var schemaState = Mocks.Schema(appId, schemaId); - A.CallTo(() => grainFactory.GetGrain(appId, null)) + A.CallTo(() => grainFactory.GetGrain(schemaId.Id, null)) .Returns(schemaGrain); A.CallTo(() => schemaGrain.GetStateAsync()) .Returns(J.AsTask(schemaState)); - A.CallTo(() => schemaState.AppId) - .Returns(BuildAppId()); - var context = - new CommandContext(new DeleteSchema { SchemaId = appId }, commandBus) + new CommandContext(new DeleteSchema { SchemaId = schemaId.Id }, commandBus) .Complete(); await sut.HandleAsync(context); - A.CallTo(() => index.RemoveSchemaAsync(appId)) + A.CallTo(() => index.RemoveSchemaAsync(schemaId.Id)) .MustHaveHappened(); } - - private NamedId BuildAppId() - { - return NamedId.Of(appId, "my-app"); - } } } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/HandlerTestBase.cs b/tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/HandlerTestBase.cs index 0cf89e968..2d04e04a5 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/HandlerTestBase.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/HandlerTestBase.cs @@ -37,7 +37,7 @@ namespace Squidex.Domain.Apps.Entities.TestHelpers protected string SchemaName { get; } = "my-schema"; - protected ClaimsPrincipal User { get; } = new ClaimsPrincipal(); + protected ClaimsPrincipal User { get; } = Mocks.FrontendUser(); protected NamedId AppNamedId { diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/Mocks.cs b/tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/Mocks.cs new file mode 100644 index 000000000..6ead64d13 --- /dev/null +++ b/tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/Mocks.cs @@ -0,0 +1,67 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Security.Claims; +using FakeItEasy; +using Squidex.Domain.Apps.Core.Apps; +using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Domain.Apps.Entities.Apps; +using Squidex.Domain.Apps.Entities.Schemas; +using Squidex.Infrastructure; +using Squidex.Infrastructure.Security; +using Squidex.Shared; + +namespace Squidex.Domain.Apps.Entities.TestHelpers +{ + public static class Mocks + { + public static IAppEntity App(NamedId appId, params Language[] languages) + { + var config = LanguagesConfig.English; + + foreach (var language in languages) + { + config = config.Set(language); + } + + var app = A.Fake(); + + A.CallTo(() => app.Id).Returns(appId.Id); + A.CallTo(() => app.Name).Returns(appId.Name); + A.CallTo(() => app.LanguagesConfig).Returns(config); + + return app; + } + + public static ISchemaEntity Schema(NamedId appId, NamedId schemaId, Schema schemaDef = null) + { + var schema = A.Fake(); + + A.CallTo(() => schema.Id).Returns(schemaId.Id); + A.CallTo(() => schema.AppId).Returns(appId); + A.CallTo(() => schema.SchemaDef).Returns(schemaDef ?? new Schema(schemaId.Name)); + + return schema; + } + + public static ClaimsPrincipal FrontendUser(string role = null) + { + var claimsIdentity = new ClaimsIdentity(); + var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); + + claimsIdentity.AddClaim(new Claim(OpenIdClaims.ClientId, DefaultClients.Frontend)); + + if (role != null) + { + claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, role)); + } + + return claimsPrincipal; + } + } +} diff --git a/tests/Squidex.Web.Tests/CommandMiddlewares/EnrichWithSchemaIdCommandMiddlewareTests.cs b/tests/Squidex.Web.Tests/CommandMiddlewares/EnrichWithSchemaIdCommandMiddlewareTests.cs index e3959732f..8282ae891 100644 --- a/tests/Squidex.Web.Tests/CommandMiddlewares/EnrichWithSchemaIdCommandMiddlewareTests.cs +++ b/tests/Squidex.Web.Tests/CommandMiddlewares/EnrichWithSchemaIdCommandMiddlewareTests.cs @@ -50,8 +50,6 @@ namespace Squidex.Web.CommandMiddlewares httpContext.Context().App = app; - var schema = A.Fake(); - A.CallTo(() => schema.Id).Returns(schemaId.Id); A.CallTo(() => schema.SchemaDef).Returns(new Schema(schemaId.Name));