Browse Source

Updated domain object to configure scripts.

pull/104/head
Sebastian Stehle 8 years ago
parent
commit
edc15588a8
  1. 2
      src/Squidex.Domain.Apps.Core/FieldExtensions.cs
  2. 8
      src/Squidex.Domain.Apps.Core/Scripting/JurassicScriptEngine.cs
  3. 10
      src/Squidex.Domain.Apps.Core/Scripting/ScriptUser.cs
  4. 28
      src/Squidex.Domain.Apps.Events/Schemas/ScriptsConfigured.cs
  5. 22
      src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoSchemaEntity.cs
  6. 5
      src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoSchemaRepository_EventHandling.cs
  7. 12
      src/Squidex.Domain.Apps.Read/Schemas/ISchemaEntity.cs
  8. 5
      src/Squidex.Domain.Apps.Read/Schemas/Services/Implementations/CachingSchemaProvider.cs
  9. 3
      src/Squidex.Domain.Apps.Write/Contents/Commands/ContentCommand.cs
  10. 24
      src/Squidex.Domain.Apps.Write/Contents/ContentChangedResult.cs
  11. 117
      src/Squidex.Domain.Apps.Write/Contents/ContentCommandMiddleware.cs
  12. 11
      src/Squidex.Domain.Apps.Write/Contents/ContentDomainObject.cs
  13. 25
      src/Squidex.Domain.Apps.Write/Schemas/Commands/ConfigureScripts.cs
  14. 5
      src/Squidex.Domain.Apps.Write/Schemas/SchemaCommandMiddleware.cs
  15. 11
      src/Squidex.Domain.Apps.Write/Schemas/SchemaDomainObject.cs
  16. 4
      src/Squidex.Infrastructure/CQRS/Commands/AggregateHandler.cs
  17. 54
      tests/Squidex.Domain.Apps.Write.Tests/Contents/ContentCommandHandlerTests.cs
  18. 13
      tests/Squidex.Domain.Apps.Write.Tests/Schemas/SchemaCommandHandlerTests.cs
  19. 50
      tests/Squidex.Domain.Apps.Write.Tests/Schemas/SchemaDomainObjectTests.cs

2
src/Squidex.Domain.Apps.Core/FieldExtensions.cs

