Browse Source

Content tests.

pull/249/head
Sebastian Stehle 8 years ago
parent
commit
f3a3bedefb
  1. 24
      src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs
  2. 30
      tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs
  3. 264
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentCommandMiddlewareTests.cs
  4. 304
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentDomainObjectTests.cs
  5. 379
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs
  6. 224
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs
  7. 27
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs

24
src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs

@ -7,6 +7,8 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Orleans.Core;
using Orleans.Runtime;
using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.Scripting; using Squidex.Domain.Apps.Core.Scripting;
using Squidex.Domain.Apps.Entities.Assets.Repositories; using Squidex.Domain.Apps.Entities.Assets.Repositories;
@ -24,7 +26,7 @@ using Squidex.Infrastructure.States;
namespace Squidex.Domain.Apps.Entities.Contents namespace Squidex.Domain.Apps.Entities.Contents
{ {
public sealed class ContentGrain : DomainObjectGrain<ContentState>, IContentGrain public class ContentGrain : DomainObjectGrain<ContentState>, IContentGrain
{ {
private readonly IAppProvider appProvider; private readonly IAppProvider appProvider;
private readonly IAssetRepository assetRepository; private readonly IAssetRepository assetRepository;
@ -37,7 +39,19 @@ namespace Squidex.Domain.Apps.Entities.Contents
IAssetRepository assetRepository, IAssetRepository assetRepository,
IScriptEngine scriptEngine, IScriptEngine scriptEngine,
IContentRepository contentRepository) IContentRepository contentRepository)
: base(store) : this(store, appProvider, assetRepository, scriptEngine, contentRepository, null, null)
{
}
protected ContentGrain(
IStore<Guid> store,
IAppProvider appProvider,
IAssetRepository assetRepository,
IScriptEngine scriptEngine,
IContentRepository contentRepository,
IGrainIdentity identity,
IGrainRuntime runtime)
: base(store, identity, runtime)
{ {
Guard.NotNull(appProvider, nameof(appProvider)); Guard.NotNull(appProvider, nameof(appProvider));
Guard.NotNull(scriptEngine, nameof(scriptEngine)); Guard.NotNull(scriptEngine, nameof(scriptEngine));
@ -74,7 +88,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
Create(c); Create(c);
return EntityCreatedResult.Create(c.Data, Version); return EntityCreatedResult.Create(c.Data, NewVersion);
}); });
case UpdateContent updateContent: case UpdateContent updateContent:
@ -89,7 +103,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
Update(c); Update(c);
return new ContentDataChangedResult(Snapshot.Data, Version); return new ContentDataChangedResult(Snapshot.Data, NewVersion);
}); });
case PatchContent patchContent: case PatchContent patchContent:
@ -104,7 +118,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
Patch(c); Patch(c);
return new ContentDataChangedResult(Snapshot.Data, Version); return new ContentDataChangedResult(Snapshot.Data, NewVersion);
}); });
case ChangeContentStatus patchContent: case ChangeContentStatus patchContent:

30
tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs

@ -86,7 +86,8 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
{ {
Data = Data =
new NamedContentData() new NamedContentData()
.AddField("city", new ContentFieldData() .AddField("city",
new ContentFieldData()
.AddValue("iv", "Berlin")) .AddValue("iv", "Berlin"))
}; };
@ -102,7 +103,8 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
{ {
Data = Data =
new NamedContentData() new NamedContentData()
.AddField("city", new ContentFieldData() .AddField("city",
new ContentFieldData()
.AddValue("iv", "Berlin")) .AddValue("iv", "Berlin"))
}; };
@ -118,7 +120,8 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
{ {
Data = Data =
new NamedContentData() new NamedContentData()
.AddField("city", new ContentFieldData() .AddField("city",
new ContentFieldData()
.AddValue("iv", new JArray())) .AddValue("iv", new JArray()))
}; };
@ -134,7 +137,8 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
{ {
Data = Data =
new NamedContentData() new NamedContentData()
.AddField("city", new ContentFieldData() .AddField("city",
new ContentFieldData()
.AddValue("iv", new JObject( .AddValue("iv", new JObject(
new JProperty("name", "Berlin")))) new JProperty("name", "Berlin"))))
}; };
@ -151,7 +155,8 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
{ {
Data = Data =
new NamedContentData() new NamedContentData()
.AddField("city", new ContentFieldData() .AddField("city",
new ContentFieldData()
.AddValue("iv", "Berlin")) .AddValue("iv", "Berlin"))
}; };
@ -167,7 +172,8 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
{ {
Data = Data =
new NamedContentData() new NamedContentData()
.AddField("city", new ContentFieldData() .AddField("city",
new ContentFieldData()
.AddValue("iv", JValue.CreateNull())) .AddValue("iv", JValue.CreateNull()))
}; };
@ -183,7 +189,8 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
{ {
Data = Data =
new NamedContentData() new NamedContentData()
.AddField("city", new ContentFieldData() .AddField("city",
new ContentFieldData()
.AddValue("iv", JValue.CreateUndefined())) .AddValue("iv", JValue.CreateUndefined()))
}; };
@ -199,7 +206,8 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
{ {
Data = Data =
new NamedContentData() new NamedContentData()
.AddField("city", new ContentFieldData() .AddField("city",
new ContentFieldData()
.AddValue("iv", new JObject( .AddValue("iv", new JObject(
new JProperty("name", "Berlin")))) new JProperty("name", "Berlin"))))
}; };
@ -216,7 +224,8 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
{ {
Data = Data =
new NamedContentData() new NamedContentData()
.AddField("city", new ContentFieldData() .AddField("city",
new ContentFieldData()
.AddValue("iv", new JArray( .AddValue("iv", new JArray(
"Berlin"))) "Berlin")))
}; };
@ -233,7 +242,8 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
{ {
Data = Data =
new NamedContentData() new NamedContentData()
.AddField("city", new ContentFieldData() .AddField("city",
new ContentFieldData()
.AddValue("iv", new JObject( .AddValue("iv", new JObject(
new JProperty("name", "Berlin")))) new JProperty("name", "Berlin"))))
}; };

