mirror of https://github.com/Squidex/squidex.git
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.
716 lines
21 KiB
716 lines
21 KiB
// ==========================================================================
|
|
// Squidex Headless CMS
|
|
// ==========================================================================
|
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|
// All rights reserved. Licensed under the MIT license.
|
|
// ==========================================================================
|
|
|
|
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;
|
|
|
|
namespace Squidex.Domain.Apps.Entities.Contents.GraphQL;
|
|
|
|
public class GraphQLMutationTests : GraphQLTestBase
|
|
{
|
|
private readonly DomainId contentId = DomainId.NewGuid();
|
|
private readonly IEnrichedContentEntity content;
|
|
private readonly CommandContext commandContext = new CommandContext(new PatchContent(), A.Dummy<ICommandBus>());
|
|
|
|
public GraphQLMutationTests()
|
|
{
|
|
content = TestContent.Create(contentId, TestSchemas.Reference1.Id, TestSchemas.Reference2.Id, null);
|
|
|
|
A.CallTo(() => commandBus.PublishAsync(A<ICommand>.Ignored, A<CancellationToken>._))
|
|
.Returns(commandContext);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Should_return_error_if_user_has_no_permission_to_create()
|
|
{
|
|
var actual = await ExecuteAsync(new TestQuery
|
|
{
|
|
Query = @"
|
|
mutation {
|
|
createMySchemaContent(data: { }) {
|
|
id
|
|
}
|
|
}"
|
|
});
|
|
|
|
var expected = new
|
|
{
|
|
errors = new[]
|
|
{
|
|
new
|
|
{
|
|
message = "You do not have the necessary permission.",
|
|
locations = new[]
|
|
{
|
|
new
|
|
{
|
|
line = 3,
|
|
column = 19
|
|
}
|
|
},
|
|
path = new[]
|
|
{
|
|
"createMySchemaContent"
|
|
}
|
|
}
|
|
},
|
|
data = new
|
|
{
|
|
createMySchemaContent = (object?)null
|
|
}
|
|
};
|
|
|
|
AssertResult(expected, actual);
|
|
|
|
A.CallTo(() => commandBus.PublishAsync(A<ICommand>._, A<CancellationToken>._))
|
|
.MustNotHaveHappened();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Should_return_single_content_if_creating_content()
|
|
{
|
|
commandContext.Complete(content);
|
|
|
|
var actual = await ExecuteAsync(new TestQuery
|
|
{
|
|
Query = @"
|
|
mutation MyMutation($data: MySchemaDataInputDto!) {
|
|
createMySchemaContent(data: $data, publish: true) {
|
|
{fields}
|
|
}
|
|
}",
|
|
Args = new
|
|
{
|
|
fields = TestContent.AllFields
|
|
},
|
|
Variables = new
|
|
{
|
|
data = TestContent.Input(content, TestSchemas.Reference1.Id, TestSchemas.Reference2.Id),
|
|
},
|
|
Permission = PermissionIds.AppContentsCreate
|
|
});
|
|
|
|
var expected = new
|
|
{
|
|
data = new
|
|
{
|
|
createMySchemaContent = TestContent.Response(content)
|
|
}
|
|
};
|
|
|
|
AssertResult(expected, actual);
|
|
|
|
A.CallTo(() => commandBus.PublishAsync(
|
|
A<CreateContent>.That.Matches(x =>
|
|
x.ExpectedVersion == EtagVersion.Any &&
|
|
x.SchemaId.Equals(TestSchemas.Default.NamedId()) &&
|
|
x.Status == Status.Published &&
|
|
x.Data.Equals(content.Data)),
|
|
A<CancellationToken>._))
|
|
.MustHaveHappened();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Should_return_single_content_if_creating_content_with_custom_id()
|
|
{
|
|
commandContext.Complete(content);
|
|
|
|
var actual = await ExecuteAsync(new TestQuery
|
|
{
|
|
Query = @"
|
|
mutation MyMutation($data: MySchemaDataInputDto!) {
|
|
createMySchemaContent(data: $data, id: '{contentId}', publish: true) {
|
|
{fields}
|
|
}
|
|
}",
|
|
Args = new
|
|
{
|
|
contentId,
|
|
fields = TestContent.AllFields
|
|
},
|
|
Variables = new
|
|
{
|
|
data = TestContent.Input(content, TestSchemas.Reference1.Id, TestSchemas.Reference2.Id)
|
|
},
|
|
Permission = PermissionIds.AppContentsCreate
|
|
});
|
|
|
|
var expected = new
|
|
{
|
|
data = new
|
|
{
|
|
createMySchemaContent = TestContent.Response(content)
|
|
}
|
|
};
|
|
|
|
AssertResult(expected, actual);
|
|
|
|
A.CallTo(() => commandBus.PublishAsync(
|
|
A<CreateContent>.That.Matches(x =>
|
|
x.ExpectedVersion == EtagVersion.Any &&
|
|
x.ContentId == contentId &&
|
|
x.SchemaId.Equals(TestSchemas.Default.NamedId()) &&
|
|
x.Status == Status.Published &&
|
|
x.Data.Equals(content.Data)),
|
|
A<CancellationToken>._))
|
|
.MustHaveHappened();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Should_return_error_if_user_has_no_permission_to_update()
|
|
{
|
|
var actual = await ExecuteAsync(new TestQuery
|
|
{
|
|
Query = @"
|
|
mutation {
|
|
updateMySchemaContent(id: '{contentId}', data: { }) {
|
|
id
|
|
}
|
|
}",
|
|
Args = new
|
|
{
|
|
contentId
|
|
}
|
|
});
|
|
|
|
var expected = new
|
|
{
|
|
errors = new[]
|
|
{
|
|
new
|
|
{
|
|
message = "You do not have the necessary permission.",
|
|
locations = new[]
|
|
{
|
|
new
|
|
{
|
|
line = 3,
|
|
column = 19
|
|
}
|
|
},
|
|
path = new[]
|
|
{
|
|
"updateMySchemaContent"
|
|
}
|
|
}
|
|
},
|
|
data = new
|
|
{
|
|
updateMySchemaContent = (object?)null
|
|
}
|
|
};
|
|
|
|
AssertResult(expected, actual);
|
|
|
|
A.CallTo(() => commandBus.PublishAsync(A<ICommand>._, A<CancellationToken>._))
|
|
.MustNotHaveHappened();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Should_return_single_content_if_updating_content()
|
|
{
|
|
commandContext.Complete(content);
|
|
|
|
var actual = await ExecuteAsync(new TestQuery
|
|
{
|
|
Query = @"
|
|
mutation MyMutation($data: MySchemaDataInputDto!) {
|
|
updateMySchemaContent(id: '{contentId}', data: $data, expectedVersion: 10) {
|
|
{fields}
|
|
}
|
|
}",
|
|
Args = new
|
|
{
|
|
contentId,
|
|
fields = TestContent.AllFields
|
|
},
|
|
Variables = new
|
|
{
|
|
data = TestContent.Input(content, TestSchemas.Reference1.Id, TestSchemas.Reference2.Id)
|
|
},
|
|
Permission = PermissionIds.AppContentsUpdateOwn
|
|
});
|
|
|
|
var expected = new
|
|
{
|
|
data = new
|
|
{
|
|
updateMySchemaContent = TestContent.Response(content)
|
|
}
|
|
};
|
|
|
|
AssertResult(expected, actual);
|
|
|
|
A.CallTo(() => commandBus.PublishAsync(
|
|
A<UpdateContent>.That.Matches(x =>
|
|
x.ContentId == contentId &&
|
|
x.ExpectedVersion == 10 &&
|
|
x.SchemaId.Equals(TestSchemas.Default.NamedId()) &&
|
|
x.Data.Equals(content.Data)),
|
|
A<CancellationToken>._))
|
|
.MustHaveHappened();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Should_return_error_if_user_has_no_permission_to_upsert()
|
|
{
|
|
var actual = await ExecuteAsync(new TestQuery
|
|
{
|
|
Query = @"
|
|
mutation {
|
|
upsertMySchemaContent(id: '{contentId}', data: { }) {
|
|
id
|
|
}
|
|
}"
|
|
});
|
|
|
|
var expected = new
|
|
{
|
|
errors = new[]
|
|
{
|
|
new
|
|
{
|
|
message = "You do not have the necessary permission.",
|
|
locations = new[]
|
|
{
|
|
new
|
|
{
|
|
line = 3,
|
|
column = 19
|
|
}
|
|
},
|
|
path = new[]
|
|
{
|
|
"upsertMySchemaContent"
|
|
}
|
|
}
|
|
},
|
|
data = new
|
|
{
|
|
upsertMySchemaContent = (object?)null
|
|
}
|
|
};
|
|
|
|
AssertResult(expected, actual);
|
|
|
|
A.CallTo(() => commandBus.PublishAsync(A<ICommand>._, A<CancellationToken>._))
|
|
.MustNotHaveHappened();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Should_return_single_content_if_upserting_content()
|
|
{
|
|
commandContext.Complete(content);
|
|
|
|
var actual = await ExecuteAsync(new TestQuery
|
|
{
|
|
Query = @"
|
|
mutation MyMutation($data: MySchemaDataInputDto!) {
|
|
upsertMySchemaContent(id: '{contentId}', data: $data, publish: true, expectedVersion: 10) {
|
|
{fields}
|
|
}
|
|
}",
|
|
Args = new
|
|
{
|
|
contentId,
|
|
fields = TestContent.AllFields
|
|
},
|
|
Variables = new
|
|
{
|
|
data = TestContent.Input(content, TestSchemas.Reference1.Id, TestSchemas.Reference2.Id)
|
|
},
|
|
Permission = PermissionIds.AppContentsUpsert
|
|
});
|
|
|
|
var expected = new
|
|
{
|
|
data = new
|
|
{
|
|
upsertMySchemaContent = TestContent.Response(content)
|
|
}
|
|
};
|
|
|
|
AssertResult(expected, actual);
|
|
|
|
A.CallTo(() => commandBus.PublishAsync(
|
|
A<UpsertContent>.That.Matches(x =>
|
|
x.ContentId == contentId &&
|
|
x.ExpectedVersion == 10 &&
|
|
x.SchemaId.Equals(TestSchemas.Default.NamedId()) &&
|
|
x.Status == Status.Published &&
|
|
x.Data.Equals(content.Data)),
|
|
A<CancellationToken>._))
|
|
.MustHaveHappened();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Should_return_error_if_user_has_no_permission_to_patch()
|
|
{
|
|
var actual = await ExecuteAsync(new TestQuery
|
|
{
|
|
Query = @"
|
|
mutation {
|
|
patchMySchemaContent(id: '{contentId}', data: { }) {
|
|
id
|
|
}
|
|
}",
|
|
Args = new
|
|
{
|
|
contentId
|
|
},
|
|
});
|
|
|
|
var expected = new
|
|
{
|
|
errors = new[]
|
|
{
|
|
new
|
|
{
|
|
message = "You do not have the necessary permission.",
|
|
locations = new[]
|
|
{
|
|
new
|
|
{
|
|
line = 3,
|
|
column = 19
|
|
}
|
|
},
|
|
path = new[]
|
|
{
|
|
"patchMySchemaContent"
|
|
}
|
|
}
|
|
},
|
|
data = new
|
|
{
|
|
patchMySchemaContent = (object?)null
|
|
}
|
|
};
|
|
|
|
AssertResult(expected, actual);
|
|
|
|
A.CallTo(() => commandBus.PublishAsync(A<ICommand>._, A<CancellationToken>._))
|
|
.MustNotHaveHappened();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Should_return_single_content_if_patching_content()
|
|
{
|
|
commandContext.Complete(content);
|
|
|
|
var actual = await ExecuteAsync(new TestQuery
|
|
{
|
|
Query = @"
|
|
mutation MyMutation($data: MySchemaDataInputDto!) {
|
|
patchMySchemaContent(id: '{contentId}', data: $data, expectedVersion: 10) {
|
|
{fields}
|
|
}
|
|
}",
|
|
Args = new
|
|
{
|
|
contentId,
|
|
fields = TestContent.AllFields
|
|
},
|
|
Variables = new
|
|
{
|
|
data = TestContent.Input(content, TestSchemas.Reference1.Id, TestSchemas.Reference2.Id)
|
|
},
|
|
Permission = PermissionIds.AppContentsUpdateOwn
|
|
});
|
|
|
|
var expected = new
|
|
{
|
|
data = new
|
|
{
|
|
patchMySchemaContent = TestContent.Response(content)
|
|
}
|
|
};
|
|
|
|
AssertResult(expected, actual);
|
|
|
|
A.CallTo(() => commandBus.PublishAsync(
|
|
A<PatchContent>.That.Matches(x =>
|
|
x.ContentId == contentId &&
|
|
x.ExpectedVersion == 10 &&
|
|
x.SchemaId.Equals(TestSchemas.Default.NamedId()) &&
|
|
x.Data.Equals(content.Data)),
|
|
A<CancellationToken>._))
|
|
.MustHaveHappened();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Should_return_error_if_user_has_no_permission_to_change_status()
|
|
{
|
|
var actual = await ExecuteAsync(new TestQuery
|
|
{
|
|
Query = @"
|
|
mutation {
|
|
changeMySchemaContent(id: '{contentId}', status: 'Published') {
|
|
id
|
|
}
|
|
}",
|
|
Args = new
|
|
{
|
|
contentId
|
|
},
|
|
});
|
|
|
|
var expected = new
|
|
{
|
|
errors = new[]
|
|
{
|
|
new
|
|
{
|
|
message = "You do not have the necessary permission.",
|
|
locations = new[]
|
|
{
|
|
new
|
|
{
|
|
line = 3,
|
|
column = 19
|
|
}
|
|
},
|
|
path = new[]
|
|
{
|
|
"changeMySchemaContent"
|
|
}
|
|
}
|
|
},
|
|
data = new
|
|
{
|
|
changeMySchemaContent = (object?)null
|
|
}
|
|
};
|
|
|
|
AssertResult(expected, actual);
|
|
|
|
A.CallTo(() => commandBus.PublishAsync(A<ICommand>._, A<CancellationToken>._))
|
|
.MustNotHaveHappened();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Should_return_single_content_if_changing_status()
|
|
{
|
|
var dueTime = InstantPattern.General.Parse("2021-12-12T11:10:09Z").Value;
|
|
|
|
commandContext.Complete(content);
|
|
|
|
var actual = await ExecuteAsync(new TestQuery
|
|
{
|
|
Query = @"
|
|
mutation {
|
|
changeMySchemaContent(id: '{contentId}', status: 'Published', dueTime: '2021-12-12T11:10:09Z', expectedVersion: 10) {
|
|
{fields}
|
|
}
|
|
}",
|
|
Args = new
|
|
{
|
|
contentId,
|
|
fields = TestContent.AllFields
|
|
},
|
|
Permission = PermissionIds.AppContentsChangeStatusOwn
|
|
});
|
|
|
|
var expected = new
|
|
{
|
|
data = new
|
|
{
|
|
changeMySchemaContent = TestContent.Response(content)
|
|
}
|
|
};
|
|
|
|
AssertResult(expected, actual);
|
|
|
|
A.CallTo(() => commandBus.PublishAsync(
|
|
A<ChangeContentStatus>.That.Matches(x =>
|
|
x.ContentId == contentId &&
|
|
x.DueTime == dueTime &&
|
|
x.ExpectedVersion == 10 &&
|
|
x.SchemaId.Equals(TestSchemas.Default.NamedId()) &&
|
|
x.Status == Status.Published),
|
|
A<CancellationToken>._))
|
|
.MustHaveHappened();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Should_return_single_content_if_changing_status_without_due_time()
|
|
{
|
|
commandContext.Complete(content);
|
|
|
|
var actual = await ExecuteAsync(new TestQuery
|
|
{
|
|
Query = @"
|
|
mutation {
|
|
changeMySchemaContent(id: '{contentId}', status: 'Published', expectedVersion: 10) {
|
|
{fields}
|
|
}
|
|
}",
|
|
Args = new
|
|
{
|
|
contentId,
|
|
fields = TestContent.AllFields
|
|
},
|
|
Permission = PermissionIds.AppContentsChangeStatusOwn
|
|
});
|
|
|
|
var expected = new
|
|
{
|
|
data = new
|
|
{
|
|
changeMySchemaContent = TestContent.Response(content)
|
|
}
|
|
};
|
|
|
|
AssertResult(expected, actual);
|
|
|
|
A.CallTo(() => commandBus.PublishAsync(
|
|
A<ChangeContentStatus>.That.Matches(x =>
|
|
x.ContentId == contentId &&
|
|
x.DueTime == null &&
|
|
x.ExpectedVersion == 10 &&
|
|
x.SchemaId.Equals(TestSchemas.Default.NamedId()) &&
|
|
x.Status == Status.Published),
|
|
A<CancellationToken>._))
|
|
.MustHaveHappened();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Should_return_single_content_if_changing_status_with_null_due_time()
|
|
{
|
|
commandContext.Complete(content);
|
|
|
|
var actual = await ExecuteAsync(new TestQuery
|
|
{
|
|
Query = @"
|
|
mutation {
|
|
changeMySchemaContent(id: '{contentId}', status: 'Published', dueTime: null, expectedVersion: 10) {
|
|
{fields}
|
|
}
|
|
}",
|
|
Args = new
|
|
{
|
|
contentId,
|
|
fields = TestContent.AllFields
|
|
},
|
|
Permission = PermissionIds.AppContentsChangeStatusOwn
|
|
});
|
|
|
|
var expected = new
|
|
{
|
|
data = new
|
|
{
|
|
changeMySchemaContent = TestContent.Response(content)
|
|
}
|
|
};
|
|
|
|
AssertResult(expected, actual);
|
|
|
|
A.CallTo(() => commandBus.PublishAsync(
|
|
A<ChangeContentStatus>.That.Matches(x =>
|
|
x.ContentId == contentId &&
|
|
x.DueTime == null &&
|
|
x.ExpectedVersion == 10 &&
|
|
x.SchemaId.Equals(TestSchemas.Default.NamedId()) &&
|
|
x.Status == Status.Published),
|
|
A<CancellationToken>._))
|
|
.MustHaveHappened();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Should_return_error_if_user_has_no_permission_to_delete()
|
|
{
|
|
var actual = await ExecuteAsync(new TestQuery
|
|
{
|
|
Query = @"
|
|
mutation {
|
|
deleteMySchemaContent(id: '{contentId}') {
|
|
version
|
|
}
|
|
}",
|
|
Args = new
|
|
{
|
|
contentId
|
|
},
|
|
});
|
|
|
|
var expected = new
|
|
{
|
|
errors = new[]
|
|
{
|
|
new
|
|
{
|
|
message = "You do not have the necessary permission.",
|
|
locations = new[]
|
|
{
|
|
new
|
|
{
|
|
line = 3,
|
|
column = 19
|
|
}
|
|
},
|
|
path = new[]
|
|
{
|
|
"deleteMySchemaContent"
|
|
}
|
|
}
|
|
},
|
|
data = (object?)null
|
|
};
|
|
|
|
AssertResult(expected, actual);
|
|
|
|
A.CallTo(() => commandBus.PublishAsync(A<ICommand>._, A<CancellationToken>._))
|
|
.MustNotHaveHappened();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Should_return_new_version_if_deleting_content()
|
|
{
|
|
commandContext.Complete(CommandResult.Empty(contentId, 1, 0));
|
|
|
|
var actual = await ExecuteAsync(new TestQuery
|
|
{
|
|
Query = @"
|
|
mutation {
|
|
deleteMySchemaContent(id: '{contentId}', expectedVersion: 10) {
|
|
version
|
|
}
|
|
}",
|
|
Args = new
|
|
{
|
|
contentId
|
|
},
|
|
Permission = PermissionIds.AppContentsDeleteOwn
|
|
});
|
|
|
|
var expected = new
|
|
{
|
|
data = new
|
|
{
|
|
deleteMySchemaContent = new
|
|
{
|
|
version = 1
|
|
}
|
|
}
|
|
};
|
|
|
|
AssertResult(expected, actual);
|
|
|
|
A.CallTo(() => commandBus.PublishAsync(
|
|
A<DeleteContent>.That.Matches(x =>
|
|
x.ContentId == contentId &&
|
|
x.ExpectedVersion == 10 &&
|
|
x.SchemaId.Equals(TestSchemas.Default.NamedId())),
|
|
A<CancellationToken>._))
|
|
.MustHaveHappened();
|
|
}
|
|
}
|
|
|