@ -40,8 +40,6 @@ namespace Squidex.Domain.Apps.Core
public static async Task ValidateAsync(this Field field, JToken value, ValidationContext context, Action<string> addError)
{
Guard.NotNull(value, nameof(value));
try
{
var typedValue = value.IsNull() ? null : field.ConvertValue(value);

8
src/Squidex.Domain.Apps.Core/Scripting/JurassicScriptEngine.cs

@ -92,12 +92,16 @@ namespace Squidex.Domain.Apps.Core.Scripting
engine.SetGlobalFunction("disallow", new Action<string>(message =>
{
throw new DomainForbiddenException(!string.IsNullOrWhiteSpace(message) ? message : "Not allowed");
var exMessage = !string.IsNullOrWhiteSpace(message) ? message : "Not allowed";
throw new DomainForbiddenException(exMessage);
}));
engine.SetGlobalFunction("reject", new Action<string>(message =>
{
throw new ValidationException($"Failed to {operationName}", !string.IsNullOrWhiteSpace(message) ? new[] { new ValidationError(message) } : null);
var errors = !string.IsNullOrWhiteSpace(message) ? new[] { new ValidationError(message) } : null;
throw new ValidationException($"Script rejected to to {operationName}.", errors);
}));
var json = JsonConvert.SerializeObject(context, serializerSettings);

10
src/Squidex.Domain.Apps.Core/Scripting/ScriptUser.cs

@ -1,4 +1,12 @@
using System.Collections.Generic;
// ==========================================================================
// ScriptUser.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using System.Security.Claims;
namespace Squidex.Domain.Apps.Core.Scripting

28
src/Squidex.Domain.Apps.Events/Schemas/ScriptsConfigured.cs

@ -0,0 +1,28 @@
// ==========================================================================
// ScriptsConfigured.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Events.Schemas
{
[TypeName("ScriptsConfiguredEvent")]
public sealed class ScriptsConfigured : SchemaEvent
{
public string ScriptQuery { get; set; }
public string ScriptCreate { get; set; }
public string ScriptUpdate { get; set; }
public string ScriptDelete { get; set; }
public string ScriptPublish { get; set; }
public string ScriptUnpublish { get; set; }
}
}

22
src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoSchemaEntity.cs

@ -25,6 +25,8 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Schemas
[BsonElement]
public string Name { get; set; }
public string ScriptUnpublish { get; set; }
[BsonRequired]
[BsonElement]
public string Schema { get; set; }
@ -53,6 +55,26 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Schemas
[BsonElement]
public bool IsDeleted { get; set; }
[BsonIgnoreIfNull]
[BsonElement]
public string ScriptQuery { get; set; }
[BsonIgnoreIfNull]
[BsonElement]
public string ScriptCreate { get; set; }
[BsonIgnoreIfNull]
[BsonElement]
public string ScriptUpdate { get; set; }
[BsonIgnoreIfNull]
[BsonElement]
public string ScriptDelete { get; set; }
[BsonIgnoreIfNull]
[BsonElement]
public string ScriptPublish { get; set; }
Schema ISchemaEntity.Schema
{
get { return schema.Value; }

5
src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoSchemaRepository_EventHandling.cs

@ -103,6 +103,11 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Schemas
return UpdateSchema(@event, headers, s => SchemaEventDispatcher.Dispatch(@event, s, registry));
}
protected Task On(ScriptsConfigured @event, EnvelopeHeaders headers)
{
return Collection.UpdateAsync(@event, headers, e => SimpleMapper.Map(@event, e));
}
protected Task On(SchemaDeleted @event, EnvelopeHeaders headers)
{
return Collection.UpdateAsync(@event, headers, e => e.IsDeleted = true);

12
src/Squidex.Domain.Apps.Read/Schemas/ISchemaEntity.cs

@ -18,6 +18,18 @@ namespace Squidex.Domain.Apps.Read.Schemas
bool IsDeleted { get; }
string ScriptQuery { get; }
string ScriptCreate { get; }
string ScriptUpdate { get; }
string ScriptDelete { get; }
string ScriptPublish { get; }
string ScriptUnpublish { get; }
Schema Schema { get; }
}
}

5
src/Squidex.Domain.Apps.Read/Schemas/Services/Implementations/CachingSchemaProvider.cs

@ -17,6 +17,7 @@ using Squidex.Infrastructure.Caching;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Tasks;
// ReSharper disable ConvertIfStatementToSwitchStatement
// ReSharper disable ConvertIfStatementToConditionalTernaryExpression
// ReSharper disable InvertIf
@ -125,6 +126,10 @@ namespace Squidex.Domain.Apps.Read.Schemas.Services.Implementations
{
Remove(schemaUpdatedEvent.AppId, schemaUpdatedEvent.SchemaId);
}
else if (@event.Payload is ScriptsConfigured scriptsConfiguredEvent)
{
Remove(scriptsConfiguredEvent.AppId, scriptsConfiguredEvent.SchemaId);
}
return TaskHelper.Done;
}

3
src/Squidex.Domain.Apps.Write/Contents/Commands/ContentCommand.cs