264
tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentCommandMiddlewareTests.cs

@ -1,264 +0,0 @@
//// ==========================================================================
//// Squidex Headless CMS
//// ==========================================================================
//// Copyright (c) Squidex UG (haftungsbeschränkt)
//// All rights reserved. Licensed under the MIT license.
//// ==========================================================================
//using System;
//using System.Security.Claims;
//using System.Threading.Tasks;
//using FakeItEasy;
//using NodaTime;
//using Squidex.Domain.Apps.Core;
//using Squidex.Domain.Apps.Core.Apps;
//using Squidex.Domain.Apps.Core.Contents;
//using Squidex.Domain.Apps.Core.Schemas;
//using Squidex.Domain.Apps.Core.Scripting;
//using Squidex.Domain.Apps.Entities.Apps;
//using Squidex.Domain.Apps.Entities.Assets.Repositories;
//using Squidex.Domain.Apps.Entities.Contents.Commands;
//using Squidex.Domain.Apps.Entities.Contents.Repositories;
//using Squidex.Domain.Apps.Entities.Schemas;
//using Squidex.Domain.Apps.Entities.TestHelpers;
//using Squidex.Infrastructure;
//using Squidex.Infrastructure.Commands;
//using Xunit;
//namespace Squidex.Domain.Apps.Entities.Contents
//{
// public class ContentCommandMiddlewareTests : HandlerTestBase<ContentDomainObject>
// {
// private readonly ISchemaEntity schema = A.Fake<ISchemaEntity>();
// private readonly IScriptEngine scriptEngine = A.Fake<IScriptEngine>();
// private readonly IAppProvider appProvider = A.Fake<IAppProvider>();
// private readonly IAppEntity app = A.Fake<IAppEntity>();
// private readonly ClaimsPrincipal user = new ClaimsPrincipal();
// private readonly LanguagesConfig languagesConfig = LanguagesConfig.Build(Language.DE);
// private readonly Guid contentId = Guid.NewGuid();
// private readonly ContentDomainObject content = new ContentDomainObject();
// private readonly ContentCommandMiddleware sut;
// protected override Guid Id
// {
// get { return contentId; }
// }
// private readonly NamedContentData invalidData =
// new NamedContentData()
// .AddField("my-field1", new ContentFieldData()
// .AddValue(null))
// .AddField("my-field2", new ContentFieldData()
// .AddValue(1));
// private readonly NamedContentData data =
// new NamedContentData()
// .AddField("my-field1", new ContentFieldData()
// .AddValue(1))
// .AddField("my-field2", new ContentFieldData()
// .AddValue(1));
// private readonly NamedContentData patch =
// new NamedContentData()
// .AddField("my-field1", new ContentFieldData()
// .AddValue(1));
// public ContentCommandMiddlewareTests()
// {
// var schemaDef =
// new Schema("my-schema")
// .AddField(new NumberField(1, "my-field1", Partitioning.Invariant,
// new NumberFieldProperties { IsRequired = true }))
// .AddField(new NumberField(2, "my-field2", Partitioning.Invariant,
// new NumberFieldProperties { IsRequired = false }));
// sut = new ContentCommandMiddleware(Handler, appProvider, A.Dummy<IAssetRepository>(), scriptEngine, A.Dummy<IContentRepository>());
// A.CallTo(() => app.LanguagesConfig).Returns(languagesConfig);
// A.CallTo(() => appProvider.GetAppAsync(AppName)).Returns(app);
// A.CallTo(() => schema.SchemaDef).Returns(schemaDef);
// A.CallTo(() => schema.ScriptCreate).Returns("<create-script>");
// A.CallTo(() => schema.ScriptChange).Returns("<change-script>");
// A.CallTo(() => schema.ScriptUpdate).Returns("<update-script>");
// A.CallTo(() => schema.ScriptDelete).Returns("<delete-script>");
// A.CallTo(() => appProvider.GetAppWithSchemaAsync(AppId, SchemaId)).Returns((app, schema));
// }
// [Fact]
// public async Task Create_should_throw_exception_if_data_is_not_valid()
// {
// A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored))
// .Returns(invalidData);
// var context = CreateContextForCommand(new CreateContent { ContentId = contentId, Data = invalidData, User = user });
// await TestCreate(content, async _ =>
// {
// await Assert.ThrowsAsync<ValidationException>(() => sut.HandleAsync(context));
// }, false);
// }
// [Fact]
// public async Task Create_should_create_content()
// {
// A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored))
// .Returns(data);
// var context = CreateContextForCommand(new CreateContent { ContentId = contentId, Data = data, User = user });
// await TestCreate(content, async _ =>
// {
// await sut.HandleAsync(context);
// });
// Assert.Equal(data, context.Result<EntityCreatedResult<NamedContentData>>().IdOrValue);
// A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<create-script>")).MustHaveHappened();
// A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<change-script>")).MustNotHaveHappened();
// }
// [Fact]
// public async Task Create_should_also_invoke_publish_script_when_publishing()
// {
// A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored))
// .Returns(data);
// var context = CreateContextForCommand(new CreateContent { ContentId = contentId, Data = data, User = user, Publish = true });
// await TestCreate(content, async _ =>
// {
// await sut.HandleAsync(context);
// });
// Assert.Equal(data, context.Result<EntityCreatedResult<NamedContentData>>().IdOrValue);
// A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<create-script>")).MustHaveHappened();
// A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<change-script>")).MustHaveHappened();
// }
// [Fact]
// public async Task Update_should_throw_exception_if_data_is_not_valid()
// {
// A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored))
// .Returns(invalidData);
// CreateContent();
// var context = CreateContextForCommand(new UpdateContent { ContentId = contentId, Data = invalidData, User = user });
// await TestUpdate(content, async _ =>
// {
// await Assert.ThrowsAsync<ValidationException>(() => sut.HandleAsync(context));
// }, false);
// }
// [Fact]
// public async Task Update_should_update_domain_object()
// {
// A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored))
// .Returns(data);
// CreateContent();
// var context = CreateContextForCommand(new UpdateContent { ContentId = contentId, Data = data, User = user });
// await TestUpdate(content, async _ =>
// {
// await sut.HandleAsync(context);
// });
// Assert.Equal(data, context.Result<ContentDataChangedResult>().Data);
// A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<update-script>")).MustHaveHappened();
// }
// [Fact]
// public async Task Patch_should_throw_exception_if_data_is_not_valid()
// {
// A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored))
// .Returns(invalidData);
// CreateContent();
// var context = CreateContextForCommand(new PatchContent { ContentId = contentId, Data = invalidData, User = user });
// await TestUpdate(content, async _ =>
// {
// await Assert.ThrowsAsync<ValidationException>(() => sut.HandleAsync(context));
// }, false);
// }
// [Fact]
// public async Task Patch_should_update_domain_object()
// {
// A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored))
// .Returns(data);
// A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored)).Returns(patch);
// CreateContent();
// var context = CreateContextForCommand(new PatchContent { ContentId = contentId, Data = patch, User = user });
// await TestUpdate(content, async _ =>
// {
// await sut.HandleAsync(context);
// });
// Assert.NotNull(context.Result<ContentDataChangedResult>().Data);
// A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<update-script>")).MustHaveHappened();
// }
// [Fact]
// public async Task ChangeStatus_should_publish_domain_object()
// {
// CreateContent();
// var context = CreateContextForCommand(new ChangeContentStatus { ContentId = contentId, User = user, Status = Status.Published });
// await TestUpdate(content, async _ =>
// {
// await sut.HandleAsync(context);
// });
// A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<change-script>")).MustHaveHappened();
// }
// [Fact]
// public async Task ChangeStatus_should_not_invoke_scripts_when_scheduled()
// {
// CreateContent();
// var context = CreateContextForCommand(new ChangeContentStatus { ContentId = contentId, User = user, Status = Status.Published, DueTime = Instant.MaxValue });
// await TestUpdate(content, async _ =>
// {
// await sut.HandleAsync(context);
// });
// A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<change-script>")).MustNotHaveHappened();
// }
// [Fact]
// public async Task Delete_should_update_domain_object()
// {
// CreateContent();
// var command = CreateContextForCommand(new DeleteContent { ContentId = contentId, User = user });
// await TestUpdate(content, async _ =>
// {
// await sut.HandleAsync(command);
// });
// A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<delete-script>")).MustHaveHappened();
// }
// private void CreateContent()
// {
// content.Create(CreateCommand(new CreateContent { Data = data }));
// }
// }
//}

