Browse Source

Enrich defaults (#1057)

* Initial

* Simplify tests.

* Enrich defaults.
pull/1058/head
Sebastian Stehle 3 years ago
committed by GitHub
parent
commit
28ee481e01
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      backend/src/Squidex.Domain.Apps.Core.Model/FieldDescriptions.Designer.cs
  2. 3
      backend/src/Squidex.Domain.Apps.Core.Model/FieldDescriptions.resx
  3. 3
      backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/BulkUpdateContentType.cs
  4. 2
      backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/BulkUpdateJob.cs
  5. 12
      backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/EnrichContentDefaults.cs
  6. 1
      backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/UpdateContent.cs
  7. 2
      backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/UpsertContent.cs
  8. 20
      backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.cs
  9. 4
      backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentsBulkUpdateCommandMiddleware.cs
  10. 2
      backend/src/Squidex.Domain.Apps.Entities/Contents/Text/TextIndexingProcess.cs
  11. 2
      backend/src/Squidex.Domain.Apps.Entities/Rules/DomainObject/RuleDomainObject.cs
  12. 31
      backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs
  13. 9
      backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs
  14. 5
      backend/src/Squidex/Areas/Api/Controllers/Contents/Models/BulkUpdateContentsJobDto.cs
  15. 36
      backend/src/Squidex/Areas/Api/Controllers/Contents/Models/UpdateContentDto.cs
  16. 6
      backend/src/Squidex/Areas/Api/Controllers/Contents/Models/UpsertContentDto.cs
  17. 362
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/DomainObject/AppDomainObjectTests.cs
  18. 211
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/DomainObject/AssetDomainObjectTests.cs
  19. 88
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/DomainObject/AssetFolderDomainObjectTests.cs
  20. 336
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentDomainObjectTests.cs
  21. 37
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentsBulkUpdateCommandMiddlewareTests.cs
  22. 128
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Rules/DomainObject/RuleDomainObjectTests.cs
  23. 388
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/DomainObject/SchemaDomainObjectTests.cs
  24. 1
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj
  25. 141
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Teams/DomainObject/TeamDomainObjectTests.cs
  26. 40
      backend/tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/AssertHelper.cs
  27. 39
      backend/tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/HandlerTestBase.cs
  28. 147
      backend/tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/VerifySettings.cs
  29. 127
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.AddLanguage_should_create_events_and_add_language.verified.txt
  30. 134
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.AddRole_should_create_events_and_add_role.verified.txt
  31. 156
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.AddWorkflow_should_create_events_and_add_workflow.verified.txt
  32. 122
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.ArchiveApp_should_create_events_and_update_deleted_flag.verified.txt
  33. 127
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.AssignContributor_should_create_events_and_add_contributor.verified.txt
  34. 127
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.AssignContributor_should_create_update_events_and_update_contributor.verified.txt
  35. 130
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.AttachClient_should_create_events_and_add_client.verified.txt
  36. 127
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.ChangePlan_from_callback_should_create_events_and_update_plan.verified.txt
  37. 122
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.ChangePlan_from_callback_should_reset_plan_for_free_plan.verified.txt
  38. 127
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.ChangePlan_should_create_events_and_update_plan.verified.txt
  39. 127
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.ChangePlan_should_not_call_billing_manager_for_callback.verified.txt
  40. 108
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.ChangePlan_should_not_make_update_for_redirect.verified.txt
  41. 122
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.ChangePlan_should_reset_plan_for_free_plan.verified.txt
  42. 155
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.Create_should_create_events_and_set_intitial_state.verified.txt
  43. 136
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.Create_should_not_assign_client_as_contributor.verified.txt
  44. 123
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.DeleteRole_should_create_events_and_delete_role.verified.txt
  45. 123
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.DeleteWorkflow_should_create_events_and_remove_workflow.verified.txt
  46. 123
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.RemoveContributor_should_create_events_and_remove_contributor.verified.txt
  47. 122
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.RemoveImage_should_create_events_and_update_image.verified.txt
  48. 123
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.RemoveLanguage_should_create_events_and_remove_language.verified.txt
  49. 123
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.RevokeClient_should_create_events_and_remove_client.verified.txt
  50. 122
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.Transfer_from_team_should_create_events_and_set_team.verified.txt
  51. 124
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.Transfer_should_create_events_and_set_team.verified.txt
  52. 132
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.UpdateClient_should_create_events_and_update_client.verified.txt
  53. 135
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.UpdateLanguage_should_create_events_and_update_language.verified.txt
  54. 147
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.UpdateRole_should_create_events_and_update_role.verified.txt
  55. 126
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.UpdateSettings_should_create_event_and_update_settings.verified.txt
  56. 185
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.UpdateWorkflow_should_create_events_and_update_workflow.verified.txt
  57. 126
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.Update_should_create_events_and_update_label_and_description.verified.txt
  58. 130
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.UploadImage_should_create_events_and_update_image.verified.txt
  59. 44
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.AnnotateMetadata_should_create_events_and_update_metadata.verified.txt
  60. 39
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.AnnotateName_should_create_events_and_update_file_name.verified.txt
  61. 39
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.AnnotateProtected_should_create_events_and_update_protected_flag.verified.txt
  62. 39
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.AnnotateSlug_should_create_events_and_update_slug.verified.txt
  63. 44
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.AnnotateTags_should_create_events_and_update_tags.verified.txt
  64. 41
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.Create_should_create_events_and_set_intitial_state.verified.txt
  65. 40
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.Delete_should_create_events_with_total_file_size_and_tags_and_update_deleted_flag.verified.txt
  66. 40
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.Move_should_create_events_and_update_parent_id.verified.txt
  67. 43
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.Update_should_create_events_and_update_file_state.verified.txt
  68. 41
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.Upsert_should_create_events_and_set_intitial_state_if_not_found.verified.txt
  69. 43
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.Upsert_should_create_events_and_update_file_state_if_found.verified.txt
  70. 31
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetFolderDomainObjectTests.Create_should_create_events_and_set_intitial_state.verified.txt
  71. 32
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetFolderDomainObjectTests.Delete_should_create_events_with_total_file_size.verified.txt
  72. 34
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetFolderDomainObjectTests.Move_should_create_events_and_update_state.verified.txt
  73. 33
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetFolderDomainObjectTests.Update_should_create_events_and_update_state.verified.txt
  74. 1
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ApplyDefaults_should_not_update_content_if_all_fields_have_a_value.verified.txt
  75. 61
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ApplyDefaults_should_update_content.verified.txt
  76. 48
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.CancelContentSchedule_create_events_and_unset_schedule.verified.txt
  77. 48
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.CancelContentSchedule_should_create_events_and_unset_schedule.verified.txt
  78. 54
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ChangeStatus_create_events_and_set_schedule_if_duetime_set.verified.txt
  79. 80
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ChangeStatus_should_also_update_if_script_changes_data.verified.txt
  80. 51
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ChangeStatus_should_create_events_and_delete_new_version_if_available.verified.txt
  81. 48
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ChangeStatus_should_create_events_and_unset_schedule_if_failed.verified.txt
  82. 58
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ChangeStatus_should_create_events_and_update_new_version_if_draft_available.verified.txt
  83. 50
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ChangeStatus_should_create_events_and_update_status_if_changed.verified.txt
  84. 50
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ChangeStatus_should_create_events_and_update_status_if_published.verified.txt
  85. 51
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ChangeStatus_should_create_events_and_update_status_if_unpublished.verified.txt
  86. 50
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ChangeStatus_should_refresh_properties_and_unset_schedule_if_completed.verified.txt
  87. 57
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.CreateDraft_should_create_events_and_update_new_state.verified.txt
  88. 70
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Create_should_change_status_if_set.verified.txt
  89. 52
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Create_should_create_events_and_update_data_and_status.verified.txt
  90. 52
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Create_should_not_change_status_if_set_to_initial.verified.txt
  91. 48
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.DeleteDraft_should_create_events_and_delete_new_version.verified.txt
  92. 48
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Delete_should_create_events_and_update_deleted_flag.verified.txt
  93. 30
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.EnrichContentDefaults_should_not_update_content_if_all_fields_have_a_value.verified.txt
  94. 63
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.EnrichContentDefaults_should_update_content.verified.txt
  95. 63
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Patch_should_create_events_and_update_data.verified.txt
  96. 71
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Patch_should_create_events_and_update_new_version_if_draft_available.verified.txt
  97. 30
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Patch_should_not_create_event_for_same_data.verified.txt
  98. 63
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Update_should_create_events_and_update_data.verified.txt
  99. 71
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Update_should_create_events_and_update_new_version_if_draft_available.verified.txt
  100. 30
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Update_should_not_create_event_for_same_data.verified.txt

9
backend/src/Squidex.Domain.Apps.Core.Model/FieldDescriptions.Designer.cs

@ -456,6 +456,15 @@ namespace Squidex.Domain.Apps.Core {
} }
} }
/// <summary>
/// Looks up a localized string similar to Enrich the content with defaults..
/// </summary>
public static string ContentRequestApplyDefaults {
get {
return ResourceManager.GetString("ContentRequestApplyDefaults", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to The data for the content.. /// Looks up a localized string similar to The data for the content..
/// </summary> /// </summary>

3
backend/src/Squidex.Domain.Apps.Core.Model/FieldDescriptions.resx

@ -249,6 +249,9 @@
<data name="ContentPartitionField" xml:space="preserve"> <data name="ContentPartitionField" xml:space="preserve">
<value>{0} field ({1}).</value> <value>{0} field ({1}).</value>
</data> </data>
<data name="ContentRequestApplyDefaults" xml:space="preserve">
<value>Enrich the content with defaults.</value>
</data>
<data name="ContentRequestData" xml:space="preserve"> <data name="ContentRequestData" xml:space="preserve">
<value>The data for the content.</value> <value>The data for the content.</value>
</data> </data>

3
backend/src/Squidex.Domain.Apps.Entities/Contents/Commands/BulkUpdateContentType.cs

@ -15,5 +15,6 @@ public enum BulkUpdateContentType
Delete, Delete,
Patch, Patch,
Update, Update,
Validate Validate,
EnrichDefaults
} }

2
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 Permanent { get; set; }
public bool EnrichDefaults { get; set; }
public long ExpectedCount { get; set; } = 1; public long ExpectedCount { get; set; } = 1;
public long ExpectedVersion { get; set; } = EtagVersion.Any; public long ExpectedVersion { get; set; } = EtagVersion.Any;

12
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
{
}

1
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 class UpdateContent : ContentDataCommand
{ {
public bool EnrichDefaults { get; set; }
} }

2
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 Patch { get; set; }
public bool EnrichDefaults { get; set; }
public UpsertContent() public UpsertContent()
{ {
ContentId = DomainId.NewGuid(); ContentId = DomainId.NewGuid();

20
backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.cs

@ -206,6 +206,21 @@ public partial class ContentDomainObject : DomainObject<WriteContent>
return Snapshot; return Snapshot;
}, ct); }, 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: case DeleteContent { Permanent: true } deleteContent:
return DeletePermanentAsync(deleteContent, async (c, ct) => return DeletePermanentAsync(deleteContent, async (c, ct) =>
{ {
@ -319,6 +334,11 @@ public partial class ContentDomainObject : DomainObject<WriteContent>
var newData = c.Data; var newData = c.Data;
if (c.EnrichDefaults)
{
newData = operation.GenerateDefaultValues(newData);
}
if (newData.Equals(Snapshot.EditingData)) if (newData.Equals(Snapshot.EditingData))
{ {
return; return;

4
backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentsBulkUpdateCommandMiddleware.cs

@ -189,6 +189,10 @@ public sealed class ContentsBulkUpdateCommandMiddleware : ICommandMiddleware
return CreateTask<ValidateContent>(id, schemaId, bulkJob, bulk, jobIndex, return CreateTask<ValidateContent>(id, schemaId, bulkJob, bulk, jobIndex,
PermissionIds.AppContentsReadOwn); PermissionIds.AppContentsReadOwn);
case BulkUpdateContentType.EnrichDefaults:
return CreateTask<EnrichContentDefaults>(id, schemaId, bulkJob, bulk, jobIndex,
PermissionIds.AppContentsUpdateOwn);
case BulkUpdateContentType.ChangeStatus: case BulkUpdateContentType.ChangeStatus:
return CreateTask<ChangeContentStatus>(id, schemaId, bulkJob, bulk, jobIndex, return CreateTask<ChangeContentStatus>(id, schemaId, bulkJob, bulk, jobIndex,
PermissionIds.AppContentsChangeStatusOwn); PermissionIds.AppContentsChangeStatusOwn);

2
backend/src/Squidex.Domain.Apps.Entities/Contents/Text/TextIndexingProcess.cs

@ -5,11 +5,9 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using LibGit2Sharp;
using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Entities.Contents.Text.State; using Squidex.Domain.Apps.Entities.Contents.Text.State;
using Squidex.Domain.Apps.Events.Contents; using Squidex.Domain.Apps.Events.Contents;
using Squidex.Infrastructure;
using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.EventSourcing;
using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Json;

2
backend/src/Squidex.Domain.Apps.Entities/Rules/DomainObject/RuleDomainObject.cs

@ -110,7 +110,7 @@ public partial class RuleDomainObject : DomainObject<Rule>
{ {
await Trigger(triggerRule); await Trigger(triggerRule);
return true; return None.Value;
}, ct); }, ct);
default: default:

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

@ -437,9 +437,36 @@ public sealed class ContentsController : ApiController
[AcceptHeader.Unpublished] [AcceptHeader.Unpublished]
[AcceptHeader.Languages] [AcceptHeader.Languages]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutContent(string app, string schema, DomainId id, [FromBody] ContentData request) public async Task<IActionResult> 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);
}
/// <summary>
/// Enrich a content item with defaults.
/// </summary>
/// <param name="app">The name of the app.</param>
/// <param name="schema">The name of the schema.</param>
/// <param name="id">The ID of the content item to update.</param>
/// <response code="200">Content updated.</response>
/// <response code="404">Content references, schema or app not found.</response>
/// <remarks>
/// You can read the generated documentation for your app at /api/content/{appName}/docs.
/// </remarks>
[HttpPut]
[Route("content/{app}/{schema}/{id}/defaults")]
[ProducesResponseType(typeof(ContentDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(PermissionIds.AppContentsUpdateOwn)]
[AcceptHeader.Unpublished]
[AcceptHeader.Languages]
[ApiCosts(1)]
public async Task<IActionResult> PutContentDefaults(string app, string schema, DomainId id)
{
var command = new EnrichContentDefaults { ContentId = id };
var response = await InvokeCommandAsync(command); var response = await InvokeCommandAsync(command);

9
backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs

@ -175,6 +175,7 @@ public sealed class SchemasOpenApiGenerator
.OperationSummary("Upsert a [schema] content item.") .OperationSummary("Upsert a [schema] content item.")
.HasQuery("patch", JsonObjectType.Boolean, FieldDescriptions.ContentRequestPatch) .HasQuery("patch", JsonObjectType.Boolean, FieldDescriptions.ContentRequestPatch)
.HasQuery("publish", JsonObjectType.Boolean, FieldDescriptions.ContentRequestPublish) .HasQuery("publish", JsonObjectType.Boolean, FieldDescriptions.ContentRequestPublish)
.HasQuery("enrichDefaults", JsonObjectType.String, FieldDescriptions.ContentRequestApplyDefaults)
.HasId() .HasId()
.HasBody("data", builder.DataSchema, Resources.OpenApiSchemaBody) .HasBody("data", builder.DataSchema, Resources.OpenApiSchemaBody)
.Responds(200, "Content item created or updated.", builder.ContentSchema) .Responds(200, "Content item created or updated.", builder.ContentSchema)
@ -184,11 +185,19 @@ public sealed class SchemasOpenApiGenerator
.RequirePermission(PermissionIds.AppContentsUpdateOwn) .RequirePermission(PermissionIds.AppContentsUpdateOwn)
.Operation("Update") .Operation("Update")
.OperationSummary("Update a [schema] content item.") .OperationSummary("Update a [schema] content item.")
.HasQuery("enrichDefaults", JsonObjectType.String, FieldDescriptions.ContentRequestApplyDefaults)
.HasId() .HasId()
.HasBody("data", builder.DataSchema, Resources.OpenApiSchemaBody) .HasBody("data", builder.DataSchema, Resources.OpenApiSchemaBody)
.Responds(200, "Content item updated.", builder.ContentSchema) .Responds(200, "Content item updated.", builder.ContentSchema)
.Responds(400, "Content data not valid."); .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}") builder.AddOperation(OpenApiOperationMethod.Patch, "/{id}")
.RequirePermission(PermissionIds.AppContentsUpdateOwn) .RequirePermission(PermissionIds.AppContentsUpdateOwn)
.Operation("Patch") .Operation("Patch")

5
backend/src/Squidex/Areas/Api/Controllers/Contents/Models/BulkUpdateContentsJobDto.cs

@ -62,6 +62,11 @@ public class BulkUpdateContentsJobDto
/// </summary> /// </summary>
public bool Permanent { get; set; } public bool Permanent { get; set; }
/// <summary>
/// Enrich the data with the default values when updating a content item.
/// </summary>
public bool EnrichDefaults { get; set; }
/// <summary> /// <summary>
/// The number of expected items. Set it to a higher number to update multiple items when a query is defined. /// The number of expected items. Set it to a higher number to update multiple items when a query is defined.
/// </summary> /// </summary>

36
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
{
/// <summary>
/// The full data for the content item.
/// </summary>
[FromBody]
public ContentData Data { get; set; }
/// <summary>
/// Enrich the content with defaults.
/// </summary>
[FromQuery(Name = "enrichDefaults")]
public bool EnrichDefaults { get; set; }
public UpdateContent ToCommand(DomainId id)
{
return SimpleMapper.Map(this, new UpdateContent { ContentId = id });
}
}

6
backend/src/Squidex/Areas/Api/Controllers/Contents/Models/UpsertContentDto.cs

@ -36,6 +36,12 @@ public class UpsertContentDto
[FromQuery(Name = "patch")] [FromQuery(Name = "patch")]
public bool Patch { get; set; } public bool Patch { get; set; }
/// <summary>
/// Enrich the content with defaults.
/// </summary>
[FromQuery(Name = "enrichDefaults")]
public bool EnrichDefaults { get; set; }
/// <summary> /// <summary>
/// True to automatically publish the content. /// True to automatically publish the content.
/// </summary> /// </summary>

362
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.Entities.TestHelpers;
using Squidex.Domain.Apps.Events.Apps; using Squidex.Domain.Apps.Events.Apps;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.Commands;
using Squidex.Infrastructure.Json.Objects; using Squidex.Infrastructure.Json.Objects;
using Squidex.Shared.Users; using Squidex.Shared.Users;
namespace Squidex.Domain.Apps.Entities.Apps.DomainObject; namespace Squidex.Domain.Apps.Entities.Apps.DomainObject;
[UsesVerify]
public class AppDomainObjectTests : HandlerTestBase<App> public class AppDomainObjectTests : HandlerTestBase<App>
{ {
private readonly IBillingPlans billingPlans = A.Fake<IBillingPlans>(); private readonly IBillingPlans billingPlans = A.Fake<IBillingPlans>();
@ -108,18 +108,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
{ {
var command = new CreateApp { Name = AppId.Name, AppId = AppId.Id }; 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); await VerifySutAsync(actual);
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 })
);
} }
[Fact] [Fact]
@ -127,17 +118,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
{ {
var command = new CreateApp { Name = AppId.Name, Actor = Client, AppId = AppId.Id }; var command = new CreateApp { Name = AppId.Name, Actor = Client, 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 await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateEvent(new AppCreated { Name = AppId.Name }, true), // Must be with client actor.
CreateEvent(new AppSettingsUpdated { Settings = initialSettings.Settings }, true)
);
} }
[Fact] [Fact]
@ -147,17 +130,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
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 })
);
} }
[Fact] [Fact]
@ -173,16 +148,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(command.Settings, sut.Snapshot.Settings);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateEvent(new AppSettingsUpdated { Settings = command.Settings })
);
} }
[Fact] [Fact]
@ -192,16 +160,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(command.File.MimeType, sut.Snapshot.Image!.MimeType);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new AppImageUploaded { Image = sut.Snapshot.Image })
);
} }
[Fact] [Fact]
@ -212,16 +173,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteUploadImage(); await ExecuteUploadImage();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Null(sut.Snapshot.Image);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateEvent(new AppImageRemoved())
);
} }
[Fact] [Fact]
@ -234,16 +188,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(new PlanChangedResult(planIdPaid)); await VerifySutAsync(actual, new PlanChangedResult(planIdPaid));
Assert.Equal(planIdPaid, sut.Snapshot.Plan!.PlanId);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new AppPlanChanged { PlanId = planIdPaid })
);
A.CallTo(() => billingManager.MustRedirectToPortalAsync(User.Identifier, A<App>._, planIdPaid, CancellationToken)) A.CallTo(() => billingManager.MustRedirectToPortalAsync(User.Identifier, A<App>._, planIdPaid, CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -259,16 +206,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); 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 await VerifySutAsync(actual, new PlanChangedResult(planIdPaid));
.ShouldHaveSameEvents(
CreateEvent(new AppPlanChanged { PlanId = planIdPaid })
);
A.CallTo(() => billingManager.MustRedirectToPortalAsync(A<string>._, A<App>._, A<string?>._, A<CancellationToken>._)) A.CallTo(() => billingManager.MustRedirectToPortalAsync(A<string>._, A<App>._, A<string?>._, A<CancellationToken>._))
.MustNotHaveHappened(); .MustNotHaveHappened();
@ -285,16 +225,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteChangePlanAsync(); await ExecuteChangePlanAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(new PlanChangedResult(planIdFree, true)); await VerifySutAsync(actual, new PlanChangedResult(planIdFree, true));
Assert.Null(sut.Snapshot.Plan);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new AppPlanReset())
);
A.CallTo(() => billingManager.MustRedirectToPortalAsync(A<string>._, A<App>._, A<string?>._, A<CancellationToken>._)) A.CallTo(() => billingManager.MustRedirectToPortalAsync(A<string>._, A<App>._, A<string?>._, A<CancellationToken>._))
.MustHaveHappenedOnceExactly(); .MustHaveHappenedOnceExactly();
@ -311,16 +244,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteChangePlanAsync(); 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 await VerifySutAsync(actual, new PlanChangedResult(planIdFree, true));
.ShouldHaveSameEvents(
CreateEvent(new AppPlanReset())
);
A.CallTo(() => billingManager.MustRedirectToPortalAsync(User.Identifier, A<App>._, planIdPaid, CancellationToken)) A.CallTo(() => billingManager.MustRedirectToPortalAsync(User.Identifier, A<App>._, planIdPaid, CancellationToken))
.MustHaveHappenedOnceExactly(); .MustHaveHappenedOnceExactly();
@ -339,11 +265,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(new PlanChangedResult(planIdPaid, false, new Uri("http://squidex.io"))); await VerifySutAsync(actual, new PlanChangedResult(planIdPaid, false, new Uri("http://squidex.io")));
Assert.Null(sut.Snapshot.Plan);
} }
[Fact] [Fact]
@ -353,11 +277,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); 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); await VerifySutAsync(actual, new PlanChangedResult(planIdPaid));
A.CallTo(() => billingManager.MustRedirectToPortalAsync(User.Identifier, A<App>._, planIdPaid, A<CancellationToken>._)) A.CallTo(() => billingManager.MustRedirectToPortalAsync(User.Identifier, A<App>._, planIdPaid, A<CancellationToken>._))
.MustNotHaveHappened(); .MustNotHaveHappened();
@ -373,16 +295,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(Role.Editor, sut.Snapshot.Contributors[contributorId]);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateEvent(new AppContributorAssigned { ContributorId = contributorId, Role = Role.Editor, IsAdded = true })
);
} }
[Fact] [Fact]
@ -393,16 +308,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAssignContributorAsync(); await ExecuteAssignContributorAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(Role.Owner, sut.Snapshot.Contributors[contributorId]);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new AppContributorAssigned { ContributorId = contributorId, Role = Role.Owner })
);
} }
[Fact] [Fact]
@ -413,16 +321,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAssignContributorAsync(); await ExecuteAssignContributorAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.False(sut.Snapshot.Contributors.ContainsKey(contributorId));
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateEvent(new AppContributorRemoved { ContributorId = contributorId })
);
} }
[Fact] [Fact]
@ -432,16 +333,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(TeamId, sut.Snapshot.TeamId);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new AppTransfered { TeamId = TeamId })
);
} }
[Fact] [Fact]
@ -452,16 +346,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteTransferAsync(); await ExecuteTransferAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Null(sut.Snapshot.TeamId); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new AppTransfered { TeamId = null })
);
} }
[Fact] [Fact]
@ -471,16 +358,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.True(sut.Snapshot.Clients.ContainsKey(clientId)); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new AppClientAttached { Id = clientId, Secret = command.Secret })
);
} }
[Fact] [Fact]
@ -491,16 +371,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAttachClientAsync(); await ExecuteAttachClientAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(clientNewName, sut.Snapshot.Clients[clientId].Name); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new AppClientUpdated { Id = clientId, Name = clientNewName, Role = Role.Developer })
);
} }
[Fact] [Fact]
@ -511,16 +384,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAttachClientAsync(); await ExecuteAttachClientAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.False(sut.Snapshot.Clients.ContainsKey(clientId)); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new AppClientRevoked { Id = clientId })
);
} }
[Fact] [Fact]
@ -530,16 +396,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.NotEmpty(sut.Snapshot.Workflows); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new AppWorkflowAdded { WorkflowId = workflowId, Name = "my-workflow" })
);
} }
[Fact] [Fact]
@ -550,16 +409,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAddWorkflowAsync(); await ExecuteAddWorkflowAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.NotEmpty(sut.Snapshot.Workflows); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new AppWorkflowUpdated { WorkflowId = workflowId, Workflow = Workflow.Default })
);
} }
[Fact] [Fact]
@ -570,16 +422,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAddWorkflowAsync(); await ExecuteAddWorkflowAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Empty(sut.Snapshot.Workflows); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new AppWorkflowDeleted { WorkflowId = workflowId })
);
} }
[Fact] [Fact]
@ -589,16 +434,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.True(sut.Snapshot.Languages.Contains(Language.DE)); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new AppLanguageAdded { Language = Language.DE })
);
} }
[Fact] [Fact]
@ -609,16 +447,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAddLanguageAsync(Language.DE); await ExecuteAddLanguageAsync(Language.DE);
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.False(sut.Snapshot.Languages.Contains(Language.DE)); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new AppLanguageRemoved { Language = Language.DE })
);
} }
[Fact] [Fact]
@ -629,16 +460,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAddLanguageAsync(Language.DE); await ExecuteAddLanguageAsync(Language.DE);
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.True(sut.Snapshot.Languages.Contains(Language.DE)); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new AppLanguageUpdated { Language = Language.DE, Fallback = [Language.EN] })
);
} }
[Fact] [Fact]
@ -648,16 +472,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(1, sut.Snapshot.Roles.CustomCount); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new AppRoleAdded { Name = roleName })
);
} }
[Fact] [Fact]
@ -668,16 +485,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAddRoleAsync(); await ExecuteAddRoleAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(0, sut.Snapshot.Roles.CustomCount); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new AppRoleDeleted { Name = roleName })
);
} }
[Fact] [Fact]
@ -688,14 +498,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAddRoleAsync(); await ExecuteAddRoleAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateEvent(new AppRoleUpdated { Name = roleName, Permissions = command.Permissions, Properties = command.Properties })
);
} }
[Fact] [Fact]
@ -705,16 +510,9 @@ public class AppDomainObjectTests : HandlerTestBase<App>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(None.Value); await VerifySutAsync(actual, None.Value);
Assert.True(sut.Snapshot.IsDeleted);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new AppDeleted())
);
A.CallTo(() => billingManager.UnsubscribeAsync(command.Actor.Identifier, A<App>._, default)) A.CallTo(() => billingManager.UnsubscribeAsync(command.Actor.Identifier, A<App>._, default))
.MustHaveHappened(); .MustHaveHappened();
@ -722,63 +520,65 @@ public class AppDomainObjectTests : HandlerTestBase<App>
private Task ExecuteCreateAsync() 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() private Task ExecuteUploadImage()
{ {
return PublishAsync(new UploadAppImage { File = new NoopAssetFile() }); return PublishAsync(sut, new UploadAppImage { File = new NoopAssetFile() });
} }
private Task ExecuteAssignContributorAsync() 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() private Task ExecuteAttachClientAsync()
{ {
return PublishAsync(new AttachClient { Id = clientId }); return PublishAsync(sut, new AttachClient { Id = clientId });
} }
private Task ExecuteAddRoleAsync() private Task ExecuteAddRoleAsync()
{ {
return PublishAsync(new AddRole { Name = roleName }); return PublishAsync(sut, new AddRole { Name = roleName });
} }
private Task ExecuteAddLanguageAsync(Language language) private Task ExecuteAddLanguageAsync(Language language)
{ {
return PublishAsync(new AddLanguage { Language = language }); return PublishAsync(sut, new AddLanguage { Language = language });
} }
private Task ExecuteAddWorkflowAsync() 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() private Task ExecuteChangePlanAsync()
{ {
return PublishAsync(new ChangePlan { PlanId = planIdPaid }); return PublishAsync(sut, new ChangePlan { PlanId = planIdPaid });
} }
private Task ExecuteTransferAsync() private Task ExecuteTransferAsync()
{ {
return PublishAsync(new TransferToTeam { TeamId = TeamId }); return PublishAsync(sut, new TransferToTeam { TeamId = TeamId });
} }
private Task ExecuteArchiveAsync() private Task ExecuteArchiveAsync()
{ {
return PublishAsync(new DeleteApp()); return PublishAsync(sut, new DeleteApp());
} }
private Task<object> PublishIdempotentAsync<T>(T command) where T : SquidexCommand, IAggregateCommand private async Task VerifySutAsync(object? actual, object? expected = null)
{ {
return PublishIdempotentAsync(sut, CreateCommand(command)); if (expected == null)
} {
actual.Should().BeEquivalentTo(sut.Snapshot, o => o.IncludingProperties());
private async Task<object> PublishAsync<T>(T command) where T : SquidexCommand, IAggregateCommand }
{ else
var actual = await sut.ExecuteAsync(CreateCommand(command), CancellationToken); {
actual.Should().BeEquivalentTo(expected);
}
return actual.Payload; await Verify(new { sut, events = LastEvents });
} }
} }