@ -7,12 +7,15 @@
// ==========================================================================
using System;
using System.Security.Claims;
using Squidex.Infrastructure.CQRS.Commands;
namespace Squidex.Domain.Apps.Write.Contents.Commands
{
public abstract class ContentCommand : SchemaCommand, IAggregateCommand
{
public ClaimsPrincipal Principal { get; set; }
public Guid ContentId { get; set; }
Guid IAggregateCommand.AggregateId

24
src/Squidex.Domain.Apps.Write/Contents/ContentChangedResult.cs

@ -0,0 +1,24 @@
// ==========================================================================
// ContentChangedResult.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Infrastructure.CQRS.Commands;
namespace Squidex.Domain.Apps.Write.Contents
{
public sealed class ContentChangedResult : EntitySavedResult
{
public NamedContentData Content { get; }
public ContentChangedResult(NamedContentData content, long version)
: base(version)
{
Content = content;
}
}
}

117
src/Squidex.Domain.Apps.Write/Contents/ContentCommandMiddleware.cs

@ -11,10 +11,14 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Core;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Core.Scripting;
using Squidex.Domain.Apps.Read.Apps;
using Squidex.Domain.Apps.Read.Apps.Services;
using Squidex.Domain.Apps.Read.Assets.Repositories;
using Squidex.Domain.Apps.Read.Contents.Repositories;
using Squidex.Domain.Apps.Read.Schemas;
using Squidex.Domain.Apps.Read.Schemas.Services;
using Squidex.Domain.Apps.Write.Contents.Commands;
using Squidex.Infrastructure;
@ -32,66 +36,120 @@ namespace Squidex.Domain.Apps.Write.Contents
private readonly IAssetRepository assetRepository;
private readonly IContentRepository contentRepository;
private readonly ISchemaProvider schemas;
private readonly IScriptEngine scriptEngine;
public ContentCommandMiddleware(
IAggregateHandler handler,
IAppProvider appProvider,
IAssetRepository assetRepository,
ISchemaProvider schemas,
IScriptEngine scriptEngine,
IContentRepository contentRepository)
{
Guard.NotNull(handler, nameof(handler));
Guard.NotNull(schemas, nameof(schemas));
Guard.NotNull(appProvider, nameof(appProvider));
Guard.NotNull(scriptEngine, nameof(scriptEngine));
Guard.NotNull(assetRepository, nameof(assetRepository));
Guard.NotNull(contentRepository, nameof(contentRepository));
this.handler = handler;
this.schemas = schemas;
this.appProvider = appProvider;
this.scriptEngine = scriptEngine;
this.assetRepository = assetRepository;
this.contentRepository = contentRepository;
}
protected async Task On(CreateContent command, CommandContext context)
{
await ValidateAsync(command, () => "Failed to create content", true);
await handler.CreateAsync<ContentDomainObject>(context, c =>
await handler.CreateAsync<ContentDomainObject>(context, async content =>
{
c.Create(command);
var schemaAndApp = await ResolveSchemaAndAppAsync(command);
var scriptContext = CreateScriptContext(content, command, command.Data);
command.Data = scriptEngine.ExecuteAndTransform(scriptContext, schemaAndApp.Schema.ScriptCreate, "create content", true);
command.Data.Enrich(schemaAndApp.Schema.Schema, schemaAndApp.App.PartitionResolver);
await ValidateAsync(schemaAndApp, command, () => "Failed to create content", false);
context.Complete(EntityCreatedResult.Create(command.Data, c.Version));
content.Create(command);
context.Complete(EntityCreatedResult.Create(command.Data, content.Version));
});
}
protected async Task On(UpdateContent command, CommandContext context)
{
await ValidateAsync(command, () => "Failed to update content");
await handler.UpdateAsync<ContentDomainObject>(context, async content =>
{
var schemaAndApp = await ResolveSchemaAndAppAsync(command);
var scriptContext = CreateScriptContext(content, command, command.Data);
command.Data = scriptEngine.ExecuteAndTransform(scriptContext, schemaAndApp.Schema.ScriptUpdate, "update content", true);
await handler.UpdateAsync<ContentDomainObject>(context, c => c.Update(command));
await ValidateAsync(schemaAndApp, command, () => "Failed to update content", false);
content.Update(command);
context.Complete(new ContentChangedResult(content.Data, content.Version));
});
}
protected async Task On(PatchContent command, CommandContext context)
{
await ValidateAsync(command, () => "Failed to patch content");
await handler.UpdateAsync<ContentDomainObject>(context, async content =>
{
var schemaAndApp = await ResolveSchemaAndAppAsync(command);
var scriptContext = CreateScriptContext(content, command, command.Data);
command.Data = scriptEngine.ExecuteAndTransform(scriptContext, schemaAndApp.Schema.ScriptUpdate, "patch content", true);
await ValidateAsync(schemaAndApp, command, () => "Failed to patch content", true);
await handler.UpdateAsync<ContentDomainObject>(context, c => c.Patch(command));
content.Patch(command);
context.Complete(new ContentChangedResult(content.Data, content.Version));
});
}
protected Task On(PublishContent command, CommandContext context)
{
return handler.UpdateAsync<ContentDomainObject>(context, c => c.Publish(command));
return handler.UpdateAsync<ContentDomainObject>(context, async content =>
{
var schemaAndApp = await ResolveSchemaAndAppAsync(command);
var scriptContext = CreateScriptContext(content, command);
scriptEngine.Execute(scriptContext, schemaAndApp.Schema.ScriptPublish, "publish content");
content.Publish(command);
});
}
protected Task On(UnpublishContent command, CommandContext context)
{
return handler.UpdateAsync<ContentDomainObject>(context, c => c.Unpublish(command));
return handler.UpdateAsync<ContentDomainObject>(context, async content =>
{
var schemaAndApp = await ResolveSchemaAndAppAsync(command);
var scriptContext = CreateScriptContext(content, command);
scriptEngine.Execute(scriptContext, schemaAndApp.Schema.ScriptUnpublish, "unpublish content");
content.Unpublish(command);
});
}
protected Task On(DeleteContent command, CommandContext context)
{
return handler.UpdateAsync<ContentDomainObject>(context, c => c.Delete(command));
return handler.UpdateAsync<ContentDomainObject>(context, async content =>
{
var schemaAndApp = await ResolveSchemaAndAppAsync(command);
var scriptContext = CreateScriptContext(content, command);
scriptEngine.Execute(scriptContext, schemaAndApp.Schema.ScriptDelete, "delete content");
content.Delete(command);
});
}
public async Task HandleAsync(CommandContext context, Func<Task> next)
@ -102,16 +160,10 @@ namespace Squidex.Domain.Apps.Write.Contents
}
}
private async Task ValidateAsync(ContentDataCommand command, Func<string> message, bool enrich = false)
private async Task ValidateAsync((ISchemaEntity Schema, IAppEntity App) schemaAndApp, ContentDataCommand command, Func<string> message, bool partial)
{
Guard.Valid(command, nameof(command), message);
var taskForApp = appProvider.FindAppByIdAsync(command.AppId.Id);
var taskForSchema = schemas.FindSchemaByIdAsync(command.SchemaId.Id);
await Task.WhenAll(taskForApp, taskForSchema);
var schemaObject = taskForSchema.Result.Schema;
var schemaErrors = new List<ValidationError>();
var appId = command.AppId.Id;
@ -127,17 +179,34 @@ namespace Squidex.Domain.Apps.Write.Contents
return assetRepository.QueryNotFoundAsync(appId, assetIds.ToList());
});
await command.Data.ValidateAsync(validationContext, schemaObject, taskForApp.Result.PartitionResolver, schemaErrors);
if (partial)
{
await command.Data.ValidatePartialAsync(validationContext, schemaAndApp.Schema.Schema, schemaAndApp.App.PartitionResolver, schemaErrors);
}
else
{
await command.Data.ValidateAsync(validationContext, schemaAndApp.Schema.Schema, schemaAndApp.App.PartitionResolver, schemaErrors);
}
if (schemaErrors.Count > 0)
{
throw new ValidationException(message(), schemaErrors);
}
}
if (enrich)
{
command.Data.Enrich(schemaObject, taskForApp.Result.PartitionResolver);
}
private static ScriptContext CreateScriptContext(ContentDomainObject content, ContentCommand command, NamedContentData data = null)
{
return new ScriptContext { ContentId = content.Id, Data = data, OldData = content.Data, User = ScriptUser.Create(command.Principal) };
}
private async Task<(ISchemaEntity Schema, IAppEntity App)> ResolveSchemaAndAppAsync(SchemaCommand command)
{
var taskForApp = appProvider.FindAppByIdAsync(command.AppId.Id);
var taskForSchema = schemas.FindSchemaByIdAsync(command.SchemaId.Id);
await Task.WhenAll(taskForApp, taskForSchema);
return (taskForSchema.Result, taskForApp.Result);
}
}
}

