Browse Source

Merge branch 'master' of github.com:Squidex/squidex

pull/926/head
Sebastian 3 years ago
parent
commit
4c6cbf822c
  1. 19
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Builder.cs
  2. 2
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/ComponentUnionGraphType.cs
  3. 2
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/EmbeddableStringGraphType.cs
  4. 6
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldVisitor.cs
  5. 5
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/SharedExtensions.cs
  6. 4
      backend/src/Squidex.Domain.Apps.Entities/Squidex.Domain.Apps.Entities.csproj
  7. 6
      backend/src/Squidex.Web/GraphQL/GraphQLRunner.cs
  8. 6
      backend/src/Squidex.Web/Squidex.Web.csproj
  9. 9
      backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs
  10. 6
      backend/src/Squidex/Squidex.csproj
  11. 33
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs
  12. 4
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj
  13. 60
      backend/tools/TestSuite/TestSuite.ApiTests/ContentQueryTests.cs

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

@ -15,6 +15,7 @@ using Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents;
using Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Dynamic;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Collections;
using GraphQLSchema = GraphQL.Types.Schema;
namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types
@ -25,6 +26,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types
private readonly Dictionary<SchemaInfo, ContentGraphType> contentTypes = new Dictionary<SchemaInfo, ContentGraphType>(ReferenceEqualityComparer.Instance);
private readonly Dictionary<SchemaInfo, ContentResultGraphType> contentResultTypes = new Dictionary<SchemaInfo, ContentResultGraphType>(ReferenceEqualityComparer.Instance);
private readonly Dictionary<FieldInfo, EmbeddableStringGraphType> embeddableStringTypes = new Dictionary<FieldInfo, EmbeddableStringGraphType>();
private readonly Dictionary<FieldInfo, ReferenceUnionGraphType> referenceUnionTypes = new Dictionary<FieldInfo, ReferenceUnionGraphType>();
private readonly Dictionary<FieldInfo, ComponentUnionGraphType> componentUnionTypes = new Dictionary<FieldInfo, ComponentUnionGraphType>();
private readonly Dictionary<FieldInfo, NestedGraphType> nestedTypes = new Dictionary<FieldInfo, NestedGraphType>();
private readonly Dictionary<string, EnumerationGraphType?> enumTypes = new Dictionary<string, EnumerationGraphType?>();
private readonly Dictionary<string, IGraphType[]> dynamicTypes = new Dictionary<string, IGraphType[]>();
private readonly FieldVisitor fieldVisitor;
@ -192,6 +196,21 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types
return enumTypes.GetOrAdd(name, x => FieldEnumType.TryCreate(name, values));
}
public ReferenceUnionGraphType GetReferenceUnion(FieldInfo fieldInfo, ReadonlyList<DomainId>? schemaIds)
{
return referenceUnionTypes.GetOrAdd(fieldInfo, x => new ReferenceUnionGraphType(this, x, schemaIds));
}
public ComponentUnionGraphType GetComponentUnion(FieldInfo fieldInfo, ReadonlyList<DomainId>? schemaIds)
{
return componentUnionTypes.GetOrAdd(fieldInfo, x => new ComponentUnionGraphType(this, x, schemaIds));
}
public NestedGraphType GetNested(FieldInfo fieldInfo)
{
return nestedTypes.GetOrAdd(fieldInfo, x => new NestedGraphType(this, x));
}
public IEnumerable<KeyValuePair<SchemaInfo, ContentGraphType>> GetAllContentTypes()
{
return contentTypes;

2
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/ComponentUnionGraphType.cs

@ -22,7 +22,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents
public ComponentUnionGraphType(Builder builder, FieldInfo fieldInfo, ReadonlyList<DomainId>? schemaIds)
{
// The name is used for equal comparison. Therefore it is important to treat it as readonly.
Name = fieldInfo.UnionReferenceType;
Name = fieldInfo.UnionComponentType;
if (schemaIds?.Any() == true)
{

2
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/EmbeddableStringGraphType.cs

@ -48,7 +48,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents
if (contentType == null)
{
var union = new ReferenceUnionGraphType(builder, fieldInfo, schemaIds);
var union = builder.GetReferenceUnion(fieldInfo, schemaIds);
if (!union.HasType)
{

6
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldVisitor.cs

@ -126,7 +126,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents
return default;
}
var type = new NestedGraphType(builder, args);
var type = builder.GetNested(args);
if (type.Fields.Count == 0)
{
@ -263,7 +263,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents
if (contentType == null)
{
var union = new ReferenceUnionGraphType(builder, fieldInfo, schemaIds);
var union = builder.GetReferenceUnion(fieldInfo, schemaIds);
if (!union.HasType)
{
@ -287,7 +287,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents
if (componentType == null)
{
var union = new ComponentUnionGraphType(builder, fieldInfo, schemaIds);
var union = builder.GetComponentUnion(fieldInfo, schemaIds);
if (!union.HasType)
{

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

@ -32,6 +32,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types
if (!string.IsNullOrWhiteSpace(formatted))
{
if (key == "search")
{
formatted = $"\"{formatted.Trim('"')}\"";
}
if (sb.Length > 1)
{
sb.Append('&');

4
backend/src/Squidex.Domain.Apps.Entities/Squidex.Domain.Apps.Entities.csproj

@ -20,8 +20,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="CsvHelper" Version="27.2.1" />
<PackageReference Include="GraphQL" Version="7.0.2" />
<PackageReference Include="GraphQL.DataLoader" Version="7.0.2" />
<PackageReference Include="GraphQL" Version="7.1.1" />
<PackageReference Include="GraphQL.DataLoader" Version="7.1.1" />
<PackageReference Include="Meziantou.Analyzer" Version="1.0.702">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

6
backend/src/Squidex.Web/GraphQL/GraphQLRunner.cs

@ -8,6 +8,7 @@
using GraphQL.Server.Transports.AspNetCore;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Net.Http.Headers;
namespace Squidex.Web.GraphQL
{
@ -19,7 +20,10 @@ namespace Squidex.Web.GraphQL
{
RequestDelegate next = x => Task.CompletedTask;
var options = new GraphQLHttpMiddlewareOptions();
var options = new GraphQLHttpMiddlewareOptions
{
DefaultResponseContentType = new MediaTypeHeaderValue("application/json")
};
middleware = ActivatorUtilities.CreateInstance<GraphQLHttpMiddleware<DummySchema>>(serviceProvider, next, options);
}

6
backend/src/Squidex.Web/Squidex.Web.csproj

@ -13,9 +13,9 @@
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="GraphQL" Version="7.0.2" />
<PackageReference Include="GraphQL.SystemTextJson" Version="7.0.2" />
<PackageReference Include="GraphQL.Server.Transports.AspNetCore" Version="7.0.0" />
<PackageReference Include="GraphQL" Version="7.1.1" />
<PackageReference Include="GraphQL.SystemTextJson" Version="7.1.1" />
<PackageReference Include="GraphQL.Server.Transports.AspNetCore" Version="7.1.1" />
<PackageReference Include="Meziantou.Analyzer" Version="1.0.702">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

9
backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs

@ -24,18 +24,17 @@ namespace Squidex.Areas.Api.Controllers.Contents
{
private readonly IContentQueryService contentQuery;
private readonly IContentWorkflow contentWorkflow;
private readonly GraphQLRunner graphQLMiddleware;
private readonly GraphQLRunner graphQLRunner;
public ContentsController(ICommandBus commandBus,
IContentQueryService contentQuery,
IContentWorkflow contentWorkflow,
GraphQLRunner graphQLMiddleware)
GraphQLRunner graphQLRunner)
: base(commandBus)
{
this.contentQuery = contentQuery;
this.contentWorkflow = contentWorkflow;
this.graphQLMiddleware = graphQLMiddleware;
this.graphQLRunner = graphQLRunner;
}
/// <summary>
@ -57,7 +56,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[ApiCosts(2)]
public Task GetGraphQL(string app)
{
return graphQLMiddleware.InvokeAsync(HttpContext);
return graphQLRunner.InvokeAsync(HttpContext);
}
/// <summary>

6
backend/src/Squidex/Squidex.csproj

@ -35,9 +35,9 @@
<ItemGroup>
<PackageReference Include="AspNet.Security.OAuth.GitHub" Version="6.0.6" />
<PackageReference Include="GraphQL" Version="7.0.2" />
<PackageReference Include="GraphQL.MicrosoftDI" Version="7.0.2" />
<PackageReference Include="GraphQL.SystemTextJson" Version="7.0.2" />
<PackageReference Include="GraphQL" Version="7.1.1" />
<PackageReference Include="GraphQL.MicrosoftDI" Version="7.1.1" />
<PackageReference Include="GraphQL.SystemTextJson" Version="7.1.1" />
<PackageReference Include="Meziantou.Analyzer" Version="1.0.702">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

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

@ -46,6 +46,39 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
AssertResult(expected, actual);
}
[Fact]
public async Task Should_query_contents_with_full_text()
{
var query = CreateQuery(@"
query {
queryMySchemaContents(search: ""Hello"") {
<FIELDS_CONTENT_FLAT>
}
}");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), TestSchemas.Default.Id.ToString(),
A<Q>.That.Matches(x => x.QueryAsOdata == "?$skip=0&$search=\"Hello\"" && x.NoTotal), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, content));
var actual = await ExecuteAsync(new ExecutionOptions { Query = query });
var expected = new
{
data = new
{
queryMySchemaContents = new[]
{
TestContent.FlatResponse(content)
}
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_return_multiple_assets_if_querying_assets()
{

4
backend/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj

@ -23,8 +23,8 @@
<ItemGroup>
<PackageReference Include="FakeItEasy" Version="7.3.1" />
<PackageReference Include="FluentAssertions" Version="6.7.0" />
<PackageReference Include="GraphQL" Version="7.0.2" />
<PackageReference Include="GraphQL.SystemTextJson" Version="7.0.2" />
<PackageReference Include="GraphQL" Version="7.1.1" />
<PackageReference Include="GraphQL.SystemTextJson" Version="7.1.1" />
<PackageReference Include="Lorem.Universal.Net" Version="4.0.80" />
<PackageReference Include="Meziantou.Analyzer" Version="1.0.702">
<PrivateAssets>all</PrivateAssets>

60
backend/tools/TestSuite/TestSuite.ApiTests/ContentQueryTests.cs

@ -8,6 +8,7 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Squidex.ClientLibrary;
using Squidex.ClientLibrary.Utils;
using TestSuite.Model;
#pragma warning disable SA1300 // Element should begin with upper-case letter
@ -627,6 +628,65 @@ namespace TestSuite.ApiTests
Assert.Equal(items.Select(x => x["data"]["number"]["iv"].Value<int>()).ToArray(), new[] { 4, 5, 6 });
}
[Fact]
public async Task Should_query_items_complex_search()
{
var query = new
{
query = @"
query ContentsQuery($search: String!) {
queryMyReadsContents(search: $search) {
id,
data {
number {
iv
}
}
}
}",
variables = new
{
search = @"The answer is 42"
}
};
await _.Contents.GraphQlAsync<QueryResult>(query);
}
[Fact]
public async Task Should_return_correct_content_type_for_graphql()
{
var query = new
{
query = @"
query ContentsQuery($filter: String!) {
queryMyReadsContents(filter: $filter, orderby: ""data/number/iv asc"") {
id,
data {
number {
iv
}
}
}
}",
variables = new
{
filter = @"data/number/iv gt 3 and data/number/iv lt 7"
}
};
using (var client = _.ClientManager.CreateHttpClient())
{
var response = await client.PostAsync(_.ClientManager.GenerateUrl($"api/content/{_.AppName}/graphql/batch"), query.ToContent());
Assert.Equal("application/json", response.Content.Headers.ContentType.MediaType);
var result = await response.Content.ReadAsJsonAsync<GraphQlResponse<QueryResult>>();
Assert.Equal(result.Data.Items.Select(x => x.Data.Number).ToArray(), new[] { 4, 5, 6 });
}
}
private sealed class QueryResult
{
[JsonProperty("queryMyReadsContents")]

Loading…
Cancel
Save