211
backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/DomainObject/AssetDomainObjectTests.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using Esprima;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Squidex.Assets; using Squidex.Assets;
@ -14,12 +15,15 @@ using Squidex.Domain.Apps.Core.Tags;
using Squidex.Domain.Apps.Entities.Assets.Commands; using Squidex.Domain.Apps.Entities.Assets.Commands;
using Squidex.Domain.Apps.Entities.Contents; using Squidex.Domain.Apps.Entities.Contents;
using Squidex.Domain.Apps.Entities.Contents.Repositories; using Squidex.Domain.Apps.Entities.Contents.Repositories;
using Squidex.Domain.Apps.Entities.Rules.Commands;
using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Domain.Apps.Entities.TestHelpers;
using Squidex.Domain.Apps.Events.Assets; using Squidex.Domain.Apps.Events.Assets;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.Commands;
namespace Squidex.Domain.Apps.Entities.Assets.DomainObject; namespace Squidex.Domain.Apps.Entities.Assets.DomainObject;
[UsesVerify]
public class AssetDomainObjectTests : HandlerTestBase<Asset> public class AssetDomainObjectTests : HandlerTestBase<Asset>
{ {
private readonly IAssetQueryService assetQuery = A.Fake<IAssetQueryService>(); private readonly IAssetQueryService assetQuery = A.Fake<IAssetQueryService>();
@ -87,27 +91,9 @@ public class AssetDomainObjectTests : HandlerTestBase<Asset>
{ {
var command = new CreateAsset { File = file, FileHash = "NewHash" }; var command = new CreateAsset { File = file, FileHash = "NewHash" };
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(0, sut.Snapshot.FileVersion);
Assert.Equal(command.FileHash, sut.Snapshot.FileHash);
LastEvents
.ShouldHaveSameEvents(
CreateAssetEvent(new AssetCreated
{
FileName = file.FileName,
FileSize = file.FileSize,
FileHash = command.FileHash,
FileVersion = 0,
Metadata = [],
MimeType = file.MimeType,
Tags = [],
Slug = file.FileName.ToAssetSlug()
})
);
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<create-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<create-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -121,7 +107,7 @@ public class AssetDomainObjectTests : HandlerTestBase<Asset>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteDeleteAsync(); await ExecuteDeleteAsync();
await PublishAsync(command); await PublishAsync(sut, command);
} }
[Fact] [Fact]
@ -132,7 +118,7 @@ public class AssetDomainObjectTests : HandlerTestBase<Asset>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteDeleteAsync(true); await ExecuteDeleteAsync(true);
await PublishAsync(command); await PublishAsync(sut, command);
} }
[Fact] [Fact]
@ -140,27 +126,9 @@ public class AssetDomainObjectTests : HandlerTestBase<Asset>
{ {
var command = new UpsertAsset { File = file, FileHash = "NewHash" }; var command = new UpsertAsset { File = file, FileHash = "NewHash" };
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(0, sut.Snapshot.FileVersion);
Assert.Equal(command.FileHash, sut.Snapshot.FileHash);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateAssetEvent(new AssetCreated
{
FileName = file.FileName,
FileSize = file.FileSize,
FileHash = command.FileHash,
FileVersion = 0,
Metadata = [],
MimeType = file.MimeType,
Tags = [],
Slug = file.FileName.ToAssetSlug()
})
);
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<create-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<create-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -173,24 +141,9 @@ public class AssetDomainObjectTests : HandlerTestBase<Asset>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(1, sut.Snapshot.FileVersion);
Assert.Equal(command.FileHash, sut.Snapshot.FileHash);
LastEvents
.ShouldHaveSameEvents(
CreateAssetEvent(new AssetUpdated
{
FileSize = file.FileSize,
FileHash = command.FileHash,
FileVersion = 1,
Metadata = [],
MimeType = file.MimeType
})
);
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<update-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<update-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -203,24 +156,9 @@ public class AssetDomainObjectTests : HandlerTestBase<Asset>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(1, sut.Snapshot.FileVersion);
Assert.Equal(command.FileHash, sut.Snapshot.FileHash);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateAssetEvent(new AssetUpdated
{
FileSize = file.FileSize,
FileHash = command.FileHash,
FileVersion = 1,
Metadata = [],
MimeType = file.MimeType
})
);
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<update-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<update-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -233,16 +171,9 @@ public class AssetDomainObjectTests : HandlerTestBase<Asset>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(command.FileName, sut.Snapshot.FileName);
LastEvents
.ShouldHaveSameEvents(
CreateAssetEvent(new AssetAnnotated { FileName = command.FileName })
);
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<annotate-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<annotate-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -255,16 +186,9 @@ public class AssetDomainObjectTests : HandlerTestBase<Asset>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(command.Slug, sut.Snapshot.Slug);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateAssetEvent(new AssetAnnotated { Slug = command.Slug })
);
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<annotate-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<annotate-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -277,16 +201,9 @@ public class AssetDomainObjectTests : HandlerTestBase<Asset>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(command.IsProtected, sut.Snapshot.IsProtected);
LastEvents
.ShouldHaveSameEvents(
CreateAssetEvent(new AssetAnnotated { IsProtected = command.IsProtected })
);
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<annotate-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<annotate-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -299,16 +216,9 @@ public class AssetDomainObjectTests : HandlerTestBase<Asset>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(command.Metadata, sut.Snapshot.Metadata); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateAssetEvent(new AssetAnnotated { Metadata = command.Metadata })
);
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<anootate-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<anootate-script>", ScriptOptions(), CancellationToken))
.MustNotHaveHappened(); .MustNotHaveHappened();
@ -321,14 +231,9 @@ public class AssetDomainObjectTests : HandlerTestBase<Asset>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateAssetEvent(new AssetAnnotated { Tags = ["tag1"] })
);
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<annotate-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<annotate-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -341,16 +246,9 @@ public class AssetDomainObjectTests : HandlerTestBase<Asset>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(parentId, sut.Snapshot.ParentId);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateAssetEvent(new AssetMoved { ParentId = parentId })
);
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<move-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<move-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -364,16 +262,9 @@ public class AssetDomainObjectTests : HandlerTestBase<Asset>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteUpdateAsync(); await ExecuteUpdateAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(None.Value); await VerifySutAsync(actual, None.Value);
Assert.True(sut.Snapshot.IsDeleted);
LastEvents
.ShouldHaveSameEvents(
CreateAssetEvent(new AssetDeleted { DeletedSize = 2048, OldTags = [] })
);
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<delete-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<delete-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -389,11 +280,8 @@ public class AssetDomainObjectTests : HandlerTestBase<Asset>
A.CallTo(() => contentRepository.HasReferrersAsync(App, Id, SearchScope.All, A<CancellationToken>._)) A.CallTo(() => contentRepository.HasReferrersAsync(App, Id, SearchScope.All, A<CancellationToken>._))
.Returns(false); .Returns(false);
var actual = await PublishAsync(command); await PublishAsync(sut, command);
actual.ShouldBeEquivalent(None.Value);
Assert.Equal(EtagVersion.Empty, sut.Snapshot.Version);
Assert.Empty(LastEvents); Assert.Empty(LastEvents);
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<delete-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<delete-script>", ScriptOptions(), CancellationToken))
@ -410,7 +298,7 @@ public class AssetDomainObjectTests : HandlerTestBase<Asset>
A.CallTo(() => contentRepository.HasReferrersAsync(App, Id, SearchScope.All, A<CancellationToken>._)) A.CallTo(() => contentRepository.HasReferrersAsync(App, Id, SearchScope.All, A<CancellationToken>._))
.Returns(true); .Returns(true);
await Assert.ThrowsAsync<DomainException>(() => PublishAsync(command)); await Assert.ThrowsAsync<DomainException>(() => PublishAsync(sut, command));
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<delete-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<delete-script>", ScriptOptions(), CancellationToken))
.MustNotHaveHappened(); .MustNotHaveHappened();
@ -426,7 +314,7 @@ public class AssetDomainObjectTests : HandlerTestBase<Asset>
A.CallTo(() => contentRepository.HasReferrersAsync(App, Id, SearchScope.All, A<CancellationToken>._)) A.CallTo(() => contentRepository.HasReferrersAsync(App, Id, SearchScope.All, A<CancellationToken>._))
.Returns(true); .Returns(true);
await PublishAsync(command); await PublishAsync(sut, command);
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<delete-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<delete-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -434,17 +322,17 @@ public class AssetDomainObjectTests : HandlerTestBase<Asset>
private Task ExecuteCreateAsync() private Task ExecuteCreateAsync()
{ {
return PublishAsync(new CreateAsset { File = file, FileHash = "123" }); return PublishAsync(sut, new CreateAsset { File = file, FileHash = "123" });
} }
private Task ExecuteUpdateAsync() private Task ExecuteUpdateAsync()
{ {
return PublishAsync(new UpdateAsset { File = file, FileHash = "456" }); return PublishAsync(sut, new UpdateAsset { File = file, FileHash = "456" });
} }
private Task ExecuteDeleteAsync(bool permanent = false) private Task ExecuteDeleteAsync(bool permanent = false)
{ {
return PublishAsync(new DeleteAsset { Permanent = permanent }); return PublishAsync(sut, new DeleteAsset { Permanent = permanent });
} }
private static ScriptOptions ScriptOptions() private static ScriptOptions ScriptOptions()
@ -452,29 +340,26 @@ public class AssetDomainObjectTests : HandlerTestBase<Asset>
return A<ScriptOptions>.That.Matches(x => x.CanDisallow && x.CanReject && x.AsContext); return A<ScriptOptions>.That.Matches(x => x.CanDisallow && x.CanReject && x.AsContext);
} }
private T CreateAssetEvent<T>(T @event) where T : AssetEvent protected override IAggregateCommand CreateCommand(IAggregateCommand command)
{ {
@event.AssetId = assetId; ((AssetCommand)command).AssetId = assetId;
return CreateEvent(@event); return base.CreateCommand(command);
} }
private T CreateAssetCommand<T>(T command) where T : AssetCommand private async Task VerifySutAsync(object? actual, object? expected = null)
{ {
command.AssetId = assetId; if (expected == null)
{
return CreateCommand(command); actual.Should().BeEquivalentTo(sut.Snapshot, o => o.IncludingProperties());
} }
else
private Task<object> PublishIdempotentAsync(AssetCommand command) {
{ actual.Should().BeEquivalentTo(expected);
return PublishIdempotentAsync(sut, CreateAssetCommand(command)); }
}
private async Task<object> PublishAsync(AssetCommand command) Assert.Equal(AppId, sut.Snapshot.AppId);
{
var actual = await sut.ExecuteAsync(CreateAssetCommand(command), CancellationToken);
return actual.Payload; await Verify(new { sut, events = LastEvents });
} }
} }