304
tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentDomainObjectTests.cs

@ -1,304 +0,0 @@
//// ==========================================================================
//// Squidex Headless CMS
//// ==========================================================================
//// Copyright (c) Squidex UG (haftungsbeschränkt)
//// All rights reserved. Licensed under the MIT license.
//// ==========================================================================
//using System;
//using FakeItEasy;
//using FluentAssertions;
//using NodaTime;
//using Squidex.Domain.Apps.Core.Contents;
//using Squidex.Domain.Apps.Entities.Contents.Commands;
//using Squidex.Domain.Apps.Entities.TestHelpers;
//using Squidex.Domain.Apps.Events.Contents;
//using Squidex.Infrastructure;
//using Squidex.Infrastructure.States;
//using Xunit;
//namespace Squidex.Domain.Apps.Entities.Contents
//{
// public class ContentDomainObjectTests : HandlerTestBase<ContentDomainObject>
// {
// private readonly NamedContentData data =
// new NamedContentData()
// .AddField("field1",
// new ContentFieldData()
// .AddValue("iv", 1));
// private readonly NamedContentData otherData =
// new NamedContentData()
// .AddField("field2",
// new ContentFieldData()
// .AddValue("iv", 2));
// private readonly NamedContentData patched;
// private readonly Guid contentId = Guid.NewGuid();
// private readonly ContentDomainObject sut = new ContentDomainObject();
// protected override Guid Id
// {
// get { return contentId; }
// }
// public ContentDomainObjectTests()
// {
// patched = otherData.MergeInto(data);
// sut.ActivateAsync(Id, A.Fake<IStore<Guid>>());
// }
// [Fact]
// public void Create_should_throw_exception_if_created()
// {
// sut.Create(CreateCommand(new CreateContent { Data = data }));
// Assert.Throws<DomainException>(() =>
// {
// sut.Create(CreateContentCommand(new CreateContent { Data = data }));
// });
// }
// [Fact]
// public void Create_should_create_events()
// {
// sut.Create(CreateContentCommand(new CreateContent { Data = data }));
// sut.GetUncomittedEvents()
// .ShouldHaveSameEvents(
// CreateContentEvent(new ContentCreated { Data = data })
// );
// }
// [Fact]
// public void Create_should_also_publish_if_set_to_true()
// {
// sut.Create(CreateContentCommand(new CreateContent { Data = data, Publish = true }));
// sut.GetUncomittedEvents()
// .ShouldHaveSameEvents(
// CreateContentEvent(new ContentCreated { Data = data }),
// CreateContentEvent(new ContentStatusChanged { Status = Status.Published })
// );
// }
// [Fact]
// public void Update_should_throw_exception_if_not_created()
// {
// Assert.Throws<DomainException>(() =>
// {
// sut.Update(CreateContentCommand(new UpdateContent { Data = data }));
// });
// }
// [Fact]
// public void Update_should_throw_exception_if_content_is_deleted()
// {
// CreateContent();
// DeleteContent();
// Assert.Throws<DomainException>(() =>
// {
// sut.Update(CreateContentCommand(new UpdateContent()));
// });
// }
// [Fact]
// public void Update_should_create_events()
// {
// CreateContent();
// sut.Update(CreateContentCommand(new UpdateContent { Data = otherData }));
// sut.GetUncomittedEvents()
// .ShouldHaveSameEvents(
// CreateContentEvent(new ContentUpdated { Data = otherData })
// );
// }
// [Fact]
// public void Update_should_not_create_event_for_same_data()
// {
// CreateContent();
// UpdateContent();
// sut.Update(CreateContentCommand(new UpdateContent { Data = data }));
// sut.GetUncomittedEvents().Should().BeEmpty();
// }
// [Fact]
// public void Patch_should_throw_exception_if_not_created()
// {
// Assert.Throws<DomainException>(() =>
// {
// sut.Patch(CreateContentCommand(new PatchContent { Data = data }));
// });
// }
// [Fact]
// public void Patch_should_throw_exception_if_content_is_deleted()
// {
// CreateContent();
// DeleteContent();
// Assert.Throws<DomainException>(() =>
// {
// sut.Patch(CreateContentCommand(new PatchContent()));
// });
// }
// [Fact]
// public void Patch_should_create_events()
// {
// CreateContent();
// UpdateContent();
// sut.Patch(CreateContentCommand(new PatchContent { Data = otherData }));
// sut.GetUncomittedEvents()
// .ShouldHaveSameEvents(
// CreateContentEvent(new ContentUpdated { Data = patched })
// );
// }
// [Fact]
// public void Patch_should_not_create_event_for_same_data()
// {
// CreateContent();
// UpdateContent();
// sut.Patch(CreateContentCommand(new PatchContent { Data = data }));
// sut.GetUncomittedEvents().Should().BeEmpty();
// }
// [Fact]
// public void ChangeStatus_should_throw_exception_if_not_created()
// {
// Assert.Throws<DomainException>(() =>
// {
// sut.ChangeStatus(CreateContentCommand(new ChangeContentStatus()));
// });
// }
// [Fact]
// public void ChangeStatus_should_throw_exception_if_content_is_deleted()
// {
// CreateContent();
// DeleteContent();
// Assert.Throws<DomainException>(() =>
// {
// sut.ChangeStatus(CreateContentCommand(new ChangeContentStatus()));
// });
// }
// [Fact]
// public void ChangeStatus_should_refresh_properties_and_create_events()
// {
// CreateContent();
// sut.ChangeStatus(CreateContentCommand(new ChangeContentStatus { Status = Status.Published }));
// Assert.Equal(Status.Published, sut.Snapshot.Status);
// sut.GetUncomittedEvents()
// .ShouldHaveSameEvents(
// CreateContentEvent(new ContentStatusChanged { Status = Status.Published })
// );
// }
// [Fact]
// public void ChangeStatus_should_refresh_properties_and_create_scheduled_events_when_command_has_due_time()
// {
// CreateContent();
// var dueTime = Instant.MaxValue;
// sut.ChangeStatus(CreateContentCommand(new ChangeContentStatus { Status = Status.Published, DueTime = dueTime }));
// Assert.Equal(Status.Draft, sut.Snapshot.Status);
// Assert.Equal(Status.Published, sut.Snapshot.ScheduledTo);
// Assert.Equal(dueTime, sut.Snapshot.ScheduledAt);
// sut.GetUncomittedEvents()
// .ShouldHaveSameEvents(
// CreateContentEvent(new ContentStatusScheduled { Status = Status.Published, DueTime = dueTime })
// );
// }
// [Fact]
// public void Delete_should_throw_exception_if_not_created()
// {
// Assert.Throws<DomainException>(() =>
// {
// sut.Delete(CreateContentCommand(new DeleteContent()));
// });
// }
// [Fact]
// public void Delete_should_throw_exception_if_already_deleted()
// {
// CreateContent();
// DeleteContent();
// Assert.Throws<DomainException>(() =>
// {
// sut.Delete(CreateContentCommand(new DeleteContent()));
// });
// }
// [Fact]
// public void Delete_should_update_properties_and_create_events()
// {
// CreateContent();
// sut.Delete(CreateContentCommand(new DeleteContent()));
// Assert.True(sut.Snapshot.IsDeleted);
// sut.GetUncomittedEvents()
// .ShouldHaveSameEvents(
// CreateContentEvent(new ContentDeleted())
// );
// }
// private void CreateContent()
// {
// sut.Create(CreateContentCommand(new CreateContent { Data = data }));
// sut.ClearUncommittedEvents();
// }
// private void UpdateContent()
// {
// sut.Update(CreateContentCommand(new UpdateContent { Data = data }));
// sut.ClearUncommittedEvents();
// }
// private void ChangeStatus(Status status)
// {
// sut.ChangeStatus(CreateContentCommand(new ChangeContentStatus { Status = status }));
// sut.ClearUncommittedEvents();
// }
// private void DeleteContent()
// {
// sut.Delete(CreateContentCommand(new DeleteContent()));
// sut.ClearUncommittedEvents();
// }
// protected T CreateContentEvent<T>(T @event) where T : ContentEvent
// {
// @event.ContentId = contentId;
// return CreateEvent(@event);
// }
// protected T CreateContentCommand<T>(T command) where T : ContentCommand
// {
// command.ContentId = contentId;
// return CreateCommand(command);
// }
// }
//}

