// ========================================================================== // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex UG (haftungsbeschraenkt) // All rights reserved. Licensed under the MIT license. // ========================================================================== using GraphQL.Types; using Squidex.Domain.Apps.Core; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Entities.Contents.GraphQL.Types; using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Infrastructure; using GraphQLSchema = GraphQL.Types.Schema; using Schema = Squidex.Domain.Apps.Core.Schemas.Schema; namespace Squidex.Domain.Apps.Entities.Contents.GraphQL; public class GraphQLIntrospectionTests : GraphQLTestBase { [Fact] public async Task Should_introspect() { var actual = await ExecuteAsync(new TestQuery { Query = @" query IntrospectionQuery { __schema { queryType { name } mutationType { name } subscriptionType { name } types { ...FullType } directives { name description args { ...InputValue } onOperation onFragment onField } } } fragment FullType on __Type { kind name description fields(includeDeprecated: true) { name description args { ...InputValue } type { ...TypeRef } isDeprecated deprecationReason } inputFields { ...InputValue } interfaces { ...TypeRef } enumValues(includeDeprecated: true) { name description isDeprecated deprecationReason } possibleTypes { ...TypeRef } } fragment InputValue on __InputValue { name description type { ...TypeRef } defaultValue } fragment TypeRef on __Type { kind name ofType { kind name ofType { kind name ofType { kind name } } } }", OperationName = "IntrospectionQuery" }); var json = serializer.Serialize(actual); Assert.NotEmpty(json); } [Fact] public async Task Should_build_graphql_schema_without_schemas() { var model = await CreateSut().GetSchemaAsync(TestApp.Default); Assert.NotNull(model); } [Fact] public async Task Should_build_graphql_schema_without_schema() { var schema = Mocks.Schema(TestApp.DefaultId, DomainId.NewGuid(), new Schema("content").Publish()); var model = await CreateSut(schema).GetSchemaAsync(TestApp.Default); Assert.NotNull(model); } [Fact] public async Task Should_build_graphql_schema_on_schema_with_ui_fields_only() { var schema = Mocks.Schema(TestApp.DefaultId, DomainId.NewGuid(), new Schema("content").Publish() .AddUI(1, "ui", Partitioning.Invariant)); var model = await CreateSut(schema).GetSchemaAsync(TestApp.Default); Assert.NotNull(model); } [Fact] public async Task Should_build_graphql_schema_on_schema_with_invalid_fields_only() { var schema = Mocks.Schema(TestApp.DefaultId, DomainId.NewGuid(), new Schema("content").Publish() .AddComponent(1, "component", Partitioning.Invariant)); var model = await CreateSut(schema).GetSchemaAsync(TestApp.Default); Assert.NotNull(model); } [Fact] public async Task Should_build_graphql_schema_on_unpublished_schema() { var schema = Mocks.Schema(TestApp.DefaultId, DomainId.NewGuid(), new Schema("content") .AddString(1, "myField", Partitioning.Invariant)); var model = await CreateSut(schema).GetSchemaAsync(TestApp.Default); Assert.NotNull(model); } [Fact] public async Task Should_build_graphql_schema_on_reserved_schema_name() { var schema = Mocks.Schema(TestApp.DefaultId, DomainId.NewGuid(), new Schema("content").Publish() .AddString(1, "myField", Partitioning.Invariant)); var graphQLSchema = await CreateSut(schema).GetSchemaAsync(TestApp.Default); Assert.Contains(graphQLSchema.AllTypes, x => x.Name == "Content2"); } [Fact] public async Task Should_build_graphql_schema_with_reserved_field_name() { var schema = Mocks.Schema(TestApp.DefaultId, DomainId.NewGuid(), new Schema("my-schema").Publish() .AddString(1, "content", Partitioning.Invariant)); var graphQLSchema = await CreateSut(schema).GetSchemaAsync(TestApp.Default); var type = FindDataType(graphQLSchema, "MySchema"); Assert.Contains(type?.Fields!, x => x.Name == "content"); } [Fact] public async Task Should_build_graphql_schema_on_invalid_field_name() { var schema = Mocks.Schema(TestApp.DefaultId, DomainId.NewGuid(), new Schema("my-schema").Publish() .AddString(1, "2-field", Partitioning.Invariant)); var graphQLSchema = await CreateSut(schema).GetSchemaAsync(TestApp.Default); var type = FindDataType(graphQLSchema, "MySchema"); Assert.Contains(type?.Fields!, x => x.Name == "gql_2Field"); } [Fact] public async Task Should_build_graphql_schema_on_duplicate_field_name() { var schema = Mocks.Schema(TestApp.DefaultId, DomainId.NewGuid(), new Schema("my-schema").Publish() .AddString(1, "my-field", Partitioning.Invariant) .AddString(2, "my_field", Partitioning.Invariant)); var graphQLSchema = await CreateSut(schema).GetSchemaAsync(TestApp.Default); var type = FindDataType(graphQLSchema, "MySchema"); Assert.Contains(type?.Fields!, x => x.Name == "myField"); Assert.Contains(type?.Fields!, x => x.Name == "myField2"); } [Fact] public async Task Should_not_build_grapqhl_schema_on_invalid_component() { var schema = Mocks.Schema(TestApp.DefaultId, DomainId.NewGuid(), new Schema("my-schema").Publish() .AddComponent(1, "my-component", Partitioning.Invariant, new ComponentFieldProperties()) .AddString(2, "my-string", Partitioning.Invariant)); var graphQLSchema = await CreateSut(schema).GetSchemaAsync(TestApp.Default); var type = FindDataType(graphQLSchema, "MySchema"); Assert.DoesNotContain(type?.Fields!, x => x.Name == "myComponent"); } [Fact] public async Task Should_not_build_grapqhl_schema_on_invalid_components() { var schema = Mocks.Schema(TestApp.DefaultId, DomainId.NewGuid(), new Schema("my-schema").Publish() .AddComponents(1, "my-components", Partitioning.Invariant, new ComponentsFieldProperties()) .AddString(2, "my-string", Partitioning.Invariant)); var graphQLSchema = await CreateSut(schema).GetSchemaAsync(TestApp.Default); var type = FindDataType(graphQLSchema, "MySchema"); Assert.DoesNotContain(type?.Fields!, x => x.Name == "myComponents"); } [Fact] public async Task Should_not_build_grapqhl_schema_on_invalid_references() { var schema = Mocks.Schema(TestApp.DefaultId, DomainId.NewGuid(), new Schema("my-schema").Publish() .AddReferences(1, "my-references", Partitioning.Invariant, new ReferencesFieldProperties { SchemaId = DomainId.NewGuid() }) .AddString(2, "my-string", Partitioning.Invariant)); var graphQLSchema = await CreateSut(schema).GetSchemaAsync(TestApp.Default); var type = FindDataType(graphQLSchema, "MySchema"); Assert.DoesNotContain(type?.Fields!, x => x.Name == "myReferences"); } private static IObjectGraphType? FindDataType(GraphQLSchema graphQLSchema, string schema) { var type = (IObjectGraphType)graphQLSchema.AllTypes.Single(x => x.Name == schema); return (IObjectGraphType?)type.GetField("flatData")?.ResolvedType?.InnerType(); } }