88
backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/DomainObject/AssetFolderDomainObjectTests.cs

@ -11,11 +11,12 @@ using Squidex.Domain.Apps.Core.Assets;
using Squidex.Domain.Apps.Entities.Assets.Commands; using Squidex.Domain.Apps.Entities.Assets.Commands;
using Squidex.Domain.Apps.Entities.Contents.Repositories; using Squidex.Domain.Apps.Entities.Contents.Repositories;
using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Domain.Apps.Entities.TestHelpers;
using Squidex.Domain.Apps.Events.Assets;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.Commands;
namespace Squidex.Domain.Apps.Entities.Assets.DomainObject; namespace Squidex.Domain.Apps.Entities.Assets.DomainObject;
[UsesVerify]
public class AssetFolderDomainObjectTests : HandlerTestBase<AssetFolder> public class AssetFolderDomainObjectTests : HandlerTestBase<AssetFolder>
{ {
private readonly IAssetQueryService assetQuery = A.Fake<IAssetQueryService>(); private readonly IAssetQueryService assetQuery = A.Fake<IAssetQueryService>();
@ -63,16 +64,9 @@ public class AssetFolderDomainObjectTests : HandlerTestBase<AssetFolder>
{ {
var command = new CreateAssetFolder { FolderName = "New Name" }; var command = new CreateAssetFolder { FolderName = "New Name" };
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(command.FolderName, sut.Snapshot.FolderName);
LastEvents
.ShouldHaveSameEvents(
CreateAssetFolderEvent(new AssetFolderCreated { FolderName = command.FolderName })
);
} }
[Fact] [Fact]
@ -82,16 +76,9 @@ public class AssetFolderDomainObjectTests : HandlerTestBase<AssetFolder>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(command.FolderName, sut.Snapshot.FolderName);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateAssetFolderEvent(new AssetFolderRenamed { FolderName = command.FolderName })
);
} }
[Fact] [Fact]
@ -101,16 +88,9 @@ public class AssetFolderDomainObjectTests : HandlerTestBase<AssetFolder>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(parentId, sut.Snapshot.ParentId);
LastEvents
.ShouldHaveSameEvents(
CreateAssetFolderEvent(new AssetFolderMoved { ParentId = parentId })
);
} }
[Fact] [Fact]
@ -120,56 +100,46 @@ public class AssetFolderDomainObjectTests : HandlerTestBase<AssetFolder>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(None.Value);
Assert.True(sut.Snapshot.IsDeleted);
LastEvents await VerifySutAsync(actual, None.Value);
.ShouldHaveSameEvents(
CreateAssetFolderEvent(new AssetFolderDeleted())
);
} }
private Task ExecuteCreateAsync() private Task ExecuteCreateAsync()
{ {
return PublishAsync(new CreateAssetFolder { FolderName = "My Folder" }); return PublishAsync(sut, new CreateAssetFolder { FolderName = "My Folder" });
} }
private Task ExecuteUpdateAsync() private Task ExecuteUpdateAsync()
{ {
return PublishAsync(new RenameAssetFolder { FolderName = "My Folder" }); return PublishAsync(sut, new RenameAssetFolder { FolderName = "My Folder" });
} }
private Task ExecuteDeleteAsync() private Task ExecuteDeleteAsync()
{ {
return PublishAsync(new DeleteAssetFolder()); return PublishAsync(sut, new DeleteAssetFolder());
} }
private T CreateAssetFolderEvent<T>(T @event) where T : AssetFolderEvent protected override IAggregateCommand CreateCommand(IAggregateCommand command)
{ {
@event.AssetFolderId = assetFolderId; ((AssetFolderCommand)command).AssetFolderId = assetFolderId;
return CreateEvent(@event); return base.CreateCommand(command);
} }
private T CreateAssetFolderCommand<T>(T command) where T : AssetFolderCommand private async Task VerifySutAsync(object? actual, object? expected = null)
{ {
command.AssetFolderId = assetFolderId; if (expected == null)
{
return CreateCommand(command); actual.Should().BeEquivalentTo(sut.Snapshot, o => o.IncludingProperties());
} }
else
private Task<object> PublishIdempotentAsync(AssetFolderCommand command) {
{ actual.Should().BeEquivalentTo(expected);
return PublishIdempotentAsync(sut, CreateAssetFolderCommand(command)); }
}
Assert.Equal(AppId, sut.Snapshot.AppId);
private async Task<object> PublishAsync(AssetFolderCommand command)
{ await Verify(new { sut, events = LastEvents });
var actual = await sut.ExecuteAsync(CreateAssetFolderCommand(command), CancellationToken);
return actual.Payload;
} }
} }

336
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentDomainObjectTests.cs

