Browse Source

Tests fixed and improved.

pull/388/head
Sebastian Stehle 7 years ago
parent
commit
7c5345d3de
  1. 2
      src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs
  2. 12
      src/Squidex.Domain.Apps.Core.Model/Schemas/SchemaExtensions.cs
  3. 22
      src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ContentReferencesExtensions.cs
  4. 2
      src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Extensions.cs
  5. 69
      src/Squidex.Domain.Apps.Entities/Contents/ContentEnricher.cs
  6. 7
      src/Squidex.Domain.Apps.Entities/Schemas/Guards/FieldPropertiesValidator.cs
  7. 5
      src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ReferencesFieldPropertiesDto.cs
  8. 8
      src/Squidex/Config/Domain/EntitiesServices.cs
  9. 2
      src/Squidex/app/features/content/pages/content/content-page.component.ts
  10. 4
      src/Squidex/app/features/schemas/pages/schema/forms/field-form-common.component.ts
  11. 17
      src/Squidex/app/features/schemas/pages/schema/types/references-ui.component.html
  12. 3
      src/Squidex/app/features/schemas/pages/schema/types/references-ui.component.ts
  13. 1
      src/Squidex/app/shared/services/schemas.types.ts
  14. 28
      src/Squidex/app/shared/state/contents.forms.ts
  15. 19
      tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs
  16. 23
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsByUserIndexCommandMiddlewareTests.cs
  17. 11
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/Invitation/InviteUserCommandMiddlewareTests.cs
  18. 21
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/RolePermissionsProviderTests.cs
  19. 28
      tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetQueryServiceTests.cs
  20. 215
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentEnricherReferencesTests.cs
  21. 8
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentEnricherTests.cs
  22. 23
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs
  23. 131
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs
  24. 6
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultWorkflowsValidatorTests.cs
  25. 61
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/DynamicContentWorkflowTests.cs
  26. 52
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs
  27. 34
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs
  28. 57
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/Guard/GuardContentTests.cs
  29. 31
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/FilterTagTransformerTests.cs
  30. 25
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/Text/GrainTextIndexerTests.cs
  31. 6
      tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/GuardRuleTests.cs
  32. 29
      tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Triggers/ContentChangedTriggerTests.cs
  33. 14
      tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/ReferencesFieldPropertiesTests.cs
  34. 31
      tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Indexes/SchemasByAppIndexCommandMiddlewareTests.cs
  35. 2
      tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/HandlerTestBase.cs
  36. 67
      tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/Mocks.cs
  37. 2
      tests/Squidex.Web.Tests/CommandMiddlewares/EnrichWithSchemaIdCommandMiddlewareTests.cs

2
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; }

12
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<IField<ReferencesFieldProperties>> ResolvingReferences(this Schema schema)
{
return schema.Fields.OfType<IField<ReferencesFieldProperties>>()
.Where(x =>
x.Properties.SchemaId != Guid.Empty &&
x.Properties.ResolveReference &&
x.Properties.MaxItems == 1 &&
(x.Properties.IsListField || schema.Fields.Count == 1));
}
}
}