11
src/Squidex.Domain.Apps.Write/Contents/ContentDomainObject.cs

@ -35,6 +35,11 @@ namespace Squidex.Domain.Apps.Write.Contents
get { return isPublished; }
}
public NamedContentData Data
{
get { return data; }
}
public ContentDomainObject(Guid id, int version)
: base(id, version)
{
@ -122,7 +127,7 @@ namespace Squidex.Domain.Apps.Write.Contents
VerifyCreatedAndNotDeleted();
if (!command.Data.Equals(data))
if (!command.Data.Equals(Data))
{
RaiseEvent(SimpleMapper.Map(command, new ContentUpdated()));
}
@ -136,9 +141,9 @@ namespace Squidex.Domain.Apps.Write.Contents
VerifyCreatedAndNotDeleted();
var newData = data.MergeInto(command.Data);
var newData = Data.MergeInto(command.Data);
if (!newData.Equals(data))
if (!newData.Equals(Data))
{
RaiseEvent(SimpleMapper.Map(command, new ContentUpdated { Data = newData }));
}

25
src/Squidex.Domain.Apps.Write/Schemas/Commands/ConfigureScripts.cs

@ -0,0 +1,25 @@
// ==========================================================================
// ConfigureScripts.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
namespace Squidex.Domain.Apps.Write.Schemas.Commands
{
public sealed class ConfigureScripts : SchemaAggregateCommand
{
public string ScriptQuery { get; set; }
public string ScriptCreate { get; set; }
public string ScriptUpdate { get; set; }
public string ScriptDelete { get; set; }
public string ScriptPublish { get; set; }
public string ScriptUnpublish { get; set; }
}
}

5
src/Squidex.Domain.Apps.Write/Schemas/SchemaCommandMiddleware.cs

@ -120,6 +120,11 @@ namespace Squidex.Domain.Apps.Write.Schemas
return handler.UpdateAsync<SchemaDomainObject>(context, s => s.Unpublish(command));
}
protected Task On(ConfigureScripts command, CommandContext context)
{
return handler.UpdateAsync<SchemaDomainObject>(context, s => s.ConfigureScripts(command));
}
public async Task HandleAsync(CommandContext context, Func<Task> next)
{
if (!await this.DispatchActionAsync(context.Command, context))

11
src/Squidex.Domain.Apps.Write/Schemas/SchemaDomainObject.cs

@ -276,6 +276,17 @@ namespace Squidex.Domain.Apps.Write.Schemas
return this;
}
public SchemaDomainObject ConfigureScripts(ConfigureScripts command)
{
Guard.NotNull(command, nameof(command));
VerifyCreatedAndNotDeleted();
RaiseEvent(SimpleMapper.Map(command, new ScriptsConfigured()));
return this;
}
public SchemaDomainObject Delete(DeleteSchema command)
{
VerifyCreatedAndNotDeleted();

4
src/Squidex.Infrastructure/CQRS/Commands/AggregateHandler.cs

@ -87,9 +87,7 @@ namespace Squidex.Infrastructure.CQRS.Commands
private static IAggregateCommand GetCommand(CommandContext context)
{
var command = context.Command as IAggregateCommand;
if (command == null)
if (!(context.Command is IAggregateCommand command))
{
throw new ArgumentException("Context must have an aggregate command.", nameof(context));
}

54
tests/Squidex.Domain.Apps.Write.Tests/Contents/ContentCommandHandlerTests.cs

@ -12,6 +12,7 @@ using FakeItEasy;
using Squidex.Domain.Apps.Core;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Core.Scripting;
using Squidex.Domain.Apps.Read.Apps;
using Squidex.Domain.Apps.Read.Apps.Services;
using Squidex.Domain.Apps.Read.Assets.Repositories;
@ -34,8 +35,10 @@ namespace Squidex.Domain.Apps.Write.Contents
private readonly ContentDomainObject content;
private readonly ISchemaProvider schemaProvider = A.Fake<ISchemaProvider>();
private readonly ISchemaEntity schemaEntity = A.Fake<ISchemaEntity>();
private readonly IScriptEngine scriptEngine = A.Fake<IScriptEngine>();
private readonly IAppProvider appProvider = A.Fake<IAppProvider>();
private readonly IAppEntity appEntity = A.Fake<IAppEntity>();
private readonly NamedContentData invalidData = new NamedContentData().AddField("my-field", new ContentFieldData().SetValue(null));
private readonly NamedContentData data = new NamedContentData().AddField("my-field", new ContentFieldData().SetValue(1));
private readonly LanguagesConfig languagesConfig = LanguagesConfig.Create(Language.DE);
private readonly Guid contentId = Guid.NewGuid();
@ -49,7 +52,7 @@ namespace Squidex.Domain.Apps.Write.Contents
content = new ContentDomainObject(contentId, -1);
sut = new ContentCommandMiddleware(Handler, appProvider, A.Dummy<IAssetRepository>(), schemaProvider, A.Dummy<IContentRepository>());
sut = new ContentCommandMiddleware(Handler, appProvider, A.Dummy<IAssetRepository>(), schemaProvider, scriptEngine, A.Dummy<IContentRepository>());
A.CallTo(() => appEntity.LanguagesConfig).Returns(languagesConfig);
A.CallTo(() => appEntity.PartitionResolver).Returns(languagesConfig.ToResolver());
@ -62,7 +65,9 @@ namespace Squidex.Domain.Apps.Write.Contents
[Fact]
public async Task Create_should_throw_exception_if_data_is_not_valid()
{
var context = CreateContextForCommand(new CreateContent { ContentId = contentId, Data = new NamedContentData() });
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored, A<string>.Ignored, true)).Returns(invalidData);
var context = CreateContextForCommand(new CreateContent { ContentId = contentId, Data = invalidData });
await TestCreate(content, async _ =>
{
@ -73,6 +78,9 @@ namespace Squidex.Domain.Apps.Write.Contents
[Fact]
public async Task Create_should_create_content()
{
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored, A<string>.Ignored, true)).Returns(data);
A.CallTo(() => schemaEntity.ScriptCreate).Returns("<create-script>");
var context = CreateContextForCommand(new CreateContent { ContentId = contentId, Data = data });
await TestCreate(content, async _ =>
@ -81,14 +89,18 @@ namespace Squidex.Domain.Apps.Write.Contents
});
Assert.Equal(data, context.Result<EntityCreatedResult<NamedContentData>>().IdOrValue);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<create-script>", "create content", true)).MustHaveHappened();
}
[Fact]
public async Task Update_should_throw_exception_if_data_is_not_valid()
{
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored, A<string>.Ignored, true)).Returns(invalidData);
CreateContent();
var context = CreateContextForCommand(new UpdateContent { ContentId = contentId, Data = new NamedContentData() });
var context = CreateContextForCommand(new UpdateContent { ContentId = contentId, Data = invalidData });
await TestUpdate(content, async _ =>
{
@ -99,6 +111,9 @@ namespace Squidex.Domain.Apps.Write.Contents
[Fact]
public async Task Update_should_update_domain_object()
{
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored, A<string>.Ignored, true)).Returns(data);
A.CallTo(() => schemaEntity.ScriptUpdate).Returns("<update-script>");
CreateContent();
var context = CreateContextForCommand(new UpdateContent { ContentId = contentId, Data = data });
@ -107,14 +122,20 @@ namespace Squidex.Domain.Apps.Write.Contents
{
await sut.HandleAsync(context);
});
Assert.Equal(data, context.Result<ContentChangedResult>().Content);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<update-script>", "update content", true)).MustHaveHappened();
}
[Fact]
public async Task Patch_should_throw_exception_if_data_is_not_valid()
{
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored, A<string>.Ignored, true)).Returns(invalidData);
CreateContent();
var context = CreateContextForCommand(new PatchContent { ContentId = contentId, Data = new NamedContentData() });
var context = CreateContextForCommand(new PatchContent { ContentId = contentId, Data = invalidData });
await TestUpdate(content, async _ =>
{
@ -125,21 +146,32 @@ namespace Squidex.Domain.Apps.Write.Contents
[Fact]
public async Task Patch_should_update_domain_object()
{
var otherContent = new NamedContentData().AddField("my-field", new ContentFieldData().SetValue(3));
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored, A<string>.Ignored, true)).Returns(data);
A.CallTo(() => schemaEntity.ScriptUpdate).Returns("<update-script>");
var path = new NamedContentData().AddField("my-field", new ContentFieldData().SetValue(3));
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored, A<string>.Ignored, true)).Returns(path);
CreateContent();
var context = CreateContextForCommand(new PatchContent { ContentId = contentId, Data = otherContent });
var context = CreateContextForCommand(new PatchContent { ContentId = contentId, Data = path });
await TestUpdate(content, async _ =>
{
await sut.HandleAsync(context);
});
Assert.NotNull(context.Result<ContentChangedResult>().Content);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<update-script>", "patch content", true)).MustHaveHappened();
}
[Fact]
public async Task Publish_should_publish_domain_object()
{
A.CallTo(() => schemaEntity.ScriptPublish).Returns("<publish-script>");
CreateContent();
var context = CreateContextForCommand(new PublishContent { ContentId = contentId });
@ -148,11 +180,15 @@ namespace Squidex.Domain.Apps.Write.Contents
{
await sut.HandleAsync(context);
});
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<publish-script>", "publish content")).MustHaveHappened();
}
[Fact]
public async Task Unpublish_should_unpublish_domain_object()
{
A.CallTo(() => schemaEntity.ScriptUnpublish).Returns("<unpublish-script>");
CreateContent();
var context = CreateContextForCommand(new UnpublishContent { ContentId = contentId });
@ -161,11 +197,15 @@ namespace Squidex.Domain.Apps.Write.Contents
{
await sut.HandleAsync(context);
});
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<unpublish-script>", "unpublish content")).MustHaveHappened();
}
[Fact]
public async Task Delete_should_update_domain_object()
{
A.CallTo(() => schemaEntity.ScriptDelete).Returns("<delete-script>");
CreateContent();
var command = CreateContextForCommand(new DeleteContent { ContentId = contentId });
@ -174,6 +214,8 @@ namespace Squidex.Domain.Apps.Write.Contents
{
await sut.HandleAsync(command);
});
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<delete-script>", "delete content")).MustHaveHappened();
}
private void CreateContent()