@ -6,6 +6,7 @@
// ========================================================================== // ==========================================================================
using System.Security.Claims; using System.Security.Claims;
using Elasticsearch.Net.Specification.WatcherApi;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using NodaTime; using NodaTime;
@ -25,6 +26,7 @@ using Squidex.Infrastructure.Validation;
namespace Squidex.Domain.Apps.Entities.Contents.DomainObject; namespace Squidex.Domain.Apps.Entities.Contents.DomainObject;
[UsesVerify]
public class ContentDomainObjectTests : HandlerTestBase<WriteContent> public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
{ {
private readonly DomainId contentId = DomainId.NewGuid(); private readonly DomainId contentId = DomainId.NewGuid();
@ -140,15 +142,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(data, sut.Snapshot.CurrentVersion.Data);
Assert.Equal(Status.Draft, sut.Snapshot.CurrentVersion.Status);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentCreated { Data = data, Status = Status.Draft })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -163,15 +157,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(data, sut.Snapshot.CurrentVersion.Data);
Assert.Equal(Status.Draft, sut.Snapshot.CurrentVersion.Status);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentCreated { Data = data, Status = Status.Draft })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -186,16 +172,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(data, sut.Snapshot.CurrentVersion.Data);
Assert.Equal(Status.Archived, sut.Snapshot.EditingStatus);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentCreated { Data = data, Status = Status.Draft }),
CreateContentEvent(new ContentStatusChanged { Status = Status.Archived })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -240,15 +217,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(CreateContentCommand(command)); var actual = await PublishAsync(CreateContentCommand(command));
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(data, sut.Snapshot.CurrentVersion.Data);
Assert.Equal(Status.Draft, sut.Snapshot.EditingStatus);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentCreated { Data = data, Status = Status.Draft })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -263,15 +232,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(CreateContentCommand(command)); var actual = await PublishAsync(CreateContentCommand(command));
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(data, sut.Snapshot.CurrentVersion.Data);
Assert.Equal(Status.Draft, sut.Snapshot.EditingStatus);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentCreated { Data = data, Status = Status.Draft })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -286,16 +247,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(CreateContentCommand(command)); var actual = await PublishAsync(CreateContentCommand(command));
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(data, sut.Snapshot.CurrentVersion.Data);
Assert.Equal(Status.Archived, sut.Snapshot.EditingStatus);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentCreated { Data = data, Status = Status.Draft }),
CreateContentEvent(new ContentStatusChanged { Status = Status.Archived })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -312,14 +264,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(CreateContentCommand(command)); var actual = await PublishAsync(CreateContentCommand(command));
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(otherData, sut.Snapshot.CurrentVersion.Data);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentUpdated { Data = otherData })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -334,14 +279,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(CreateContentCommand(command)); var actual = await PublishAsync(CreateContentCommand(command));
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(patched, sut.Snapshot.CurrentVersion.Data);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentUpdated { Data = patched })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(patched, data, Status.Draft), "<update-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(patched, data, Status.Draft), "<update-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -356,14 +294,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(CreateContentCommand(command)); var actual = await PublishAsync(CreateContentCommand(command));
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(otherData, sut.Snapshot.CurrentVersion.Data);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentUpdated { Data = otherData })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -378,16 +309,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(CreateContentCommand(command)); var actual = await PublishAsync(CreateContentCommand(command));
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(otherData, sut.Snapshot.CurrentVersion.Data);
Assert.Equal(Status.Archived, sut.Snapshot.EditingStatus);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentUpdated { Data = otherData }),
CreateContentEvent(new ContentStatusChanged { Status = Status.Archived })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -404,11 +326,6 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
await ExecuteDeleteAsync(); await ExecuteDeleteAsync();
await PublishAsync(command); await PublishAsync(command);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentCreated { Data = data, Status = Status.Draft })
);
} }
[Fact] [Fact]
@ -420,11 +337,6 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
await ExecuteDeleteAsync(true); await ExecuteDeleteAsync(true);
await PublishAsync(command); await PublishAsync(command);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentCreated { Data = data, Status = Status.Draft })
);
} }
[Fact] [Fact]
@ -436,14 +348,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(otherData, sut.Snapshot.CurrentVersion.Data);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentUpdated { Data = otherData })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -460,14 +365,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(otherData, sut.Snapshot.NewVersion?.Data);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentUpdated { Data = otherData })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -482,9 +380,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Single(LastEvents);
A.CallTo(() => scriptEngine.TransformAsync(A<DataScriptVars>._, "<update-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(A<DataScriptVars>._, "<update-script>", ScriptOptions(), CancellationToken))
.MustNotHaveHappened(); .MustNotHaveHappened();
@ -509,14 +405,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.NotEqual(data, sut.Snapshot.CurrentVersion.Data);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentUpdated { Data = patched })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(patched, data, Status.Draft), "<update-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(patched, data, Status.Draft), "<update-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -533,14 +422,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(patched, sut.Snapshot.NewVersion?.Data);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentUpdated { Data = patched })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(patched, data, Status.Draft), "<update-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(patched, data, Status.Draft), "<update-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -555,9 +437,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Single(LastEvents);
A.CallTo(() => scriptEngine.TransformAsync(A<DataScriptVars>._, "<update-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(A<DataScriptVars>._, "<update-script>", ScriptOptions(), CancellationToken))
.MustNotHaveHappened(); .MustNotHaveHappened();
@ -572,14 +452,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(Status.Archived, sut.Snapshot.CurrentVersion.Status);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentStatusChanged { Status = Status.Archived })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Archived, Status.Draft), "<change-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Archived, Status.Draft), "<change-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -594,14 +467,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(Status.Archived, sut.Snapshot.CurrentVersion.Status);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentStatusChanged { Status = Status.Archived })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Archived, Status.Draft), "<change-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Archived, Status.Draft), "<change-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -617,14 +483,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(Status.Draft, sut.Snapshot.CurrentVersion.Status);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentStatusChanged { Status = Status.Draft, Change = StatusChange.Unpublished })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Draft, Status.Published), "<change-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Draft, Status.Published), "<change-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -643,16 +502,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(Status.Draft, sut.Snapshot.CurrentVersion.Status);
Assert.Equal(otherData, sut.Snapshot.CurrentVersion.Data);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentUpdated { Data = otherData }),
CreateContentEvent(new ContentStatusChanged { Status = Status.Draft, Change = StatusChange.Unpublished })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Draft, Status.Published), "<change-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Draft, Status.Published), "<change-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -669,14 +519,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(Status.Archived, sut.Snapshot.NewVersion?.Status);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentStatusChanged { Change = StatusChange.Change, Status = Status.Archived })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Archived, Status.Draft), "<change-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Archived, Status.Draft), "<change-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -693,14 +536,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Null(sut.Snapshot.NewVersion?.Status);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentStatusChanged { Change = StatusChange.Published, Status = Status.Published })
);
A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Published, Status.Draft), "<change-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(DataScriptVars(data, null, Status.Published, Status.Draft), "<change-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -717,17 +553,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(Status.Draft, sut.Snapshot.CurrentVersion.Status);
Assert.Equal(Status.Published, sut.Snapshot.ScheduleJob?.Status);
Assert.Equal(dueTime, sut.Snapshot.ScheduleJob?.DueTime);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentStatusScheduled { Status = Status.Published, DueTime = dueTime })
);
A.CallTo(() => scriptEngine.ExecuteAsync(A<DataScriptVars>._, "<change-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.ExecuteAsync(A<DataScriptVars>._, "<change-script>", ScriptOptions(), CancellationToken))
.MustNotHaveHappened(); .MustNotHaveHappened();
@ -748,14 +574,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Null(sut.Snapshot.ScheduleJob);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentStatusChanged { Status = Status.Archived })
);
A.CallTo(() => scriptEngine.TransformAsync(A<DataScriptVars>._, "<change-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.TransformAsync(A<DataScriptVars>._, "<change-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -776,14 +595,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Null(sut.Snapshot.ScheduleJob);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentSchedulingCancelled())
);
A.CallTo(() => scriptEngine.ExecuteAsync(A<DataScriptVars>._, "<change-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.ExecuteAsync(A<DataScriptVars>._, "<change-script>", ScriptOptions(), CancellationToken))
.MustNotHaveHappened(); .MustNotHaveHappened();
@ -818,7 +630,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
} }
[Fact] [Fact]
public async Task CancelContentSchedule_create_events_and_unset_schedule() public async Task CancelContentSchedule_should_create_events_and_unset_schedule()
{ {
var command = new CancelContentSchedule(); var command = new CancelContentSchedule();
@ -827,45 +639,58 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Null(sut.Snapshot.ScheduleJob);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentSchedulingCancelled())
);
} }
[Fact] [Fact]
public async Task Validate_should_not_update_state() public async Task Validate_should_not_update_state()
{ {
await ExecuteCreateAsync();
var command = new ValidateContent(); var command = new ValidateContent();
await ExecuteCreateAsync();
await PublishAsync(command); await PublishAsync(command);
Assert.Equal(0, sut.Version); Assert.Equal(0, sut.Version);
} }
[Fact] [Fact]
public async Task Delete_should_create_events_and_update_deleted_flag() public async Task EnrichContentDefaults_should_update_content()
{ {
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var command = new DeleteContent(); Schema =
Schema.AddString(3, "defaults", Partitioning.Invariant,
new StringFieldProperties { DefaultValue = "Default Value" });
var command = new EnrichContentDefaults();
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(None.Value); await VerifySutAsync(actual);
}
Assert.True(sut.Snapshot.IsDeleted); [Fact]
public async Task EnrichContentDefaults_should_not_update_content_if_all_fields_have_a_value()
{
await ExecuteCreateAsync();
LastEvents var command = new EnrichContentDefaults();
.ShouldHaveSameEvents(
CreateContentEvent(new ContentDeleted()) var actual = await PublishAsync(command);
);
await VerifySutAsync(actual);
}
[Fact]
public async Task Delete_should_create_events_and_update_deleted_flag()
{
await ExecuteCreateAsync();
var command = new DeleteContent();
var actual = await PublishAsync(command);
await VerifySutAsync(actual, None.Value);
A.CallTo(() => scriptEngine.ExecuteAsync(DataScriptVars(data, null, Status.Draft), "<delete-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.ExecuteAsync(DataScriptVars(data, null, Status.Draft), "<delete-script>", ScriptOptions(), CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -880,9 +705,6 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(None.Value);
Assert.Equal(EtagVersion.Empty, sut.Snapshot.Version);
Assert.Empty(LastEvents); Assert.Empty(LastEvents);
A.CallTo(() => scriptEngine.ExecuteAsync(DataScriptVars(data, null, Status.Draft), "<delete-script>", ScriptOptions(), CancellationToken)) A.CallTo(() => scriptEngine.ExecuteAsync(DataScriptVars(data, null, Status.Draft), "<delete-script>", ScriptOptions(), CancellationToken))
@ -925,14 +747,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(Status.Draft, sut.Snapshot.NewVersion?.Status);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentDraftCreated { Status = Status.Draft })
);
} }
[Fact] [Fact]
@ -946,14 +761,7 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
var actual = await PublishAsync(command); var actual = await PublishAsync(command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Null(sut.Snapshot.NewVersion);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentDraftDeleted())
);
} }
private Task ExecuteCreateAsync() private Task ExecuteCreateAsync()
@ -1023,13 +831,27 @@ public class ContentDomainObjectTests : HandlerTestBase<WriteContent>
{ {
command.ContentId = contentId; command.ContentId = contentId;
return CreateCommand(command); return (T)CreateCommand(command);
} }
private async Task<object> PublishAsync(ContentCommand command) private Task<object> PublishAsync(ContentCommand command)
{ {
var actual = await sut.ExecuteAsync(CreateContentCommand(command), CancellationToken); return PublishAsync(sut, CreateContentCommand(command));
}
private async Task VerifySutAsync(object? actual, object? expected = null)
{
if (expected == null)
{
actual.Should().BeEquivalentTo(sut.Snapshot, o => o.IncludingProperties());
}
else
{
actual.Should().BeEquivalentTo(expected);
}
Assert.Equal(AppId, sut.Snapshot.AppId);
return actual.Payload; await Verify(new { sut, events = LastEvents });
} }
} }

37
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentsBulkUpdateCommandMiddlewareTests.cs