22
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<Guid>();
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<Guid> 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<Guid> GetReferencedIds(this NamedContentData source, IField field, Ids strategy = Ids.All)
{
Guard.NotNull(field, nameof(field));

2
src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Extensions.cs

@ -20,7 +20,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
{
public static List<Guid> 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<Guid> deletedIds, IJsonSerializer serializer)

69
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<Guid, IEnrichedContentEntity> EmptyReferences = new Dictionary<Guid, IEnrichedContentEntity>();
private static readonly ILookup<Guid, IEnrichedContentEntity> EmptyReferences = Enumerable.Empty<IEnrichedContentEntity>().ToLookup(x => x.Id);
private readonly Lazy<IContentQueryService> contentQuery;
private readonly IContentWorkflow contentWorkflow;
@ -92,25 +93,21 @@ namespace Squidex.Domain.Apps.Entities.Contents
private async Task ResolveReferencesAsync(Guid schemaId, IEnumerable<ContentEntity> contents, Context context)
{
var appId = contents.First().AppId.Id;
var schema = await ContentQuery.GetSchemaOrThrowAsync(context, schemaId.ToString());
var referenceFields =
schema.SchemaDef.Fields.OfType<IField<ReferencesFieldProperties>>()
.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<Guid, JsonObject>();
var formatted = new Dictionary<IContentEntity, JsonObject>();
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<Dictionary<Guid, IEnrichedContentEntity>> GetReferencesAsync(Guid schemaId, IEnumerable<ContentEntity> contents, IField field, Context context)
private static JsonObject CreateFallback(Context context, List<IEnrichedContentEntity> 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<ILookup<Guid, IEnrichedContentEntity>> GetReferencesAsync(ISchemaEntity schema, IEnumerable<ContentEntity> contents, Context context)
{
var ids = new HashSet<Guid>();
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
{

7
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<ValidationError> Visit(StringFieldProperties properties)

5
src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ReferencesFieldPropertiesDto.cs

@ -28,6 +28,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields
/// </summary>
public bool AllowDuplicates { get; set; }
/// <summary>
/// True to resolve references in the content list.
/// </summary>
public bool ResolveReference { get; set; }
/// <summary>
/// The editor that is used to manage this field.
/// </summary>

8
src/Squidex/Config/Domain/EntitiesServices.cs

@ -99,13 +99,13 @@ namespace Squidex.Config.Domain
services.AddSingletonAs<AssetEnricher>()
.As<IAssetEnricher>();
services.AddSingletonAs<AssetQueryService>()
.As<IAssetQueryService>();
services.AddSingletonAs<ContentEnricher>()
.As<IContentEnricher>();
services.AddSingletonAs(c => new Lazy<IContentEnricher>(() => c.GetRequiredService<IContentEnricher>()))
services.AddSingletonAs<AssetQueryService>()
.As<IAssetQueryService>();
services.AddSingletonAs(c => new Lazy<IContentQueryService>(() => c.GetRequiredService<IContentQueryService>()))
.AsSelf();
services.AddSingletonAs<ContentQueryService>()

2
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);

4
src/Squidex/app/features/schemas/pages/schema/forms/field-form-common.component.ts

@ -55,7 +55,7 @@ import { FieldDto } from '@app/shared';
</div>
<div class="form-group row" *ngIf="field.properties.isContentField">
<div class="col-6 offset-3">
<div class="col-9 offset-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="{{field.fieldId}}_fieldListfield" formControlName="isListField" />
<label class="form-check-label" for="{{field.fieldId}}_fieldListfield">
@ -70,7 +70,7 @@ import { FieldDto } from '@app/shared';
</div>
<div class="form-group row" *ngIf="field.properties.isContentField">
<div class="col-6 offset-3">
<div class="col-9 offset-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="{{field.fieldId}}_fieldReferencefield" formControlName="isReferenceField" />
<label class="form-check-label" for="{{field.fieldId}}_fieldReferencefield">

17
src/Squidex/app/features/schemas/pages/schema/types/references-ui.component.html

@ -18,5 +18,20 @@
<span class="radio-label">Dropdown</span>
</label>
</div>
</div>
</div>
<div class="form-group row" *ngIf="field.properties.isContentField">
<div class="col-9 offset-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="{{field.fieldId}}_fieldResolveReferences" formControlName="resolveReference" />
<label class="form-check-label" for="{{field.fieldId}}_fieldResolveReferences">
Resolve reference
</label>
</div>
<sqx-form-hint>
If check the reference is resolved for the content list.<br />Can only be checken when the MaxItems field in the validation tab is set to 1.
</sqx-form-hint>
</div>
</div>
</div>

3
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));
}
}