379
tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs

@ -0,0 +1,379 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Security.Claims;
using System.Threading.Tasks;
using FakeItEasy;
using NodaTime;
using Orleans.Core;
using Orleans.Runtime;
using Squidex.Domain.Apps.Core;
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Core.Scripting;
using Squidex.Domain.Apps.Entities.Apps;
using Squidex.Domain.Apps.Entities.Assets.Repositories;
using Squidex.Domain.Apps.Entities.Contents.Commands;
using Squidex.Domain.Apps.Entities.Contents.Repositories;
using Squidex.Domain.Apps.Entities.Contents.State;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Domain.Apps.Entities.TestHelpers;
using Squidex.Domain.Apps.Events.Contents;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Commands;
using Squidex.Infrastructure.States;
using Xunit;
namespace Squidex.Domain.Apps.Entities.Contents
{
public class ContentDomainObjectTests : HandlerTestBase<ContentGrain, ContentState>
{
private readonly ISchemaEntity schema = A.Fake<ISchemaEntity>();
private readonly IScriptEngine scriptEngine = A.Fake<IScriptEngine>();
private readonly IAppProvider appProvider = A.Fake<IAppProvider>();
private readonly IAppEntity app = A.Fake<IAppEntity>();
private readonly ClaimsPrincipal user = new ClaimsPrincipal();
private readonly LanguagesConfig languagesConfig = LanguagesConfig.Build(Language.DE);
private readonly NamedContentData invalidData =
new NamedContentData()
.AddField("my-field1",
new ContentFieldData()
.AddValue(null))
.AddField("my-field2",
new ContentFieldData()
.AddValue(1));
private readonly NamedContentData data =
new NamedContentData()
.AddField("my-field1",
new ContentFieldData()
.AddValue("iv", 1));
private readonly NamedContentData patch =
new NamedContentData()
.AddField("my-field2",
new ContentFieldData()
.AddValue("iv", 2));
private readonly NamedContentData otherData =
new NamedContentData()
.AddField("my-field1",
new ContentFieldData()
.AddValue("iv", 2))
.AddField("my-field2",
new ContentFieldData()
.AddValue("iv", 2));
private readonly NamedContentData patched;
private readonly Guid contentId = Guid.NewGuid();
private readonly ContentGrain sut;
public class MyContentGrain : ContentGrain
{
public MyContentGrain(
IStore<Guid> store,
IAppProvider appProvider,
IAssetRepository assetRepository,
IScriptEngine scriptEngine,
IContentRepository contentRepository,
IGrainIdentity identity,
IGrainRuntime runtime)
: base(store, appProvider, assetRepository, scriptEngine, contentRepository, identity, runtime)
{
}
}
protected override Guid Id
{
get { return contentId; }
}
public ContentDomainObjectTests()
{
var schemaDef =
new Schema("my-schema")
.AddField(new NumberField(1, "my-field1", Partitioning.Invariant,
new NumberFieldProperties { IsRequired = true }))
.AddField(new NumberField(2, "my-field2", Partitioning.Invariant,
new NumberFieldProperties { IsRequired = false }));
A.CallTo(() => app.LanguagesConfig).Returns(languagesConfig);
A.CallTo(() => appProvider.GetAppAsync(AppName)).Returns(app);
A.CallTo(() => appProvider.GetAppWithSchemaAsync(AppId, SchemaId)).Returns((app, schema));
A.CallTo(() => schema.SchemaDef).Returns(schemaDef);
A.CallTo(() => schema.ScriptCreate).Returns("<create-script>");
A.CallTo(() => schema.ScriptChange).Returns("<change-script>");
A.CallTo(() => schema.ScriptUpdate).Returns("<update-script>");
A.CallTo(() => schema.ScriptDelete).Returns("<delete-script>");
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.That.Matches(x => ReferenceEquals(x.Data, data)), A<string>.Ignored))
.Returns(data);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.That.Matches(x => ReferenceEquals(x.Data, invalidData)), A<string>.Ignored))
.Returns(invalidData);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.That.Matches(x => ReferenceEquals(x.Data, patch)), A<string>.Ignored))
.Returns(patch);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.That.Matches(x => ReferenceEquals(x.Data, otherData)), A<string>.Ignored))
.Returns(otherData);
patched = patch.MergeInto(data);
sut = new MyContentGrain(Store, appProvider, A.Dummy<IAssetRepository>(), scriptEngine, A.Dummy<IContentRepository>(), Identity, Runtime);
sut.OnActivateAsync();
}
[Fact]
public async Task Command_should_throw_exception_if_content_is_deleted()
{
await ExecuteCreateAsync();
await ExecuteDeleteAsync();
await Assert.ThrowsAsync<DomainException>(ExecuteUpdateAsync);
}
[Fact]
public async Task Create_should_create_events_and_update_state()
{
var command = new CreateContent { Data = data };
var result = await sut.ExecuteAsync(J(CreateContentCommand(command)));
result.ShouldBeEquivalent(EntityCreatedResult.Create(data, 0));
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentCreated { Data = data })
);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<create-script>"))
.MustHaveHappened();
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<change-script>"))
.MustNotHaveHappened();
}
[Fact]
public async Task Create_should_also_publish()
{
var command = new CreateContent { Data = data, Publish = true };
var result = await sut.ExecuteAsync(J(CreateContentCommand(command)));
result.ShouldBeEquivalent(EntityCreatedResult.Create(data, 1));
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentCreated { Data = data }),
CreateContentEvent(new ContentStatusChanged { Status = Status.Published })
);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<create-script>"))
.MustHaveHappened();
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<change-script>"))
.MustHaveHappened();
}
[Fact]
public async Task Create_should_throw_when_invalid_data_is_passed()
{
var command = new CreateContent { Data = invalidData };
await Assert.ThrowsAsync<ValidationException>(() => sut.ExecuteAsync(J(CreateContentCommand(command))));
}
[Fact]
public async Task Update_should_create_events_and_update_state()
{
var command = new UpdateContent { Data = otherData };
await ExecuteCreateAsync();
var result = await sut.ExecuteAsync(J(CreateContentCommand(command)));
result.ShouldBeEquivalent(new ContentDataChangedResult(otherData, 1));
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentUpdated { Data = otherData })
);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<update-script>"))
.MustHaveHappened();
}
[Fact]
public async Task Update_should_not_create_event_for_same_data()
{
var command = new UpdateContent { Data = data };
await ExecuteCreateAsync();
var result = await sut.ExecuteAsync(J(CreateContentCommand(command)));
result.ShouldBeEquivalent(new ContentDataChangedResult(data, 0));
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentCreated { Data = data })
);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<update-script>"))
.MustHaveHappened();
}
[Fact]
public async Task Update_should_throw_when_invalid_data_is_passed()
{
var command = new UpdateContent { Data = invalidData };
await ExecuteCreateAsync();
await Assert.ThrowsAsync<ValidationException>(() => sut.ExecuteAsync(J(CreateContentCommand(command))));
}
[Fact]
public async Task Patch_should_create_events_and_update_state()
{
var command = new PatchContent { Data = patch };
await ExecuteCreateAsync();
var result = await sut.ExecuteAsync(J(CreateContentCommand(command)));
result.ShouldBeEquivalent(new ContentDataChangedResult(otherData, 1));
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentUpdated { Data = patched })
);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<update-script>"))
.MustHaveHappened();
}
[Fact]
public async Task Patch_should_not_create_event_for_same_data()
{
var command = new PatchContent { Data = data };
await ExecuteCreateAsync();
var result = await sut.ExecuteAsync(J(CreateContentCommand(command)));
result.ShouldBeEquivalent(new ContentDataChangedResult(data, 0));
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentCreated { Data = data })
);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<update-script>"))
.MustHaveHappened();
}
[Fact]
public async Task ChangedStatus_should_create_events_and_update_state()
{
var command = new ChangeContentStatus { Status = Status.Published };
await ExecuteCreateAsync();
var result = await sut.ExecuteAsync(J(CreateContentCommand(command)));
result.ShouldBeEquivalent(new EntitySavedResult(1));
Assert.Equal(Status.Published, sut.Snapshot.Status);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentStatusChanged { Status = Status.Published })
);
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<change-script>"))
.MustHaveHappened();
}
[Fact]
public async Task ChangeStatus_should_refresh_properties_and_create_scheduled_events_when_command_has_due_time()
{
var dueTime = Instant.MaxValue;
var command = new ChangeContentStatus { Status = Status.Published, DueTime = dueTime };
await ExecuteCreateAsync();
var result = await sut.ExecuteAsync(J(CreateContentCommand(command)));
result.ShouldBeEquivalent(new EntitySavedResult(1));
Assert.Equal(Status.Draft, sut.Snapshot.Status);
Assert.Equal(Status.Published, sut.Snapshot.ScheduledTo);
Assert.Equal(dueTime, sut.Snapshot.ScheduledAt);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentStatusScheduled { Status = Status.Published, DueTime = dueTime })
);
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<change-script>"))
.MustNotHaveHappened();
}
[Fact]
public async Task Delete_should_update_properties_and_create_events()
{
var command = new DeleteContent();
await ExecuteCreateAsync();
var result = await sut.ExecuteAsync(J(CreateContentCommand(command)));
result.ShouldBeEquivalent(new EntitySavedResult(1));
Assert.True(sut.Snapshot.IsDeleted);
LastEvents
.ShouldHaveSameEvents(
CreateContentEvent(new ContentDeleted())
);
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<delete-script>"))
.MustHaveHappened();
}
private Task ExecuteCreateAsync()
{
return sut.ExecuteAsync(J(CreateContentCommand(new CreateContent { Data = data })));
}
private Task ExecuteUpdateAsync()
{
return sut.ExecuteAsync(J(CreateContentCommand(new UpdateContent { Data = data })));
}
private Task ExecuteDeleteAsync()
{
return sut.ExecuteAsync(J(CreateContentCommand(new DeleteContent())));
}
protected T CreateContentEvent<T>(T @event) where T : ContentEvent
{
@event.ContentId = contentId;
return CreateEvent(@event);
}
protected T CreateContentCommand<T>(T command) where T : ContentCommand
{
command.ContentId = contentId;
return CreateCommand(command);
}
}
}