@ -315,6 +315,43 @@ public class ContentsBulkUpdateCommandMiddlewareTests : GivenContext
.MustNotHaveHappened(); .MustNotHaveHappened();
} }
[Fact]
public async Task Should_update_content_defaults()
{
SetupContext(PermissionIds.AppContentsUpdateOwn);
var (id, _, _) = CreateTestData(false);
var command = BulkCommand(BulkUpdateContentType.EnrichDefaults, new BulkUpdateJob(), id);
var actual = await PublishAsync(command);
Assert.Single(actual);
Assert.Single(actual, x => x.JobIndex == 0 && x.Id == id && x.Exception == null);
A.CallTo(() => commandBus.PublishAsync(
A<EnrichContentDefaults>.That.Matches(x => x.ContentId == id), A<CancellationToken>._))
.MustHaveHappened();
}
[Fact]
public async Task Should_throw_security_exception_if_user_has_no_permission_for_defaults()
{
SetupContext(PermissionIds.AppContentsReadOwn);
var (id, _, _) = CreateTestData(false);
var command = BulkCommand(BulkUpdateContentType.EnrichDefaults, new BulkUpdateJob(), id);
var actual = await PublishAsync(command);
Assert.Single(actual);
Assert.Single(actual, x => x.JobIndex == 0 && x.Id == id && x.Exception is DomainForbiddenException);
A.CallTo(() => commandBus.PublishAsync(A<ICommand>._, A<CancellationToken>._))
.MustNotHaveHappened();
}
[Fact] [Fact]
public async Task Should_patch_content() public async Task Should_patch_content()
{ {

128
backend/tests/Squidex.Domain.Apps.Entities.Tests/Rules/DomainObject/RuleDomainObjectTests.cs

@ -14,10 +14,12 @@ using Squidex.Domain.Apps.Entities.Rules.Commands;
using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Domain.Apps.Entities.TestHelpers;
using Squidex.Domain.Apps.Events.Rules; using Squidex.Domain.Apps.Events.Rules;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.Commands;
using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.EventSourcing;
namespace Squidex.Domain.Apps.Entities.Rules.DomainObject; namespace Squidex.Domain.Apps.Entities.Rules.DomainObject;
[UsesVerify]
public class RuleDomainObjectTests : HandlerTestBase<Rule> public class RuleDomainObjectTests : HandlerTestBase<Rule>
{ {
private readonly IRuleEnqueuer ruleEnqueuer = A.Fake<IRuleEnqueuer>(); private readonly IRuleEnqueuer ruleEnqueuer = A.Fake<IRuleEnqueuer>();
@ -64,19 +66,9 @@ public class RuleDomainObjectTests : HandlerTestBase<Rule>
{ {
var command = MakeCreateCommand(); var command = MakeCreateCommand();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(AppId, sut.Snapshot.AppId);
Assert.Same(command.Trigger, sut.Snapshot.Trigger);
Assert.Same(command.Action, sut.Snapshot.Action);
LastEvents
.ShouldHaveSameEvents(
CreateRuleEvent(new RuleCreated { Trigger = command.Trigger!, Action = command.Action! })
);
} }
[Fact] [Fact]
@ -86,21 +78,9 @@ public class RuleDomainObjectTests : HandlerTestBase<Rule>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.True(sut.Snapshot.IsEnabled);
Assert.Same(command.Trigger, sut.Snapshot.Trigger);
Assert.Same(command.Action, sut.Snapshot.Action);
Assert.Equal(command.Name, sut.Snapshot.Name); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateRuleEvent(new RuleUpdated { Trigger = command.Trigger, Action = command.Action, Name = command.Name })
);
} }
[Fact] [Fact]
@ -111,16 +91,9 @@ public class RuleDomainObjectTests : HandlerTestBase<Rule>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteDisableAsync(); await ExecuteDisableAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.True(sut.Snapshot.IsEnabled); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateRuleEvent(new RuleEnabled())
);
} }
[Fact] [Fact]
@ -134,16 +107,9 @@ public class RuleDomainObjectTests : HandlerTestBase<Rule>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteDisableAsync(); await ExecuteDisableAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.True(sut.Snapshot.IsEnabled); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateRuleEvent(new RuleUpdated { IsEnabled = true })
);
} }
[Fact] [Fact]
@ -153,16 +119,9 @@ public class RuleDomainObjectTests : HandlerTestBase<Rule>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.False(sut.Snapshot.IsEnabled);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateRuleEvent(new RuleDisabled())
);
} }
[Fact] [Fact]
@ -175,16 +134,9 @@ public class RuleDomainObjectTests : HandlerTestBase<Rule>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.False(sut.Snapshot.IsEnabled);
LastEvents
.ShouldHaveSameEvents(
CreateRuleEvent(new RuleUpdated { IsEnabled = false })
);
} }
[Fact] [Fact]
@ -194,16 +146,9 @@ public class RuleDomainObjectTests : HandlerTestBase<Rule>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(None.Value);
Assert.True(sut.Snapshot.IsDeleted);
LastEvents await VerifySutAsync(actual, None.Value);
.ShouldHaveSameEvents(
CreateRuleEvent(new RuleDeleted())
);
} }
[Fact] [Fact]
@ -213,9 +158,9 @@ public class RuleDomainObjectTests : HandlerTestBase<Rule>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await PublishAsync(command); var actual = await PublishAsync(sut, command);
Assert.Equal(0, sut.Version); await VerifySutAsync(actual, None.Value);
A.CallTo(() => ruleEnqueuer.EnqueueAsync(sut.Snapshot.Id, sut.Snapshot, A.CallTo(() => ruleEnqueuer.EnqueueAsync(sut.Snapshot.Id, sut.Snapshot,
A<Envelope<IEvent>>.That.Matches(x => x.Payload is RuleManuallyTriggered))) A<Envelope<IEvent>>.That.Matches(x => x.Payload is RuleManuallyTriggered)))
@ -224,17 +169,17 @@ public class RuleDomainObjectTests : HandlerTestBase<Rule>
private Task ExecuteCreateAsync() private Task ExecuteCreateAsync()
{ {
return PublishAsync(MakeCreateCommand()); return PublishAsync(sut, MakeCreateCommand());
} }
private Task ExecuteDisableAsync() private Task ExecuteDisableAsync()
{ {
return PublishAsync(new DisableRule()); return PublishAsync(sut, new DisableRule());
} }
private Task ExecuteDeleteAsync() private Task ExecuteDeleteAsync()
{ {
return PublishAsync(new DeleteRule()); return PublishAsync(sut, new DeleteRule());
} }
private static CreateRule MakeCreateCommand() private static CreateRule MakeCreateCommand()
@ -268,29 +213,26 @@ public class RuleDomainObjectTests : HandlerTestBase<Rule>
}; };
} }
private T CreateRuleEvent<T>(T @event) where T : RuleEvent protected override IAggregateCommand CreateCommand(IAggregateCommand command)
{ {
@event.RuleId = ruleId; ((RuleCommand)command).RuleId = ruleId;
return CreateEvent(@event); return base.CreateCommand(command);
} }
private T CreateRuleCommand<T>(T command) where T : RuleCommand private async Task VerifySutAsync(object? actual, object? expected = null)
{ {
command.RuleId = ruleId; if (expected == null)
{
return CreateCommand(command); actual.Should().BeEquivalentTo(sut.Snapshot, o => o.IncludingProperties());
} }
else
private Task<object> PublishIdempotentAsync(RuleCommand command) {
{ actual.Should().BeEquivalentTo(expected);
return PublishIdempotentAsync(sut, CreateRuleCommand(command)); }
}
private async Task<object?> PublishAsync(RuleCommand command) Assert.Equal(AppId, sut.Snapshot.AppId);
{
var actual = await sut.ExecuteAsync(CreateRuleCommand(command), CancellationToken);
return actual.Payload; await Verify(new { sut, events = LastEvents });
} }
} }

388
backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/DomainObject/SchemaDomainObjectTests.cs

@ -10,13 +10,12 @@ using Squidex.Domain.Apps.Core;
using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Schemas.Commands; using Squidex.Domain.Apps.Entities.Schemas.Commands;
using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Domain.Apps.Entities.TestHelpers;
using Squidex.Domain.Apps.Events.Schemas;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.Collections; using Squidex.Infrastructure.Collections;
using Squidex.Infrastructure.Commands;
namespace Squidex.Domain.Apps.Entities.Schemas.DomainObject; namespace Squidex.Domain.Apps.Entities.Schemas.DomainObject;
[UsesVerify]
public class SchemaDomainObjectTests : HandlerTestBase<Schema> public class SchemaDomainObjectTests : HandlerTestBase<Schema>
{ {
private readonly string fieldName = "age"; private readonly string fieldName = "age";
@ -60,21 +59,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
Properties = new SchemaProperties() Properties = new SchemaProperties()
}; };
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(AppId, sut.Snapshot.AppId);
Assert.Equal(SchemaId.Id, sut.Snapshot.Id);
Assert.Equal(SchemaId.Name, sut.Snapshot.Name);
Assert.Equal(SchemaType.Default, sut.Snapshot.Type);
var schema = new Schema { Name = command.Name, Properties = command.Properties };
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new SchemaCreated { Schema = schema })
);
} }
[Fact] [Fact]
@ -103,17 +90,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
] ]
}; };
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
var @event = (SchemaCreated)LastEvents.Single().Payload; await VerifySutAsync(actual);
Assert.Equal(AppId, sut.Snapshot.AppId);
Assert.Equal(SchemaId.Id, sut.Snapshot.Id);
Assert.Equal(SchemaId.Name, sut.Snapshot.Name);
Assert.Equal(SchemaType.Default, sut.Snapshot.Type);
Assert.Equal(3, @event.Schema.Fields.Count);
} }
[Fact] [Fact]
@ -126,16 +105,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(command.Properties, sut.Snapshot.Properties); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new SchemaUpdated { Properties = command.Properties })
);
} }
[Fact] [Fact]
@ -151,16 +123,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal("<query-script>", sut.Snapshot.Scripts.Query); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new SchemaScriptsConfigured { Scripts = command.Scripts })
);
} }
[Fact] [Fact]
@ -176,16 +141,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.NotEmpty(sut.Snapshot.FieldRules);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateEvent(new SchemaFieldRulesConfigured { FieldRules = FieldRules.Create(FieldRule.Disable("field1")) })
);
} }
[Fact] [Fact]
@ -199,16 +157,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAddFieldAsync(fieldName); await ExecuteAddFieldAsync(fieldName);
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(command.FieldsInLists, sut.Snapshot.FieldsInLists);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateEvent(new SchemaUIFieldsConfigured { FieldsInLists = command.FieldsInLists })
);
} }
[Fact] [Fact]
@ -222,16 +173,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAddFieldAsync(fieldName); await ExecuteAddFieldAsync(fieldName);
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(command.FieldsInReferences, sut.Snapshot.FieldsInReferences);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new SchemaUIFieldsConfigured { FieldsInReferences = command.FieldsInReferences })
);
} }
[Fact] [Fact]
@ -241,16 +185,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.True(sut.Snapshot.IsPublished);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateEvent(new SchemaPublished())
);
} }
[Fact] [Fact]
@ -261,16 +198,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecutePublishAsync(); await ExecutePublishAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.False(sut.Snapshot.IsPublished);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new SchemaUnpublished())
);
} }
[Fact] [Fact]
@ -280,16 +210,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(command.Name, sut.Snapshot.Category); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new SchemaCategoryChanged { Name = command.Name })
);
} }
[Fact] [Fact]
@ -305,16 +228,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(command.PreviewUrls, sut.Snapshot.PreviewUrls); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new SchemaPreviewUrlsConfigured { PreviewUrls = command.PreviewUrls })
);
} }
[Fact] [Fact]
@ -324,16 +240,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(None.Value);
Assert.True(sut.Snapshot.IsDeleted); await VerifySutAsync(actual, None.Value);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new SchemaDeleted())
);
} }
[Fact] [Fact]
@ -349,14 +258,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteAddFieldAsync("field1"); await ExecuteAddFieldAsync("field1");
await ExecuteAddFieldAsync("field2"); await ExecuteAddFieldAsync("field2");
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateEvent(new SchemaFieldsReordered { FieldIds = command.FieldIds })
);
} }
[Fact] [Fact]
@ -373,14 +277,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteAddFieldAsync("field1", 1); await ExecuteAddFieldAsync("field1", 1);
await ExecuteAddFieldAsync("field2", 1); await ExecuteAddFieldAsync("field2", 1);
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new SchemaFieldsReordered { ParentFieldId = arrayId, FieldIds = command.FieldIds })
);
} }
[Fact] [Fact]
@ -395,16 +294,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(command.Properties, GetField(1).RawProperties);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateEvent(new FieldAdded { Name = fieldName, FieldId = fieldId, Properties = command.Properties })
);
} }
[Fact] [Fact]
@ -420,16 +312,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAddArrayFieldAsync(); await ExecuteAddArrayFieldAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Same(command.Properties, GetNestedField(1, 2).RawProperties);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateEvent(new FieldAdded { ParentFieldId = arrayId, Name = fieldName, FieldId = nestedId, Properties = command.Properties })
);
} }
[Fact] [Fact]
@ -445,16 +330,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAddFieldAsync(fieldName); await ExecuteAddFieldAsync(fieldName);
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(command.Properties, GetField(1).RawProperties);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new FieldUpdated { FieldId = fieldId, Properties = command.Properties })
);
} }
[Fact] [Fact]
@ -471,16 +349,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteAddArrayFieldAsync(); await ExecuteAddArrayFieldAsync();
await ExecuteAddFieldAsync(fieldName, 1); await ExecuteAddFieldAsync(fieldName, 1);
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Same(command.Properties, GetNestedField(1, 2).RawProperties);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateEvent(new FieldUpdated { ParentFieldId = arrayId, FieldId = nestedId, Properties = command.Properties })
);
} }
[Fact] [Fact]
@ -495,16 +366,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAddFieldAsync(fieldName); await ExecuteAddFieldAsync(fieldName);
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.True(GetField(1).IsLocked);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new FieldLocked { FieldId = fieldId })
);
} }
[Fact] [Fact]
@ -520,16 +384,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteAddArrayFieldAsync(); await ExecuteAddArrayFieldAsync();
await ExecuteAddFieldAsync(fieldName, 1); await ExecuteAddFieldAsync(fieldName, 1);
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.True(GetNestedField(1, 2).IsLocked); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new FieldLocked { ParentFieldId = arrayId, FieldId = nestedId })
);
} }
[Fact] [Fact]
@ -544,16 +401,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAddFieldAsync(fieldName); await ExecuteAddFieldAsync(fieldName);
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.True(GetField(1).IsHidden); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new FieldHidden { FieldId = fieldId })
);
} }
[Fact] [Fact]
@ -569,16 +419,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteAddArrayFieldAsync(); await ExecuteAddArrayFieldAsync();
await ExecuteAddFieldAsync(fieldName, 1); await ExecuteAddFieldAsync(fieldName, 1);
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.True(GetNestedField(1, 2).IsHidden);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateEvent(new FieldHidden { ParentFieldId = arrayId, FieldId = nestedId })
);
} }
[Fact] [Fact]
@ -594,16 +437,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteAddFieldAsync(fieldName); await ExecuteAddFieldAsync(fieldName);
await ExecuteHideFieldAsync(1); await ExecuteHideFieldAsync(1);
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.False(GetField(1).IsHidden);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateEvent(new FieldShown { FieldId = fieldId })
);
} }
[Fact] [Fact]
@ -620,16 +456,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteAddFieldAsync(fieldName, 1); await ExecuteAddFieldAsync(fieldName, 1);
await ExecuteHideFieldAsync(2, 1); await ExecuteHideFieldAsync(2, 1);
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.False(GetNestedField(1, 2).IsHidden);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new FieldShown { ParentFieldId = arrayId, FieldId = nestedId })
);
} }
[Fact] [Fact]
@ -644,16 +473,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAddFieldAsync(fieldName); await ExecuteAddFieldAsync(fieldName);
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.True(GetField(1).IsDisabled); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new FieldDisabled { FieldId = fieldId })
);
} }
[Fact] [Fact]
@ -669,16 +491,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteAddArrayFieldAsync(); await ExecuteAddArrayFieldAsync();
await ExecuteAddFieldAsync(fieldName, 1); await ExecuteAddFieldAsync(fieldName, 1);
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.True(GetNestedField(1, 2).IsDisabled); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new FieldDisabled { ParentFieldId = arrayId, FieldId = nestedId })
);
} }
[Fact] [Fact]
@ -694,16 +509,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteAddFieldAsync(fieldName); await ExecuteAddFieldAsync(fieldName);
await ExecuteDisableFieldAsync(1); await ExecuteDisableFieldAsync(1);
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.False(GetField(1).IsDisabled); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new FieldEnabled { FieldId = fieldId })
);
} }
[Fact] [Fact]
@ -720,16 +528,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteAddFieldAsync(fieldName, 1); await ExecuteAddFieldAsync(fieldName, 1);
await ExecuteDisableFieldAsync(2, 1); await ExecuteDisableFieldAsync(2, 1);
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.False(GetNestedField(1, 2).IsDisabled); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new FieldEnabled { ParentFieldId = arrayId, FieldId = nestedId })
);
} }
[Fact] [Fact]
@ -744,16 +545,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAddFieldAsync(fieldName); await ExecuteAddFieldAsync(fieldName);
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Null(GetField(1));
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateEvent(new FieldDeleted { FieldId = fieldId })
);
} }
[Fact] [Fact]
@ -769,16 +563,9 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteAddArrayFieldAsync(); await ExecuteAddArrayFieldAsync();
await ExecuteAddFieldAsync(fieldName, 1); await ExecuteAddFieldAsync(fieldName, 1);
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Null(GetNestedField(1, 2));
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateEvent(new FieldDeleted { ParentFieldId = arrayId, FieldId = nestedId })
);
} }
[Fact] [Fact]
@ -791,61 +578,44 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(command.Category, sut.Snapshot.Category);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new SchemaCategoryChanged { Name = command.Category })
);
} }
private Task ExecuteCreateAsync() private Task ExecuteCreateAsync()
{ {
return PublishAsync(new CreateSchema { Name = SchemaId.Name, SchemaId = SchemaId.Id }); return PublishAsync(sut, new CreateSchema { Name = SchemaId.Name, SchemaId = SchemaId.Id });
} }
private Task ExecuteAddArrayFieldAsync() private Task ExecuteAddArrayFieldAsync()
{ {
return PublishAsync(new AddField { Properties = new ArrayFieldProperties(), Name = arrayName }); return PublishAsync(sut, new AddField { Properties = new ArrayFieldProperties(), Name = arrayName });
} }
private Task ExecuteAddFieldAsync(string name, long? parentId = null) private Task ExecuteAddFieldAsync(string name, long? parentId = null)
{ {
return PublishAsync(new AddField { ParentFieldId = parentId, Properties = ValidProperties(), Name = name }); return PublishAsync(sut, new AddField { ParentFieldId = parentId, Properties = ValidProperties(), Name = name });
} }
private Task ExecuteHideFieldAsync(long id, long? parentId = null) private Task ExecuteHideFieldAsync(long id, long? parentId = null)
{ {
return PublishAsync(new HideField { ParentFieldId = parentId, FieldId = id }); return PublishAsync(sut, new HideField { ParentFieldId = parentId, FieldId = id });
} }
private Task ExecuteDisableFieldAsync(long id, long? parentId = null) private Task ExecuteDisableFieldAsync(long id, long? parentId = null)
{ {
return PublishAsync(new DisableField { ParentFieldId = parentId, FieldId = id }); return PublishAsync(sut, new DisableField { ParentFieldId = parentId, FieldId = id });
} }
private Task ExecutePublishAsync() private Task ExecutePublishAsync()
{ {
return PublishAsync(new PublishSchema()); return PublishAsync(sut, new PublishSchema());
} }
private Task ExecuteDeleteAsync() private Task ExecuteDeleteAsync()
{ {
return PublishAsync(new DeleteSchema()); return PublishAsync(sut, new DeleteSchema());
}
private IField GetField(int id)
{
return sut.Snapshot.FieldsById.GetValueOrDefault(id)!;
}
private IField GetNestedField(int parentId, int childId)
{
return ((IArrayField)sut.Snapshot.FieldsById[parentId]).FieldsById.GetValueOrDefault(childId)!;
} }
private static StringFieldProperties ValidProperties() private static StringFieldProperties ValidProperties()
@ -853,15 +623,19 @@ public class SchemaDomainObjectTests : HandlerTestBase<Schema>
return new StringFieldProperties { MinLength = 10, MaxLength = 20 }; return new StringFieldProperties { MinLength = 10, MaxLength = 20 };
} }
private Task<object> PublishIdempotentAsync<T>(T command) where T : SquidexCommand, IAggregateCommand private async Task VerifySutAsync(object? actual, object? expected = null)
{ {
return PublishIdempotentAsync(sut, CreateCommand(command)); if (expected == null)
} {
actual.Should().BeEquivalentTo(sut.Snapshot, o => o.IncludingProperties());
}
else
{
actual.Should().BeEquivalentTo(expected);
}
private async Task<object> PublishAsync<T>(T command) where T : SquidexCommand, IAggregateCommand Assert.Equal(AppId, sut.Snapshot.AppId);
{
var actual = await sut.ExecuteAsync(CreateCommand(command), CancellationToken);
return actual.Payload; await Verify(new { sut, events = LastEvents });
} }
} }

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