1
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() {

28
src/Squidex/app/shared/state/contents.forms.ts

@ -61,24 +61,26 @@ export class SaveQueryForm extends Form<FormGroup, any> {
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];

19
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()
{

23
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<IGrainFactory>();
private readonly ICommandBus commandBus = A.Fake<ICommandBus>();
private readonly IAppsByUserIndex index = A.Fake<IAppsByUserIndex>();
private readonly Guid appId = Guid.NewGuid();
private readonly NamedId<Guid> 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<IAppGrain>();
var appState = A.Fake<IAppEntity>();
var appState = Mocks.App(appId);
A.CallTo(() => grainFactory.GetGrain<IAppGrain>(appId, null))
A.CallTo(() => grainFactory.GetGrain<IAppGrain>(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();
}
}

11
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<IAppEntity>();
var result = Mocks.App(NamedId.Of(Guid.NewGuid(), "my-app"));
context.Complete(app);
context.Complete(result);
await sut.HandleAsync(context);
Assert.Same(context.Result<InvitedResult>().App, app);
Assert.Same(context.Result<InvitedResult>().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<IAppEntity>();
var result = Mocks.App(NamedId.Of(Guid.NewGuid(), "my-app"));
context.Complete(result);

21
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<IAppProvider>();
private readonly IAppEntity app = A.Fake<IAppEntity>();
private readonly NamedId<Guid> 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<Guid>.Ignored))
.Returns(new List<ISchemaEntity>
{
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<ISchemaEntity>();
A.CallTo(() => schema.SchemaDef).Returns(new Schema(name));
return schema;
}
}
}

28
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<ITagService>();
private readonly IAssetEnricher assetEnricher = A.Fake<IAssetEnricher>();
private readonly IAssetRepository assetRepository = A.Fake<IAssetRepository>();
private readonly IAppEntity app = A.Fake<IAppEntity>();
private readonly ITagService tagService = A.Fake<ITagService>();
private readonly NamedId<Guid> 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<IEnumerable<IAssetEntity>>.That.IsSameSequenceAs(found1, found2)))
.Returns(new List<IEnrichedAssetEntity> { 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<IEnumerable<IAssetEntity>>.That.IsSameSequenceAs(found1, found2)))
.Returns(new List<IEnrichedAssetEntity> { 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<Query>.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<Query>.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<Query>.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<Query>.That.Is("Skip: 20; Take: 200; Sort: lastModified Descending")))
.MustHaveHappened();

215
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<IContentWorkflow>();
private readonly IContentQueryService contentQuery = A.Fake<IContentQueryService>();
private readonly NamedId<Guid> appId = NamedId.Of(Guid.NewGuid(), "my-app");
private readonly NamedId<Guid> refSchemaId1 = NamedId.Of(Guid.NewGuid(), "my-ref1");
private readonly NamedId<Guid> refSchemaId2 = NamedId.Of(Guid.NewGuid(), "my-ref2");
private readonly NamedId<Guid> 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<Guid> 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<IContentQueryService>(() => 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<Context>.Ignored, A<IReadOnlyList<Guid>>.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<Context>.Ignored, A<IReadOnlyList<Guid>>.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
};
}
}
}

8
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);

23
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<ContentState>
{
private readonly ISchemaEntity schema = A.Fake<ISchemaEntity>();
private readonly IScriptEngine scriptEngine = A.Fake<IScriptEngine>();
private readonly Guid contentId = Guid.NewGuid();
private readonly IAppEntity app;
private readonly IAppProvider appProvider = A.Fake<IAppProvider>();
private readonly IContentRepository contentRepository = A.Dummy<IContentRepository>();
private readonly IContentWorkflow contentWorkflow = A.Fake<IContentWorkflow>(x => x.Wrapping(new DefaultContentWorkflow()));
private readonly IAppProvider appProvider = A.Fake<IAppProvider>();
private readonly IAppEntity appEntity = A.Fake<IAppEntity>();
private readonly LanguagesConfig languagesConfig = LanguagesConfig.Build(Language.DE);
private readonly ISchemaEntity schema;
private readonly IScriptEngine scriptEngine = A.Fake<IScriptEngine>();
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 = "<change-script>",
@ -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<ScriptContext>.Ignored, A<string>.Ignored))
.ReturnsLazily(x => x.GetArgument<ScriptContext>(0).Data);

