From 343f76aa611ccf72a9301a70a945f0049347105a Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Wed, 17 Jan 2018 01:42:01 +0100 Subject: [PATCH] Update operation finished. --- .../GraphQL/Types/AppMutationsGraphType.cs | 20 +- .../ContentDataChangedResultGraphType.cs | 44 +++ .../Contents/GraphQL/GraphQLMutationTests.cs | 266 +++++++++++++----- 3 files changed, 248 insertions(+), 82 deletions(-) create mode 100644 src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentDataChangedResultGraphType.cs diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AppMutationsGraphType.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AppMutationsGraphType.cs index dc3ac8a4e..e3c3a22d8 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AppMutationsGraphType.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AppMutationsGraphType.cs @@ -32,11 +32,13 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types var contentType = model.GetContentType(schema.Id); var contentDataType = model.GetContentDataType(schema.Id); + var resultType = new ContentDataChangedResultGraphType(schemaType, schemaName, contentDataType); + var inputType = new ContentDataGraphInputType(model, schema); AddContentCreate(schemaId, schemaType, schemaName, inputType, contentDataType, contentType); - AddContentUpdate(schemaId, schemaType, schemaName, inputType, contentDataType); - AddContentPatch(schemaId, schemaType, schemaName, inputType, contentDataType); + AddContentUpdate(schemaId, schemaType, schemaName, inputType, resultType); + AddContentPatch(schemaId, schemaType, schemaName, inputType, resultType); AddContentPublish(schemaId, schemaType, schemaName); AddContentUnpublish(schemaId, schemaType, schemaName); AddContentArchive(schemaId, schemaType, schemaName); @@ -93,7 +95,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types }); } - private void AddContentUpdate(NamedId schemaId, string schemaType, string schemaName, ContentDataGraphInputType inputType, IComplexGraphType contentDataType) + private void AddContentUpdate(NamedId schemaId, string schemaType, string schemaName, ContentDataGraphInputType inputType, IComplexGraphType resultType) { AddField(new FieldType { @@ -120,7 +122,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types DefaultValue = EtagVersion.Any } }, - ResolvedType = new NonNullGraphType(contentDataType), + ResolvedType = new NonNullGraphType(resultType), Resolver = ResolveAsync(async (c, publish) => { var contentId = c.GetArgument("id"); @@ -131,13 +133,13 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types var result = commandContext.Result(); - return result.Data; + return result; }), Description = $"Update an {schemaName} content by id." }); } - private void AddContentPatch(NamedId schemaId, string schemaType, string schemaName, ContentDataGraphInputType inputType, IComplexGraphType contentDataType) + private void AddContentPatch(NamedId schemaId, string schemaType, string schemaName, ContentDataGraphInputType inputType, IComplexGraphType resultType) { AddField(new FieldType { @@ -164,7 +166,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types DefaultValue = EtagVersion.Any } }, - ResolvedType = new NonNullGraphType(contentDataType), + ResolvedType = new NonNullGraphType(resultType), Resolver = ResolveAsync(async (c, publish) => { var contentId = c.GetArgument("id"); @@ -175,7 +177,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types var result = commandContext.Result(); - return result.Data; + return result; }), Description = $"Patch a {schemaName} content." }); @@ -303,7 +305,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types return action(c, command => { - command.ExpectedVersion = c.GetArgument("expectedVersion"); + command.ExpectedVersion = c.GetArgument("expectedVersion", EtagVersion.Any); return e.CommandBus.PublishAsync(command); }); diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentDataChangedResultGraphType.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentDataChangedResultGraphType.cs new file mode 100644 index 000000000..1c9e6e822 --- /dev/null +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentDataChangedResultGraphType.cs @@ -0,0 +1,44 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using GraphQL.Resolvers; +using GraphQL.Types; + +namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types +{ + public sealed class ContentDataChangedResultGraphType : ObjectGraphType + { + public ContentDataChangedResultGraphType(string schemaType, string schemaName, IComplexGraphType contentDataType) + { + Name = $"{schemaName}DataChangedResultDto"; + + AddField(new FieldType + { + Name = "version", + ResolvedType = new IntGraphType(), + Resolver = Resolve(x => x.Version), + Description = $"The new version of the {schemaName} content." + }); + + AddField(new FieldType + { + Name = "data", + ResolvedType = new NonNullGraphType(contentDataType), + Resolver = Resolve(x => x.Data), + Description = $"The new data of the {schemaName} content." + }); + + Description = $"The result of the {schemaName} mutation"; + } + + private static IFieldResolver Resolve(Func action) + { + return new FuncFieldResolver(c => action(c.Source)); + } + } +} diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLMutationTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLMutationTests.cs index 9c513477e..64224e695 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLMutationTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLMutationTests.cs @@ -29,53 +29,150 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL } [Fact] - public async Task Should_return_single_content_when_patching_content() + public async Task Should_return_single_content_when_updating_content() { var contentId = Guid.NewGuid(); var content = CreateContent(contentId, Guid.Empty, Guid.Empty); var query = $@" mutation OP($data: MySchemaInputDto!) {{ - patchMySchemaContent(id: ""{contentId}"", data: $data) {{ - myString {{ - de - }} - myNumber {{ - iv - }} - myBoolean {{ - iv - }} - myDatetime {{ - iv - }} - myJson {{ - iv - }} - myGeolocation {{ - iv - }} - myTags {{ - iv + updateMySchemaContent(id: ""{contentId}"", data: $data, expectedVersion: 10) {{ + version + data {{ + myString {{ + de + }} + myNumber {{ + iv + }} + myBoolean {{ + iv + }} + myDatetime {{ + iv + }} + myJson {{ + iv + }} + myGeolocation {{ + iv + }} + myTags {{ + iv + }} }} }} }}"; - commandContext.Complete(new ContentDataChangedResult(content.Data, 1)); + commandContext.Complete(new ContentDataChangedResult(content.Data, 13)); - var camelContent = new NamedContentData(); + var inputContent = GetInputContent(content); - foreach (var kvp in content.Data) + var variables = + new JObject( + new JProperty("data", inputContent)); + + var result = await sut.QueryAsync(app, user, new GraphQLQuery { Query = query, Variables = variables }); + + var expected = new { - if (kvp.Key != "my-json") + data = new { - camelContent[kvp.Key.ToCamelCase()] = kvp.Value; + updateMySchemaContent = new + { + version = 13, + data = new + { + myString = new + { + de = "value" + }, + myNumber = new + { + iv = 1 + }, + myBoolean = new + { + iv = true + }, + myDatetime = new + { + iv = content.LastModified.ToDateTimeUtc() + }, + myJson = new + { + iv = new + { + value = 1 + } + }, + myGeolocation = new + { + iv = new + { + latitude = 10, + longitude = 20 + } + }, + myTags = new + { + iv = new[] + { + "tag1", + "tag2" + } + } + } + } } - } + }; + + AssertResult(expected, result); + } + + [Fact] + public async Task Should_return_single_content_when_patching_content() + { + var contentId = Guid.NewGuid(); + var content = CreateContent(contentId, Guid.Empty, Guid.Empty); + + var query = $@" + mutation OP($data: MySchemaInputDto!) {{ + patchMySchemaContent(id: ""{contentId}"", data: $data, expectedVersion: 10) {{ + version + data {{ + myString {{ + de + }} + myNumber {{ + iv + }} + myBoolean {{ + iv + }} + myDatetime {{ + iv + }} + myJson {{ + iv + }} + myGeolocation {{ + iv + }} + myTags {{ + iv + }} + }} + }} + }}"; + + commandContext.Complete(new ContentDataChangedResult(content.Data, 13)); + + var inputContent = GetInputContent(content); var variables = new JObject( - new JProperty("data", JObject.FromObject(camelContent))); + new JProperty("data", inputContent)); var result = await sut.QueryAsync(app, user, new GraphQLQuery { Query = query, Variables = variables }); @@ -85,43 +182,46 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL { patchMySchemaContent = new { - myString = new - { - de = "value" - }, - myNumber = new - { - iv = 1 - }, - myBoolean = new - { - iv = true - }, - myDatetime = new - { - iv = content.LastModified.ToDateTimeUtc() - }, - myJson = new - { - iv = new + version = 13, + data = new { + myString = new { - value = 1 - } - }, - myGeolocation = new - { - iv = new + de = "value" + }, + myNumber = new { - latitude = 10, - longitude = 20 - } - }, - myTags = new - { - iv = new[] + iv = 1 + }, + myBoolean = new + { + iv = true + }, + myDatetime = new + { + iv = content.LastModified.ToDateTimeUtc() + }, + myJson = new + { + iv = new + { + value = 1 + } + }, + myGeolocation = new + { + iv = new + { + latitude = 10, + longitude = 20 + } + }, + myTags = new { - "tag1", - "tag2" + iv = new[] + { + "tag1", + "tag2" + } } } } @@ -138,7 +238,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL var query = $@" mutation {{ - publishMySchemaContent(id: ""{contentId}"") {{ + publishMySchemaContent(id: ""{contentId}"", expectedVersion: 10) {{ version }} }}"; @@ -164,7 +264,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL A.That.Matches(x => x.SchemaId.Equals(schema.NamedId()) && x.ContentId == contentId && - x.Status == Status.Published))) + x.Status == Status.Published && + x.ExpectedVersion == 10))) .MustHaveHappened(); } @@ -175,7 +276,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL var query = $@" mutation {{ - unpublishMySchemaContent(id: ""{contentId}"") {{ + unpublishMySchemaContent(id: ""{contentId}"", expectedVersion: 10) {{ version }} }}"; @@ -201,7 +302,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL A.That.Matches(x => x.SchemaId.Equals(schema.NamedId()) && x.ContentId == contentId && - x.Status == Status.Draft))) + x.Status == Status.Draft && + x.ExpectedVersion == 10))) .MustHaveHappened(); } @@ -212,7 +314,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL var query = $@" mutation {{ - archiveMySchemaContent(id: ""{contentId}"") {{ + archiveMySchemaContent(id: ""{contentId}"", expectedVersion: 10) {{ version }} }}"; @@ -238,7 +340,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL A.That.Matches(x => x.SchemaId.Equals(schema.NamedId()) && x.ContentId == contentId && - x.Status == Status.Archived))) + x.Status == Status.Archived && + x.ExpectedVersion == 10))) .MustHaveHappened(); } @@ -249,7 +352,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL var query = $@" mutation {{ - restoreMySchemaContent(id: ""{contentId}"") {{ + restoreMySchemaContent(id: ""{contentId}"", expectedVersion: 10) {{ version }} }}"; @@ -275,7 +378,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL A.That.Matches(x => x.SchemaId.Equals(schema.NamedId()) && x.ContentId == contentId && - x.Status == Status.Draft))) + x.Status == Status.Draft && + x.ExpectedVersion == 10))) .MustHaveHappened(); } @@ -286,7 +390,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL var query = $@" mutation {{ - deleteMySchemaContent(id: ""{contentId}"") {{ + deleteMySchemaContent(id: ""{contentId}"", expectedVersion: 10) {{ version }} }}"; @@ -311,8 +415,24 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL A.CallTo(() => commandBus.PublishAsync( A.That.Matches(x => x.SchemaId.Equals(schema.NamedId()) && - x.ContentId == contentId))) + x.ContentId == contentId && + x.ExpectedVersion == 10))) .MustHaveHappened(); } + + private static JObject GetInputContent(IContentEntity content) + { + var camelContent = new NamedContentData(); + + foreach (var kvp in content.Data) + { + if (kvp.Key != "my-json") + { + camelContent[kvp.Key.ToCamelCase()] = kvp.Value; + } + } + + return JObject.FromObject(camelContent); + } } }