Headless CMS and Content Managment Hub
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1605 lines
47 KiB

// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
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;
namespace Squidex.Domain.Apps.Entities.Contents.GraphQL;
public class GraphQLQueriesTests : GraphQLTestBase
{
[Theory]
[InlineData("")]
[InlineData(" ")]
public async Task Should_return_error_empty_query(string query)
{
var actual = await ExecuteAsync(new TestQuery
{
Query = query
});
var expected = new
{
errors = new object[]
{
new
{
message = "Document does not contain any operations.",
extensions = new
{
code = "NO_OPERATION",
codes = new[]
{
"NO_OPERATION"
}
}
}
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_query_contents_with_full_text()
{
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 TestQuery
{
Query = @"
query {
queryMySchemaContents(search: 'Hello') {
{fields}
}
}",
Args = new
{
fields = TestContent.AllFlatFields
}
});
var expected = new
{
data = new
{
queryMySchemaContents = new[]
{
TestContent.FlatResponse(content)
}
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_query_contents_with_ids()
{
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIds(contentId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, content));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
queryContentsByIds(ids: ['{contentId}']) {
... on Content {
id
}
... on MySchema {
flatData {
myNumber
}
}
}
}",
Args = new
{
contentId
}
});
var expected = new
{
data = new
{
queryContentsByIds = new[]
{
new
{
id = contentId,
flatData = new
{
myNumber = 1
}
}
}
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_query_contents_with_ids_and_dynamic_data()
{
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIds(contentId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, content));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
queryContentsByIds(ids: ['{contentId}']) {
... on Content {
data: data__dynamic
}
}
}",
Args = new
{
contentId
}
});
var expected = new
{
data = new
{
queryContentsByIds = new[]
{
new
{
data = content.Data
}
}
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_return_multiple_assets_if_querying_assets()
{
var asset = TestAsset.Create(DomainId.NewGuid());
A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), null,
A<Q>.That.Matches(x => x.QueryAsOdata == "?$top=30&$skip=5&$filter=my-query" && x.NoTotal),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, asset));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
queryAssets(filter: 'my-query', top: 30, skip: 5) {
{fields}
}
}",
Args = new
{
fields = TestAsset.AllFields
}
});
var expected = new
{
data = new
{
queryAssets = new[]
{
TestAsset.Response(asset)
}
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_return_multiple_assets_with_total_if_querying_assets_with_total()
{
var asset = TestAsset.Create(DomainId.NewGuid());
A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), null,
A<Q>.That.Matches(x => x.QueryAsOdata == "?$top=30&$skip=5&$filter=my-query" && !x.NoTotal),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(10, asset));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
queryAssetsWithTotal(filter: 'my-query', top: 30, skip: 5) {
total
items {
{fields}
}
}
}",
Args = new
{
fields = TestAsset.AllFields
}
});
var expected = new
{
data = new
{
queryAssetsWithTotal = new
{
total = 10,
items = new[]
{
TestAsset.Response(asset)
}
}
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_return_null_if_single_asset_not_found()
{
var assetId = DomainId.NewGuid();
A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), null,
A<Q>.That.HasIdsWithoutTotal(assetId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom<IEnrichedAssetEntity>(1));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
findAsset(id: '{assetId}') {
id,
version
}
}",
Args = new
{
assetId
}
});
var expected = new
{
data = new
{
findAsset = (object?)null
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_return_single_asset_if_finding_asset()
{
var assetId = DomainId.NewGuid();
var asset = TestAsset.Create(assetId);
A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), null,
A<Q>.That.HasIdsWithoutTotal(assetId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, asset));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
findAsset(id: '{assetId}') {
{fields}
}
}",
Args = new
{
assetId,
fields = TestAsset.AllFields
}
});
var expected = new
{
data = new
{
findAsset = TestAsset.Response(asset)
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_return_multiple_flat_contents_if_querying_contents()
{
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 == "?$top=30&$skip=5" && x.NoTotal),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, content));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
queryMySchemaContents(top: 30, skip: 5) {
{fields}
}
}",
Args = new
{
fields = TestContent.AllFlatFields
}
});
var expected = new
{
data = new
{
queryMySchemaContents = new[]
{
TestContent.FlatResponse(content)
}
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_return_multiple_contents_if_querying_contents()
{
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 == "?$top=30&$skip=5" && x.NoTotal),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, content));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
queryMySchemaContents(top: 30, skip: 5) {
{fields}
}
}",
Args = new
{
fields = TestContent.AllFields
}
});
var expected = new
{
data = new
{
queryMySchemaContents = new[]
{
TestContent.Response(content)
}
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_return_multiple_contents_with_total_if_querying_contents_with_total()
{
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 == "?$top=30&$skip=5" && !x.NoTotal),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(10, content));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
queryMySchemaContentsWithTotal(top: 30, skip: 5) {
total
items {
{fields}
}
}
}",
Args = new
{
fields = TestContent.AllFields
}
});
var expected = new
{
data = new
{
queryMySchemaContentsWithTotal = new
{
total = 10,
items = new[]
{
TestContent.Response(content)
}
}
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_return_null_if_single_content_not_found()
{
var contentId = DomainId.NewGuid();
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom<IEnrichedContentEntity>(1));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
findMySchemaContent(id: '{contentId}') {
id,
version
}
}",
Args = new
{
contentId
}
});
var expected = new
{
data = new
{
findMySchemaContent = (object?)null
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_return_null_if_single_content_from_another_schema()
{
var contentId = DomainId.NewGuid();
var content = TestContent.CreateRef(TestSchemas.Reference1.NamedId(), contentId, "reference1-field", "reference1");
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(10, content));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
findMySchemaContent(id: '{contentId}') {
id,
version
}
}",
Args = new
{
contentId
}
});
var expected = new
{
data = new
{
findMySchemaContent = (object?)null
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_return_single_content_if_finding_content()
{
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
findMySchemaContent(id: '{contentId}') {
{fields}
}
}",
Args = new
{
contentId,
fields = TestContent.AllFields
}
});
var expected = new
{
data = new
{
findMySchemaContent = TestContent.Response(content)
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_return_single_content_if_finding_content_with_version()
{
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId);
A.CallTo(() => contentQuery.FindAsync(MatchsContentContext(), TestSchemas.Default.Id.ToString(), contentId, 3,
A<CancellationToken>._))
.Returns(content);
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
findMySchemaContent(id: '{contentId}', version: 3) {
{fields}
}
}",
Args = new
{
contentId,
fields = TestContent.AllFields
}
});
var expected = new
{
data = new
{
findMySchemaContent = TestContent.Response(content)
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_also_fetch_embedded_contents_if_field_is_included_in_query()
{
var contentRefId = DomainId.NewGuid();
var contentRef = TestContent.CreateRef(TestSchemas.Reference1.NamedId(), contentRefId, "reference1-field", "reference1");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, contentRefId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentRefId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, contentRef));
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
findMySchemaContent(id: '{contentId}') {
id
data {
myEmbeds {
iv {
text
contents {
... on Content {
id
}
... on MyReference1 {
data {
reference1Field {
iv
}
}
}
}
}
}
}
}
}",
Args = new
{
contentId
}
});
var expected = new
{
data = new
{
findMySchemaContent = new
{
id = content.Id,
data = new
{
myEmbeds = new
{
iv = new
{
text = $"assets:{DomainId.Empty}, contents:{contentRefId}",
contents = new[]
{
new
{
id = contentRefId,
data = new
{
reference1Field = new
{
iv = "reference1"
}
}
}
}
}
}
}
}
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_also_fetch_referenced_contents_if_field_is_included_in_query()
{
var contentRefId = DomainId.NewGuid();
var contentRef = TestContent.CreateRef(TestSchemas.Reference1.NamedId(), contentRefId, "reference1-field", "reference1");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, contentRefId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentRefId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, contentRef));
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
findMySchemaContent(id: '{contentId}') {
id
data {
myReferences {
iv {
id
data {
reference1Field {
iv
}
}
}
}
}
}
}",
Args = new
{
contentId
}
});
var expected = new
{
data = new
{
findMySchemaContent = new
{
id = content.Id,
data = new
{
myReferences = new
{
iv = new[]
{
new
{
id = contentRefId,
data = new
{
reference1Field = new
{
iv = "reference1"
}
}
}
}
}
}
}
}
};
AssertResult(expected, actual);
}
[Fact]
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.Reference1.NamedId(), contentRefId, "reference1-field", "reference1");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, contentRefId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentRefId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, contentRef));
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
findMySchemaContent(id: '{contentId}') {
id
flatData {
myReferences {
id
}
}
}
}",
Args = new
{
contentId
}
});
var expected = new
{
data = new
{
findMySchemaContent = new
{
id = content.Id,
flatData = new
{
myReferences = new[]
{
new
{
id = contentRefId
}
}
}
}
}
};
AssertResult(expected, actual);
}
[Fact]
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.Reference1.NamedId(), contentRefId, "reference1-field", "reference1");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, contentRefId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentRefId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, contentRef));
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
var query = new TestQuery
{
Query = @"
query {
findMySchemaContent(id: '{contentId}') {
id
flatData {
myReferences @cache(duration: 1000) {
id
}
}
}
}",
Args = new
{
contentId
}
};
var actual1 = await ExecuteAsync(query);
var actual2 = await ExecuteAsync(query);
var expected = new
{
data = new
{
findMySchemaContent = new
{
id = content.Id,
flatData = new
{
myReferences = new[]
{
new
{
id = contentRefId
}
}
}
}
}
};
AssertResult(expected, actual1);
AssertResult(expected, actual2);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentRefId),
A<CancellationToken>._))
.MustHaveHappenedOnceExactly();
}
[Fact]
public async Task Should_also_fetch_referencing_contents_if_field_is_included_in_query()
{
var contentRefId = DomainId.NewGuid();
var contentRef = TestContent.CreateRef(TestSchemas.Reference1.NamedId(), contentRefId, "reference1-field", "reference1");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, contentRefId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentRefId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, contentRef));
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), content.SchemaId.Id.ToString(),
A<Q>.That.Matches(x => x.QueryAsOdata == "?$top=30&$skip=5" && x.Reference == contentRefId && x.NoTotal),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
findMyReference1Content(id: '{contentId}') {
id
referencingMySchemaContents(top: 30, skip: 5) {
id
data {
myLocalizedString {
de_DE
}
}
}
}
}",
Args = new
{
contentId = contentRefId
}
});
var expected = new
{
data = new
{
findMyReference1Content = new
{
id = contentRefId,
referencingMySchemaContents = new[]
{
new
{
id = contentId,
data = new
{
myLocalizedString = new
{
de_DE = "de-DE"
}
}
}
}
}
}
};
AssertResult(expected, actual);
}
[Fact]
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.Reference1.NamedId(), contentRefId, "reference1-field", "reference1");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, contentRefId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentRefId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, contentRef));
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), content.SchemaId.Id.ToString(),
A<Q>.That.Matches(x => x.QueryAsOdata == "?$top=30&$skip=5" && x.Reference == contentRefId && !x.NoTotal),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(10, content));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
findMyReference1Content(id: '{contentId}') {
id
referencingMySchemaContentsWithTotal(top: 30, skip: 5) {
total
items {
id
data {
myLocalizedString {
de_DE
}
}
}
}
}
}",
Args = new
{
contentId = contentRefId
}
});
var expected = new
{
data = new
{
findMyReference1Content = new
{
id = contentRefId,
referencingMySchemaContentsWithTotal = new
{
total = 10,
items = new[]
{
new
{
id = contentId,
data = new
{
myLocalizedString = new
{
de_DE = "de-DE"
}
}
}
}
}
}
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_also_fetch_references_contents_if_field_is_included_in_query()
{
var contentRefId = DomainId.NewGuid();
var contentRef = TestContent.CreateRef(TestSchemas.Reference1.NamedId(), contentRefId, "reference1-field", "reference1");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, contentRefId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), contentRef.SchemaId.Id.ToString(),
A<Q>.That.Matches(x => x.QueryAsOdata == "?$top=30&$skip=5" && x.Referencing == contentId && x.NoTotal),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, contentRef));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
findMySchemaContent(id: '{contentId}') {
id
referencesMyReference1Contents(top: 30, skip: 5) {
id
}
}
}",
Args = new
{
contentId
}
});
var expected = new
{
data = new
{
findMySchemaContent = new
{
id = contentId,
referencesMyReference1Contents = new[]
{
new
{
id = contentRefId
}
}
}
}
};
AssertResult(expected, actual);
}
[Fact]
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.Reference1.NamedId(), contentRefId, "reference1-field", "reference1");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, contentRefId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), contentRef.SchemaId.Id.ToString(),
A<Q>.That.Matches(x => x.QueryAsOdata == "?$top=30&$skip=5" && x.Referencing == contentId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(10, contentRef));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
findMySchemaContent(id: '{contentId}') {
id
referencesMyReference1ContentsWithTotal(top: 30, skip: 5) {
total
items {
id
}
}
}
}",
Args = new
{
contentId
}
});
var expected = new
{
data = new
{
findMySchemaContent = new
{
id = contentId,
referencesMyReference1ContentsWithTotal = new
{
total = 10,
items = new[]
{
new
{
id = contentRefId
}
}
}
}
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_also_fetch_union_contents_if_field_is_included_in_query()
{
var contentRefId = DomainId.NewGuid();
var contentRef = TestContent.CreateRef(TestSchemas.Reference1.NamedId(), contentRefId, "reference1-field", "reference1");
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, contentRefId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentRefId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, contentRef));
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
findMySchemaContent(id: '{contentId}') {
id
data {
myUnion {
iv {
... on Content {
id
}
... on MyReference1 {
data {
reference1Field {
iv
}
}
}
__typename
}
}
}
}
}",
Args = new
{
contentId
}
});
var expected = new
{
data = new
{
findMySchemaContent = new
{
id = content.Id,
data = new
{
myUnion = new
{
iv = new[]
{
new
{
id = contentRefId,
data = new
{
reference1Field = new
{
iv = "reference1"
}
},
__typename = "MyReference1"
}
}
}
}
}
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_also_fetch_embedded_assets_if_field_is_included_in_query()
{
var assetRefId = DomainId.NewGuid();
var assetRef = TestAsset.Create(assetRefId);
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, assetId: assetRefId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), null,
A<Q>.That.HasIdsWithoutTotal(assetRefId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, assetRef));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
findMySchemaContent(id: '{contentId}') {
id
data {
myEmbeds {
iv {
text
assets {
id
}
}
}
}
}
}",
Args = new
{
contentId
}
});
var expected = new
{
data = new
{
findMySchemaContent = new
{
id = content.Id,
data = new
{
myEmbeds = new
{
iv = new
{
text = $"assets:{assetRefId}, contents:{DomainId.Empty}",
assets = new[]
{
new
{
id = assetRefId
}
}
}
}
}
}
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_also_fetch_referenced_assets_if_field_is_included_in_query()
{
var assetRefId = DomainId.NewGuid();
var assetRef = TestAsset.Create(assetRefId);
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, assetId: assetRefId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), null,
A<Q>.That.HasIdsWithoutTotal(assetRefId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, assetRef));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
findMySchemaContent(id: '{contentId}') {
id
data {
myAssets {
iv {
id
}
}
}
}
}",
Args = new
{
contentId
}
});
var expected = new
{
data = new
{
findMySchemaContent = new
{
id = content.Id,
data = new
{
myAssets = new
{
iv = new[]
{
new
{
id = assetRefId
}
}
}
}
}
}
};
AssertResult(expected, actual);
}
[Fact]
public async Task Should_not_return_data_if_field_not_part_of_content()
{
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId, data: new ContentData());
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
findMySchemaContent(id: '{contentId}') {
id
version
created
createdBy
lastModified
lastModifiedBy
url
data {
myInvalid {
iv
}
}
}
}",
Args = new
{
contentId
}
});
var json = serializer.Serialize(actual);
Assert.Contains("\"errors\"", json, StringComparison.Ordinal);
}
[Fact]
public async Task Should_query_only_selected_fields()
{
await ExecuteAsync(new TestQuery
{
Query = @"
query {
queryMySchemaContents @optimizeFieldQueries {
data {
myNumber {
iv
}
}
}
}"
});
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), TestSchemas.Default.Id.ToString(),
A<Q>.That.HasFields(new[] { "my-number" }),
A<CancellationToken>._))
.MustHaveHappened();
}
[Fact]
public async Task Should_query_only_selected_flat_fields()
{
await ExecuteAsync(new TestQuery
{
Query = @"
query {
queryMySchemaContents @optimizeFieldQueries {
flatData {
myNumber
}
}
}"
});
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), TestSchemas.Default.Id.ToString(),
A<Q>.That.HasFields(new[] { "my-number" }),
A<CancellationToken>._))
.MustHaveHappened();
}
[Fact]
public async Task Should_query_all_fields_when_directive_not_applied()
{
await ExecuteAsync(new TestQuery
{
Query = @"
query {
queryMySchemaContents {
data {
myNumber {
iv
}
}
}
}"
});
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), TestSchemas.Default.Id.ToString(),
A<Q>.That.Matches(x => x.Fields == null),
A<CancellationToken>._))
.MustHaveHappened();
}
[Fact]
public async Task Should_query_all_fields_when_dynamic_data_is_queried()
{
await ExecuteAsync(new TestQuery
{
Query = @"
query {
queryMySchemaContents @optimizeFieldQueries {
flatData {
myNumber
}
data__dynamic
}
}"
});
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), TestSchemas.Default.Id.ToString(),
A<Q>.That.Matches(x => x.Fields == null),
A<CancellationToken>._))
.MustHaveHappened();
}
[Fact]
public async Task Should_query_all_fields_across_schemas()
{
await ExecuteAsync(new TestQuery
{
Query = @"
query {
queryContentsByIds(ids: ['42']) @optimizeFieldQueries {
...on MySchema {
flatData {
myNumber
}
}
}
}"
});
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasFields(new[] { "my-number" }),
A<CancellationToken>._))
.MustHaveHappened();
}
[Fact]
public async Task Should_not_fetch_user_if_only_is_id_queried()
{
var contentId = DomainId.NewGuid();
var content = TestContent.Create(contentId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(),
A<Q>.That.HasIdsWithoutTotal(contentId),
A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
var actual = await ExecuteAsync(new TestQuery
{
Query = @"
query {
findMySchemaContent(id: '{contentId}') {
createdByUser {
id
}
}
}",
Args = new
{
contentId
}
});
var expected = new
{
data = new
{
findMySchemaContent = new
{
createdByUser = new
{
id = content.CreatedBy.Identifier
}
}
}
};
AssertResult(expected, actual);
A.CallTo(() => userResolver.FindByIdAsync(A<string>._, A<CancellationToken>._))
.MustNotHaveHappened();
}
}