Browse Source

Component fixes. (#1010)

pull/1011/head
Sebastian Stehle 3 years ago
committed by GitHub
parent
commit
eb5246492c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Builder.cs
  2. 51
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/DataInputGraphType.cs
  3. 18
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/NestedInputGraphType.cs
  4. 135
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/FieldMap.cs
  5. 39
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Primitives/JsonGraphType.cs
  6. 23
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/SharedExtensions.cs
  7. 18
      backend/tests/Squidex.Domain.Apps.Entities.Tests/AppProviderExtensionsTests.cs
  8. 2
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DefaultContentWorkflowTests.cs
  9. 10
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/Guards/GuardContentTests.cs
  10. 2
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DynamicContentWorkflowTests.cs
  11. 22
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLIntrospectionTests.cs
  12. 31
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLMutationTests.cs
  13. 61
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs
  14. 2
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs
  15. 185
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/TestContent.cs
  16. 2
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/TestQuery.cs
  17. 45
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/TestSchemas.cs
  18. 6
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/MongoDb/ContentsQueryFixture.cs
  19. 46
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ResolveReferencesTests.cs
  20. 2
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/SchemasSearchSourceTests.cs
  21. 27
      backend/tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/Mocks.cs
  22. 60
      tools/TestSuite/TestSuite.ApiTests/GraphQLFixture.cs
  23. 75
      tools/TestSuite/TestSuite.ApiTests/GraphQLTests.cs
  24. 1
      tools/TestSuite/TestSuite.ApiTests/TestSuite.ApiTests.csproj
  25. 9
      tools/TestSuite/TestSuite.Shared/Model/Geography.cs

13
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Builder.cs

@ -48,6 +48,8 @@ internal sealed class Builder
public IInterfaceGraphType ComponentInterface { get; } = new ComponentInterfaceGraphType();
public FieldMap FieldMap { get; private set; }
public Builder(IAppEntity app, GraphQLOptions options)
{
partitionResolver = app.PartitionResolver();
@ -64,7 +66,7 @@ internal sealed class Builder
allSchemas.AddRange(SchemaInfo.Build(schemas, typeNames).Where(x => x.Fields.Count > 0));
// Only published normal schemas (not components are used for entities).
var normalSchemas = allSchemas.Where(x => x.Schema.SchemaDef.IsPublished && x.Schema.SchemaDef.Type != SchemaType.Component).ToList();
var normalSchemas = allSchemas.Where(IsNormalSchema).ToList();
foreach (var schemaInfo in normalSchemas)
{
@ -74,7 +76,7 @@ internal sealed class Builder
contentResultTypes[schemaInfo] = new ContentResultGraphType(contentType, schemaInfo);
}
foreach (var schemaInfo in normalSchemas)
foreach (var schemaInfo in allSchemas)
{
var componentType = new ComponentGraphType(schemaInfo);
@ -92,6 +94,8 @@ internal sealed class Builder
newSchema.Directives.Register(SharedTypes.CacheDirective);
newSchema.Directives.Register(SharedTypes.OptimizeFieldQueriesDirective);
FieldMap = new FieldMap(allSchemas);
if (normalSchemas.Any())
{
var mutations = new ApplicationMutations(this, normalSchemas);
@ -132,6 +136,11 @@ internal sealed class Builder
return newSchema;
}
private static bool IsNormalSchema(SchemaInfo schema)
{
return schema.Schema.SchemaDef.IsPublished && schema.Schema.SchemaDef.Type != SchemaType.Component;
}
public FieldGraphSchema GetGraphType(FieldInfo fieldInfo)
{
return fieldInfo.Field.Accept(fieldVisitor, fieldInfo);

51
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/DataInputGraphType.cs

@ -6,16 +6,15 @@
// ==========================================================================
using GraphQL.Types;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Primitives;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure.Json.Objects;
namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents;
internal sealed class DataInputGraphType : InputObjectGraphType
{
private readonly FieldMap fieldMap;
public DataInputGraphType(Builder builder, SchemaInfo schemaInfo)
{
// The name is used for equal comparison. Therefore it is important to treat it as readonly.
@ -62,52 +61,12 @@ internal sealed class DataInputGraphType : InputObjectGraphType
}
Description = $"The structure of the {schemaInfo.DisplayName} data input type.";
fieldMap = builder.FieldMap;
}
public override object ParseDictionary(IDictionary<string, object?> value)
{
var result = new ContentData();
static ContentFieldData ToFieldData(IDictionary<string, object> source, IComplexGraphType type)
{
var result = new ContentFieldData();
foreach (var field in type.Fields)
{
if (source.TryGetValue(field.Name, out var value))
{
if (value is IEnumerable<object> list && field.ResolvedType?.InnerType() is IComplexGraphType nestedType)
{
var array = new JsonArray(list.Count());
foreach (var item in list)
{
if (item is JsonValue { Value: JsonObject } nested)
{
array.Add(nested);
}
}
result[field.SourceName()] = array;
}
else
{
result[field.SourceName()] = JsonGraphType.ParseJson(value);
}
}
}
return result;
}
foreach (var field in Fields)
{
if (field.ResolvedType is IComplexGraphType complexType && value.TryGetValue(field.Name, out var fieldValue) && fieldValue is IDictionary<string, object> nested)
{
result[field.SourceName()] = ToFieldData(nested, complexType);
}
}
return result;
return fieldMap.MapData(this, value);
}
}

18
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/NestedInputGraphType.cs

@ -6,13 +6,13 @@
// ==========================================================================
using GraphQL.Types;
using Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Primitives;
using Squidex.Infrastructure.Json.Objects;
namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents;
internal sealed class NestedInputGraphType : InputObjectGraphType
{
private readonly FieldMap fieldMap;
public NestedInputGraphType(Builder builder, FieldInfo fieldInfo)
{
// The name is used for equal comparison. Therefore it is important to treat it as readonly.
@ -38,20 +38,12 @@ internal sealed class NestedInputGraphType : InputObjectGraphType
}
Description = $"The structure of the {fieldInfo.DisplayName} nested schema.";
fieldMap = builder.FieldMap;
}
public override object ParseDictionary(IDictionary<string, object?> value)
{
var result = JsonValue.Object();
foreach (var field in Fields)
{
if (value.TryGetValue(field.Name, out var fieldValue))
{
result[field.SourceName()] = JsonGraphType.ParseJson(fieldValue);
}
}
return new JsonValue(result);
return fieldMap.MapNested(this, value);
}
}

135
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/FieldMap.cs

@ -0,0 +1,135 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using GraphQL.Types;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents;
using Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Primitives;
using Squidex.Infrastructure.Json.Objects;
namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types;
internal sealed class FieldMap
{
private readonly Dictionary<string, Dictionary<string, string>> schemas = new Dictionary<string, Dictionary<string, string>>();
public FieldMap(IEnumerable<SchemaInfo> source)
{
foreach (var schema in source)
{
var fieldMap = schema.Fields.ToDictionary(x => x.FieldName, x => x.Field.Name);
schemas[schema.Schema.Id.ToString()] = fieldMap;
schemas[schema.Schema.SchemaDef.Name] = fieldMap;
}
}
public ContentData MapData(IInputObjectGraphType inputType, IDictionary<string, object?> source)
{
var result = new ContentData();
foreach (var field in inputType.Fields)
{
if (field.ResolvedType is IComplexGraphType complexType && source.TryGetValue(field.Name, out var value) && value is IDictionary<string, object> nested)
{
result[field.SourceName()] = MapField(nested, complexType);
}
}
return result;
}
public JsonValue MapNested(IInputObjectGraphType inputType, IDictionary<string, object?> source)
{
var result = new JsonObject(source.Count);
foreach (var field in inputType.Fields)
{
if (source.TryGetValue(field.Name, out var value))
{
result[field.SourceName()] = MapValue(JsonGraphType.ParseJson(value));
}
}
return result;
}
private ContentFieldData MapField(IDictionary<string, object> source, IComplexGraphType type)
{
var result = new ContentFieldData();
foreach (var field in type.Fields)
{
if (source.TryGetValue(field.Name, out var value))
{
result[field.SourceName()] = MapValue(JsonGraphType.ParseJson(value));
}
}
return result;
}
private JsonValue MapValue(JsonValue source)
{
switch (source.Value)
{
case JsonArray arr:
return MapArray(arr);
case JsonObject obj:
return MapObject(obj);
default:
return source;
}
}
private JsonValue MapArray(JsonArray source)
{
var result = new JsonArray(source.Count);
foreach (var value in source)
{
result.Add(MapValue(value));
}
return result;
}
private JsonValue MapObject(JsonObject source)
{
Dictionary<string, string>? fieldMap = null;
if (source.TryGetValue(Component.Discriminator, out var d1) && d1.Value is string discriminator)
{
schemas.TryGetValue(discriminator, out fieldMap);
}
else if (source.TryGetValue(Component.Descriptor, out var d2) && d2.Value is string descriptor)
{
schemas.TryGetValue(descriptor, out fieldMap);
}
if (fieldMap == null)
{
return source;
}
var result = new JsonObject(source.Count);
foreach (var (key, value) in source)
{
var sourceName = key;
if (fieldMap != null && fieldMap.TryGetValue(key, out var name))
{
sourceName = name;
}
result[sourceName] = MapValue(value);
}
return result;
}
}

39
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Primitives/JsonGraphType.cs

@ -23,8 +23,10 @@ public sealed class JsonGraphType : JsonNoopGraphType
return ParseJson(value);
}
public static JsonValue ParseJson(object? input)
public static JsonValue ParseJson(object? input, Func<object, IReadOnlyDictionary<string, string>?>? keyMap = null)
{
keyMap ??= x => null;
switch (input)
{
case GraphQLBooleanValue booleanValue:
@ -44,7 +46,7 @@ public sealed class JsonGraphType : JsonNoopGraphType
case GraphQLListValue listValue:
{
var json = new JsonArray();
var json = new JsonArray(listValue.Values?.Count ?? 0);
if (listValue.Values != null)
{
@ -59,13 +61,22 @@ public sealed class JsonGraphType : JsonNoopGraphType
case GraphQLObjectValue objectValue:
{
var json = JsonValue.Object();
var json = new JsonObject(objectValue.Fields?.Count ?? 0);
if (objectValue.Fields != null)
{
var map = keyMap(objectValue);
foreach (var field in objectValue.Fields)
{
json[field.Name.ToString()] = ParseJson(field.Value);
var sourceField = field.Name.ToString();
if (map?.TryGetValue(sourceField, out var temp) == true)
{
sourceField = temp;
}
json[sourceField] = ParseJson(field.Value);
}
}
@ -74,7 +85,7 @@ public sealed class JsonGraphType : JsonNoopGraphType
case IEnumerable<object> list:
{
var json = new JsonArray();
var json = new JsonArray(list.Count());
foreach (var item in list)
{
@ -86,11 +97,23 @@ public sealed class JsonGraphType : JsonNoopGraphType
case IDictionary<string, object> obj:
{
var json = JsonValue.Object();
var json = new JsonObject(obj.Count);
foreach (var (key, value) in obj)
if (obj.Count > 0)
{
json[key] = ParseJson(value);
var map = keyMap(obj);
foreach (var (key, value) in obj)
{
var sourceField = key;
if (map?.TryGetValue(sourceField, out var temp) == true)
{
sourceField = temp;
}
json[sourceField] = ParseJson(value);
}
}
return json;

23
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/SharedExtensions.cs

@ -10,9 +10,7 @@ using GraphQL.Types;
using GraphQL.Utilities;
using GraphQLParser;
using GraphQLParser.AST;
using Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents;
using Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Directives;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json.Objects;
using Squidex.Infrastructure.ObjectPool;
@ -93,7 +91,7 @@ public static class SharedExtensions
return typed.SourceName;
}
throw new InvalidOperationException("Invalid field type");
return field.Name;
}
internal static DomainId SchemaId(this FieldType field)
@ -126,6 +124,25 @@ public static class SharedExtensions
return type;
}
public static bool TryGetValue(this GraphQLObjectValue source, string fieldName, out object value)
{
value = null!;
if (source.Fields != null)
{
foreach (var field in source.Fields)
{
if (field.Name == fieldName)
{
value = field.Value;
return true;
}
}
}
return false;
}
public static TimeSpan CacheDuration(this IResolveFieldContext context)
{
return CacheDirective.CacheDuration(context);

18
backend/tests/Squidex.Domain.Apps.Entities.Tests/AppProviderExtensionsTests.cs

@ -35,7 +35,7 @@ public class AppProviderExtensionsTests : GivenContext
public async Task Should_resolve_self_as_component()
{
var schema =
Mocks.Schema(AppId, schemaId,
Mocks.Schema(AppId, schemaId.Id,
new Schema(schemaId.Name)
.AddComponent(1, "1", Partitioning.Invariant, new ComponentFieldProperties
{
@ -60,7 +60,7 @@ public class AppProviderExtensionsTests : GivenContext
.Returns(component);
var schema =
Mocks.Schema(AppId, schemaId,
Mocks.Schema(AppId, schemaId.Id,
new Schema(schemaId.Name)
.AddComponent(1, "1", Partitioning.Invariant, new ComponentFieldProperties
{
@ -82,7 +82,7 @@ public class AppProviderExtensionsTests : GivenContext
.Returns(component);
var schema =
Mocks.Schema(AppId, schemaId,
Mocks.Schema(AppId, schemaId.Id,
new Schema(schemaId.Name)
.AddComponents(1, "1", Partitioning.Invariant, new ComponentsFieldProperties
{
@ -104,7 +104,7 @@ public class AppProviderExtensionsTests : GivenContext
.Returns(component);
var schema =
Mocks.Schema(AppId, schemaId,
Mocks.Schema(AppId, schemaId.Id,
new Schema(schemaId.Name)
.AddArray(1, "1", Partitioning.Invariant, a => a
.AddComponent(2, "2", new ComponentFieldProperties
@ -122,7 +122,7 @@ public class AppProviderExtensionsTests : GivenContext
public async Task Should_resolve_self_referencing_component()
{
var component =
Mocks.Schema(AppId, componentId1,
Mocks.Schema(AppId, componentId1.Id,
new Schema(componentId1.Name)
.AddComponent(1, "1", Partitioning.Invariant, new ComponentFieldProperties
{
@ -133,7 +133,7 @@ public class AppProviderExtensionsTests : GivenContext
.Returns(component);
var schema =
Mocks.Schema(AppId, schemaId,
Mocks.Schema(AppId, schemaId.Id,
new Schema(schemaId.Name)
.AddComponent(1, "1", Partitioning.Invariant, new ComponentFieldProperties
{
@ -150,7 +150,7 @@ public class AppProviderExtensionsTests : GivenContext
public async Task Should_resolve_component_of_component()
{
var component1 =
Mocks.Schema(AppId, componentId1,
Mocks.Schema(AppId, componentId1.Id,
new Schema(componentId1.Name)
.AddComponent(1, "1", Partitioning.Invariant, new ComponentFieldProperties
{
@ -158,7 +158,7 @@ public class AppProviderExtensionsTests : GivenContext
}));
var component2 =
Mocks.Schema(AppId, componentId2,
Mocks.Schema(AppId, componentId2.Id,
new Schema(componentId2.Name)
.AddComponent(1, "1", Partitioning.Invariant, new ComponentFieldProperties
{
@ -172,7 +172,7 @@ public class AppProviderExtensionsTests : GivenContext
.Returns(component2);
var schema =
Mocks.Schema(AppId, schemaId,
Mocks.Schema(AppId, schemaId.Id,
new Schema(schemaId.Name)
.AddComponent(1, "1", Partitioning.Invariant, new ComponentFieldProperties
{

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

@ -192,6 +192,6 @@ public class DefaultContentWorkflowTests
ValidateOnPublish = validateOnPublish
});
return Mocks.Schema(NamedId.Of(DomainId.NewGuid(), "my-app"), NamedId.Of(DomainId.NewGuid(), schema.Name), schema);
return Mocks.Schema(NamedId.Of(DomainId.NewGuid(), "my-app"), DomainId.NewGuid(), schema);
}
}

10
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/Guards/GuardContentTests.cs

@ -35,19 +35,19 @@ public class GuardContentTests : GivenContext, IClassFixture<TranslationsFixture
public GuardContentTests()
{
normalUnpublishedSchema =
Mocks.Schema(AppId, SchemaId, new Schema(SchemaId.Name));
Mocks.Schema(AppId, SchemaId.Id, new Schema(SchemaId.Name));
normalSchema =
Mocks.Schema(AppId, SchemaId, new Schema(SchemaId.Name).Publish());
Mocks.Schema(AppId, SchemaId.Id, new Schema(SchemaId.Name).Publish());
singletonUnpublishedSchema =
Mocks.Schema(AppId, SchemaId, new Schema(SchemaId.Name, type: SchemaType.Singleton));
Mocks.Schema(AppId, SchemaId.Id, new Schema(SchemaId.Name, type: SchemaType.Singleton));
singletonSchema =
Mocks.Schema(AppId, SchemaId, new Schema(SchemaId.Name, type: SchemaType.Singleton).Publish());
Mocks.Schema(AppId, SchemaId.Id, new Schema(SchemaId.Name, type: SchemaType.Singleton).Publish());
componentSchema =
Mocks.Schema(AppId, SchemaId, new Schema(SchemaId.Name, type: SchemaType.Component).Publish());
Mocks.Schema(AppId, SchemaId.Id, new Schema(SchemaId.Name, type: SchemaType.Component).Publish());
}
[Fact]

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

@ -417,7 +417,7 @@ public class DynamicContentWorkflowTests : GivenContext
ValidateOnPublish = validateOnPublish
});
return Mocks.Schema(AppId, simpleSchemaId, schema);
return Mocks.Schema(AppId, simpleSchemaId.Id, schema);
}
private ContentEntity CreateContent(Status status, int value, bool simple = false)

22
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLIntrospectionTests.cs

@ -130,7 +130,7 @@ public class GraphQLIntrospectionTests : GraphQLTestBase
{
var schema =
Mocks.Schema(TestApp.DefaultId,
NamedId.Of(DomainId.NewGuid(), "content"),
DomainId.NewGuid(),
new Schema("content").Publish());
var model = await CreateSut(schema).GetSchemaAsync(TestApp.Default);
@ -143,7 +143,7 @@ public class GraphQLIntrospectionTests : GraphQLTestBase
{
var schema =
Mocks.Schema(TestApp.DefaultId,
NamedId.Of(DomainId.NewGuid(), "content"),
DomainId.NewGuid(),
new Schema("content").Publish()
.AddUI(1, "ui", Partitioning.Invariant));
@ -157,7 +157,7 @@ public class GraphQLIntrospectionTests : GraphQLTestBase
{
var schema =
Mocks.Schema(TestApp.DefaultId,
NamedId.Of(DomainId.NewGuid(), "content"),
DomainId.NewGuid(),
new Schema("content").Publish()
.AddComponent(1, "component", Partitioning.Invariant));
@ -171,7 +171,7 @@ public class GraphQLIntrospectionTests : GraphQLTestBase
{
var schema =
Mocks.Schema(TestApp.DefaultId,
NamedId.Of(DomainId.NewGuid(), "content"),
DomainId.NewGuid(),
new Schema("content")
.AddString(1, "myField", Partitioning.Invariant));
@ -185,7 +185,7 @@ public class GraphQLIntrospectionTests : GraphQLTestBase
{
var schema =
Mocks.Schema(TestApp.DefaultId,
NamedId.Of(DomainId.NewGuid(), "content"),
DomainId.NewGuid(),
new Schema("content").Publish()
.AddString(1, "myField", Partitioning.Invariant));
@ -199,7 +199,7 @@ public class GraphQLIntrospectionTests : GraphQLTestBase
{
var schema =
Mocks.Schema(TestApp.DefaultId,
NamedId.Of(DomainId.NewGuid(), "my-schema"),
DomainId.NewGuid(),
new Schema("my-schema").Publish()
.AddString(1, "content", Partitioning.Invariant));
@ -215,7 +215,7 @@ public class GraphQLIntrospectionTests : GraphQLTestBase
{
var schema =
Mocks.Schema(TestApp.DefaultId,
NamedId.Of(DomainId.NewGuid(), "my-schema"),
DomainId.NewGuid(),
new Schema("my-schema").Publish()
.AddString(1, "2-field", Partitioning.Invariant));
@ -231,7 +231,7 @@ public class GraphQLIntrospectionTests : GraphQLTestBase
{
var schema =
Mocks.Schema(TestApp.DefaultId,
NamedId.Of(DomainId.NewGuid(), "my-schema"),
DomainId.NewGuid(),
new Schema("my-schema").Publish()
.AddString(1, "my-field", Partitioning.Invariant)
.AddString(2, "my_field", Partitioning.Invariant));
@ -249,7 +249,7 @@ public class GraphQLIntrospectionTests : GraphQLTestBase
{
var schema =
Mocks.Schema(TestApp.DefaultId,
NamedId.Of(DomainId.NewGuid(), "my-schema"),
DomainId.NewGuid(),
new Schema("my-schema").Publish()
.AddComponent(1, "my-component", Partitioning.Invariant,
new ComponentFieldProperties())
@ -267,7 +267,7 @@ public class GraphQLIntrospectionTests : GraphQLTestBase
{
var schema =
Mocks.Schema(TestApp.DefaultId,
NamedId.Of(DomainId.NewGuid(), "my-schema"),
DomainId.NewGuid(),
new Schema("my-schema").Publish()
.AddComponents(1, "my-components", Partitioning.Invariant,
new ComponentsFieldProperties())
@ -285,7 +285,7 @@ public class GraphQLIntrospectionTests : GraphQLTestBase
{
var schema =
Mocks.Schema(TestApp.DefaultId,
NamedId.Of(DomainId.NewGuid(), "my-schema"),
DomainId.NewGuid(),
new Schema("my-schema").Publish()
.AddReferences(1, "my-references", Partitioning.Invariant,
new ReferencesFieldProperties { SchemaId = DomainId.NewGuid() })

31
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLMutationTests.cs

@ -8,6 +8,7 @@
using NodaTime.Text;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Entities.Contents.Commands;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Commands;
using Squidex.Shared;
@ -22,7 +23,7 @@ public class GraphQLMutationTests : GraphQLTestBase
public GraphQLMutationTests()
{
content = TestContent.Create(contentId, TestSchemas.Ref1.Id, TestSchemas.Ref2.Id, null);
content = TestContent.Create(contentId, TestSchemas.Reference1.Id, TestSchemas.Reference2.Id, null);
A.CallTo(() => commandBus.PublishAsync(A<ICommand>.Ignored, A<CancellationToken>._))
.Returns(commandContext);
@ -93,7 +94,7 @@ public class GraphQLMutationTests : GraphQLTestBase
},
Variables = new
{
data = TestContent.Input(content, TestSchemas.Ref1.Id, TestSchemas.Ref2.Id),
data = TestContent.Input(content, TestSchemas.Reference1.Id, TestSchemas.Reference2.Id),
},
Permission = PermissionIds.AppContentsCreate
});
@ -111,7 +112,7 @@ public class GraphQLMutationTests : GraphQLTestBase
A.CallTo(() => commandBus.PublishAsync(
A<CreateContent>.That.Matches(x =>
x.ExpectedVersion == EtagVersion.Any &&
x.SchemaId.Equals(TestSchemas.DefaultId) &&
x.SchemaId.Equals(TestSchemas.Default.NamedId()) &&
x.Status == Status.Published &&
x.Data.Equals(content.Data)),
A<CancellationToken>._))
@ -138,7 +139,7 @@ public class GraphQLMutationTests : GraphQLTestBase
},
Variables = new
{
data = TestContent.Input(content, TestSchemas.Ref1.Id, TestSchemas.Ref2.Id)
data = TestContent.Input(content, TestSchemas.Reference1.Id, TestSchemas.Reference2.Id)
},
Permission = PermissionIds.AppContentsCreate
});
@ -157,7 +158,7 @@ public class GraphQLMutationTests : GraphQLTestBase
A<CreateContent>.That.Matches(x =>
x.ExpectedVersion == EtagVersion.Any &&
x.ContentId == contentId &&
x.SchemaId.Equals(TestSchemas.DefaultId) &&
x.SchemaId.Equals(TestSchemas.Default.NamedId()) &&
x.Status == Status.Published &&
x.Data.Equals(content.Data)),
A<CancellationToken>._))
@ -234,7 +235,7 @@ public class GraphQLMutationTests : GraphQLTestBase
},
Variables = new
{
data = TestContent.Input(content, TestSchemas.Ref1.Id, TestSchemas.Ref2.Id)
data = TestContent.Input(content, TestSchemas.Reference1.Id, TestSchemas.Reference2.Id)
},
Permission = PermissionIds.AppContentsUpdateOwn
});
@ -253,7 +254,7 @@ public class GraphQLMutationTests : GraphQLTestBase
A<UpdateContent>.That.Matches(x =>
x.ContentId == contentId &&
x.ExpectedVersion == 10 &&
x.SchemaId.Equals(TestSchemas.DefaultId) &&
x.SchemaId.Equals(TestSchemas.Default.NamedId()) &&
x.Data.Equals(content.Data)),
A<CancellationToken>._))
.MustHaveHappened();
@ -325,7 +326,7 @@ public class GraphQLMutationTests : GraphQLTestBase
},
Variables = new
{
data = TestContent.Input(content, TestSchemas.Ref1.Id, TestSchemas.Ref2.Id)
data = TestContent.Input(content, TestSchemas.Reference1.Id, TestSchemas.Reference2.Id)
},
Permission = PermissionIds.AppContentsUpsert
});
@ -344,7 +345,7 @@ public class GraphQLMutationTests : GraphQLTestBase
A<UpsertContent>.That.Matches(x =>
x.ContentId == contentId &&
x.ExpectedVersion == 10 &&
x.SchemaId.Equals(TestSchemas.DefaultId) &&
x.SchemaId.Equals(TestSchemas.Default.NamedId()) &&
x.Status == Status.Published &&
x.Data.Equals(content.Data)),
A<CancellationToken>._))
@ -421,7 +422,7 @@ public class GraphQLMutationTests : GraphQLTestBase
},
Variables = new
{
data = TestContent.Input(content, TestSchemas.Ref1.Id, TestSchemas.Ref2.Id)
data = TestContent.Input(content, TestSchemas.Reference1.Id, TestSchemas.Reference2.Id)
},
Permission = PermissionIds.AppContentsUpdateOwn
});
@ -440,7 +441,7 @@ public class GraphQLMutationTests : GraphQLTestBase
A<PatchContent>.That.Matches(x =>
x.ContentId == contentId &&
x.ExpectedVersion == 10 &&
x.SchemaId.Equals(TestSchemas.DefaultId) &&
x.SchemaId.Equals(TestSchemas.Default.NamedId()) &&
x.Data.Equals(content.Data)),
A<CancellationToken>._))
.MustHaveHappened();
@ -534,7 +535,7 @@ public class GraphQLMutationTests : GraphQLTestBase
x.ContentId == contentId &&
x.DueTime == dueTime &&
x.ExpectedVersion == 10 &&
x.SchemaId.Equals(TestSchemas.DefaultId) &&
x.SchemaId.Equals(TestSchemas.Default.NamedId()) &&
x.Status == Status.Published),
A<CancellationToken>._))
.MustHaveHappened();
@ -576,7 +577,7 @@ public class GraphQLMutationTests : GraphQLTestBase
x.ContentId == contentId &&
x.DueTime == null &&
x.ExpectedVersion == 10 &&
x.SchemaId.Equals(TestSchemas.DefaultId) &&
x.SchemaId.Equals(TestSchemas.Default.NamedId()) &&
x.Status == Status.Published),
A<CancellationToken>._))
.MustHaveHappened();
@ -618,7 +619,7 @@ public class GraphQLMutationTests : GraphQLTestBase
x.ContentId == contentId &&
x.DueTime == null &&
x.ExpectedVersion == 10 &&
x.SchemaId.Equals(TestSchemas.DefaultId) &&
x.SchemaId.Equals(TestSchemas.Default.NamedId()) &&
x.Status == Status.Published),
A<CancellationToken>._))
.MustHaveHappened();
@ -708,7 +709,7 @@ public class GraphQLMutationTests : GraphQLTestBase
A<DeleteContent>.That.Matches(x =>
x.ContentId == contentId &&
x.ExpectedVersion == 10 &&
x.SchemaId.Equals(TestSchemas.DefaultId)),
x.SchemaId.Equals(TestSchemas.Default.NamedId())),
A<CancellationToken>._))
.MustHaveHappened();
}

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

@ -7,6 +7,7 @@
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Entities.Assets;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Domain.Apps.Entities.TestHelpers;
using Squidex.Infrastructure;
@ -502,7 +503,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
public async Task Should_return_null_if_single_content_from_another_schema()
{
var contentId = DomainId.NewGuid();
var content = TestContent.CreateRef(TestSchemas.Ref1Id, contentId, "ref1-field", "ref1");
var content = TestContent.CreateRef(TestSchemas.Reference1.NamedId(), contentId, "reference1-field", "reference1");
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentId),
@ -612,7 +613,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
public async Task Should_also_fetch_embedded_contents_if_field_is_included_in_query()
{
var contentRefId = DomainId.NewGuid();
var contentRef = TestContent.CreateRef(TestSchemas.Ref1Id, contentRefId, "schemaRef1Field", "ref1");
var contentRef = TestContent.CreateRef(TestSchemas.Reference1.NamedId(), contentRefId, "reference1-field", "reference1");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, contentRefId);
@ -641,9 +642,9 @@ public class GraphQLQueriesTests : GraphQLTestBase
... on Content {
id
}
... on MyRefSchema1 {
... on MyReference1 {
data {
schemaRef1Field {
reference1Field {
iv
}
}
@ -681,9 +682,9 @@ public class GraphQLQueriesTests : GraphQLTestBase
id = contentRefId,
data = new
{
schemaRef1Field = new
reference1Field = new
{
iv = "ref1"
iv = "reference1"
}
}
}
@ -702,7 +703,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
public async Task Should_also_fetch_referenced_contents_if_field_is_included_in_query()
{
var contentRefId = DomainId.NewGuid();
var contentRef = TestContent.CreateRef(TestSchemas.Ref1Id, contentRefId, "schemaRef1Field", "ref1");
var contentRef = TestContent.CreateRef(TestSchemas.Reference1.NamedId(), contentRefId, "reference1-field", "reference1");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, contentRefId);
@ -728,7 +729,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
iv {
id
data {
schemaRef1Field {
reference1Field {
iv
}
}
@ -761,9 +762,9 @@ public class GraphQLQueriesTests : GraphQLTestBase
id = contentRefId,
data = new
{
schemaRef1Field = new
reference1Field = new
{
iv = "ref1"
iv = "reference1"
}
}
}
@ -781,7 +782,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
public async Task Should_also_fetch_referenced_contents_from_flat_data_if_field_is_included_in_query()
{
var contentRefId = DomainId.NewGuid();
var contentRef = TestContent.CreateRef(TestSchemas.Ref1Id, contentRefId, "schemaRef1Field", "ref1");
var contentRef = TestContent.CreateRef(TestSchemas.Reference1.NamedId(), contentRefId, "reference1-field", "reference1");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, contentRefId);
@ -843,7 +844,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
public async Task Should_cache_referenced_contents_from_flat_data_if_field_is_included_in_query()
{
var contentRefId = DomainId.NewGuid();
var contentRef = TestContent.CreateRef(TestSchemas.Ref1Id, contentRefId, "schemaRef1Field", "ref1");
var contentRef = TestContent.CreateRef(TestSchemas.Reference1.NamedId(), contentRefId, "reference1-field", "reference1");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, contentRefId);
@ -914,7 +915,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
public async Task Should_also_fetch_referencing_contents_if_field_is_included_in_query()
{
var contentRefId = DomainId.NewGuid();
var contentRef = TestContent.CreateRef(TestSchemas.Ref1Id, contentRefId, "ref1-field", "ref1");
var contentRef = TestContent.CreateRef(TestSchemas.Reference1.NamedId(), contentRefId, "reference1-field", "reference1");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, contentRefId);
@ -933,7 +934,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
{
Query = @"
query {
findMyRefSchema1Content(id: '{contentId}') {
findMyReference1Content(id: '{contentId}') {
id
referencingMySchemaContents(top: 30, skip: 5) {
id
@ -955,7 +956,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
{
data = new
{
findMyRefSchema1Content = new
findMyReference1Content = new
{
id = contentRefId,
referencingMySchemaContents = new[]
@ -983,7 +984,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
public async Task Should_also_fetch_referencing_contents_with_total_if_field_is_included_in_query()
{
var contentRefId = DomainId.NewGuid();
var contentRef = TestContent.CreateRef(TestSchemas.Ref1Id, contentRefId, "ref1-field", "ref1");
var contentRef = TestContent.CreateRef(TestSchemas.Reference1.NamedId(), contentRefId, "reference1-field", "reference1");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, contentRefId);
@ -1002,7 +1003,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
{
Query = @"
query {
findMyRefSchema1Content(id: '{contentId}') {
findMyReference1Content(id: '{contentId}') {
id
referencingMySchemaContentsWithTotal(top: 30, skip: 5) {
total
@ -1027,7 +1028,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
{
data = new
{
findMyRefSchema1Content = new
findMyReference1Content = new
{
id = contentRefId,
referencingMySchemaContentsWithTotal = new
@ -1059,7 +1060,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
public async Task Should_also_fetch_references_contents_if_field_is_included_in_query()
{
var contentRefId = DomainId.NewGuid();
var contentRef = TestContent.CreateRef(TestSchemas.Ref1Id, contentRefId, "ref1-field", "ref1");
var contentRef = TestContent.CreateRef(TestSchemas.Reference1.NamedId(), contentRefId, "reference1-field", "reference1");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, contentRefId);
@ -1080,7 +1081,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
query {
findMySchemaContent(id: '{contentId}') {
id
referencesMyRefSchema1Contents(top: 30, skip: 5) {
referencesMyReference1Contents(top: 30, skip: 5) {
id
}
}
@ -1098,7 +1099,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
findMySchemaContent = new
{
id = contentId,
referencesMyRefSchema1Contents = new[]
referencesMyReference1Contents = new[]
{
new
{
@ -1116,7 +1117,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
public async Task Should_also_fetch_references_contents_with_total_if_field_is_included_in_query()
{
var contentRefId = DomainId.NewGuid();
var contentRef = TestContent.CreateRef(TestSchemas.Ref1Id, contentRefId, "ref1-field", "ref1");
var contentRef = TestContent.CreateRef(TestSchemas.Reference1.NamedId(), contentRefId, "reference1-field", "reference1");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, contentRefId);
@ -1137,7 +1138,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
query {
findMySchemaContent(id: '{contentId}') {
id
referencesMyRefSchema1ContentsWithTotal(top: 30, skip: 5) {
referencesMyReference1ContentsWithTotal(top: 30, skip: 5) {
total
items {
id
@ -1158,7 +1159,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
findMySchemaContent = new
{
id = contentId,
referencesMyRefSchema1ContentsWithTotal = new
referencesMyReference1ContentsWithTotal = new
{
total = 10,
items = new[]
@ -1180,7 +1181,7 @@ public class GraphQLQueriesTests : GraphQLTestBase
public async Task Should_also_fetch_union_contents_if_field_is_included_in_query()
{
var contentRefId = DomainId.NewGuid();
var contentRef = TestContent.CreateRef(TestSchemas.Ref1Id, contentRefId, "schemaRef1Field", "ref1");
var contentRef = TestContent.CreateRef(TestSchemas.Reference1.NamedId(), contentRefId, "reference1-field", "reference1");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, contentRefId);
@ -1207,9 +1208,9 @@ public class GraphQLQueriesTests : GraphQLTestBase
... on Content {
id
}
... on MyRefSchema1 {
... on MyReference1 {
data {
schemaRef1Field {
reference1Field {
iv
}
}
@ -1244,12 +1245,12 @@ public class GraphQLQueriesTests : GraphQLTestBase
id = contentRefId,
data = new
{
schemaRef1Field = new
reference1Field = new
{
iv = "ref1"
iv = "reference1"
}
},
__typename = "MyRefSchema1"
__typename = "MyReference1"
}
}
}

2
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs

@ -76,7 +76,7 @@ public abstract class GraphQLTestBase : IClassFixture<TranslationsFixture>
protected Task<ExecutionResult> ExecuteAsync(TestQuery query)
{
// Use a shared instance to test caching.
sut ??= CreateSut(TestSchemas.Default, TestSchemas.Ref1, TestSchemas.Ref2);
sut ??= CreateSut(TestSchemas.Default, TestSchemas.Reference1, TestSchemas.Reference2, TestSchemas.Component);
var options = query.ToOptions(sut.Services);

185
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/TestContent.cs

@ -7,6 +7,7 @@
using NodaTime;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json.Objects;
@ -88,7 +89,7 @@ public static class TestContent
iv {
schemaId
schemaName
schemaRef1Field
componentField
}
}
myComponents__Dynamic {
@ -97,15 +98,20 @@ public static class TestContent
myComponents {
iv {
__typename
... on MyRefSchema1Component {
... on MyReference1Component {
schemaId
schemaName
schemaRef1Field
reference1Field
}
... on MyRefSchema2Component {
... on MyReference2Component {
schemaId
schemaName
schemaRef2Field
reference2Field
}
... on MyComponentComponent {
schemaId
schemaName
componentField
}
}
}
@ -176,20 +182,25 @@ public static class TestContent
myComponent {
schemaId
schemaName
schemaRef1Field
componentField
}
myComponents__Dynamic
myComponents {
__typename
... on MyRefSchema1Component {
... on MyReference1Component {
schemaId
schemaName
reference1Field
}
... on MyReference2Component {
schemaId
schemaName
schemaRef1Field
reference2Field
}
... on MyRefSchema2Component {
... on MyComponentComponent {
schemaId
schemaName
schemaRef2Field
componentField
}
}
myTags
@ -249,21 +260,25 @@ public static class TestContent
new ContentFieldData()
.AddInvariant(
JsonValue.Object()
.Add(Component.Discriminator, TestSchemas.Ref1.Id)
.Add(Component.Descriptor, TestSchemas.Ref1.SchemaDef.Name)
.Add("schemaRef1Field", "Component1")))
.Add(Component.Discriminator, TestSchemas.Component.Id)
.Add(Component.Descriptor, TestSchemas.Component.SchemaDef.Name)
.Add("component-field", "Component1")))
.AddField("my-components",
new ContentFieldData()
.AddInvariant(
JsonValue.Array(
JsonValue.Object()
.Add(Component.Discriminator, TestSchemas.Ref1.Id)
.Add(Component.Descriptor, TestSchemas.Ref1.SchemaDef.Name)
.Add("schemaRef1Field", "Component1"),
.Add(Component.Discriminator, TestSchemas.Reference1.Id)
.Add(Component.Descriptor, TestSchemas.Reference1.SchemaDef.Name)
.Add("reference1-field", "Component1"),
JsonValue.Object()
.Add(Component.Discriminator, TestSchemas.Ref2.Id)
.Add(Component.Descriptor, TestSchemas.Ref2.SchemaDef.Name)
.Add("schemaRef2Field", "Component2"))))
.Add(Component.Discriminator, TestSchemas.Reference2.Id)
.Add(Component.Descriptor, TestSchemas.Reference2.SchemaDef.Name)
.Add("reference2-field", "Component2"),
JsonValue.Object()
.Add(Component.Discriminator, TestSchemas.Component.Id)
.Add(Component.Descriptor, TestSchemas.Component.SchemaDef.Name)
.Add("component-field", "Component3"))))
.AddField("my-json",
new ContentFieldData()
.AddInvariant(
@ -321,7 +336,7 @@ public static class TestContent
LastModified = now,
LastModifiedBy = RefToken.Client("client1"),
Data = data,
SchemaId = TestSchemas.DefaultId,
SchemaId = TestSchemas.Default.NamedId(),
Status = Status.Draft,
StatusColor = "red",
NewStatus = Status.Published,
@ -492,9 +507,9 @@ public static class TestContent
{
iv = new Dictionary<string, object>
{
["schemaId"] = TestSchemas.Ref1.Id.ToString(),
["schemaName"] = TestSchemas.Ref1.SchemaDef.Name,
["schemaRef1Field"] = "Component1"
["schemaId"] = TestSchemas.Component.Id.ToString(),
["schemaName"] = TestSchemas.Component.SchemaDef.Name,
["componentField"] = "Component1"
}
},
["myComponents"] = new
@ -503,15 +518,21 @@ public static class TestContent
{
new Dictionary<string, object>
{
["schemaId"] = TestSchemas.Ref1.Id.ToString(),
["schemaName"] = TestSchemas.Ref1.SchemaDef.Name,
["schemaRef1Field"] = "Component1"
["schemaId"] = TestSchemas.Reference1.Id.ToString(),
["schemaName"] = TestSchemas.Reference1.SchemaDef.Name,
["reference1Field"] = "Component1"
},
new Dictionary<string, object>
{
["schemaId"] = TestSchemas.Ref2.Id.ToString(),
["schemaName"] = TestSchemas.Ref2.SchemaDef.Name,
["schemaRef2Field"] = "Component2"
["schemaId"] = TestSchemas.Reference2.Id.ToString(),
["schemaName"] = TestSchemas.Reference2.SchemaDef.Name,
["reference2Field"] = "Component2"
},
new Dictionary<string, object>
{
["schemaId"] = TestSchemas.Component.Id.ToString(),
["schemaName"] = TestSchemas.Component.SchemaDef.Name,
["componentField"] = "Component3"
}
}
},
@ -659,18 +680,18 @@ public static class TestContent
{
iv = new Dictionary<string, object>
{
["schemaId"] = TestSchemas.Ref1.Id.ToString(),
["schemaName"] = TestSchemas.Ref1.SchemaDef.Name,
["schemaRef1Field"] = "Component1"
["schemaId"] = TestSchemas.Component.Id.ToString(),
["schemaName"] = TestSchemas.Component.SchemaDef.Name,
["component-field"] = "Component1"
}
},
["myComponent"] = new
{
iv = new Dictionary<string, object>
{
["schemaId"] = TestSchemas.Ref1.Id.ToString(),
["schemaName"] = TestSchemas.Ref1.SchemaDef.Name,
["schemaRef1Field"] = "Component1"
["schemaId"] = TestSchemas.Component.Id.ToString(),
["schemaName"] = TestSchemas.Component.SchemaDef.Name,
["componentField"] = "Component1"
}
},
["myComponents__Dynamic"] = new
@ -679,15 +700,21 @@ public static class TestContent
{
new Dictionary<string, object>
{
["schemaId"] = TestSchemas.Ref1.Id.ToString(),
["schemaName"] = TestSchemas.Ref1.SchemaDef.Name,
["schemaRef1Field"] = "Component1"
["schemaId"] = TestSchemas.Reference1.Id.ToString(),
["schemaName"] = TestSchemas.Reference1.SchemaDef.Name,
["reference1-field"] = "Component1"
},
new Dictionary<string, object>
{
["schemaId"] = TestSchemas.Reference2.Id.ToString(),
["schemaName"] = TestSchemas.Reference2.SchemaDef.Name,
["reference2-field"] = "Component2"
},
new Dictionary<string, object>
{
["schemaId"] = TestSchemas.Ref2.Id.ToString(),
["schemaName"] = TestSchemas.Ref2.SchemaDef.Name,
["schemaRef2Field"] = "Component2"
["schemaId"] = TestSchemas.Component.Id.ToString(),
["schemaName"] = TestSchemas.Component.SchemaDef.Name,
["component-field"] = "Component3"
}
}
},
@ -697,17 +724,24 @@ public static class TestContent
{
new Dictionary<string, object>
{
["__typename"] = "MyRefSchema1Component",
["schemaId"] = TestSchemas.Ref1.Id.ToString(),
["schemaName"] = TestSchemas.Ref1.SchemaDef.Name,
["schemaRef1Field"] = "Component1"
["__typename"] = "MyReference1Component",
["schemaId"] = TestSchemas.Reference1.Id.ToString(),
["schemaName"] = TestSchemas.Reference1.SchemaDef.Name,
["reference1Field"] = "Component1"
},
new Dictionary<string, object>
{
["__typename"] = "MyReference2Component",
["schemaId"] = TestSchemas.Reference2.Id.ToString(),
["schemaName"] = TestSchemas.Reference2.SchemaDef.Name,
["reference2Field"] = "Component2"
},
new Dictionary<string, object>
{
["__typename"] = "MyRefSchema2Component",
["schemaId"] = TestSchemas.Ref2.Id.ToString(),
["schemaName"] = TestSchemas.Ref2.SchemaDef.Name,
["schemaRef2Field"] = "Component2"
["__typename"] = "MyComponentComponent",
["schemaId"] = TestSchemas.Component.Id.ToString(),
["schemaName"] = TestSchemas.Component.SchemaDef.Name,
["componentField"] = "Component3"
}
}
},
@ -788,46 +822,59 @@ public static class TestContent
},
["myComponent__Dynamic"] = new Dictionary<string, object>
{
["schemaId"] = TestSchemas.Ref1.Id.ToString(),
["schemaName"] = TestSchemas.Ref1.SchemaDef.Name,
["schemaRef1Field"] = "Component1"
["schemaId"] = TestSchemas.Component.Id.ToString(),
["schemaName"] = TestSchemas.Component.SchemaDef.Name,
["component-field"] = "Component1"
},
["myComponent"] = new Dictionary<string, object>
{
["schemaId"] = TestSchemas.Ref1.Id.ToString(),
["schemaName"] = TestSchemas.Ref1.SchemaDef.Name,
["schemaRef1Field"] = "Component1"
["schemaId"] = TestSchemas.Component.Id.ToString(),
["schemaName"] = TestSchemas.Component.SchemaDef.Name,
["componentField"] = "Component1"
},
["myComponents__Dynamic"] = new[]
{
new Dictionary<string, object>
{
["schemaId"] = TestSchemas.Ref1.Id.ToString(),
["schemaName"] = TestSchemas.Ref1.SchemaDef.Name,
["schemaRef1Field"] = "Component1"
["schemaId"] = TestSchemas.Reference1.Id.ToString(),
["schemaName"] = TestSchemas.Reference1.SchemaDef.Name,
["reference1-field"] = "Component1"
},
new Dictionary<string, object>
{
["schemaId"] = TestSchemas.Ref2.Id.ToString(),
["schemaName"] = TestSchemas.Ref2.SchemaDef.Name,
["schemaRef2Field"] = "Component2"
["schemaId"] = TestSchemas.Reference2.Id.ToString(),
["schemaName"] = TestSchemas.Reference2.SchemaDef.Name,
["reference2-field"] = "Component2"
},
new Dictionary<string, object>
{
["schemaId"] = TestSchemas.Component.Id.ToString(),
["schemaName"] = TestSchemas.Component.SchemaDef.Name,
["component-field"] = "Component3"
}
},
["myComponents"] = new object[]
{
new Dictionary<string, object>
{
["__typename"] = "MyRefSchema1Component",
["schemaId"] = TestSchemas.Ref1.Id.ToString(),
["schemaName"] = TestSchemas.Ref1.SchemaDef.Name,
["schemaRef1Field"] = "Component1"
["__typename"] = "MyReference1Component",
["schemaId"] = TestSchemas.Reference1.Id.ToString(),
["schemaName"] = TestSchemas.Reference1.SchemaDef.Name,
["reference1Field"] = "Component1"
},
new Dictionary<string, object>
{
["__typename"] = "MyReference2Component",
["schemaId"] = TestSchemas.Reference2.Id.ToString(),
["schemaName"] = TestSchemas.Reference2.SchemaDef.Name,
["reference2Field"] = "Component2"
},
new Dictionary<string, object>
{
["__typename"] = "MyRefSchema2Component",
["schemaId"] = TestSchemas.Ref2.Id.ToString(),
["schemaName"] = TestSchemas.Ref2.SchemaDef.Name,
["schemaRef2Field"] = "Component2"
["__typename"] = "MyComponentComponent",
["schemaId"] = TestSchemas.Component.Id.ToString(),
["schemaName"] = TestSchemas.Component.SchemaDef.Name,
["componentField"] = "Component3"
}
},
["myTags"] = new[]

2
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/TestQuery.cs

@ -73,7 +73,7 @@ public sealed class TestQuery
return new Context(Mocks.FrontendUser(), TestApp.Default);
}
var permission = PermissionIds.ForApp(permissionId, TestApp.Default.Name, TestSchemas.DefaultId.Name).Id;
var permission = PermissionIds.ForApp(permissionId, TestApp.Default.Name, TestSchemas.Default.SchemaDef.Name).Id;
return new Context(Mocks.FrontendUser(permission: permission), TestApp.Default);
}

45
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/TestSchemas.cs

@ -16,26 +16,13 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL;
public static class TestSchemas
{
public static readonly NamedId<DomainId> DefaultId = NamedId.Of(DomainId.NewGuid(), "my-schema");
public static readonly NamedId<DomainId> Ref1Id = NamedId.Of(DomainId.NewGuid(), "my-ref-schema1");
public static readonly NamedId<DomainId> Ref2Id = NamedId.Of(DomainId.NewGuid(), "my-ref-schema2");
public static readonly ISchemaEntity Default;
public static readonly ISchemaEntity Ref1;
public static readonly ISchemaEntity Ref2;
public static readonly ISchemaEntity Reference1;
public static readonly ISchemaEntity Reference2;
public static readonly ISchemaEntity Component;
static TestSchemas()
{
Ref1 = Mocks.Schema(TestApp.DefaultId, Ref1Id,
new Schema(Ref1Id.Name)
.Publish()
.AddString(1, "schemaRef1Field", Partitioning.Invariant));
Ref2 = Mocks.Schema(TestApp.DefaultId, Ref2Id,
new Schema(Ref2Id.Name)
.Publish()
.AddString(1, "schemaRef2Field", Partitioning.Invariant));
var enums = ReadonlyList.Create("EnumA", "EnumB", "EnumC");
var jsonSchema = @"
@ -56,8 +43,22 @@ public static class TestSchemas
nestedArray: [String]
}";
Default = Mocks.Schema(TestApp.DefaultId, DefaultId,
new Schema(DefaultId.Name)
Component = Mocks.Schema(TestApp.DefaultId, DomainId.NewGuid(),
new Schema("my-component", type: SchemaType.Component)
.AddString(1, "component-field", Partitioning.Invariant));
Reference1 = Mocks.Schema(TestApp.DefaultId, DomainId.NewGuid(),
new Schema("my-reference1")
.Publish()
.AddString(1, "reference1-field", Partitioning.Invariant));
Reference2 = Mocks.Schema(TestApp.DefaultId, DomainId.NewGuid(),
new Schema("my-reference2")
.Publish()
.AddString(1, "reference2-field", Partitioning.Invariant));
Default = Mocks.Schema(TestApp.DefaultId, DomainId.NewGuid(),
new Schema("my-schema")
.Publish()
.AddJson(1, "my-json", Partitioning.Invariant,
new JsonFieldProperties())
@ -78,15 +79,15 @@ public static class TestSchemas
.AddDateTime(9, "my-datetime", Partitioning.Invariant,
new DateTimeFieldProperties())
.AddReferences(10, "my-references", Partitioning.Invariant,
new ReferencesFieldProperties { SchemaId = Ref1Id.Id })
new ReferencesFieldProperties { SchemaId = Reference1.Id })
.AddReferences(11, "my-union", Partitioning.Invariant,
new ReferencesFieldProperties())
.AddGeolocation(12, "my-geolocation", Partitioning.Invariant,
new GeolocationFieldProperties())
.AddComponent(13, "my-component", Partitioning.Invariant,
new ComponentFieldProperties { SchemaId = Ref1Id.Id })
new ComponentFieldProperties { SchemaId = Component.Id })
.AddComponents(14, "my-components", Partitioning.Invariant,
new ComponentsFieldProperties { SchemaIds = ReadonlyList.Create(Ref1.Id, Ref2.Id) })
new ComponentsFieldProperties { SchemaIds = ReadonlyList.Create(Reference1.Id, Reference2.Id, Component.Id) })
.AddTags(15, "my-tags", Partitioning.Invariant,
new TagsFieldProperties())
.AddTags(16, "my-tags-enum", Partitioning.Invariant,
@ -97,7 +98,7 @@ public static class TestSchemas
.AddNumber(122, "nested-number",
new NumberFieldProperties()))
.AddString(17, "my-embeds", Partitioning.Invariant,
new StringFieldProperties { IsEmbeddable = true, SchemaIds = ReadonlyList.Create(Ref1.Id, Ref2.Id) })
new StringFieldProperties { IsEmbeddable = true, SchemaIds = ReadonlyList.Create(Reference1.Id, Reference2.Id) })
.SetScripts(new SchemaScripts { Query = "<query-script>" }));
}
}

6
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/MongoDb/ContentsQueryFixture.cs

@ -221,12 +221,10 @@ public abstract class ContentsQueryFixture : IAsyncLifetime
new Schema("my-schema")
.AddField(Fields.Number(1, "value", Partitioning.Invariant));
var schema =
return
Mocks.Schema(
NamedId.Of(appId, "my-app"),
NamedId.Of(schemaId, "my-schema"),
schemaId,
schemaDef);
return schema;
}
}

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

@ -21,14 +21,14 @@ public class ResolveReferencesTests : GivenContext, IClassFixture<TranslationsFi
{
private readonly IContentQueryService contentQuery = A.Fake<IContentQueryService>();
private readonly IRequestCache requestCache = A.Fake<IRequestCache>();
private readonly NamedId<DomainId> refSchemaId1 = NamedId.Of(DomainId.NewGuid(), "my-ref1");
private readonly NamedId<DomainId> refSchemaId2 = NamedId.Of(DomainId.NewGuid(), "my-ref2");
private readonly NamedId<DomainId> referenceSchemaId1 = NamedId.Of(DomainId.NewGuid(), "my-ref1");
private readonly NamedId<DomainId> referenceSchemaId2 = NamedId.Of(DomainId.NewGuid(), "my-ref2");
private readonly ProvideSchema schemaProvider;
private readonly ResolveReferences sut;
public ResolveReferencesTests()
{
var refSchemaDef =
var referencedSchemaDef =
new Schema("my-ref")
.AddString(1, "name", Partitioning.Invariant,
new StringFieldProperties())
@ -43,14 +43,14 @@ public class ResolveReferencesTests : GivenContext, IClassFixture<TranslationsFi
ResolveReference = true,
MinItems = 1,
MaxItems = 1,
SchemaId = refSchemaId1.Id
SchemaId = referenceSchemaId1.Id
})
.AddReferences(2, "ref2", Partitioning.Invariant, new ReferencesFieldProperties
{
ResolveReference = true,
MinItems = 1,
MaxItems = 1,
SchemaId = refSchemaId2.Id
SchemaId = referenceSchemaId2.Id
})
.SetFieldsInLists("ref1", "ref2");
@ -63,13 +63,13 @@ public class ResolveReferencesTests : GivenContext, IClassFixture<TranslationsFi
{
return Task.FromResult((Schema, ResolvedComponents.Empty));
}
else if (x == refSchemaId1.Id)
else if (x == referenceSchemaId1.Id)
{
return Task.FromResult((Mocks.Schema(AppId, refSchemaId1, refSchemaDef), ResolvedComponents.Empty));
return Task.FromResult((Mocks.Schema(AppId, referenceSchemaId1.Id, referencedSchemaDef), ResolvedComponents.Empty));
}
else if (x == refSchemaId2.Id)
else if (x == referenceSchemaId2.Id)
{
return Task.FromResult((Mocks.Schema(AppId, refSchemaId2, refSchemaDef), ResolvedComponents.Empty));
return Task.FromResult((Mocks.Schema(AppId, referenceSchemaId2.Id, referencedSchemaDef), ResolvedComponents.Empty));
}
else
{
@ -83,10 +83,10 @@ public class ResolveReferencesTests : GivenContext, IClassFixture<TranslationsFi
[Fact]
public async Task Should_add_referenced_id_and_as_dependency()
{
var ref1_1 = CreateRefContent(DomainId.NewGuid(), 1, "ref1_1", 13, refSchemaId1);
var ref1_2 = CreateRefContent(DomainId.NewGuid(), 2, "ref1_2", 17, refSchemaId1);
var ref2_1 = CreateRefContent(DomainId.NewGuid(), 3, "ref2_1", 23, refSchemaId2);
var ref2_2 = CreateRefContent(DomainId.NewGuid(), 4, "ref2_2", 29, refSchemaId2);
var ref1_1 = CreateRefContent(DomainId.NewGuid(), 1, "ref1_1", 13, referenceSchemaId1);
var ref1_2 = CreateRefContent(DomainId.NewGuid(), 2, "ref1_2", 17, referenceSchemaId1);
var ref2_1 = CreateRefContent(DomainId.NewGuid(), 3, "ref2_1", 23, referenceSchemaId2);
var ref2_2 = CreateRefContent(DomainId.NewGuid(), 4, "ref2_2", 29, referenceSchemaId2);
var contents = new[]
{
@ -100,10 +100,10 @@ public class ResolveReferencesTests : GivenContext, IClassFixture<TranslationsFi
await sut.EnrichAsync(FrontendContext, contents, schemaProvider, default);
A.CallTo(() => requestCache.AddDependency(DomainId.Combine(AppId, refSchemaId1.Id), 0))
A.CallTo(() => requestCache.AddDependency(DomainId.Combine(AppId, referenceSchemaId1.Id), 0))
.MustHaveHappened();
A.CallTo(() => requestCache.AddDependency(DomainId.Combine(AppId, refSchemaId2.Id), 0))
A.CallTo(() => requestCache.AddDependency(DomainId.Combine(AppId, referenceSchemaId2.Id), 0))
.MustHaveHappened();
A.CallTo(() => requestCache.AddDependency(ref1_1.UniqueId, ref1_1.Version))
@ -122,10 +122,10 @@ public class ResolveReferencesTests : GivenContext, IClassFixture<TranslationsFi
[Fact]
public async Task Should_enrich_with_reference_data()
{
var ref1_1 = CreateRefContent(DomainId.NewGuid(), 1, "ref1_1", 13, refSchemaId1);
var ref1_2 = CreateRefContent(DomainId.NewGuid(), 2, "ref1_2", 17, refSchemaId1);
var ref2_1 = CreateRefContent(DomainId.NewGuid(), 3, "ref2_1", 23, refSchemaId2);
var ref2_2 = CreateRefContent(DomainId.NewGuid(), 3, "ref2_2", 29, refSchemaId2);
var ref1_1 = CreateRefContent(DomainId.NewGuid(), 1, "ref1_1", 13, referenceSchemaId1);
var ref1_2 = CreateRefContent(DomainId.NewGuid(), 2, "ref1_2", 17, referenceSchemaId1);
var ref2_1 = CreateRefContent(DomainId.NewGuid(), 3, "ref2_1", 23, referenceSchemaId2);
var ref2_2 = CreateRefContent(DomainId.NewGuid(), 3, "ref2_2", 29, referenceSchemaId2);
var contents = new[]
{
@ -175,10 +175,10 @@ public class ResolveReferencesTests : GivenContext, IClassFixture<TranslationsFi
[Fact]
public async Task Should_not_enrich_if_content_has_more_items()
{
var ref1_1 = CreateRefContent(DomainId.NewGuid(), 1, "ref1_1", 13, refSchemaId1);
var ref1_2 = CreateRefContent(DomainId.NewGuid(), 2, "ref1_2", 17, refSchemaId1);
var ref2_1 = CreateRefContent(DomainId.NewGuid(), 3, "ref2_1", 23, refSchemaId2);
var ref2_2 = CreateRefContent(DomainId.NewGuid(), 4, "ref2_2", 29, refSchemaId2);
var ref1_1 = CreateRefContent(DomainId.NewGuid(), 1, "ref1_1", 13, referenceSchemaId1);
var ref1_2 = CreateRefContent(DomainId.NewGuid(), 2, "ref1_2", 17, referenceSchemaId1);
var ref2_1 = CreateRefContent(DomainId.NewGuid(), 3, "ref2_1", 23, referenceSchemaId2);
var ref2_2 = CreateRefContent(DomainId.NewGuid(), 4, "ref2_2", 29, referenceSchemaId2);
var contents = new[]
{

2
backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/SchemasSearchSourceTests.cs

@ -119,6 +119,6 @@ public class SchemasSearchSourceTests : GivenContext, IClassFixture<Translations
private ISchemaEntity CreateSchema(string name, SchemaType type = SchemaType.Default)
{
return Mocks.Schema(AppId, NamedId.Of(DomainId.NewGuid(), name), new Schema(name, type: type));
return Mocks.Schema(AppId, DomainId.NewGuid(), new Schema(name, type: type));
}
}

27
backend/tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/Mocks.cs

@ -39,18 +39,29 @@ public static class Mocks
return app;
}
public static ISchemaEntity Schema(NamedId<DomainId> appId, NamedId<DomainId> schemaId, Schema? schemaDef = null)
public static ISchemaEntity Schema(NamedId<DomainId> appId, NamedId<DomainId> schemaId)
{
var schema = A.Fake<ISchemaEntity>();
var schemaEntity = A.Fake<ISchemaEntity>();
var schemaDef = new Schema(schemaId.Name).Publish();
schemaDef ??= new Schema(schemaId.Name).Publish();
A.CallTo(() => schemaEntity.Id).Returns(schemaId.Id);
A.CallTo(() => schemaEntity.AppId).Returns(appId);
A.CallTo(() => schemaEntity.SchemaDef).Returns(schemaDef);
A.CallTo(() => schemaEntity.UniqueId).Returns(DomainId.Combine(appId, schemaId.Id));
A.CallTo(() => schema.Id).Returns(schemaId.Id);
A.CallTo(() => schema.AppId).Returns(appId);
A.CallTo(() => schema.SchemaDef).Returns(schemaDef);
A.CallTo(() => schema.UniqueId).Returns(DomainId.Combine(appId, schemaId.Id));
return schemaEntity;
}
public static ISchemaEntity Schema(NamedId<DomainId> appId, DomainId schemaId, Schema schemaDef)
{
var schemaEntity = A.Fake<ISchemaEntity>();
A.CallTo(() => schemaEntity.Id).Returns(schemaId);
A.CallTo(() => schemaEntity.AppId).Returns(appId);
A.CallTo(() => schemaEntity.SchemaDef).Returns(schemaDef);
A.CallTo(() => schemaEntity.UniqueId).Returns(DomainId.Combine(appId, schemaId));
return schema;
return schemaEntity;
}
public static ITeamEntity Team(DomainId teamId, string teamName)

60
tools/TestSuite/TestSuite.ApiTests/GraphQLFixture.cs

@ -63,6 +63,23 @@ public sealed class GraphQLFixture : ContentFixture
}
}
var createLocationRequest = new CreateSchemaDto
{
Name = "location",
Fields = new List<UpsertSchemaFieldDto>
{
new UpsertSchemaFieldDto
{
Name = "name",
Properties = new StringFieldPropertiesDto()
}
},
Type = SchemaType.Component
};
var locationsId = await CreateSchemaAsync(createLocationRequest);
// STEP 1: Create cities schema.
var createCitiesRequest = new CreateSchemaDto
{
@ -73,6 +90,28 @@ public sealed class GraphQLFixture : ContentFixture
{
Name = "name",
Properties = new StringFieldPropertiesDto()
},
new UpsertSchemaFieldDto
{
Name = "topLocation",
Properties = new ComponentFieldPropertiesDto
{
SchemaIds = new List<string>
{
locationsId
}
}
},
new UpsertSchemaFieldDto
{
Name = "locations",
Properties = new ComponentsFieldPropertiesDto
{
SchemaIds = new List<string>
{
locationsId
}
}
}
},
IsPublished = true
@ -149,6 +188,27 @@ public sealed class GraphQLFixture : ContentFixture
name = new
{
iv = name
},
topLocation = new
{
iv = new
{
name = $"{name} Top Location"
}
},
locations = new
{
iv = new[]
{
new
{
name = $"{name} Location 1",
},
new
{
name = $"{name} Location 2",
}
}
}
};

75
tools/TestSuite/TestSuite.ApiTests/GraphQLTests.cs

@ -6,6 +6,7 @@
// ==========================================================================
using System.Net.Http.Json;
using FluentAssertions;
using Newtonsoft.Json.Linq;
using Squidex.ClientLibrary;
using Squidex.ClientLibrary.Utils;
@ -61,6 +62,80 @@ public sealed class GraphQLTests : IClassFixture<GraphQLFixture>
Assert.Equal(2, result["findMyWritesContent"]["flatData"]["json"]["obj"]["value"].Value<int>());
}
[Fact]
public async Task Should_query_graphql_with_components()
{
var query = new
{
query = @"
{
cities: queryCitiesContents {
data: flatData {
name,
topLocation {
name
},
locations {
name
}
}
}
}"
};
var result = await _.Client.SharedDynamicContents.GraphQlAsync<JToken>(query);
var cities = result["cities"].ToObject<List<City>>();
cities.Should().BeEquivalentTo(new List<City>
{
new City
{
Data = new CityData
{
Name = "Leipzig",
TopLocation = new LocationData
{
Name = "Leipzig Top Location"
},
Locations = new List<LocationData>
{
new LocationData
{
Name = "Leipzig Location 1"
},
new LocationData
{
Name = "Leipzig Location 2"
}
}
}
},
new City
{
Data = new CityData
{
Name = "Munich",
TopLocation = new LocationData
{
Name = "Munich Top Location"
},
Locations = new List<LocationData>
{
new LocationData
{
Name = "Munich Location 1"
},
new LocationData
{
Name = "Munich Location 2"
}
}
}
}
});
}
[Fact]
public async Task Should_query_graphql_by_reference_selector()
{

1
tools/TestSuite/TestSuite.ApiTests/TestSuite.ApiTests.csproj

@ -15,6 +15,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Codeuctivity.ImageSharpCompare" Version="3.0.118" />
<PackageReference Include="FluentAssertions" Version="6.11.0" />
<PackageReference Include="GraphQL.Client" Version="5.1.1" />
<PackageReference Include="GraphQL.Client.Serializer.Newtonsoft" Version="5.1.1" />
<PackageReference Include="Meziantou.Analyzer" Version="2.0.22">

9
tools/TestSuite/TestSuite.Shared/Model/Geography.cs

@ -39,6 +39,15 @@ public sealed class City
}
public sealed class CityData
{
public string Name { get; set; }
public LocationData TopLocation { get; set; }
public List<LocationData> Locations { get; set; }
}
public sealed class LocationData
{
public string Name { get; set; }
}

Loading…
Cancel
Save