@ -39,6 +39,7 @@
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" /> <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" />
<PackageReference Include="System.Reactive.Linq" Version="6.0.0" /> <PackageReference Include="System.Reactive.Linq" Version="6.0.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" /> <PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Verify.Xunit" Version="22.8.0" />
<PackageReference Include="xunit" Version="2.6.3" /> <PackageReference Include="xunit" Version="2.6.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.5"> <PackageReference Include="xunit.runner.visualstudio" Version="2.5.5">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>

141
backend/tests/Squidex.Domain.Apps.Entities.Tests/Teams/DomainObject/TeamDomainObjectTests.cs

@ -7,18 +7,17 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Core.Teams; using Squidex.Domain.Apps.Core.Teams;
using Squidex.Domain.Apps.Core.TestHelpers; using Squidex.Domain.Apps.Core.TestHelpers;
using Squidex.Domain.Apps.Entities.Billing; using Squidex.Domain.Apps.Entities.Billing;
using Squidex.Domain.Apps.Entities.Teams.Commands; using Squidex.Domain.Apps.Entities.Teams.Commands;
using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Domain.Apps.Entities.TestHelpers;
using Squidex.Domain.Apps.Events.Teams;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Shared.Users; using Squidex.Shared.Users;
namespace Squidex.Domain.Apps.Entities.Teams.DomainObject; namespace Squidex.Domain.Apps.Entities.Teams.DomainObject;
[UsesVerify]
public class TeamDomainObjectTests : HandlerTestBase<Team> public class TeamDomainObjectTests : HandlerTestBase<Team>
{ {
private readonly IBillingPlans billingPlans = A.Fake<IBillingPlans>(); private readonly IBillingPlans billingPlans = A.Fake<IBillingPlans>();
@ -74,17 +73,9 @@ public class TeamDomainObjectTests : HandlerTestBase<Team>
{ {
var command = new CreateTeam { Name = name, TeamId = TeamId }; var command = new CreateTeam { Name = name, TeamId = TeamId };
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await VerifySutAsync(actual);
Assert.Equal(name, sut.Snapshot.Name);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new TeamCreated { Name = name }),
CreateEvent(new TeamContributorAssigned { ContributorId = User.Identifier, Role = Role.Owner })
);
} }
[Fact] [Fact]
@ -92,16 +83,9 @@ public class TeamDomainObjectTests : HandlerTestBase<Team>
{ {
var command = new CreateTeam { Name = name, Actor = Client, TeamId = TeamId }; var command = new CreateTeam { Name = name, Actor = Client, TeamId = TeamId };
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(name, sut.Snapshot.Name); await VerifySutAsync(actual);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new TeamCreated { Name = name }, true) // Must be with client User.
);
} }
[Fact] [Fact]
@ -111,16 +95,9 @@ public class TeamDomainObjectTests : HandlerTestBase<Team>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(command.Name, sut.Snapshot.Name);
LastEvents await VerifySutAsync(actual);
.ShouldHaveSameEvents(
CreateEvent(new TeamUpdated { Name = command.Name })
);
} }
[Fact] [Fact]
@ -133,16 +110,9 @@ public class TeamDomainObjectTests : HandlerTestBase<Team>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(new PlanChangedResult(planPaid.Id)); await VerifySutAsync(actual, new PlanChangedResult(planPaid.Id));
Assert.Equal(planPaid.Id, sut.Snapshot.Plan!.PlanId);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new TeamPlanChanged { PlanId = planPaid.Id })
);
A.CallTo(() => billingManager.MustRedirectToPortalAsync(User.Identifier, A<Team>._, planPaid.Id, CancellationToken)) A.CallTo(() => billingManager.MustRedirectToPortalAsync(User.Identifier, A<Team>._, planPaid.Id, CancellationToken))
.MustHaveHappened(); .MustHaveHappened();
@ -158,16 +128,9 @@ public class TeamDomainObjectTests : HandlerTestBase<Team>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(new PlanChangedResult(planPaid.Id));
Assert.Equal(planPaid.Id, sut.Snapshot.Plan!.PlanId); await VerifySutAsync(actual, new PlanChangedResult(planPaid.Id));
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new TeamPlanChanged { PlanId = planPaid.Id })
);
A.CallTo(() => billingManager.MustRedirectToPortalAsync(A<string>._, A<Team>._, A<string?>._, A<CancellationToken>._)) A.CallTo(() => billingManager.MustRedirectToPortalAsync(A<string>._, A<Team>._, A<string?>._, A<CancellationToken>._))
.MustNotHaveHappened(); .MustNotHaveHappened();
@ -184,16 +147,9 @@ public class TeamDomainObjectTests : HandlerTestBase<Team>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteChangePlanAsync(); await ExecuteChangePlanAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(new PlanChangedResult(planFree.Id, true));
Assert.Null(sut.Snapshot.Plan);
LastEvents await VerifySutAsync(actual, new PlanChangedResult(planFree.Id, true));
.ShouldHaveSameEvents(
CreateEvent(new TeamPlanReset())
);
A.CallTo(() => billingManager.MustRedirectToPortalAsync(A<string>._, A<Team>._, A<string?>._, CancellationToken)) A.CallTo(() => billingManager.MustRedirectToPortalAsync(A<string>._, A<Team>._, A<string?>._, CancellationToken))
.MustHaveHappenedOnceExactly(); .MustHaveHappenedOnceExactly();
@ -210,16 +166,9 @@ public class TeamDomainObjectTests : HandlerTestBase<Team>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteChangePlanAsync(); await ExecuteChangePlanAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(new PlanChangedResult(planFree.Id, true)); await VerifySutAsync(actual, new PlanChangedResult(planFree.Id, true));
Assert.Null(sut.Snapshot.Plan);
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new TeamPlanReset())
);
A.CallTo(() => billingManager.MustRedirectToPortalAsync(User.Identifier, A<Team>._, planPaid.Id, CancellationToken)) A.CallTo(() => billingManager.MustRedirectToPortalAsync(User.Identifier, A<Team>._, planPaid.Id, CancellationToken))
.MustHaveHappenedOnceExactly(); .MustHaveHappenedOnceExactly();
@ -238,11 +187,9 @@ public class TeamDomainObjectTests : HandlerTestBase<Team>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(new PlanChangedResult(planPaid.Id, false, new Uri("http://squidex.io")));
Assert.Null(sut.Snapshot.Plan); await VerifySutAsync(actual, new PlanChangedResult(planPaid.Id, false, new Uri("http://squidex.io")));
} }
[Fact] [Fact]
@ -252,11 +199,9 @@ public class TeamDomainObjectTests : HandlerTestBase<Team>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(new PlanChangedResult(planPaid.Id)); await VerifySutAsync(actual, new PlanChangedResult(planPaid.Id));
Assert.Equal(planPaid.Id, sut.Snapshot.Plan?.PlanId);
A.CallTo(() => billingManager.MustRedirectToPortalAsync(User.Identifier, A<Team>._, planPaid.Id, A<CancellationToken>._)) A.CallTo(() => billingManager.MustRedirectToPortalAsync(User.Identifier, A<Team>._, planPaid.Id, A<CancellationToken>._))
.MustNotHaveHappened(); .MustNotHaveHappened();
@ -272,16 +217,9 @@ public class TeamDomainObjectTests : HandlerTestBase<Team>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
var actual = await PublishIdempotentAsync(command); var actual = await PublishIdempotentAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot);
Assert.Equal(command.Role, sut.Snapshot.Contributors[contributorId]);
LastEvents await Verify(actual);
.ShouldHaveSameEvents(
CreateEvent(new TeamContributorAssigned { ContributorId = contributorId, Role = command.Role, IsAdded = true })
);
} }
[Fact] [Fact]
@ -292,42 +230,37 @@ public class TeamDomainObjectTests : HandlerTestBase<Team>
await ExecuteCreateAsync(); await ExecuteCreateAsync();
await ExecuteAssignContributorAsync(); await ExecuteAssignContributorAsync();
var actual = await PublishAsync(command); var actual = await PublishAsync(sut, command);
actual.ShouldBeEquivalent(sut.Snapshot); await Verify(actual);
Assert.False(sut.Snapshot.Contributors.ContainsKey(contributorId));
LastEvents
.ShouldHaveSameEvents(
CreateEvent(new TeamContributorRemoved { ContributorId = contributorId })
);
} }
private Task ExecuteCreateAsync() private Task ExecuteCreateAsync()
{ {
return PublishAsync(new CreateTeam { Name = name, TeamId = TeamId }); return PublishAsync(sut, new CreateTeam { Name = name, TeamId = TeamId });
} }
private Task ExecuteAssignContributorAsync() private Task ExecuteAssignContributorAsync()
{ {
return PublishAsync(new AssignContributor { ContributorId = contributorId }); return PublishAsync(sut, new AssignContributor { ContributorId = contributorId });
} }
private Task ExecuteChangePlanAsync() private Task ExecuteChangePlanAsync()
{ {
return PublishAsync(new ChangePlan { PlanId = planPaid.Id }); return PublishAsync(sut, new ChangePlan { PlanId = planPaid.Id });
}
private Task<object> PublishIdempotentAsync(TeamCommand command)
{
return PublishIdempotentAsync(sut, CreateCommand(command));
} }
private async Task<object> PublishAsync(TeamCommand command) private async Task VerifySutAsync(object? actual, object? expected = null)
{ {
var actual = await sut.ExecuteAsync(CreateCommand(command), CancellationToken); if (expected == null)
{
return actual.Payload; actual.Should().BeEquivalentTo(sut.Snapshot, o => o.IncludingProperties());
}
else
{
actual.Should().BeEquivalentTo(expected);
}
await Verify(new { sut, events = LastEvents });
} }
} }

40
backend/tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/AssertHelper.cs

@ -1,40 +0,0 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using Squidex.Infrastructure.EventSourcing;
namespace Squidex.Domain.Apps.Entities.TestHelpers;
public static class AssertHelper
{
public static void ShouldHaveSameEvents(this IEnumerable<Envelope<IEvent>> events, params IEvent[] others)
{
var source = events.Select(x => x.Payload).ToArray();
source.Should().HaveSameCount(others);
for (var i = 0; i < source.Length; i++)
{
var lhs = source[i];
var rhs = others[i];
lhs.ShouldBeSameEvent(rhs);
}
}
public static void ShouldBeSameEvent(this IEvent lhs, IEvent rhs)
{
lhs.Should().BeOfType(rhs.GetType());
((object)lhs).Should().BeEquivalentTo(rhs, o => o.IncludingAllRuntimeProperties());
}
public static void ShouldBeEquivalent<T>(this T lhs, T rhs)
{
lhs.Should().BeEquivalentTo(rhs, o => o.IncludingProperties());
}
}

39
backend/tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/HandlerTestBase.cs

