diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/FieldDescriptions.Designer.cs b/backend/src/Squidex.Domain.Apps.Core.Model/FieldDescriptions.Designer.cs
index f3eda195b..69285d96d 100644
--- a/backend/src/Squidex.Domain.Apps.Core.Model/FieldDescriptions.Designer.cs
+++ b/backend/src/Squidex.Domain.Apps.Core.Model/FieldDescriptions.Designer.cs
@@ -456,6 +456,15 @@ namespace Squidex.Domain.Apps.Core {
}
}
+ ///
+ /// Looks up a localized string similar to Enrich the content with defaults..
+ ///
+ public static string ContentRequestApplyDefaults {
+ get {
+ return ResourceManager.GetString("ContentRequestApplyDefaults", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to The data for the content..
///
diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/FieldDescriptions.resx b/backend/src/Squidex.Domain.Apps.Core.Model/FieldDescriptions.resx
index fdfd15fe8..244ff2e51 100644
--- a/backend/src/Squidex.Domain.Apps.Core.Model/FieldDescriptions.resx
+++ b/backend/src/Squidex.Domain.Apps.Core.Model/FieldDescriptions.resx
@@ -249,6 +249,9 @@
{0} field ({1}).
+
+ Enrich the content with defaults.
+
The data for the content.
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/BulkUpdateContentType.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/BulkUpdateContentType.cs
index d992a9cba..06b9098ac 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/BulkUpdateContentType.cs
+++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/BulkUpdateContentType.cs
@@ -15,5 +15,6 @@ public enum BulkUpdateContentType
Delete,
Patch,
Update,
- Validate
+ Validate,
+ EnrichDefaults
}
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/BulkUpdateJob.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/BulkUpdateJob.cs
index c6e9b8de9..a0ca5d9c9 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/BulkUpdateJob.cs
+++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/BulkUpdateJob.cs
@@ -33,6 +33,8 @@ public sealed class BulkUpdateJob
public bool Permanent { get; set; }
+ public bool EnrichDefaults { get; set; }
+
public long ExpectedCount { get; set; } = 1;
public long ExpectedVersion { get; set; } = EtagVersion.Any;
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/EnrichContentDefaults.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/EnrichContentDefaults.cs
new file mode 100644
index 000000000..6a8d39dc9
--- /dev/null
+++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/EnrichContentDefaults.cs
@@ -0,0 +1,12 @@
+// ==========================================================================
+// Squidex Headless CMS
+// ==========================================================================
+// Copyright (c) Squidex UG (haftungsbeschraenkt)
+// All rights reserved. Licensed under the MIT license.
+// ==========================================================================
+
+namespace Squidex.Domain.Apps.Entities.Contents.Commands;
+
+public sealed class EnrichContentDefaults : ContentCommand
+{
+}
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/UpdateContent.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/UpdateContent.cs
index 3e6fbbe53..1959a9898 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/UpdateContent.cs
+++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/UpdateContent.cs
@@ -9,4 +9,5 @@ namespace Squidex.Domain.Apps.Entities.Contents.Commands;
public class UpdateContent : ContentDataCommand
{
+ public bool EnrichDefaults { get; set; }
}
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/UpsertContent.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/UpsertContent.cs
index 70906fb91..8207cbd48 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/UpsertContent.cs
+++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/UpsertContent.cs
@@ -19,6 +19,8 @@ public sealed class UpsertContent : ContentDataCommand, ISchemaCommand
public bool Patch { get; set; }
+ public bool EnrichDefaults { get; set; }
+
public UpsertContent()
{
ContentId = DomainId.NewGuid();
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.cs
index 0fb171308..e24c9defc 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.cs
+++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.cs
@@ -206,6 +206,21 @@ public partial class ContentDomainObject : DomainObject
return Snapshot;
}, ct);
+ case EnrichContentDefaults enrichContentDefaults:
+ return ApplyReturnAsync(enrichContentDefaults, async (c, ct) =>
+ {
+ var operation = await ContentOperation.CreateAsync(serviceProvider, c, () => Snapshot);
+
+ var newData = operation.GenerateDefaultValues(Snapshot.EditingData.Clone());
+
+ if (!newData.Equals(Snapshot.EditingData))
+ {
+ Update(c, newData);
+ }
+
+ return Snapshot;
+ }, ct);
+
case DeleteContent { Permanent: true } deleteContent:
return DeletePermanentAsync(deleteContent, async (c, ct) =>
{
@@ -319,6 +334,11 @@ public partial class ContentDomainObject : DomainObject
var newData = c.Data;
+ if (c.EnrichDefaults)
+ {
+ newData = operation.GenerateDefaultValues(newData);
+ }
+
if (newData.Equals(Snapshot.EditingData))
{
return;
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentsBulkUpdateCommandMiddleware.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentsBulkUpdateCommandMiddleware.cs
index bb9a5036f..386b3b739 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentsBulkUpdateCommandMiddleware.cs
+++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentsBulkUpdateCommandMiddleware.cs
@@ -189,6 +189,10 @@ public sealed class ContentsBulkUpdateCommandMiddleware : ICommandMiddleware
return CreateTask(id, schemaId, bulkJob, bulk, jobIndex,
PermissionIds.AppContentsReadOwn);
+ case BulkUpdateContentType.EnrichDefaults:
+ return CreateTask(id, schemaId, bulkJob, bulk, jobIndex,
+ PermissionIds.AppContentsUpdateOwn);
+
case BulkUpdateContentType.ChangeStatus:
return CreateTask(id, schemaId, bulkJob, bulk, jobIndex,
PermissionIds.AppContentsChangeStatusOwn);
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/Text/TextIndexingProcess.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/Text/TextIndexingProcess.cs
index d3703de56..f9b4a1dad 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Contents/Text/TextIndexingProcess.cs
+++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/Text/TextIndexingProcess.cs
@@ -5,11 +5,9 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
-using LibGit2Sharp;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Entities.Contents.Text.State;
using Squidex.Domain.Apps.Events.Contents;
-using Squidex.Infrastructure;
using Squidex.Infrastructure.EventSourcing;
using Squidex.Infrastructure.Json;
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Rules/DomainObject/RuleDomainObject.cs b/backend/src/Squidex.Domain.Apps.Entities/Rules/DomainObject/RuleDomainObject.cs
index 020a3e6f0..a423fb449 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Rules/DomainObject/RuleDomainObject.cs
+++ b/backend/src/Squidex.Domain.Apps.Entities/Rules/DomainObject/RuleDomainObject.cs
@@ -110,7 +110,7 @@ public partial class RuleDomainObject : DomainObject
{
await Trigger(triggerRule);
- return true;
+ return None.Value;
}, ct);
default:
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs
index 2ade95a56..1f584281f 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs
@@ -437,9 +437,36 @@ public sealed class ContentsController : ApiController
[AcceptHeader.Unpublished]
[AcceptHeader.Languages]
[ApiCosts(1)]
- public async Task PutContent(string app, string schema, DomainId id, [FromBody] ContentData request)
+ public async Task PutContent(string app, string schema, DomainId id, UpdateContentDto request)
{
- var command = new UpdateContent { ContentId = id, Data = request };
+ var command = request.ToCommand(id);
+
+ var response = await InvokeCommandAsync(command);
+
+ return Ok(response);
+ }
+
+ ///
+ /// Enrich a content item with defaults.
+ ///
+ /// The name of the app.
+ /// The name of the schema.
+ /// The ID of the content item to update.
+ /// Content updated.
+ /// Content references, schema or app not found.
+ ///
+ /// You can read the generated documentation for your app at /api/content/{appName}/docs.
+ ///
+ [HttpPut]
+ [Route("content/{app}/{schema}/{id}/defaults")]
+ [ProducesResponseType(typeof(ContentDto), StatusCodes.Status200OK)]
+ [ApiPermissionOrAnonymous(PermissionIds.AppContentsUpdateOwn)]
+ [AcceptHeader.Unpublished]
+ [AcceptHeader.Languages]
+ [ApiCosts(1)]
+ public async Task PutContentDefaults(string app, string schema, DomainId id)
+ {
+ var command = new EnrichContentDefaults { ContentId = id };
var response = await InvokeCommandAsync(command);
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs
index b4f32027b..57ed3ef12 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs
@@ -175,6 +175,7 @@ public sealed class SchemasOpenApiGenerator
.OperationSummary("Upsert a [schema] content item.")
.HasQuery("patch", JsonObjectType.Boolean, FieldDescriptions.ContentRequestPatch)
.HasQuery("publish", JsonObjectType.Boolean, FieldDescriptions.ContentRequestPublish)
+ .HasQuery("enrichDefaults", JsonObjectType.String, FieldDescriptions.ContentRequestApplyDefaults)
.HasId()
.HasBody("data", builder.DataSchema, Resources.OpenApiSchemaBody)
.Responds(200, "Content item created or updated.", builder.ContentSchema)
@@ -184,11 +185,19 @@ public sealed class SchemasOpenApiGenerator
.RequirePermission(PermissionIds.AppContentsUpdateOwn)
.Operation("Update")
.OperationSummary("Update a [schema] content item.")
+ .HasQuery("enrichDefaults", JsonObjectType.String, FieldDescriptions.ContentRequestApplyDefaults)
.HasId()
.HasBody("data", builder.DataSchema, Resources.OpenApiSchemaBody)
.Responds(200, "Content item updated.", builder.ContentSchema)
.Responds(400, "Content data not valid.");
+ builder.AddOperation(OpenApiOperationMethod.Put, "/{id}/defaults")
+ .RequirePermission(PermissionIds.AppContentsUpdateOwn)
+ .Operation("UpdateDefaults")
+ .OperationSummary("Apply a [schema] content item. defaults")
+ .HasId()
+ .Responds(200, "Content item updated.", builder.ContentSchema);
+
builder.AddOperation(OpenApiOperationMethod.Patch, "/{id}")
.RequirePermission(PermissionIds.AppContentsUpdateOwn)
.Operation("Patch")
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/BulkUpdateContentsJobDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/BulkUpdateContentsJobDto.cs
index f16713ec3..fb4b758e9 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/BulkUpdateContentsJobDto.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/BulkUpdateContentsJobDto.cs
@@ -62,6 +62,11 @@ public class BulkUpdateContentsJobDto
///
public bool Permanent { get; set; }
+ ///
+ /// Enrich the data with the default values when updating a content item.
+ ///
+ public bool EnrichDefaults { get; set; }
+
///
/// The number of expected items. Set it to a higher number to update multiple items when a query is defined.
///
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/UpdateContentDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/UpdateContentDto.cs
new file mode 100644
index 000000000..e3c48e8ab
--- /dev/null
+++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/UpdateContentDto.cs
@@ -0,0 +1,36 @@
+// ==========================================================================
+// Squidex Headless CMS
+// ==========================================================================
+// Copyright (c) Squidex UG (haftungsbeschraenkt)
+// All rights reserved. Licensed under the MIT license.
+// ==========================================================================
+
+using Microsoft.AspNetCore.Mvc;
+using Squidex.Domain.Apps.Core.Contents;
+using Squidex.Domain.Apps.Entities.Contents.Commands;
+using Squidex.Infrastructure;
+using Squidex.Infrastructure.Reflection;
+using Squidex.Web;
+
+namespace Squidex.Areas.Api.Controllers.Contents.Models;
+
+[OpenApiRequest]
+public class UpdateContentDto
+{
+ ///
+ /// The full data for the content item.
+ ///
+ [FromBody]
+ public ContentData Data { get; set; }
+
+ ///
+ /// Enrich the content with defaults.
+ ///
+ [FromQuery(Name = "enrichDefaults")]
+ public bool EnrichDefaults { get; set; }
+
+ public UpdateContent ToCommand(DomainId id)
+ {
+ return SimpleMapper.Map(this, new UpdateContent { ContentId = id });
+ }
+}
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/UpsertContentDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/UpsertContentDto.cs
index 73a268410..56303da75 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/UpsertContentDto.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/UpsertContentDto.cs
@@ -36,6 +36,12 @@ public class UpsertContentDto
[FromQuery(Name = "patch")]
public bool Patch { get; set; }
+ ///
+ /// Enrich the content with defaults.
+ ///
+ [FromQuery(Name = "enrichDefaults")]
+ public bool EnrichDefaults { get; set; }
+
///
/// True to automatically publish the content.
///
diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/DomainObject/AppDomainObjectTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/DomainObject/AppDomainObjectTests.cs
index bb3077c4c..9d5a63ed2 100644
--- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/DomainObject/AppDomainObjectTests.cs
+++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/DomainObject/AppDomainObjectTests.cs
@@ -16,12 +16,12 @@ using Squidex.Domain.Apps.Entities.Billing;
using Squidex.Domain.Apps.Entities.TestHelpers;
using Squidex.Domain.Apps.Events.Apps;
using Squidex.Infrastructure;
-using Squidex.Infrastructure.Commands;
using Squidex.Infrastructure.Json.Objects;
using Squidex.Shared.Users;
namespace Squidex.Domain.Apps.Entities.Apps.DomainObject;
+[UsesVerify]
public class AppDomainObjectTests : HandlerTestBase
{
private readonly IBillingPlans billingPlans = A.Fake();
@@ -108,18 +108,9 @@ public class AppDomainObjectTests : HandlerTestBase
{
var command = new CreateApp { Name = AppId.Name, AppId = AppId.Id };
- var actual = await PublishAsync(command);
+ var actual = await PublishAsync(sut, command);
- actual.ShouldBeEquivalent(sut.Snapshot);
-
- Assert.Equal(AppId.Name, sut.Snapshot.Name);
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppCreated { Name = AppId.Name }),
- CreateEvent(new AppContributorAssigned { ContributorId = User.Identifier, Role = Role.Owner }),
- CreateEvent(new AppSettingsUpdated { Settings = initialSettings.Settings })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -127,17 +118,9 @@ public class AppDomainObjectTests : HandlerTestBase
{
var command = new CreateApp { Name = AppId.Name, Actor = Client, AppId = AppId.Id };
- var actual = await PublishAsync(command);
-
- actual.ShouldBeEquivalent(sut.Snapshot);
-
- Assert.Equal(AppId.Name, sut.Snapshot.Name);
+ var actual = await PublishAsync(sut, command);
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppCreated { Name = AppId.Name }, true), // Must be with client actor.
- CreateEvent(new AppSettingsUpdated { Settings = initialSettings.Settings }, true)
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -147,17 +130,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
- var actual = await PublishIdempotentAsync(command);
+ var actual = await PublishIdempotentAsync(sut, command);
- actual.ShouldBeEquivalent(sut.Snapshot);
-
- Assert.Equal(command.Label, sut.Snapshot.Label);
- Assert.Equal(command.Description, sut.Snapshot.Description);
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppUpdated { Label = command.Label, Description = command.Description })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -173,16 +148,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
- var actual = await PublishIdempotentAsync(command);
-
- actual.ShouldBeEquivalent(sut.Snapshot);
-
- Assert.Equal(command.Settings, sut.Snapshot.Settings);
+ var actual = await PublishIdempotentAsync(sut, command);
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppSettingsUpdated { Settings = command.Settings })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -192,16 +160,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
- var actual = await PublishAsync(command);
+ var actual = await PublishAsync(sut, command);
- actual.ShouldBeEquivalent(sut.Snapshot);
-
- Assert.Equal(command.File.MimeType, sut.Snapshot.Image!.MimeType);
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppImageUploaded { Image = sut.Snapshot.Image })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -212,16 +173,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
await ExecuteUploadImage();
- var actual = await PublishIdempotentAsync(command);
-
- actual.ShouldBeEquivalent(sut.Snapshot);
-
- Assert.Null(sut.Snapshot.Image);
+ var actual = await PublishIdempotentAsync(sut, command);
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppImageRemoved())
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -234,16 +188,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
- var actual = await PublishIdempotentAsync(command);
+ var actual = await PublishIdempotentAsync(sut, command);
- actual.ShouldBeEquivalent(new PlanChangedResult(planIdPaid));
-
- Assert.Equal(planIdPaid, sut.Snapshot.Plan!.PlanId);
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppPlanChanged { PlanId = planIdPaid })
- );
+ await VerifySutAsync(actual, new PlanChangedResult(planIdPaid));
A.CallTo(() => billingManager.MustRedirectToPortalAsync(User.Identifier, A._, planIdPaid, CancellationToken))
.MustHaveHappened();
@@ -259,16 +206,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
- var actual = await PublishIdempotentAsync(command);
-
- actual.ShouldBeEquivalent(new PlanChangedResult(planIdPaid));
-
- Assert.Equal(planIdPaid, sut.Snapshot.Plan!.PlanId);
+ var actual = await PublishIdempotentAsync(sut, command);
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppPlanChanged { PlanId = planIdPaid })
- );
+ await VerifySutAsync(actual, new PlanChangedResult(planIdPaid));
A.CallTo(() => billingManager.MustRedirectToPortalAsync(A._, A._, A._, A._))
.MustNotHaveHappened();
@@ -285,16 +225,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
await ExecuteChangePlanAsync();
- var actual = await PublishIdempotentAsync(command);
+ var actual = await PublishIdempotentAsync(sut, command);
- actual.ShouldBeEquivalent(new PlanChangedResult(planIdFree, true));
-
- Assert.Null(sut.Snapshot.Plan);
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppPlanReset())
- );
+ await VerifySutAsync(actual, new PlanChangedResult(planIdFree, true));
A.CallTo(() => billingManager.MustRedirectToPortalAsync(A._, A._, A._, A._))
.MustHaveHappenedOnceExactly();
@@ -311,16 +244,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
await ExecuteChangePlanAsync();
- var actual = await PublishIdempotentAsync(command);
-
- actual.ShouldBeEquivalent(new PlanChangedResult(planIdFree, true));
-
- Assert.Null(sut.Snapshot.Plan);
+ var actual = await PublishIdempotentAsync(sut, command);
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppPlanReset())
- );
+ await VerifySutAsync(actual, new PlanChangedResult(planIdFree, true));
A.CallTo(() => billingManager.MustRedirectToPortalAsync(User.Identifier, A._, planIdPaid, CancellationToken))
.MustHaveHappenedOnceExactly();
@@ -339,11 +265,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
- var actual = await PublishIdempotentAsync(command);
+ var actual = await PublishIdempotentAsync(sut, command);
- actual.ShouldBeEquivalent(new PlanChangedResult(planIdPaid, false, new Uri("http://squidex.io")));
-
- Assert.Null(sut.Snapshot.Plan);
+ await VerifySutAsync(actual, new PlanChangedResult(planIdPaid, false, new Uri("http://squidex.io")));
}
[Fact]
@@ -353,11 +277,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
- var actual = await PublishIdempotentAsync(command);
-
- actual.ShouldBeEquivalent(new PlanChangedResult(planIdPaid));
+ var actual = await PublishIdempotentAsync(sut, command);
- Assert.Equal(planIdPaid, sut.Snapshot.Plan?.PlanId);
+ await VerifySutAsync(actual, new PlanChangedResult(planIdPaid));
A.CallTo(() => billingManager.MustRedirectToPortalAsync(User.Identifier, A._, planIdPaid, A._))
.MustNotHaveHappened();
@@ -373,16 +295,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
- var actual = await PublishIdempotentAsync(command);
-
- actual.ShouldBeEquivalent(sut.Snapshot);
-
- Assert.Equal(Role.Editor, sut.Snapshot.Contributors[contributorId]);
+ var actual = await PublishIdempotentAsync(sut, command);
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppContributorAssigned { ContributorId = contributorId, Role = Role.Editor, IsAdded = true })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -393,16 +308,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
await ExecuteAssignContributorAsync();
- var actual = await PublishIdempotentAsync(command);
+ var actual = await PublishIdempotentAsync(sut, command);
- actual.ShouldBeEquivalent(sut.Snapshot);
-
- Assert.Equal(Role.Owner, sut.Snapshot.Contributors[contributorId]);
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppContributorAssigned { ContributorId = contributorId, Role = Role.Owner })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -413,16 +321,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
await ExecuteAssignContributorAsync();
- var actual = await PublishAsync(command);
-
- actual.ShouldBeEquivalent(sut.Snapshot);
-
- Assert.False(sut.Snapshot.Contributors.ContainsKey(contributorId));
+ var actual = await PublishAsync(sut, command);
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppContributorRemoved { ContributorId = contributorId })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -432,16 +333,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
- var actual = await PublishAsync(command);
+ var actual = await PublishAsync(sut, command);
- actual.ShouldBeEquivalent(sut.Snapshot);
-
- Assert.Equal(TeamId, sut.Snapshot.TeamId);
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppTransfered { TeamId = TeamId })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -452,16 +346,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
await ExecuteTransferAsync();
- var actual = await PublishAsync(command);
-
- actual.ShouldBeEquivalent(sut.Snapshot);
+ var actual = await PublishAsync(sut, command);
- Assert.Null(sut.Snapshot.TeamId);
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppTransfered { TeamId = null })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -471,16 +358,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
- var actual = await PublishAsync(command);
-
- actual.ShouldBeEquivalent(sut.Snapshot);
+ var actual = await PublishAsync(sut, command);
- Assert.True(sut.Snapshot.Clients.ContainsKey(clientId));
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppClientAttached { Id = clientId, Secret = command.Secret })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -491,16 +371,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
await ExecuteAttachClientAsync();
- var actual = await PublishIdempotentAsync(command);
-
- actual.ShouldBeEquivalent(sut.Snapshot);
+ var actual = await PublishIdempotentAsync(sut, command);
- Assert.Equal(clientNewName, sut.Snapshot.Clients[clientId].Name);
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppClientUpdated { Id = clientId, Name = clientNewName, Role = Role.Developer })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -511,16 +384,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
await ExecuteAttachClientAsync();
- var actual = await PublishAsync(command);
-
- actual.ShouldBeEquivalent(sut.Snapshot);
+ var actual = await PublishAsync(sut, command);
- Assert.False(sut.Snapshot.Clients.ContainsKey(clientId));
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppClientRevoked { Id = clientId })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -530,16 +396,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
- var actual = await PublishAsync(command);
-
- actual.ShouldBeEquivalent(sut.Snapshot);
+ var actual = await PublishAsync(sut, command);
- Assert.NotEmpty(sut.Snapshot.Workflows);
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppWorkflowAdded { WorkflowId = workflowId, Name = "my-workflow" })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -550,16 +409,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
await ExecuteAddWorkflowAsync();
- var actual = await PublishIdempotentAsync(command);
-
- actual.ShouldBeEquivalent(sut.Snapshot);
+ var actual = await PublishIdempotentAsync(sut, command);
- Assert.NotEmpty(sut.Snapshot.Workflows);
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppWorkflowUpdated { WorkflowId = workflowId, Workflow = Workflow.Default })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -570,16 +422,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
await ExecuteAddWorkflowAsync();
- var actual = await PublishAsync(command);
-
- actual.ShouldBeEquivalent(sut.Snapshot);
+ var actual = await PublishAsync(sut, command);
- Assert.Empty(sut.Snapshot.Workflows);
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppWorkflowDeleted { WorkflowId = workflowId })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -589,16 +434,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
- var actual = await PublishAsync(command);
-
- actual.ShouldBeEquivalent(sut.Snapshot);
+ var actual = await PublishAsync(sut, command);
- Assert.True(sut.Snapshot.Languages.Contains(Language.DE));
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppLanguageAdded { Language = Language.DE })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -609,16 +447,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
await ExecuteAddLanguageAsync(Language.DE);
- var actual = await PublishAsync(command);
-
- actual.ShouldBeEquivalent(sut.Snapshot);
+ var actual = await PublishAsync(sut, command);
- Assert.False(sut.Snapshot.Languages.Contains(Language.DE));
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppLanguageRemoved { Language = Language.DE })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -629,16 +460,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
await ExecuteAddLanguageAsync(Language.DE);
- var actual = await PublishIdempotentAsync(command);
-
- actual.ShouldBeEquivalent(sut.Snapshot);
+ var actual = await PublishIdempotentAsync(sut, command);
- Assert.True(sut.Snapshot.Languages.Contains(Language.DE));
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppLanguageUpdated { Language = Language.DE, Fallback = [Language.EN] })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -648,16 +472,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
- var actual = await PublishAsync(command);
-
- actual.ShouldBeEquivalent(sut.Snapshot);
+ var actual = await PublishAsync(sut, command);
- Assert.Equal(1, sut.Snapshot.Roles.CustomCount);
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppRoleAdded { Name = roleName })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -668,16 +485,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
await ExecuteAddRoleAsync();
- var actual = await PublishAsync(command);
-
- actual.ShouldBeEquivalent(sut.Snapshot);
+ var actual = await PublishAsync(sut, command);
- Assert.Equal(0, sut.Snapshot.Roles.CustomCount);
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppRoleDeleted { Name = roleName })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -688,14 +498,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
await ExecuteAddRoleAsync();
- var actual = await PublishIdempotentAsync(command);
-
- actual.ShouldBeEquivalent(sut.Snapshot);
+ var actual = await PublishIdempotentAsync(sut, command);
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppRoleUpdated { Name = roleName, Permissions = command.Permissions, Properties = command.Properties })
- );
+ await VerifySutAsync(actual);
}
[Fact]
@@ -705,16 +510,9 @@ public class AppDomainObjectTests : HandlerTestBase
await ExecuteCreateAsync();
- var actual = await PublishAsync(command);
+ var actual = await PublishAsync(sut, command);
- actual.ShouldBeEquivalent(None.Value);
-
- Assert.True(sut.Snapshot.IsDeleted);
-
- LastEvents
- .ShouldHaveSameEvents(
- CreateEvent(new AppDeleted())
- );
+ await VerifySutAsync(actual, None.Value);
A.CallTo(() => billingManager.UnsubscribeAsync(command.Actor.Identifier, A._, default))
.MustHaveHappened();
@@ -722,63 +520,65 @@ public class AppDomainObjectTests : HandlerTestBase
private Task ExecuteCreateAsync()
{
- return PublishAsync(new CreateApp { Name = AppId.Name, AppId = AppId.Id });
+ return PublishAsync(sut, new CreateApp { Name = AppId.Name, AppId = AppId.Id });
}
private Task ExecuteUploadImage()
{
- return PublishAsync(new UploadAppImage { File = new NoopAssetFile() });
+ return PublishAsync(sut, new UploadAppImage { File = new NoopAssetFile() });
}
private Task ExecuteAssignContributorAsync()
{
- return PublishAsync(new AssignContributor { ContributorId = contributorId, Role = Role.Editor });
+ return PublishAsync(sut, new AssignContributor { ContributorId = contributorId, Role = Role.Editor });
}
private Task ExecuteAttachClientAsync()
{
- return PublishAsync(new AttachClient { Id = clientId });
+ return PublishAsync(sut, new AttachClient { Id = clientId });
}
private Task ExecuteAddRoleAsync()
{
- return PublishAsync(new AddRole { Name = roleName });
+ return PublishAsync(sut, new AddRole { Name = roleName });
}
private Task ExecuteAddLanguageAsync(Language language)
{
- return PublishAsync(new AddLanguage { Language = language });
+ return PublishAsync(sut, new AddLanguage { Language = language });
}
private Task ExecuteAddWorkflowAsync()
{
- return PublishAsync(new AddWorkflow { WorkflowId = workflowId, Name = "my-workflow" });
+ return PublishAsync(sut, new AddWorkflow { WorkflowId = workflowId, Name = "my-workflow" });
}
private Task ExecuteChangePlanAsync()
{
- return PublishAsync(new ChangePlan { PlanId = planIdPaid });
+ return PublishAsync(sut, new ChangePlan { PlanId = planIdPaid });
}
private Task ExecuteTransferAsync()
{
- return PublishAsync(new TransferToTeam { TeamId = TeamId });
+ return PublishAsync(sut, new TransferToTeam { TeamId = TeamId });
}
private Task ExecuteArchiveAsync()
{
- return PublishAsync(new DeleteApp());
+ return PublishAsync(sut, new DeleteApp());
}
- private Task