13
tests/Squidex.Domain.Apps.Write.Tests/Schemas/SchemaCommandHandlerTests.cs

@ -125,6 +125,19 @@ namespace Squidex.Domain.Apps.Write.Schemas
});
}
[Fact]
public async Task ConfigureScripts_should_update_domain_object()
{
CreateSchema();
var context = CreateContextForCommand(new ConfigureScripts());
await TestUpdate(schema, async _ =>
{
await sut.HandleAsync(context);
});
}
[Fact]
public async Task DeleteSchema_should_update_domain_object()
{

50
tests/Squidex.Domain.Apps.Write.Tests/Schemas/SchemaDomainObjectTests.cs

@ -159,6 +159,56 @@ namespace Squidex.Domain.Apps.Write.Schemas
);
}
[Fact]
public void ConfigureScripts_should_throw_exception_if_not_created()
{
Assert.Throws<DomainException>(() =>
{
sut.ConfigureScripts(CreateCommand(new ConfigureScripts()));
});
}
[Fact]
public void ConfigureScripts_should_throw_exception_if_schema_is_deleted()
{
CreateSchema();
DeleteSchema();
Assert.Throws<DomainException>(() =>
{
sut.ConfigureScripts(CreateCommand(new ConfigureScripts()));
});
}
[Fact]
public void ConfigureScripts_should_create_events()
{
CreateSchema();
sut.ConfigureScripts(CreateCommand(new ConfigureScripts
{
ScriptCreate = "<create>",
ScriptUpdate = "<update>",
ScriptDelete = "<delete>",
ScriptPublish = "<publish>",
ScriptUnpublish = "<unpublish>",
ScriptQuery = "<query>",
}));
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new ScriptsConfigured
{
ScriptCreate = "<create>",
ScriptUpdate = "<update>",
ScriptDelete = "<delete>",
ScriptPublish = "<publish>",
ScriptUnpublish = "<unpublish>",
ScriptQuery = "<query>",
})
);
}
[Fact]
public void Reorder_should_throw_exception_if_not_created()
{

Loading…
Cancel
Save