mirror of https://github.com/Squidex/squidex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
4.9 KiB
146 lines
4.9 KiB
// ==========================================================================
|
|
// Squidex Headless CMS
|
|
// ==========================================================================
|
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|
// All rights reserved. Licensed under the MIT license.
|
|
// ==========================================================================
|
|
|
|
using Squidex.Domain.Apps.Events;
|
|
using Squidex.Domain.Apps.Events.Teams;
|
|
using Squidex.Infrastructure;
|
|
using Squidex.Infrastructure.Commands;
|
|
using Squidex.Infrastructure.EventSourcing;
|
|
using Squidex.Infrastructure.States;
|
|
|
|
namespace Squidex.Domain.Apps.Entities.TestHelpers;
|
|
|
|
public abstract class HandlerTestBase<TState> : GivenContext
|
|
{
|
|
private readonly IPersistenceFactory<TState> persistenceFactory = A.Fake<IStore<TState>>();
|
|
private readonly IPersistence<TState> persistence = A.Fake<IPersistence<TState>>();
|
|
|
|
protected abstract DomainId Id { get; }
|
|
|
|
public IPersistenceFactory<TState> PersistenceFactory
|
|
{
|
|
get => persistenceFactory;
|
|
}
|
|
|
|
public IEnumerable<Envelope<IEvent>> LastEvents { get; private set; } = [];
|
|
|
|
protected HandlerTestBase()
|
|
{
|
|
#pragma warning disable MA0056 // Do not call overridable members in constructor
|
|
A.CallTo(() => persistenceFactory.WithSnapshotsAndEventSourcing(A<Type>._, Id, A<HandleSnapshot<TState>>._, A<HandleEvent>._))
|
|
.Returns(persistence);
|
|
|
|
A.CallTo(() => persistenceFactory.WithEventSourcing(A<Type>._, Id, A<HandleEvent>._))
|
|
.Returns(persistence);
|
|
|
|
A.CallTo(() => persistence.WriteEventsAsync(A<IReadOnlyList<Envelope<IEvent>>>._, CancellationToken))
|
|
.Invokes((IReadOnlyList<Envelope<IEvent>> events, CancellationToken _) => LastEvents = events);
|
|
|
|
A.CallTo(() => persistence.DeleteAsync(CancellationToken))
|
|
.Invokes(() => LastEvents = []);
|
|
#pragma warning restore MA0056 // Do not call overridable members in constructor
|
|
}
|
|
|
|
protected CommandContext CreateCommandContext<TCommand>(TCommand command) where TCommand : IAggregateCommand
|
|
{
|
|
return new CommandContext(CreateCommand(command), A.Dummy<ICommandBus>());
|
|
}
|
|
|
|
protected async Task<CommandContext> HandleAsync<TCommand>(ICommandMiddleware middleware, TCommand command,
|
|
CancellationToken ct = default) where TCommand : IAggregateCommand
|
|
{
|
|
var context = new CommandContext(CreateCommand(command), A.Dummy<ICommandBus>());
|
|
|
|
await middleware.HandleAsync(context, ct);
|
|
|
|
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()
|
|
{
|
|
LastEvents = [];
|
|
|
|
var actual = await ExecuteCoreAsync(domainObject, command);
|
|
|
|
var previousSnapshot = domainObject.Snapshot;
|
|
var previousVersion = domainObject.Snapshot.Version;
|
|
|
|
await ExecuteCoreAsync(domainObject, command);
|
|
|
|
Assert.Same(previousSnapshot, domainObject.Snapshot);
|
|
Assert.Equal(previousVersion, domainObject.Snapshot.Version);
|
|
|
|
return actual;
|
|
}
|
|
|
|
private async Task<object> ExecuteCoreAsync<T>(DomainObject<T> domainObject, IAggregateCommand command) where T : Entity, new()
|
|
{
|
|
var actual = await domainObject.ExecuteAsync(CreateCommand(command), CancellationToken);
|
|
|
|
return actual.Payload;
|
|
}
|
|
|
|
protected virtual IAggregateCommand CreateCommand(IAggregateCommand command)
|
|
{
|
|
if (command is SquidexCommand baseCommand)
|
|
{
|
|
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)
|
|
{
|
|
appCommand.AppId = AppId;
|
|
}
|
|
|
|
if (command is ISchemaCommand { SchemaId: null } schemaCommand)
|
|
{
|
|
schemaCommand.SchemaId = SchemaId;
|
|
}
|
|
|
|
if (command is ITeamCommand teamCommand && teamCommand.TeamId == default)
|
|
{
|
|
teamCommand.TeamId = TeamId;
|
|
}
|
|
|
|
return command;
|
|
}
|
|
|
|
protected TEvent CreateEvent<TEvent>(TEvent @event, bool fromClient = false) where TEvent : SquidexEvent
|
|
{
|
|
@event.Actor = fromClient ? Client : User;
|
|
|
|
if (@event is AppEvent appEvent)
|
|
{
|
|
appEvent.AppId = AppId;
|
|
}
|
|
|
|
if (@event is SchemaEvent schemaEvent)
|
|
{
|
|
schemaEvent.SchemaId = SchemaId;
|
|
}
|
|
|
|
if (@event is TeamEvent teamEvent && teamEvent.TeamId == default)
|
|
{
|
|
teamEvent.TeamId = TeamId;
|
|
}
|
|
|
|
return @event;
|
|
}
|
|
}
|
|
|