// ========================================================================== // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex UG (haftungsbeschränkt) // All rights reserved. Licensed under the MIT license. // ========================================================================== using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using FakeItEasy; using Orleans.Core; using Orleans.Runtime; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Entities.Schemas.Commands; using Squidex.Domain.Apps.Entities.Schemas.State; using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Domain.Apps.Events.Schemas; using Squidex.Infrastructure; using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.States; using Xunit; namespace Squidex.Domain.Apps.Entities.Schemas { public class SchemaGrainTests : HandlerTestBase { private readonly IAppProvider appProvider = A.Fake(); private readonly FieldRegistry registry = new FieldRegistry(new TypeNameRegistry()); private readonly string fieldName = "age"; private readonly NamedId fieldId; private readonly SchemaGrain sut; public sealed class MySchemaGrain : SchemaGrain { public MySchemaGrain(IStore store, IAppProvider appProvider, FieldRegistry registry, IGrainIdentity identity, IGrainRuntime runtime) : base(store, appProvider, registry, identity, runtime) { } } protected override Guid Id { get { return SchemaId; } } public SchemaGrainTests() { A.CallTo(() => appProvider.GetSchemaAsync(AppId, SchemaName)) .Returns((ISchemaEntity)null); fieldId = new NamedId(1, fieldName); sut = new MySchemaGrain(Store, appProvider, registry, Identity, Runtime); sut.OnActivateAsync().Wait(); } [Fact] public async Task Command_should_throw_exception_if_rule_is_deleted() { await ExecuteCreateAsync(); await ExecuteDeleteAsync(); await Assert.ThrowsAsync(ExecutePublishAsync); } [Fact] public async Task Create_should_create_schema_and_create_events() { var properties = new SchemaProperties(); var command = new CreateSchema { Name = SchemaName, SchemaId = SchemaId, Properties = properties }; var result = await sut.ExecuteAsync(J(CreateCommand(command))); result.ShouldBeEquivalent(EntityCreatedResult.Create(Id, 0)); Assert.Equal(AppId, sut.Snapshot.AppId.Id); Assert.Equal(SchemaName, sut.Snapshot.Name); Assert.Equal(SchemaName, sut.Snapshot.SchemaDef.Name); LastEvents .ShouldHaveSameEvents( CreateEvent(new SchemaCreated { Name = SchemaName, Properties = properties }) ); } [Fact] public async Task Create_should_create_schema_with_initial_fields() { var properties = new SchemaProperties(); var fields = new List { new CreateSchemaField { Name = "field1", Properties = ValidProperties() }, new CreateSchemaField { Name = "field2", Properties = ValidProperties() } }; var command = new CreateSchema { Name = SchemaName, SchemaId = SchemaId, Properties = properties, Fields = fields }; var result = await sut.ExecuteAsync(J(CreateCommand(command))); result.ShouldBeEquivalent(EntityCreatedResult.Create(Id, 0)); var @event = (SchemaCreated)LastEvents.Single().Payload; Assert.Equal(AppId, sut.Snapshot.AppId.Id); Assert.Equal(SchemaName, sut.Snapshot.Name); Assert.Equal(SchemaName, sut.Snapshot.SchemaDef.Name); Assert.Equal(2, @event.Fields.Count); } [Fact] public async Task Update_should_create_events_and_update_state() { var command = new UpdateSchema { Properties = new SchemaProperties() }; await ExecuteCreateAsync(); var result = await sut.ExecuteAsync(J(CreateCommand(command))); result.ShouldBeEquivalent(new EntitySavedResult(1)); Assert.Equal(command.Properties, sut.Snapshot.SchemaDef.Properties); LastEvents .ShouldHaveSameEvents( CreateEvent(new SchemaUpdated { Properties = command.Properties }) ); } [Fact] public async Task ConfigureScripts_should_create_events() { var command = new ConfigureScripts { ScriptQuery = "", ScriptCreate = "", ScriptUpdate = "", ScriptDelete = "", ScriptChange = "" }; await ExecuteCreateAsync(); var result = await sut.ExecuteAsync(J(CreateCommand(command))); result.ShouldBeEquivalent(new EntitySavedResult(1)); LastEvents .ShouldHaveSameEvents( CreateEvent(new ScriptsConfigured { ScriptQuery = "", ScriptCreate = "", ScriptUpdate = "", ScriptDelete = "", ScriptChange = "" }) ); } [Fact] public async Task Reorder_should_create_events_and_update_state() { var command = new ReorderFields { FieldIds = new List { 1, 2 } }; await ExecuteCreateAsync(); await ExecuteAddFieldAsync("field1"); await ExecuteAddFieldAsync("field2"); var result = await sut.ExecuteAsync(J(CreateCommand(command))); result.ShouldBeEquivalent(new EntitySavedResult(3)); LastEvents .ShouldHaveSameEvents( CreateEvent(new SchemaFieldsReordered { FieldIds = command.FieldIds }) ); } [Fact] public async Task Publish_should_create_events_and_update_state() { var command = new PublishSchema(); await ExecuteCreateAsync(); var result = await sut.ExecuteAsync(J(CreateCommand(command))); result.ShouldBeEquivalent(new EntitySavedResult(1)); Assert.True(sut.Snapshot.SchemaDef.IsPublished); LastEvents .ShouldHaveSameEvents( CreateEvent(new SchemaPublished()) ); } [Fact] public async Task Unpublish_should_create_events_and_update_state() { var command = new UnpublishSchema(); await ExecuteCreateAsync(); await ExecutePublishAsync(); var result = await sut.ExecuteAsync(J(CreateCommand(command))); result.ShouldBeEquivalent(new EntitySavedResult(2)); Assert.False(sut.Snapshot.SchemaDef.IsPublished); LastEvents .ShouldHaveSameEvents( CreateEvent(new SchemaUnpublished()) ); } [Fact] public async Task Delete_should_create_events_and_update_state() { var command = new DeleteSchema(); await ExecuteCreateAsync(); var result = await sut.ExecuteAsync(J(CreateCommand(command))); result.ShouldBeEquivalent(new EntitySavedResult(1)); Assert.True(sut.Snapshot.IsDeleted); LastEvents .ShouldHaveSameEvents( CreateEvent(new SchemaDeleted()) ); } [Fact] public async Task Add_should_create_events_and_update_state() { var command = new AddField { Name = fieldName, Properties = ValidProperties() }; await ExecuteCreateAsync(); var result = await sut.ExecuteAsync(J(CreateCommand(command))); result.ShouldBeEquivalent(EntityCreatedResult.Create(1, 1)); Assert.Equal(command.Properties, sut.Snapshot.SchemaDef.FieldsById[1].RawProperties); LastEvents .ShouldHaveSameEvents( CreateEvent(new FieldAdded { Name = fieldName, FieldId = fieldId, Properties = command.Properties }) ); } [Fact] public async Task UpdateField_should_create_events_and_update_state() { var command = new UpdateField { FieldId = 1, Properties = new StringFieldProperties() }; await ExecuteCreateAsync(); await ExecuteAddFieldAsync(fieldName); var result = await sut.ExecuteAsync(J(CreateCommand(command))); result.ShouldBeEquivalent(new EntitySavedResult(2)); Assert.Equal(command.Properties, sut.Snapshot.SchemaDef.FieldsById[1].RawProperties); LastEvents .ShouldHaveSameEvents( CreateEvent(new FieldUpdated { FieldId = fieldId, Properties = command.Properties }) ); } [Fact] public async Task LockField_should_create_events_and_update_state() { var command = new LockField { FieldId = 1 }; await ExecuteCreateAsync(); await ExecuteAddFieldAsync(fieldName); var result = await sut.ExecuteAsync(J(CreateCommand(command))); result.ShouldBeEquivalent(new EntitySavedResult(2)); Assert.False(sut.Snapshot.SchemaDef.FieldsById[1].IsDisabled); LastEvents .ShouldHaveSameEvents( CreateEvent(new FieldLocked { FieldId = fieldId }) ); } [Fact] public async Task HideField_should_create_events_and_update_state() { var command = new HideField { FieldId = 1 }; await ExecuteCreateAsync(); await ExecuteAddFieldAsync(fieldName); var result = await sut.ExecuteAsync(J(CreateCommand(command))); result.ShouldBeEquivalent(new EntitySavedResult(2)); Assert.True(sut.Snapshot.SchemaDef.FieldsById[1].IsHidden); LastEvents .ShouldHaveSameEvents( CreateEvent(new FieldHidden { FieldId = fieldId }) ); } [Fact] public async Task ShowField_should_create_events_and_update_state() { var command = new ShowField { FieldId = 1 }; await ExecuteCreateAsync(); await ExecuteAddFieldAsync(fieldName); await ExecuteHideFieldAsync(1); var result = await sut.ExecuteAsync(J(CreateCommand(command))); result.ShouldBeEquivalent(new EntitySavedResult(3)); Assert.False(sut.Snapshot.SchemaDef.FieldsById[1].IsHidden); LastEvents .ShouldHaveSameEvents( CreateEvent(new FieldShown { FieldId = fieldId }) ); } [Fact] public async Task DisableField_should_create_events_and_update_state() { var command = new DisableField { FieldId = 1 }; await ExecuteCreateAsync(); await ExecuteAddFieldAsync(fieldName); var result = await sut.ExecuteAsync(J(CreateCommand(command))); result.ShouldBeEquivalent(new EntitySavedResult(2)); Assert.True(sut.Snapshot.SchemaDef.FieldsById[1].IsDisabled); LastEvents .ShouldHaveSameEvents( CreateEvent(new FieldDisabled { FieldId = fieldId }) ); } [Fact] public async Task EnableField_should_create_events_and_update_state() { var command = new EnableField { FieldId = 1 }; await ExecuteCreateAsync(); await ExecuteAddFieldAsync(fieldName); await ExecuteDisableFieldAsync(1); var result = await sut.ExecuteAsync(J(CreateCommand(command))); result.ShouldBeEquivalent(new EntitySavedResult(3)); Assert.False(sut.Snapshot.SchemaDef.FieldsById[1].IsDisabled); LastEvents .ShouldHaveSameEvents( CreateEvent(new FieldEnabled { FieldId = fieldId }) ); } [Fact] public async Task DeleteField_should_create_events_and_update_state() { var command = new DeleteField { FieldId = 1 }; await ExecuteCreateAsync(); await ExecuteAddFieldAsync(fieldName); var result = await sut.ExecuteAsync(J(CreateCommand(command))); result.ShouldBeEquivalent(new EntitySavedResult(2)); Assert.False(sut.Snapshot.SchemaDef.FieldsById.ContainsKey(1)); LastEvents .ShouldHaveSameEvents( CreateEvent(new FieldDeleted { FieldId = fieldId }) ); } private Task ExecuteCreateAsync() { return sut.ExecuteAsync(J(CreateCommand(new CreateSchema { Name = SchemaName }))); } private Task ExecuteAddFieldAsync(string name) { return sut.ExecuteAsync(J(CreateCommand(new AddField { Properties = ValidProperties(), Name = name }))); } private Task ExecuteHideFieldAsync(long id) { return sut.ExecuteAsync(J(CreateCommand(new HideField { FieldId = id }))); } private Task ExecuteDisableFieldAsync(long id) { return sut.ExecuteAsync(J(CreateCommand(new DisableField { FieldId = id }))); } private Task ExecutePublishAsync() { return sut.ExecuteAsync(J(CreateCommand(new PublishSchema()))); } private Task ExecuteDeleteAsync() { return sut.ExecuteAsync(J(CreateCommand(new DeleteSchema()))); } private static StringFieldProperties ValidProperties() { return new StringFieldProperties { MinLength = 10, MaxLength = 20 }; } } }