224
tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs

@ -1,224 +0,0 @@
// ==========================================================================
// 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.Security.Claims;
using System.Threading.Tasks;
using FakeItEasy;
using Microsoft.OData.UriParser;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.Scripting;
using Squidex.Domain.Apps.Entities.Apps;
using Squidex.Domain.Apps.Entities.Contents.Edm;
using Squidex.Domain.Apps.Entities.Contents.Repositories;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Security;
using Xunit;
namespace Squidex.Domain.Apps.Entities.Contents
{
public class ContentQueryServiceTests
{
private readonly IContentRepository contentRepository = A.Fake<IContentRepository>();
private readonly IScriptEngine scriptEngine = A.Fake<IScriptEngine>();
private readonly ISchemaEntity schema = A.Fake<ISchemaEntity>();
private readonly IContentEntity content = A.Fake<IContentEntity>();
private readonly IAppEntity app = A.Fake<IAppEntity>();
private readonly IAppProvider appProvider = A.Fake<IAppProvider>();
private readonly Guid appId = Guid.NewGuid();
private readonly Guid schemaId = Guid.NewGuid();
private readonly Guid contentId = Guid.NewGuid();
private readonly string appName = "my-app";
private readonly NamedContentData contentData = new NamedContentData();
private readonly NamedContentData contentTransformed = new NamedContentData();
private readonly ClaimsPrincipal user;
private readonly ClaimsIdentity identity = new ClaimsIdentity();
private readonly EdmModelBuilder modelBuilder = A.Fake<EdmModelBuilder>();
private readonly ContentQueryService sut;
public ContentQueryServiceTests()
{
user = new ClaimsPrincipal(identity);
A.CallTo(() => app.Id).Returns(appId);
A.CallTo(() => app.Name).Returns(appName);
A.CallTo(() => content.Id).Returns(contentId);
A.CallTo(() => content.Data).Returns(contentData);
A.CallTo(() => content.Status).Returns(Status.Published);
sut = new ContentQueryService(contentRepository, appProvider, scriptEngine, modelBuilder);
}
[Fact]
public async Task Should_return_schema_from_id_if_string_is_guid()
{
A.CallTo(() => appProvider.GetSchemaAsync(appId, schemaId, false))
.Returns(schema);
var result = await sut.FindSchemaAsync(app, schemaId.ToString());
Assert.Equal(schema, result);
}
[Fact]
public async Task Should_return_schema_from_name_if_string_not_guid()
{
A.CallTo(() => appProvider.GetSchemaAsync(appId, "my-schema"))
.Returns(schema);
var result = await sut.FindSchemaAsync(app, "my-schema");
Assert.Equal(schema, result);
}
[Fact]
public async Task Should_throw_if_schema_not_found()
{
A.CallTo(() => appProvider.GetSchemaAsync(appId, "my-schema"))
.Returns((ISchemaEntity)null);
await Assert.ThrowsAsync<DomainObjectNotFoundException>(() => sut.FindSchemaAsync(app, "my-schema"));
}
[Fact]
public async Task Should_return_content_from_repository_and_transform()
{
A.CallTo(() => appProvider.GetSchemaAsync(appId, schemaId, false))
.Returns(schema);
A.CallTo(() => contentRepository.FindContentAsync(app, schema, contentId))
.Returns(content);
A.CallTo(() => schema.ScriptQuery)
.Returns("<script-query>");
A.CallTo(() => scriptEngine.Transform(A<ScriptContext>.That.Matches(x => x.User == user && x.ContentId == contentId && ReferenceEquals(x.Data, contentData)), "<query-script>"))
.Returns(contentTransformed);
var result = await sut.FindContentAsync(app, schemaId.ToString(), user, contentId);
Assert.Equal(schema, result.Schema);
Assert.Equal(contentTransformed, result.Content.Data);
Assert.Equal(content.Id, result.Content.Id);
}
[Fact]
public async Task Should_throw_if_content_to_find_does_not_exist()
{
A.CallTo(() => appProvider.GetSchemaAsync(appId, schemaId, false))
.Returns(schema);
A.CallTo(() => contentRepository.FindContentAsync(app, schema, contentId))
.Returns((IContentEntity)null);
await Assert.ThrowsAsync<DomainObjectNotFoundException>(async () => await sut.FindContentAsync(app, schemaId.ToString(), user, contentId));
}
[Fact]
public async Task Should_return_contents_with_ids_from_repository_and_transform()
{
await TestManyIdRequest(true, false, new HashSet<Guid> { Guid.NewGuid() }, Status.Draft, Status.Published);
}
[Fact]
public async Task Should_return_non_archived_contents_from_repository_and_transform()
{
await TestManyRequest(true, false, Status.Draft, Status.Published);
}
[Fact]
public async Task Should_return_archived_contents_from_repository_and_transform()
{
await TestManyRequest(true, true, Status.Archived);
}
[Fact]
public async Task Should_return_draft_contents_from_repository_and_transform()
{
await TestManyRequest(false, false, Status.Published);
}
[Fact]
public async Task Should_return_draft_contents_from_repository_and_transform_when_requesting_archive_as_non_frontend()
{
await TestManyRequest(false, true, Status.Published);
}
private async Task TestManyRequest(bool isFrontend, bool archive, params Status[] status)
{
SetupClaims(isFrontend);
SetupFakeWithOdataQuery(status);
SetupFakeWithScripting();
var result = await sut.QueryAsync(app, schemaId.ToString(), user, archive, string.Empty);
Assert.Equal(schema, result.Schema);
Assert.Equal(contentData, result.Contents[0].Data);
Assert.Equal(content.Id, result.Contents[0].Id);
Assert.Equal(123, result.Contents.Total);
}
private async Task TestManyIdRequest(bool isFrontend, bool archive, HashSet<Guid> ids, params Status[] status)
{
SetupClaims(isFrontend);
SetupFakeWithIdQuery(status, ids);
SetupFakeWithScripting();
var result = await sut.QueryAsync(app, schemaId.ToString(), user, archive, ids);
Assert.Equal(schema, result.Schema);
Assert.Equal(contentData, result.Contents[0].Data);
Assert.Equal(content.Id, result.Contents[0].Id);
Assert.Equal(123, result.Contents.Total);
}
private void SetupClaims(bool isFrontend)
{
if (isFrontend)
{
identity.AddClaim(new Claim(OpenIdClaims.ClientId, "squidex-frontend"));
}
}
private void SetupFakeWithIdQuery(Status[] status, HashSet<Guid> ids)
{
A.CallTo(() => appProvider.GetSchemaAsync(appId, schemaId, false))
.Returns(schema);
A.CallTo(() => contentRepository.QueryAsync(app, schema, A<Status[]>.That.IsSameSequenceAs(status), ids))
.Returns(ResultList.Create(Enumerable.Repeat(content, 1), 123));
}
private void SetupFakeWithOdataQuery(Status[] status)
{
A.CallTo(() => appProvider.GetSchemaAsync(appId, schemaId, false))
.Returns(schema);
A.CallTo(() => contentRepository.QueryAsync(app, schema, A<Status[]>.That.IsSameSequenceAs(status), A<ODataUriParser>.Ignored))
.Returns(ResultList.Create(Enumerable.Repeat(content, 1), 123));
}
private void SetupFakeWithScripting()
{
A.CallTo(() => schema.ScriptQuery)
.Returns("<script-query>");
A.CallTo(() => scriptEngine.Transform(A<ScriptContext>.That.Matches(x => x.User == user && x.ContentId == contentId && ReferenceEquals(x.Data, contentData)), "<query-script>"))
.Returns(contentTransformed);
}
}
}