131
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<IAppProvider>();
private readonly IAssetUrlGenerator urlGenerator = A.Fake<IAssetUrlGenerator>();
private readonly IContentEnricher contentEnricher = A.Fake<IContentEnricher>();
private readonly IContentRepository contentRepository = A.Fake<IContentRepository>();
private readonly IContentVersionLoader contentVersionLoader = A.Fake<IContentVersionLoader>();
private readonly ISchemaEntity schema;
private readonly IScriptEngine scriptEngine = A.Fake<IScriptEngine>();
private readonly ISchemaEntity schema = A.Fake<ISchemaEntity>();
private readonly IAppEntity app = A.Fake<IAppEntity>();
private readonly IAppProvider appProvider = A.Fake<IAppProvider>();
private readonly IAssetUrlGenerator urlGenerator = A.Fake<IAssetUrlGenerator>();
private readonly Guid contentId = Guid.NewGuid();
private readonly NamedId<Guid> appId = NamedId.Of(Guid.NewGuid(), "my-app");
private readonly NamedId<Guid> 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<object[]> 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 = "<query-script>" });
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<DomainObjectNotFoundException>(() => 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<DomainObjectNotFoundException>(() => 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<Status[]>.That.Is(Status.Published), false, A<Query>.That.Is("Take: 30; Sort: lastModified Descending"), false))
A.CallTo(() => contentRepository.QueryAsync(app, schema, A<Status[]>.That.Is(Status.Published), false,
A<Query>.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<Status[]>.That.Is(status), false, A<Query>.That.Is("Skip: 20; Take: 200; Sort: lastModified Descending"), false))
A.CallTo(() => contentRepository.QueryAsync(app, schema, A<Status[]>.That.Is(status), false,
A<Query>.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<DomainForbiddenException>(() => 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<DomainObjectNotFoundException>(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<DomainForbiddenException>(() => 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<ValidationException>(() => sut.QueryAsync(context, schemaId.Name, query));
await Assert.ThrowsAsync<ValidationException>(() => 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<Guid>();
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<IEnumerable<IContentEntity>>.Ignored, context))
A.CallTo(() => contentEnricher.EnrichAsync(A<IEnumerable<IContentEntity>>.Ignored, requestContext))
.ReturnsLazily(x =>
{
var input = (IEnumerable<IContentEntity>)x.Arguments[0];

6
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<ISchemaEntity>();
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<Guid>.Ignored, false))
.Returns(Task.FromResult<ISchemaEntity>(null));

61
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<IAppProvider>();
private readonly NamedId<Guid> appId = NamedId.Of(Guid.NewGuid(), "my-app");
private readonly NamedId<Guid> schemaId = NamedId.Of(Guid.NewGuid(), "my-schema");
private readonly NamedId<Guid> simpleSchemaId = NamedId.Of(Guid.NewGuid(), "my-simple-schema");
private readonly IAppProvider appProvider = A.Fake<IAppProvider>();
private readonly IAppEntity appEntity = A.Fake<IAppEntity>();
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<Status, WorkflowStep>
@ -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<ISchemaEntity>();
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;
}
}
}

52
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<Q>.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<Q>.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<Q>.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5")))
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.Id.ToString(), A<Q>.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<Q>.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5")))
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.Id.ToString(), A<Q>.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("<ID>", 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("<ID>", 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("<ID>", contentId.ToString());
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.ToString(), A<Q>.Ignored))
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.Id.ToString(), A<Q>.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("<ID>", 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<Q>.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("<ID>", 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("<ID>", 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("<ID>", 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<Context>.That.Matches(x => x.App == app && x.User == user);
return A<Context>.That.Matches(x => x.App == app && x.User == requestContext.User);
}
private Context MatchsContentContext()
{
return A<Context>.That.Matches(x => x.App == app && x.User == user);
return A<Context>.That.Matches(x => x.App == app && x.User == requestContext.User);
}
}
}

34
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<IContentQueryService>();
protected readonly IAppEntity app;
protected readonly IAssetQueryService assetQuery = A.Fake<IAssetQueryService>();
protected readonly ISchemaEntity schema = A.Fake<ISchemaEntity>();
protected readonly IJsonSerializer serializer = TestUtils.CreateSerializer(TypeNameHandling.None);
protected readonly IContentQueryService contentQuery = A.Fake<IContentQueryService>();
protected readonly IDependencyResolver dependencyResolver;
protected readonly IAppEntity app = A.Dummy<IAppEntity>();
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<Guid> appId = NamedId.Of(Guid.NewGuid(), "my-app");
protected readonly NamedId<Guid> 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 = "<query-script>" })
.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<IAppProvider>();
A.CallTo(() => appProvider.GetSchemasAsync(appId))
A.CallTo(() => appProvider.GetSchemasAsync(appId.Id))
.Returns(new List<ISchemaEntity> { schema });
var dataLoaderContext = new DataLoaderContextAccessor();