@ -45,13 +45,13 @@ public abstract class HandlerTestBase<TState> : GivenContext
#pragma warning restore MA0056 // Do not call overridable members in constructor #pragma warning restore MA0056 // Do not call overridable members in constructor
} }
protected CommandContext CreateCommandContext<TCommand>(TCommand command) where TCommand : SquidexCommand protected CommandContext CreateCommandContext<TCommand>(TCommand command) where TCommand : IAggregateCommand
{ {
return new CommandContext(CreateCommand(command), A.Dummy<ICommandBus>()); return new CommandContext(CreateCommand(command), A.Dummy<ICommandBus>());
} }
protected async Task<CommandContext> HandleAsync<TCommand>(ICommandMiddleware middleware, TCommand command, protected async Task<CommandContext> HandleAsync<TCommand>(ICommandMiddleware middleware, TCommand command,
CancellationToken ct = default) where TCommand : SquidexCommand CancellationToken ct = default) where TCommand : IAggregateCommand
{ {
var context = new CommandContext(CreateCommand(command), A.Dummy<ICommandBus>()); var context = new CommandContext(CreateCommand(command), A.Dummy<ICommandBus>());
@ -60,29 +60,48 @@ public abstract class HandlerTestBase<TState> : GivenContext
return context; return context;
} }
protected async Task<object> PublishAsync<T>(DomainObject<T> domainObject, IAggregateCommand command) where T : Entity, new()
{
LastEvents = [];
return await ExecuteCoreAsync(domainObject, command);
}
protected async Task<object> PublishIdempotentAsync<T>(DomainObject<T> domainObject, IAggregateCommand command) where T : Entity, new() protected async Task<object> PublishIdempotentAsync<T>(DomainObject<T> domainObject, IAggregateCommand command) where T : Entity, new()
{ {
var actual = await domainObject.ExecuteAsync(command, CancellationToken); LastEvents = [];
var actual = await ExecuteCoreAsync(domainObject, command);
var previousSnapshot = domainObject.Snapshot; var previousSnapshot = domainObject.Snapshot;
var previousVersion = domainObject.Snapshot.Version; var previousVersion = domainObject.Snapshot.Version;
await domainObject.ExecuteAsync(command, CancellationToken); await ExecuteCoreAsync(domainObject, command);
Assert.Same(previousSnapshot, domainObject.Snapshot); Assert.Same(previousSnapshot, domainObject.Snapshot);
Assert.Equal(previousVersion, domainObject.Snapshot.Version); Assert.Equal(previousVersion, domainObject.Snapshot.Version);
return actual.Payload; return actual;
} }
protected TCommand CreateCommand<TCommand>(TCommand command) where TCommand : SquidexCommand private async Task<object> ExecuteCoreAsync<T>(DomainObject<T> domainObject, IAggregateCommand command) where T : Entity, new()
{ {
command.ExpectedVersion = EtagVersion.Any; var actual = await domainObject.ExecuteAsync(CreateCommand(command), CancellationToken);
command.Actor ??= User;
if (command.User == null && command.Actor.IsUser) return actual.Payload;
}
protected virtual IAggregateCommand CreateCommand(IAggregateCommand command)
{
if (command is SquidexCommand baseCommand)
{ {
command.User = ApiContext.UserPrincipal; baseCommand.ExpectedVersion = EtagVersion.Any;
baseCommand.Actor ??= User;
if (baseCommand.User == null && baseCommand.Actor.IsUser)
{
baseCommand.User = ApiContext.UserPrincipal;
}
} }
if (command is IAppCommand { AppId: null } appCommand) if (command is IAppCommand { AppId: null } appCommand)

147
backend/tests/Squidex.Domain.Apps.Entities.Tests/TestHelpers/VerifySettings.cs

@ -0,0 +1,147 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Runtime.CompilerServices;
using Argon;
using NodaTime;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json.Objects;
namespace Squidex.Domain.Apps.Entities.TestHelpers;
public static partial class VerifySettings
{
private sealed class JsonArrayConverter : WriteOnlyJsonConverter<JsonArray>
{
public override void Write(VerifyJsonWriter writer, JsonArray value)
{
writer.WriteStartArray();
foreach (var item in value)
{
writer.Serialize(item);
}
writer.WriteEndArray();
}
}
private sealed class JsonObjectConverter : WriteOnlyJsonConverter<JsonObject>
{
public override void Write(VerifyJsonWriter writer, JsonObject value)
{
writer.WriteStartObject();
foreach (var (key, item) in value)
{
writer.WritePropertyName(key);
writer.Serialize(item);
}
writer.WriteEndObject();
}
}
private sealed class JsonValueConverter : WriteOnlyJsonConverter<JsonValue>
{
public override void Write(VerifyJsonWriter writer, JsonValue value)
{
switch (value.Type)
{
case JsonValueType.Null:
writer.WriteNull();
break;
case JsonValueType.Array:
writer.Serialize(value.AsArray);
break;
case JsonValueType.Boolean:
writer.WriteValue(value.AsBoolean);
break;
case JsonValueType.Number:
writer.WriteValue(value.AsNumber);
break;
case JsonValueType.Object:
writer.Serialize(value.AsObject);
break;
case JsonValueType.String:
writer.WriteValue(value.AsString);
break;
}
}
}
private sealed class ContractResolver : IContractResolver
{
private readonly IContractResolver inner;
public ContractResolver(IContractResolver inner)
{
this.inner = inner;
}
public JsonNameTable GetNameTable()
{
return inner.GetNameTable();
}
public JsonContract ResolveContract(Type type)
{
var contract = inner.ResolveContract(type);
if (contract is not JsonDictionaryContract dictionaryContract)
{
return contract;
}
var originalKeyResolver = dictionaryContract.DictionaryKeyResolver!;
dictionaryContract.DictionaryKeyResolver = (name, original) =>
{
if (original is string id && Guid.TryParse(id, out var guid1))
{
var index = Counter.Current.Next(guid1);
return $"Guid_{index}";
}
if (original is DomainId id2 && Guid.TryParse(id2.ToString(), out var guid2))
{
var index = Counter.Current.Next(guid2);
return $"Guid_{index}";
}
return originalKeyResolver(name, original);
};
return contract;
}
}
[ModuleInitializer]
public static void Initialize()
{
DerivePathInfo((sourceFile, projectDirectory, type, method) =>
{
var path = Path.Combine(projectDirectory, "Verify");
return new PathInfo(path, type.Name, method.Name);
});
VerifierSettings.AddExtraSettings(s =>
{
s.Converters.Add(new JsonArrayConverter());
s.Converters.Add(new JsonObjectConverter());
s.Converters.Add(new JsonValueConverter());
s.ContractResolver = new ContractResolver(s.ContractResolver!);
});
VerifierSettings.ScrubInlineGuids();
VerifierSettings.IgnoreMembersWithType<Instant>();
VerifierSettings.IgnoreMember("Secret");
}
}

127
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.AddLanguage_should_create_events_and_add_language.verified.txt

@ -0,0 +1,127 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en,
de
],
Languages: {
de: {
IsOptional: false
},
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3,
UniqueId: Guid_1
},
Version: 3,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
Language: de,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

134
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.AddRole_should_create_events_and_add_role.verified.txt

@ -0,0 +1,134 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
CustomCount: 1,
Custom: [
{
Name: My Role,
IsDefault: false
}
],
All: [
{
Name: My Role,
IsDefault: false
},
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3,
UniqueId: Guid_1
},
Version: 3,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
Name: My Role,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

156
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.AddWorkflow_should_create_events_and_add_workflow.verified.txt

@ -0,0 +1,156 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
Workflows: {
Guid_2: {
Initial: Draft,
Name: my-workflow,
Steps: {
Archived: {
Color: #eb3142,
NoUpdate: {},
Validate: false,
Transitions: {
Draft: {}
}
},
Draft: {
Color: #8091a5,
Validate: false,
Transitions: {
Archived: {},
Published: {}
}
},
Published: {
Color: #4bb958,
Validate: false,
Transitions: {
Archived: {},
Draft: {}
}
}
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3,
UniqueId: Guid_1
},
Version: 3,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
WorkflowId: Guid_2,
Name: my-workflow,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

122
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.ArchiveApp_should_create_events_and_update_deleted_flag.verified.txt

@ -0,0 +1,122 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: true,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3,
UniqueId: Guid_1
},
Version: 3,
ObjectState: Deleted
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

127
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.AssignContributor_should_create_events_and_add_contributor.verified.txt

@ -0,0 +1,127 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
Guid_2: Editor,
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3,
UniqueId: Guid_1
},
Version: 3,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
ContributorId: Guid_2,
Role: Editor,
IsCreated: false,
IsAdded: true,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

127
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.AssignContributor_should_create_update_events_and_update_contributor.verified.txt

@ -0,0 +1,127 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
Guid_2: Owner,
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 4,
UniqueId: Guid_1
},
Version: 4,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
ContributorId: Guid_2,
Role: Owner,
IsCreated: false,
IsAdded: false,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

130
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.AttachClient_should_create_events_and_add_client.verified.txt

@ -0,0 +1,130 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Clients: {
client: {
Name: client,
AllowAnonymous: false,
Role: Editor
}
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3,
UniqueId: Guid_1
},
Version: 3,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
Id: client,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

127
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.ChangePlan_from_callback_should_create_events_and_update_plan.verified.txt

@ -0,0 +1,127 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Plan: {
Owner: subject:me,
PlanId: premium
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3,
UniqueId: Guid_1
},
Version: 3,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
PlanId: premium,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

122
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.ChangePlan_from_callback_should_reset_plan_for_free_plan.verified.txt

@ -0,0 +1,122 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 4,
UniqueId: Guid_1
},
Version: 4,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

127
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.ChangePlan_should_create_events_and_update_plan.verified.txt

@ -0,0 +1,127 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Plan: {
Owner: subject:me,
PlanId: premium
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3,
UniqueId: Guid_1
},
Version: 3,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
PlanId: premium,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

127
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.ChangePlan_should_not_call_billing_manager_for_callback.verified.txt

@ -0,0 +1,127 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Plan: {
Owner: subject:me,
PlanId: premium
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3,
UniqueId: Guid_1
},
Version: 3,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
PlanId: premium,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

108
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.ChangePlan_should_not_make_update_for_redirect.verified.txt

@ -0,0 +1,108 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 2,
UniqueId: Guid_1
},
Version: 2,
ObjectState: Created
}
}

122
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.ChangePlan_should_reset_plan_for_free_plan.verified.txt

@ -0,0 +1,122 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 4,
UniqueId: Guid_1
},
Version: 4,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

155
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.Create_should_create_events_and_set_intitial_state.verified.txt

@ -0,0 +1,155 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 2,
UniqueId: Guid_1
},
Version: 2,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
Name: my-app,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
},
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
ContributorId: me,
Role: Owner,
IsCreated: false,
IsAdded: false,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
},
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

136
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.Create_should_not_assign_client_as_contributor.verified.txt

@ -0,0 +1,136 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: client:client,
LastModifiedBy: client:client,
Version: 1,
UniqueId: Guid_1
},
Version: 1,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
Name: my-app,
AppId: Guid_1,my-app,
Actor: client:client,
FromRule: false
}
},
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AppId: Guid_1,my-app,
Actor: client:client,
FromRule: false
}
}
]
}

123
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.DeleteRole_should_create_events_and_delete_role.verified.txt

@ -0,0 +1,123 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 4,
UniqueId: Guid_1
},
Version: 4,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
Name: My Role,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

123
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.DeleteWorkflow_should_create_events_and_remove_workflow.verified.txt

@ -0,0 +1,123 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 4,
UniqueId: Guid_1
},
Version: 4,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
WorkflowId: Guid_3,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

123
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.RemoveContributor_should_create_events_and_remove_contributor.verified.txt

@ -0,0 +1,123 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 4,
UniqueId: Guid_1
},
Version: 4,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
ContributorId: Guid_3,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

122
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.RemoveImage_should_create_events_and_update_image.verified.txt

@ -0,0 +1,122 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 4,
UniqueId: Guid_1
},
Version: 4,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

123
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.RemoveLanguage_should_create_events_and_remove_language.verified.txt

@ -0,0 +1,123 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 4,
UniqueId: Guid_1
},
Version: 4,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
Language: de,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

123
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.RevokeClient_should_create_events_and_remove_client.verified.txt

@ -0,0 +1,123 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 4,
UniqueId: Guid_1
},
Version: 4,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
Id: client,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

122
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.Transfer_from_team_should_create_events_and_set_team.verified.txt

@ -0,0 +1,122 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 4,
UniqueId: Guid_1
},
Version: 4,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

124
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.Transfer_should_create_events_and_set_team.verified.txt

@ -0,0 +1,124 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
TeamId: Guid_2,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3,
UniqueId: Guid_1
},
Version: 3,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
TeamId: Guid_2,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

132
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.UpdateClient_should_create_events_and_update_client.verified.txt

@ -0,0 +1,132 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Clients: {
client: {
Name: My Client,
AllowAnonymous: false,
Role: Developer
}
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 4,
UniqueId: Guid_1
},
Version: 4,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
Id: client,
Name: My Client,
Role: Developer,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

135
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.UpdateLanguage_should_create_events_and_update_language.verified.txt

@ -0,0 +1,135 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en,
de
],
Languages: {
de: {
IsOptional: false,
Fallbacks: [
en
]
},
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 4,
UniqueId: Guid_1
},
Version: 4,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
Language: de,
IsOptional: false,
IsMaster: false,
Fallback: [
en
],
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

147
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.UpdateRole_should_create_events_and_update_role.verified.txt

@ -0,0 +1,147 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
CustomCount: 1,
Custom: [
{
Name: My Role,
Permissions: [
{
Id: clients.read
}
],
IsDefault: false
}
],
All: [
{
Name: My Role,
Permissions: [
{
Id: clients.read
}
],
IsDefault: false
},
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 4,
UniqueId: Guid_1
},
Version: 4,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
Name: My Role,
Permissions: [
clients.read
],
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

126
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.UpdateSettings_should_create_event_and_update_settings.verified.txt

@ -0,0 +1,126 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: false,
HideDateTimeModeButton: true
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3,
UniqueId: Guid_1
},
Version: 3,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
Settings: {
HideScheduler: false,
HideDateTimeModeButton: true
},
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

185
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.UpdateWorkflow_should_create_events_and_update_workflow.verified.txt

@ -0,0 +1,185 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
Workflows: {
Guid_2: {
Initial: Draft,
Name: Unnamed,
Steps: {
Archived: {
Color: #eb3142,
NoUpdate: {},
Validate: false,
Transitions: {
Draft: {}
}
},
Draft: {
Color: #8091a5,
Validate: false,
Transitions: {
Archived: {},
Published: {}
}
},
Published: {
Color: #4bb958,
Validate: false,
Transitions: {
Archived: {},
Draft: {}
}
}
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 4,
UniqueId: Guid_1
},
Version: 4,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
WorkflowId: Guid_2,
Workflow: {
Initial: Draft,
Name: Unnamed,
Steps: {
Archived: {
Color: #eb3142,
NoUpdate: {},
Validate: false,
Transitions: {
Draft: {}
}
},
Draft: {
Color: #8091a5,
Validate: false,
Transitions: {
Archived: {},
Published: {}
}
},
Published: {
Color: #4bb958,
Validate: false,
Transitions: {
Archived: {},
Draft: {}
}
}
}
},
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

126
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.Update_should_create_events_and_update_label_and_description.verified.txt

@ -0,0 +1,126 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Label: my-label,
Description: my-description,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3,
UniqueId: Guid_1
},
Version: 3,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_2,
Timestamp: DateTimeOffset_1
},
Payload: {
Label: my-label,
Description: my-description,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

130
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AppDomainObjectTests.UploadImage_should_create_events_and_update_image.verified.txt

@ -0,0 +1,130 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
Name: my-app,
Contributors: {
me: Owner
},
Roles: {
All: [
{
Name: Owner,
Permissions: [
{
Id: *
}
],
IsDefault: true
},
{
Name: Reader,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets.read
},
{
Id: contents.*.read
}
],
IsDefault: true
},
{
Name: Editor,
Properties: {
ui.api.hide: true
},
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: workflows.read
}
],
IsDefault: true
},
{
Name: Developer,
Permissions: [
{
Id: assets
},
{
Id: contents.*
},
{
Id: roles.read
},
{
Id: rules
},
{
Id: schemas
},
{
Id: workflows
}
],
IsDefault: true
}
]
},
Image: {
MimeType: image/png,
Etag: Guid_2
},
Settings: {
HideScheduler: true,
HideDateTimeModeButton: false
},
AssetScripts: {},
Languages: {
Master: en,
AllKeys: [
en
],
Languages: {
en: {
IsOptional: false
}
}
},
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3,
UniqueId: Guid_1
},
Version: 3,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
Image: {
MimeType: image/png,
Etag: Guid_2
},
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

44
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.AnnotateMetadata_should_create_events_and_update_metadata.verified.txt

@ -0,0 +1,44 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
FileName: image.png,
FileHash: 123,
MimeType: image/png,
Slug: image.png,
FileSize: 1024,
TotalSize: 1024,
IsProtected: false,
Metadata: {
pixelWidth: 800.0
},
UniqueId: Guid_2--Guid_1,
AppId: Guid_2,my-app,
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
Metadata: {
pixelWidth: 800.0
},
AssetId: Guid_1,
AppId: Guid_2,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