27
tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs

@ -97,26 +97,35 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
data = data ?? data = data ??
new NamedContentData() new NamedContentData()
.AddField("my-string", .AddField("my-string",
new ContentFieldData().AddValue("de", "value")) new ContentFieldData()
.AddValue("de", "value"))
.AddField("my-assets", .AddField("my-assets",
new ContentFieldData().AddValue("iv", JToken.FromObject(new[] { assetId }))) new ContentFieldData()
.AddValue("iv", JToken.FromObject(new[] { assetId })))
.AddField("my-number", .AddField("my-number",
new ContentFieldData().AddValue("iv", 1)) new ContentFieldData()
.AddValue("iv", 1))
.AddField("my-boolean", .AddField("my-boolean",
new ContentFieldData().AddValue("iv", true)) new ContentFieldData()
.AddValue("iv", true))
.AddField("my-datetime", .AddField("my-datetime",
new ContentFieldData().AddValue("iv", now.ToDateTimeUtc())) new ContentFieldData()
.AddValue("iv", now.ToDateTimeUtc()))
.AddField("my-tags", .AddField("my-tags",
new ContentFieldData().AddValue("iv", JToken.FromObject(new[] { "tag1", "tag2" }))) new ContentFieldData()
.AddValue("iv", JToken.FromObject(new[] { "tag1", "tag2" })))
.AddField("my-references", .AddField("my-references",
new ContentFieldData().AddValue("iv", JToken.FromObject(new[] { refId }))) new ContentFieldData()
.AddValue("iv", JToken.FromObject(new[] { refId })))
.AddField("my-geolocation", .AddField("my-geolocation",
new ContentFieldData().AddValue("iv", JToken.FromObject(new { latitude = 10, longitude = 20 }))); new ContentFieldData()
.AddValue("iv", JToken.FromObject(new { latitude = 10, longitude = 20 })));
if (!noJson) if (!noJson)
{ {
data.AddField("my-json", data.AddField("my-json",
new ContentFieldData().AddValue("iv", JToken.FromObject(new { value = 1 }))); new ContentFieldData()
.AddValue("iv", JToken.FromObject(new { value = 1 })));
} }
var content = new ContentEntity var content = new ContentEntity

Loading…
Cancel
Save