57
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<ISchemaEntity>();
private readonly IContentWorkflow contentWorkflow = A.Fake<IContentWorkflow>();
private readonly ClaimsPrincipal user = new ClaimsPrincipal();
private readonly NamedId<Guid> 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<NamedContentData>.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)

31
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<ITagService>();
private readonly ISchemaEntity schema = A.Fake<ISchemaEntity>();
private readonly Guid appId = Guid.NewGuid();
private readonly Guid schemaId = Guid.NewGuid();
private readonly ISchemaEntity schema;
private readonly NamedId<Guid> appId = NamedId.Of(Guid.NewGuid(), "my-app");
private readonly NamedId<Guid> 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<HashSet<string>>.That.Contains("name1")))
A.CallTo(() => tagService.GetTagIdsAsync(appId.Id, TagGroups.Schemas(schemaId.Id), A<HashSet<string>>.That.Contains("name1")))
.Returns(new Dictionary<string, string> { ["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<HashSet<string>>.That.Contains("name1")))
A.CallTo(() => tagService.GetTagIdsAsync(appId.Id, TagGroups.Assets, A<HashSet<string>>.That.Contains("name1")))
.Returns(new Dictionary<string, string>());
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<string>.Ignored, A<HashSet<string>>.Ignored))
A.CallTo(() => tagService.GetTagIdsAsync(appId.Id, A<string>.Ignored, A<HashSet<string>>.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<string>.Ignored, A<HashSet<string>>.Ignored))
A.CallTo(() => tagService.GetTagIdsAsync(appId.Id, A<string>.Ignored, A<HashSet<string>>.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<string>.Ignored, A<HashSet<string>>.Ignored))
A.CallTo(() => tagService.GetTagIdsAsync(appId.Id, A<string>.Ignored, A<HashSet<string>>.Ignored))
.MustNotHaveHappened();
}
}