39
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.AnnotateName_should_create_events_and_update_file_name.verified.txt

@ -0,0 +1,39 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
FileName: My New Image.png,
FileHash: 123,
MimeType: image/png,
Slug: image.png,
FileSize: 1024,
TotalSize: 1024,
IsProtected: false,
UniqueId: Guid_2--Guid_1,
AppId: Guid_2,my-app,
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
FileName: My New Image.png,
AssetId: Guid_1,
AppId: Guid_2,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

39
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.AnnotateProtected_should_create_events_and_update_protected_flag.verified.txt

@ -0,0 +1,39 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
FileName: image.png,
FileHash: 123,
MimeType: image/png,
Slug: image.png,
FileSize: 1024,
TotalSize: 1024,
IsProtected: true,
UniqueId: Guid_2--Guid_1,
AppId: Guid_2,my-app,
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
IsProtected: true,
AssetId: Guid_1,
AppId: Guid_2,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

39
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.AnnotateSlug_should_create_events_and_update_slug.verified.txt

@ -0,0 +1,39 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
FileName: image.png,
FileHash: 123,
MimeType: image/png,
Slug: my-new-image.png,
FileSize: 1024,
TotalSize: 1024,
IsProtected: false,
UniqueId: Guid_2--Guid_1,
AppId: Guid_2,my-app,
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
Slug: my-new-image.png,
AssetId: Guid_1,
AppId: Guid_2,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

44
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.AnnotateTags_should_create_events_and_update_tags.verified.txt

@ -0,0 +1,44 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
FileName: image.png,
FileHash: 123,
MimeType: image/png,
Slug: image.png,
FileSize: 1024,
TotalSize: 1024,
IsProtected: false,
Tags: [
tag1
],
UniqueId: Guid_2--Guid_1,
AppId: Guid_2,my-app,
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
Tags: [
tag1
],
AssetId: Guid_1,
AppId: Guid_2,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

41
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.Create_should_create_events_and_set_intitial_state.verified.txt

@ -0,0 +1,41 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
FileName: image.png,
FileHash: NewHash,
MimeType: image/png,
Slug: image.png,
FileSize: 1024,
TotalSize: 1024,
IsProtected: false,
UniqueId: Guid_2--Guid_1,
AppId: Guid_2,my-app,
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me
},
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
FileName: image.png,
FileHash: NewHash,
MimeType: image/png,
Slug: image.png,
FileSize: 1024,
AssetId: Guid_1,
AppId: Guid_2,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

40
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.Delete_should_create_events_with_total_file_size_and_tags_and_update_deleted_flag.verified.txt

@ -0,0 +1,40 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
FileName: image.png,
FileHash: 456,
MimeType: image/png,
Slug: image.png,
FileSize: 1024,
FileVersion: 1,
TotalSize: 2048,
IsProtected: false,
UniqueId: Guid_2--Guid_1,
AppId: Guid_2,my-app,
IsDeleted: true,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 2
},
Version: 2,
ObjectState: Deleted
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
DeletedSize: 2048,
AssetId: Guid_1,
AppId: Guid_2,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

40
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.Move_should_create_events_and_update_parent_id.verified.txt

@ -0,0 +1,40 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
FileName: image.png,
FileHash: 123,
MimeType: image/png,
Slug: image.png,
FileSize: 1024,
TotalSize: 1024,
IsProtected: false,
ParentId: Guid_2,
UniqueId: Guid_3--Guid_1,
AppId: Guid_3,my-app,
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
ParentId: Guid_2,
AssetId: Guid_1,
AppId: Guid_3,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

43
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.Update_should_create_events_and_update_file_state.verified.txt

@ -0,0 +1,43 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
FileName: image.png,
FileHash: NewHash,
MimeType: image/png,
Slug: image.png,
FileSize: 1024,
FileVersion: 1,
TotalSize: 2048,
IsProtected: false,
UniqueId: Guid_2--Guid_1,
AppId: Guid_2,my-app,
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
MimeType: image/png,
FileHash: NewHash,
FileSize: 1024,
FileVersion: 1,
AssetId: Guid_1,
AppId: Guid_2,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

41
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.Upsert_should_create_events_and_set_intitial_state_if_not_found.verified.txt

@ -0,0 +1,41 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
FileName: image.png,
FileHash: NewHash,
MimeType: image/png,
Slug: image.png,
FileSize: 1024,
TotalSize: 1024,
IsProtected: false,
UniqueId: Guid_2--Guid_1,
AppId: Guid_2,my-app,
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me
},
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
FileName: image.png,
FileHash: NewHash,
MimeType: image/png,
Slug: image.png,
FileSize: 1024,
AssetId: Guid_1,
AppId: Guid_2,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

43
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetDomainObjectTests.Upsert_should_create_events_and_update_file_state_if_found.verified.txt

@ -0,0 +1,43 @@
{
sut: {
UniqueId: Guid_1,
Snapshot: {
FileName: image.png,
FileHash: NewHash,
MimeType: image/png,
Slug: image.png,
FileSize: 1024,
FileVersion: 1,
TotalSize: 2048,
IsProtected: false,
UniqueId: Guid_2--Guid_1,
AppId: Guid_2,my-app,
IsDeleted: false,
Id: Guid_1,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
MimeType: image/png,
FileHash: NewHash,
FileSize: 1024,
FileVersion: 1,
AssetId: Guid_1,
AppId: Guid_2,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

31
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetFolderDomainObjectTests.Create_should_create_events_and_set_intitial_state.verified.txt

@ -0,0 +1,31 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
FolderName: New Name,
UniqueId: Guid_1--Guid_2,
AppId: Guid_1,my-app,
IsDeleted: false,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me
},
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
FolderName: New Name,
AssetFolderId: Guid_2,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

32
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetFolderDomainObjectTests.Delete_should_create_events_with_total_file_size.verified.txt

@ -0,0 +1,32 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
FolderName: My Folder,
UniqueId: Guid_1--Guid_2,
AppId: Guid_1,my-app,
IsDeleted: true,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Deleted
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
AssetFolderId: Guid_2,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

34
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetFolderDomainObjectTests.Move_should_create_events_and_update_state.verified.txt

@ -0,0 +1,34 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
FolderName: My Folder,
ParentId: Guid_3,
UniqueId: Guid_1--Guid_2,
AppId: Guid_1,my-app,
IsDeleted: false,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
ParentId: Guid_3,
AssetFolderId: Guid_2,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

33
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/AssetFolderDomainObjectTests.Update_should_create_events_and_update_state.verified.txt

@ -0,0 +1,33 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
FolderName: New Name,
UniqueId: Guid_1--Guid_2,
AppId: Guid_1,my-app,
IsDeleted: false,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_3,
Timestamp: DateTimeOffset_1
},
Payload: {
FolderName: New Name,
AssetFolderId: Guid_2,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

1
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ApplyDefaults_should_not_update_content_if_all_fields_have_a_value.verified.txt

@ -0,0 +1 @@


61
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ApplyDefaults_should_update_content.verified.txt

@ -0,0 +1,61 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Draft,
Data: {
defaults: {
iv: Default Value
},
my-field1: {
iv: 1.0
}
}
},
EditingData: {
defaults: {
iv: Default Value
},
my-field1: {
iv: 1.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me
},
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
Status: Draft,
Data: {
defaults: {
iv: Default Value
},
my-field1: {
iv: 1.0
}
},
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

48
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.CancelContentSchedule_create_events_and_unset_schedule.verified.txt

@ -0,0 +1,48 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Draft,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 2
},
Version: 2,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

48
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.CancelContentSchedule_should_create_events_and_unset_schedule.verified.txt

@ -0,0 +1,48 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Draft,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 2
},
Version: 2,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

54
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ChangeStatus_create_events_and_set_schedule_if_duetime_set.verified.txt

@ -0,0 +1,54 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Draft,
Data: {
my-field1: {
iv: 1.0
}
}
},
ScheduleJob: {
Id: Guid_4,
Status: Published,
ScheduledBy: subject:me
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_5,
Timestamp: DateTimeOffset_1
},
Payload: {
Status: Published,
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

80
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ChangeStatus_should_also_update_if_script_changes_data.verified.txt

@ -0,0 +1,80 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Draft,
Data: {
my-field1: {
iv: 2.0
},
my-field2: {
iv: 2.0
}
}
},
EditingData: {
my-field1: {
iv: 2.0
},
my-field2: {
iv: 2.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3
},
Version: 3,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
Data: {
my-field1: {
iv: 2.0
},
my-field2: {
iv: 2.0
}
},
NewVersion: false,
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
},
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_5,
Timestamp: DateTimeOffset_1
},
Payload: {
Change: Unpublished,
Status: Draft,
NewVersion: false,
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

51
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ChangeStatus_should_create_events_and_delete_new_version_if_available.verified.txt

@ -0,0 +1,51 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Published,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Published,
IsPublished: true,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3
},
Version: 3,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
Change: Published,
Status: Published,
NewVersion: false,
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

48
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ChangeStatus_should_create_events_and_unset_schedule_if_failed.verified.txt

@ -0,0 +1,48 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Draft,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 2
},
Version: 2,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

58
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ChangeStatus_should_create_events_and_update_new_version_if_draft_available.verified.txt

@ -0,0 +1,58 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
NewVersion: {
Status: Archived,
Data: {
my-field1: {
iv: 1.0
}
}
},
CurrentVersion: {
Status: Published,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Archived,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3
},
Version: 3,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
Status: Archived,
NewVersion: false,
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

50
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ChangeStatus_should_create_events_and_update_status_if_changed.verified.txt

@ -0,0 +1,50 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Archived,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Archived,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
Status: Archived,
NewVersion: false,
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

50
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ChangeStatus_should_create_events_and_update_status_if_published.verified.txt

@ -0,0 +1,50 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Archived,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Archived,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
Status: Archived,
NewVersion: false,
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

51
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ChangeStatus_should_create_events_and_update_status_if_unpublished.verified.txt

@ -0,0 +1,51 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Draft,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 2
},
Version: 2,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
Change: Unpublished,
Status: Draft,
NewVersion: false,
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

50
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.ChangeStatus_should_refresh_properties_and_unset_schedule_if_completed.verified.txt

@ -0,0 +1,50 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Archived,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Archived,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 2
},
Version: 2,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
Status: Archived,
NewVersion: false,
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

57
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.CreateDraft_should_create_events_and_update_new_state.verified.txt

@ -0,0 +1,57 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
NewVersion: {
Status: Draft,
Data: {
my-field1: {
iv: 1.0
}
}
},
CurrentVersion: {
Status: Published,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 2
},
Version: 2,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
Status: Draft,
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

70
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Create_should_change_status_if_set.verified.txt

@ -0,0 +1,70 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Archived,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Archived,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
Status: Draft,
Data: {
my-field1: {
iv: 1.0
}
},
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
},
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_5,
Timestamp: DateTimeOffset_1
},
Payload: {
Status: Archived,
NewVersion: false,
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

52
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Create_should_create_events_and_update_data_and_status.verified.txt

@ -0,0 +1,52 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Draft,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me
},
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
Status: Draft,
Data: {
my-field1: {
iv: 1.0
}
},
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

52
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Create_should_not_change_status_if_set_to_initial.verified.txt

@ -0,0 +1,52 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Draft,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me
},
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
Status: Draft,
Data: {
my-field1: {
iv: 1.0
}
},
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

48
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.DeleteDraft_should_create_events_and_delete_new_version.verified.txt

@ -0,0 +1,48 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Published,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Published,
IsPublished: true,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3
},
Version: 3,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

48
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Delete_should_create_events_and_update_deleted_flag.verified.txt

@ -0,0 +1,48 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Draft,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: true,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Deleted
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

30
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.EnrichContentDefaults_should_not_update_content_if_all_fields_have_a_value.verified.txt

@ -0,0 +1,30 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Draft,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me
},
ObjectState: Created
}
}

63
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.EnrichContentDefaults_should_update_content.verified.txt

@ -0,0 +1,63 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Draft,
Data: {
defaults: {
iv: Default Value
},
my-field1: {
iv: 1.0
}
}
},
EditingData: {
defaults: {
iv: Default Value
},
my-field1: {
iv: 1.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
Data: {
defaults: {
iv: Default Value
},
my-field1: {
iv: 1.0
}
},
NewVersion: false,
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

63
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Patch_should_create_events_and_update_data.verified.txt

@ -0,0 +1,63 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Draft,
Data: {
my-field1: {
iv: 1.0
},
my-field2: {
iv: 2.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
},
my-field2: {
iv: 2.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
Data: {
my-field1: {
iv: 1.0
},
my-field2: {
iv: 2.0
}
},
NewVersion: false,
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

71
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Patch_should_create_events_and_update_new_version_if_draft_available.verified.txt

@ -0,0 +1,71 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
NewVersion: {
Status: Draft,
Data: {
my-field1: {
iv: 1.0
},
my-field2: {
iv: 2.0
}
}
},
CurrentVersion: {
Status: Published,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
},
my-field2: {
iv: 2.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3
},
Version: 3,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
Data: {
my-field1: {
iv: 1.0
},
my-field2: {
iv: 2.0
}
},
NewVersion: false,
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

30
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Patch_should_not_create_event_for_same_data.verified.txt

@ -0,0 +1,30 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Draft,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me
},
ObjectState: Created
}
}

63
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Update_should_create_events_and_update_data.verified.txt

@ -0,0 +1,63 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Draft,
Data: {
my-field1: {
iv: 2.0
},
my-field2: {
iv: 2.0
}
}
},
EditingData: {
my-field1: {
iv: 2.0
},
my-field2: {
iv: 2.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 1
},
Version: 1,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
Data: {
my-field1: {
iv: 2.0
},
my-field2: {
iv: 2.0
}
},
NewVersion: false,
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

71
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Update_should_create_events_and_update_new_version_if_draft_available.verified.txt

@ -0,0 +1,71 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
NewVersion: {
Status: Draft,
Data: {
my-field1: {
iv: 2.0
},
my-field2: {
iv: 2.0
}
}
},
CurrentVersion: {
Status: Published,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 2.0
},
my-field2: {
iv: 2.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me,
Version: 3
},
Version: 3,
ObjectState: Created
},
events: [
{
Headers: {
AggregateId: Guid_1--Guid_2,
EventId: Guid_4,
Timestamp: DateTimeOffset_1
},
Payload: {
Data: {
my-field1: {
iv: 2.0
},
my-field2: {
iv: 2.0
}
},
NewVersion: false,
ContentId: Guid_2,
SchemaId: Guid_3,my-schema,
AppId: Guid_1,my-app,
Actor: subject:me,
FromRule: false
}
}
]
}

30
backend/tests/Squidex.Domain.Apps.Entities.Tests/Verify/ContentDomainObjectTests.Update_should_not_create_event_for_same_data.verified.txt

@ -0,0 +1,30 @@
{
sut: {
UniqueId: Guid_1--Guid_2,
Snapshot: {
SchemaId: Guid_3,my-schema,
CurrentVersion: {
Status: Draft,
Data: {
my-field1: {
iv: 1.0
}
}
},
EditingData: {
my-field1: {
iv: 1.0
}
},
EditingStatus: Draft,
IsPublished: false,
AppId: Guid_1,my-app,
IsDeleted: false,
UniqueId: Guid_1--Guid_2,
Id: Guid_2,
CreatedBy: subject:me,
LastModifiedBy: subject:me
},
ObjectState: Created
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save