25
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<IGrainFactory>();
private readonly ITextIndexerGrain grain = A.Fake<ITextIndexerGrain>();
private readonly Guid schemaId = Guid.NewGuid();
private readonly Guid contentId = Guid.NewGuid();
private readonly NamedId<Guid> appId = NamedId.Of(Guid.NewGuid(), "my-app");
private readonly NamedId<Guid> schemaId = NamedId.Of(Guid.NewGuid(), "my-schema");
private readonly NamedContentData data = new NamedContentData();
private readonly GrainTextIndexer sut;
public GrainTextIndexerTests()
{
A.CallTo(() => grainFactory.GetGrain<ITextIndexerGrain>(schemaId, null))
app = Mocks.App(appId);
A.CallTo(() => grainFactory.GetGrain<ITextIndexerGrain>(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<SearchContext>.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<IAppEntity>();
A.CallTo(() => app.LanguagesConfig).Returns(LanguagesConfig.Build(Language.EN, Language.DE));
return app;
}
private Envelope<IEvent> E(ContentEvent contentEvent)
{
contentEvent.ContentId = contentId;
contentEvent.SchemaId = NamedId.Of(schemaId, "my-schema");
contentEvent.SchemaId = schemaId;
return new Envelope<IEvent>(contentEvent);
}

6
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<Guid> appId = NamedId.Of(Guid.NewGuid(), "my-app");
private readonly NamedId<Guid> schemaId = NamedId.Of(Guid.NewGuid(), "my-schema");
private readonly IAppProvider appProvider = A.Fake<IAppProvider>();
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<Guid>.Ignored, false))
.Returns(A.Fake<ISchemaEntity>());
A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, schemaId.Id, false))
.Returns(Mocks.Schema(appId, schemaId));
}
[Fact]

29
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<IAppProvider>();
private readonly Guid appId = Guid.NewGuid();
private readonly Guid schemaId = Guid.NewGuid();
private readonly NamedId<Guid> appId = NamedId.Of(Guid.NewGuid(), "my-app");
private readonly NamedId<Guid> 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<ValidationError>
@ -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<Guid>.Ignored, false))
A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, A<Guid>.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<ISchemaEntity>(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<ValidationError>
{
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<ContentChangedTriggerSchemaV2>()
};
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<Guid>.Ignored, false))
.Returns(A.Fake<ISchemaEntity>());
A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, A<Guid>.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);
}

14
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<ValidationError>
{
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()
{

31
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<IGrainFactory>();
private readonly ICommandBus commandBus = A.Fake<ICommandBus>();
private readonly ISchemasByAppIndex index = A.Fake<ISchemasByAppIndex>();
private readonly Guid appId = Guid.NewGuid();
private readonly NamedId<Guid> appId = NamedId.Of(Guid.NewGuid(), "my-app");
private readonly NamedId<Guid> schemaId = NamedId.Of(Guid.NewGuid(), "my-schema");
private readonly SchemasByAppIndexCommandMiddleware sut;
public SchemasByAppIndexCommandMiddlewareTests()
{
A.CallTo(() => grainFactory.GetGrain<ISchemasByAppIndex>(appId, null))
A.CallTo(() => grainFactory.GetGrain<ISchemasByAppIndex>(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<ISchemaGrain>();
var schemaState = A.Fake<ISchemaEntity>();
var schemaState = Mocks.Schema(appId, schemaId);
A.CallTo(() => grainFactory.GetGrain<ISchemaGrain>(appId, null))
A.CallTo(() => grainFactory.GetGrain<ISchemaGrain>(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<Guid> BuildAppId()
{
return NamedId.Of(appId, "my-app");
}
}
}

2
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<Guid> AppNamedId
{

67
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<Guid> appId, params Language[] languages)
{
var config = LanguagesConfig.English;
foreach (var language in languages)
{
config = config.Set(language);
}
var app = A.Fake<IAppEntity>();
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<Guid> appId, NamedId<Guid> schemaId, Schema schemaDef = null)
{
var schema = A.Fake<ISchemaEntity>();
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;
}
}
}

2
tests/Squidex.Web.Tests/CommandMiddlewares/EnrichWithSchemaIdCommandMiddlewareTests.cs

@ -50,8 +50,6 @@ namespace Squidex.Web.CommandMiddlewares
httpContext.Context().App = app;
var schema = A.Fake<ISchemaEntity>();
A.CallTo(() => schema.Id).Returns(schemaId.Id);
A.CallTo(() => schema.SchemaDef).Returns(new Schema(schemaId.Name));

Loading…
Cancel
Save