Browse Source

Tests fixed

pull/1/head
Sebastian 9 years ago
parent
commit
b82ec725a6
  1. 2
      Squidex.sln
  2. 2
      src/Squidex.Infrastructure.Redis/RedisExternalSystem.cs
  3. 1
      src/Squidex.Infrastructure/CQRS/Commands/ICommand.cs
  4. 11
      src/Squidex.Infrastructure/CQRS/Events/EventReceiver.cs
  5. 5
      src/Squidex.Infrastructure/Language.cs
  6. 4
      src/Squidex.Infrastructure/NamedId.cs
  7. 8
      src/Squidex.Read.MongoDb/Apps/MongoAppRepository_EventHandling.cs
  8. 11
      src/Squidex.Read.MongoDb/Schemas/MongoSchemaRepository_EventHandling.cs
  9. 17
      src/Squidex.Read/Apps/AppHistoryEventsCreator.cs
  10. 3
      src/Squidex.Read/Apps/Repositories/IAppRepository.cs
  11. 3
      src/Squidex.Read/Apps/Services/IAppProvider.cs
  12. 55
      src/Squidex.Read/Apps/Services/Implementations/CachingAppProvider.cs
  13. 4
      src/Squidex.Read/History/HistoryEventToStore.cs
  14. 3
      src/Squidex.Read/Schemas/Repositories/ISchemaRepository.cs
  15. 3
      src/Squidex.Read/Schemas/Services/ISchemaProvider.cs
  16. 64
      src/Squidex.Read/Schemas/Services/Implementations/CachingSchemaProvider.cs
  17. 12
      src/Squidex.Write/Apps/AppDomainObject.cs
  18. 2
      src/Squidex.Write/Contents/ContentDomainObject.cs
  19. 2
      src/Squidex.Write/SchemaAggregateCommand.cs
  20. 10
      src/Squidex.Write/Schemas/SchemaDomainObject.cs
  21. 3
      src/Squidex.Write/SquidexCommand.cs
  22. 4
      src/Squidex/Config/Domain/StoreMongoDbModule.cs
  23. 8
      src/Squidex/Config/Domain/Usages.cs
  24. 2
      src/Squidex/app/features/content/pages/contents/contents-page.component.html
  25. 2
      src/Squidex/app/features/content/pages/schemas/schemas-page.component.html
  26. 4
      src/Squidex/appsettings.json
  27. 24
      tests/Squidex.Infrastructure.Tests/CQRS/Commands/DefaultDomainObjectRepositoryTests.cs
  28. 4
      tests/Squidex.Infrastructure.Tests/CQRS/Commands/EnrichWithTimestampHandlerTests.cs
  29. 11
      tests/Squidex.Infrastructure.Tests/CQRS/EnvelopeExtensionsTests.cs
  30. 55
      tests/Squidex.Infrastructure.Tests/CQRS/Events/EnrichWithActorProcessorTests.cs
  31. 148
      tests/Squidex.Infrastructure.Tests/CQRS/Events/EventReceiverTests.cs
  32. 82
      tests/Squidex.Infrastructure.Tests/CQRS/Replay/ReplayGeneratorTests.cs
  33. 22
      tests/Squidex.Infrastructure.Tests/LanguageTests.cs
  34. 148
      tests/Squidex.Infrastructure.Tests/NamedIdTest.cs
  35. 4
      tests/Squidex.Infrastructure.Tests/PropertiesBagTests.cs
  36. 37
      tests/Squidex.Infrastructure.Tests/RefTokenTests.cs
  37. 40
      tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs
  38. 114
      tests/Squidex.Read.Tests/Apps/CachingAppProviderTests.cs
  39. 114
      tests/Squidex.Read.Tests/Schemas/CachingSchemaProviderTests.cs
  40. 67
      tests/Squidex.Write.Tests/Apps/AppCommandHandlerTests.cs
  41. 332
      tests/Squidex.Write.Tests/Apps/AppDomainObjectTests.cs
  42. 45
      tests/Squidex.Write.Tests/Contents/ContentCommandHandlerTests.cs
  43. 184
      tests/Squidex.Write.Tests/Contents/ContentDomainObjectTests.cs
  44. 71
      tests/Squidex.Write.Tests/EnrichWithAppIdProcessorTests.cs
  45. 74
      tests/Squidex.Write.Tests/EnrichWithSchemaIdProcessorTests.cs
  46. 59
      tests/Squidex.Write.Tests/Schemas/SchemaCommandHandlerTests.cs
  47. 332
      tests/Squidex.Write.Tests/Schemas/SchemaDomainObjectTests.cs
  48. 31
      tests/Squidex.Write.Tests/TestHelpers/AssertHelper.cs
  49. 71
      tests/Squidex.Write.Tests/TestHelpers/HandlerTestBase.cs

2
Squidex.sln

@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{24A3171D-2905-49C9-8A49-A473799014E8}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4B5539DB-F68E-4DBA-B22A-72B9FE7FE2D8}"
ProjectSection(SolutionItems) = preProject
global.json = global.json

2
src/Squidex.Infrastructure.Redis/RedisExternalSystem.cs

@ -11,7 +11,7 @@ using StackExchange.Redis;
namespace Squidex.Infrastructure.Redis
{
public class RedisExternalSystem
public sealed class RedisExternalSystem : IExternalSystem
{
private readonly IConnectionMultiplexer redis;

1
src/Squidex.Infrastructure/CQRS/Commands/ICommand.cs

@ -5,6 +5,7 @@
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
namespace Squidex.Infrastructure.CQRS.Commands
{
public interface ICommand

11
src/Squidex.Infrastructure/CQRS/Events/EventReceiver.cs

@ -46,7 +46,14 @@ namespace Squidex.Infrastructure.CQRS.Events
{
if (disposing)
{
timer?.Dispose();
try
{
timer?.Dispose();
}
catch (Exception ex)
{
logger.LogCritical(InfrastructureErrors.EventHandlingFailed, ex, "Event stream {0} has been aborted");
}
}
}
@ -98,6 +105,8 @@ namespace Squidex.Infrastructure.CQRS.Events
try
{
await consumer.On(@event, eventNumber);
logger.LogDebug("[{0}]: Handled event {1} ({2})", consumer, @event.Payload, @event.Headers.EventId());
}
catch (Exception ex)
{

5
src/Squidex.Infrastructure/Language.cs

@ -112,5 +112,10 @@ namespace Squidex.Infrastructure
return null;
}
public override string ToString()
{
return EnglishName;
}
}
}

4
src/Squidex.Infrastructure/NamedId.cs

@ -38,12 +38,12 @@ namespace Squidex.Infrastructure
public bool Equals(NamedId<T> other)
{
return other != null && (ReferenceEquals(this, other) || Id.Equals(other.Id));
return other != null && (ReferenceEquals(this, other) || (Id.Equals(other.Id) && Name.Equals(other.Name)));
}
public override int GetHashCode()
{
return Id.GetHashCode();
return (Id.GetHashCode() * 397) ^ Name.GetHashCode();
}
}
}

8
src/Squidex.Read.MongoDb/Apps/MongoAppRepository_EventHandling.cs

@ -21,7 +21,7 @@ namespace Squidex.Read.MongoDb.Apps
{
public partial class MongoAppRepository
{
public event Action<Guid> AppSaved;
public event Action<NamedId<Guid>> AppSaved;
public Task On(Envelope<IEvent> @event)
{
@ -35,7 +35,7 @@ namespace Squidex.Read.MongoDb.Apps
SimpleMapper.Map(@event, a);
});
AppSaved?.Invoke(headers.AggregateId());
AppSaved?.Invoke(@event.AppId);
}
protected Task On(AppContributorAssigned @event, EnvelopeHeaders headers)
@ -104,11 +104,11 @@ namespace Squidex.Read.MongoDb.Apps
});
}
public async Task UpdateAsync(SquidexEvent @event, EnvelopeHeaders headers, Action<MongoAppEntity> updater)
public async Task UpdateAsync(AppEvent @event, EnvelopeHeaders headers, Action<MongoAppEntity> updater)
{
await Collection.UpdateAsync(@event, headers, updater);
AppSaved?.Invoke(headers.AggregateId());
AppSaved?.Invoke(@event.AppId);
}
}
}

11
src/Squidex.Read.MongoDb/Schemas/MongoSchemaRepository_EventHandling.cs

@ -12,6 +12,7 @@ using Squidex.Core.Schemas;
using Squidex.Events;
using Squidex.Events.Schemas;
using Squidex.Events.Schemas.Utils;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Dispatching;
@ -22,7 +23,7 @@ namespace Squidex.Read.MongoDb.Schemas
{
public partial class MongoSchemaRepository
{
public event Action<Guid> SchemaSaved;
public event Action<NamedId<Guid>, NamedId<Guid>> SchemaSaved;
public Task On(Envelope<IEvent> @event)
{
@ -35,7 +36,7 @@ namespace Squidex.Read.MongoDb.Schemas
await Collection.CreateAsync(@event, headers, s => { UpdateSchema(s, schema); SimpleMapper.Map(@event, s); });
SchemaSaved?.Invoke(headers.AggregateId());
SchemaSaved?.Invoke(@event.AppId, @event.SchemaId);
}
protected Task On(FieldDeleted @event, EnvelopeHeaders headers)
@ -92,14 +93,14 @@ namespace Squidex.Read.MongoDb.Schemas
{
await Collection.UpdateAsync(@event, headers, s => s.IsDeleted = true);
SchemaSaved?.Invoke(headers.AggregateId());
SchemaSaved?.Invoke(@event.AppId, @event.SchemaId);
}
private async Task UpdateSchema(SquidexEvent @event, EnvelopeHeaders headers, Func<Schema, Schema> updater)
private async Task UpdateSchema(SchemaEvent @event, EnvelopeHeaders headers, Func<Schema, Schema> updater)
{
await Collection.UpdateAsync(@event, headers, e => UpdateSchema(e, updater));
SchemaSaved?.Invoke(headers.AggregateId());
SchemaSaved?.Invoke(@event.AppId, @event.SchemaId);
}
private void UpdateSchema(MongoSchemaEntity entity, Func<Schema, Schema> updater)

17
src/Squidex.Read/Apps/AppHistoryEventsCreator.cs

@ -61,8 +61,7 @@ namespace Squidex.Read.Apps
return Task.FromResult(
ForEvent(@event, channel)
.AddParameter("Contributor", @event.ContributorId)
.AddParameter("Permission", @event.Permission.ToString()));
.AddParameter("Contributor", @event.ContributorId).AddParameter("Permission", @event.Permission));
}
protected Task<HistoryEventToStore> On(AppClientAttached @event, EnvelopeHeaders headers)
@ -89,8 +88,7 @@ namespace Squidex.Read.Apps
return Task.FromResult(
ForEvent(@event, channel)
.AddParameter("Id", @event.Id)
.AddParameter("Name", !string.IsNullOrWhiteSpace(@event.Name) ? @event.Name : @event.Id));
.AddParameter("Id", @event.Id).AddParameter("Name", ClientName(@event)));
}
protected Task<HistoryEventToStore> On(AppLanguageAdded @event, EnvelopeHeaders headers)
@ -99,7 +97,7 @@ namespace Squidex.Read.Apps
return Task.FromResult(
ForEvent(@event, channel)
.AddParameter("Language", @event.Language.EnglishName));
.AddParameter("Language", @event.Language));
}
protected Task<HistoryEventToStore> On(AppLanguageRemoved @event, EnvelopeHeaders headers)
@ -108,7 +106,7 @@ namespace Squidex.Read.Apps
return Task.FromResult(
ForEvent(@event, channel)
.AddParameter("Language", @event.Language.EnglishName));
.AddParameter("Language", @event.Language));
}
protected Task<HistoryEventToStore> On(AppMasterLanguageSet @event, EnvelopeHeaders headers)
@ -117,12 +115,17 @@ namespace Squidex.Read.Apps
return Task.FromResult(
ForEvent(@event, channel)
.AddParameter("Language", @event.Language.EnglishName));
.AddParameter("Language", @event.Language));
}
protected override Task<HistoryEventToStore> CreateEventCoreAsync(Envelope<IEvent> @event)
{
return this.DispatchFuncAsync(@event.Payload, @event.Headers, (HistoryEventToStore)null);
}
private static string ClientName(AppClientRenamed @event)
{
return !string.IsNullOrWhiteSpace(@event.Name) ? @event.Name : @event.Id;
}
}
}

3
src/Squidex.Read/Apps/Repositories/IAppRepository.cs

@ -9,12 +9,13 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Squidex.Infrastructure;
namespace Squidex.Read.Apps.Repositories
{
public interface IAppRepository
{
event Action<Guid> AppSaved;
event Action<NamedId<Guid>> AppSaved;
Task<IReadOnlyList<IAppEntity>> QueryAllAsync(string subjectId);

3
src/Squidex.Read/Apps/Services/IAppProvider.cs

@ -8,6 +8,7 @@
using System;
using System.Threading.Tasks;
using Squidex.Infrastructure;
namespace Squidex.Read.Apps.Services
{
@ -17,6 +18,6 @@ namespace Squidex.Read.Apps.Services
Task<IAppEntity> FindAppByNameAsync(string name);
void Remove(Guid id);
void Remove(NamedId<Guid> id);
}
}

55
src/Squidex.Read/Apps/Services/Implementations/CachingAppProvider.cs

@ -22,13 +22,6 @@ namespace Squidex.Read.Apps.Services.Implementations
private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes(30);
private readonly IAppRepository repository;
private sealed class CacheItem
{
public IAppEntity Entity;
public string Name;
}
public CachingAppProvider(IMemoryCache cache, IAppRepository repository)
: base(cache)
{
@ -40,23 +33,22 @@ namespace Squidex.Read.Apps.Services.Implementations
public async Task<IAppEntity> FindAppByIdAsync(Guid appId)
{
var cacheKey = BuildIdCacheKey(appId);
var cacheItem = Cache.Get<CacheItem>(cacheKey);
if (cacheItem == null)
{
var entity = await repository.FindAppAsync(appId);
IAppEntity result;
cacheItem = new CacheItem { Entity = entity, Name = entity.Name };
if (!Cache.TryGetValue(cacheKey, out result))
{
result = await repository.FindAppAsync(appId);
Cache.Set(cacheKey, cacheItem, CacheDuration);
Cache.Set(cacheKey, result, CacheDuration);
if (cacheItem.Entity != null)
if (result != null)
{
Cache.Set(BuildNameCacheKey(cacheItem.Name), cacheItem, CacheDuration);
Cache.Set(BuildNameCacheKey(result.Name), result, CacheDuration);
}
}
return cacheItem.Entity;
return result;
}
public async Task<IAppEntity> FindAppByNameAsync(string name)
@ -64,37 +56,28 @@ namespace Squidex.Read.Apps.Services.Implementations
Guard.NotNullOrEmpty(name, nameof(name));
var cacheKey = BuildNameCacheKey(name);
var cacheItem = Cache.Get<CacheItem>(cacheKey);
if (cacheItem == null)
{
var entity = await repository.FindAppAsync(name);
IAppEntity result;
cacheItem = new CacheItem { Entity = entity, Name = name };
if (!Cache.TryGetValue(cacheKey, out result))
{
result = await repository.FindAppAsync(name);
Cache.Set(cacheKey, cacheItem, CacheDuration);
Cache.Set(cacheKey, result, CacheDuration);
if (cacheItem.Entity != null)
if (result != null)
{
Cache.Set(BuildIdCacheKey(cacheItem.Entity.Id), cacheItem, CacheDuration);
Cache.Set(BuildIdCacheKey(result.Id), result, CacheDuration);
}
}
return cacheItem.Entity;
return result;
}
public void Remove(Guid id)
public void Remove(NamedId<Guid> id)
{
var cacheKey = BuildIdCacheKey(id);
var cacheItem = Cache.Get<CacheItem>(cacheKey);
if (cacheItem?.Name != null)
{
Cache.Remove(BuildNameCacheKey(cacheItem.Name));
}
Cache.Remove(cacheKey);
Cache.Remove(BuildIdCacheKey(id.Id));
Cache.Remove(BuildNameCacheKey(id.Name));
}
private static string BuildNameCacheKey(string name)

4
src/Squidex.Read/History/HistoryEventToStore.cs

@ -34,9 +34,9 @@ namespace Squidex.Read.History
Message = message;
}
public HistoryEventToStore AddParameter(string key, string value)
public HistoryEventToStore AddParameter(string key, object value)
{
parameters[key] = value;
parameters[key] = value.ToString();
return this;
}

3
src/Squidex.Read/Schemas/Repositories/ISchemaRepository.cs

@ -9,12 +9,13 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Squidex.Infrastructure;
namespace Squidex.Read.Schemas.Repositories
{
public interface ISchemaRepository
{
event Action<Guid> SchemaSaved;
event Action<NamedId<Guid>, NamedId<Guid>> SchemaSaved;
Task<IReadOnlyList<ISchemaEntity>> QueryAllAsync(Guid appId);

3
src/Squidex.Read/Schemas/Services/ISchemaProvider.cs

@ -8,6 +8,7 @@
using System;
using System.Threading.Tasks;
using Squidex.Infrastructure;
namespace Squidex.Read.Schemas.Services
{
@ -17,6 +18,6 @@ namespace Squidex.Read.Schemas.Services
Task<ISchemaEntityWithSchema> FindSchemaByNameAsync(Guid appId, string name);
void Remove(Guid id);
void Remove(NamedId<Guid> appId, NamedId<Guid> schemaId);
}
}

64
src/Squidex.Read/Schemas/Services/Implementations/CachingSchemaProvider.cs

@ -23,15 +23,6 @@ namespace Squidex.Read.Schemas.Services.Implementations
private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes(10);
private readonly ISchemaRepository repository;
private sealed class CacheItem
{
public ISchemaEntityWithSchema Entity;
public Guid AppId;
public string Name;
}
public CachingSchemaProvider(IMemoryCache cache, ISchemaRepository repository)
: base(cache)
{
@ -43,30 +34,22 @@ namespace Squidex.Read.Schemas.Services.Implementations
public async Task<ISchemaEntityWithSchema> FindSchemaByIdAsync(Guid id)
{
var cacheKey = BuildIdCacheKey(id);
var cacheItem = Cache.Get<CacheItem>(cacheKey);
if (cacheItem == null)
{
var entity = await repository.FindSchemaAsync(id);
ISchemaEntityWithSchema result;
if (entity == null)
{
cacheItem = new CacheItem();
}
else
{
cacheItem = new CacheItem { Entity = entity, Name = entity.Name, AppId = entity.AppId };
}
if (!Cache.TryGetValue(cacheKey, out result))
{
result = await repository.FindSchemaAsync(id);
Cache.Set(cacheKey, cacheItem, CacheDuration);
Cache.Set(cacheKey, result, CacheDuration);
if (cacheItem.Entity != null)
if (result != null)
{
Cache.Set(BuildNameCacheKey(cacheItem.Entity.AppId, cacheItem.Entity.Name), cacheItem, CacheDuration);
Cache.Set(BuildNameCacheKey(result.AppId, result.Name), result, CacheDuration);
}
}
return cacheItem.Entity;
return result;
}
public async Task<ISchemaEntityWithSchema> FindSchemaByNameAsync(Guid appId, string name)
@ -74,37 +57,28 @@ namespace Squidex.Read.Schemas.Services.Implementations
Guard.NotNullOrEmpty(name, nameof(name));
var cacheKey = BuildNameCacheKey(appId, name);
var cacheItem = Cache.Get<CacheItem>(cacheKey);
if (cacheItem == null)
{
var entity = await repository.FindSchemaAsync(appId, name);
ISchemaEntityWithSchema result;
cacheItem = new CacheItem { Entity = entity, Name = name, AppId = appId };
if (!Cache.TryGetValue(cacheKey, out result))
{
result = await repository.FindSchemaAsync(appId, name);
Cache.Set(cacheKey, cacheItem, CacheDuration);
Cache.Set(cacheKey, result, CacheDuration);
if (cacheItem.Entity != null)
if (result != null)
{
Cache.Set(BuildIdCacheKey(cacheItem.Entity.Id), cacheItem, CacheDuration);
Cache.Set(BuildIdCacheKey(result.Id), result, CacheDuration);
}
}
return cacheItem.Entity;
return result;
}
public void Remove(Guid id)
public void Remove(NamedId<Guid> appId, NamedId<Guid> schemaId)
{
var cacheKey = BuildIdCacheKey(id);
var cacheItem = Cache.Get<CacheItem>(cacheKey);
if (cacheItem?.Name != null)
{
Cache.Remove(BuildNameCacheKey(cacheItem.AppId, cacheItem.Name));
}
Cache.Remove(cacheKey);
Cache.Remove(BuildIdCacheKey(schemaId.Id));
Cache.Remove(BuildNameCacheKey(appId.Id, schemaId.Name));
}
private static string BuildNameCacheKey(Guid appId, string name)

12
src/Squidex.Write/Apps/AppDomainObject.cs

@ -9,10 +9,10 @@
using System;
using System.Collections.Generic;
using Squidex.Core.Apps;
using Squidex.Events;
using Squidex.Events.Apps;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Dispatching;
using Squidex.Infrastructure.Reflection;
@ -200,6 +200,16 @@ namespace Squidex.Write.Apps
return this;
}
protected void RaiseEvent(AppEvent @event)
{
if (@event.AppId == null)
{
@event.AppId = new NamedId<Guid>(Id, name);
}
base.RaiseEvent(Envelope<IEvent>.Create(@event));
}
private static AppLanguageAdded CreateInitialLanguage(NamedId<Guid> id)
{
return new AppLanguageAdded { AppId = id, Language = DefaultLanguage };

2
src/Squidex.Write/Contents/ContentDomainObject.cs

@ -135,7 +135,7 @@ namespace Squidex.Write.Contents
if (!newData.Equals(data))
{
RaiseEvent(new ContentUpdated { Data = newData });
RaiseEvent(SimpleMapper.Map(command, new ContentUpdated { Data = newData }));
}
return this;

2
src/Squidex.Write/SchemaAggregateCommand.cs

@ -15,7 +15,7 @@ namespace Squidex.Write
{
Guid IAggregateCommand.AggregateId
{
get { return AppId.Id; }
get { return SchemaId.Id; }
}
}
}

10
src/Squidex.Write/Schemas/SchemaDomainObject.cs

@ -134,7 +134,7 @@ namespace Squidex.Write.Schemas
VerifyNotCreated();
RaiseEvent(SimpleMapper.Map(command, new SchemaCreated()));
RaiseEvent(SimpleMapper.Map(command, new SchemaCreated { SchemaId = new NamedId<Guid>(Id, command.Name) }));
return this;
}
@ -211,7 +211,7 @@ namespace Squidex.Write.Schemas
VerifyCreatedAndNotDeleted();
RaiseEvent(new SchemaPublished());
RaiseEvent(SimpleMapper.Map(command, new SchemaPublished()));
return this;
}
@ -222,7 +222,7 @@ namespace Squidex.Write.Schemas
VerifyCreatedAndNotDeleted();
RaiseEvent(new SchemaUnpublished());
RaiseEvent(SimpleMapper.Map(command, new SchemaUnpublished()));
return this;
}
@ -231,13 +231,15 @@ namespace Squidex.Write.Schemas
{
VerifyCreatedAndNotDeleted();
RaiseEvent(new SchemaDeleted());
RaiseEvent(SimpleMapper.Map(command, new SchemaDeleted()));
return this;
}
protected void RaiseEvent(FieldCommand fieldCommand, FieldEvent @event)
{
SimpleMapper.Map(fieldCommand, @event);
Field field;
if (schema.Fields.TryGetValue(fieldCommand.FieldId, out field))

3
src/Squidex.Write/SquidexCommand.cs

@ -7,10 +7,11 @@
// ==========================================================================
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Commands;
namespace Squidex.Write
{
public abstract class SquidexCommand
public abstract class SquidexCommand : ICommand
{
public RefToken Actor { get; set; }
}

4
src/Squidex/Config/Domain/StoreMongoDbModule.cs

@ -126,7 +126,7 @@ namespace Squidex.Config.Domain
c.Resolve<MongoAppRepository>()))
.As<IEventCatchConsumer>()
.SingleInstance();
/*
builder.Register(c =>
new MongoDbConsumerWrapper(
c.ResolveNamed<IMongoDatabase>(MongoDatabaseName),
@ -146,7 +146,7 @@ namespace Squidex.Config.Domain
c.ResolveNamed<IMongoDatabase>(MongoDatabaseName),
c.Resolve<MongoHistoryEventRepository>()))
.As<IEventCatchConsumer>()
.SingleInstance();*/
.SingleInstance();
}
}
}

8
src/Squidex/Config/Domain/Usages.cs

@ -33,16 +33,16 @@ namespace Squidex.Config.Domain
var appProvider = app.ApplicationServices.GetRequiredService<IAppProvider>();
app.ApplicationServices.GetRequiredService<IAppRepository>().AppSaved += id =>
app.ApplicationServices.GetRequiredService<IAppRepository>().AppSaved += appId =>
{
appProvider.Remove(id);
appProvider.Remove(appId);
};
var schemaProvider = app.ApplicationServices.GetRequiredService<ISchemaProvider>();
app.ApplicationServices.GetRequiredService<ISchemaRepository>().SchemaSaved += id =>
app.ApplicationServices.GetRequiredService<ISchemaRepository>().SchemaSaved += (appId, schemaId) =>
{
schemaProvider.Remove(id);
schemaProvider.Remove(appId, schemaId);
};
return app;

2
src/Squidex/app/features/content/pages/contents/contents-page.component.html

@ -5,7 +5,7 @@
<div class="panel-title-row">
<div class="float-right">
<form class="form-inline" (ngSubmit)="search()">
<input class="form-control" [formControl]="contentsFilter" placeholder="Search for content..." />
<input class="form-control" [formControl]="contentsFilter" placeholder="Search for content" />
</form>
<sqx-language-selector class="languages-buttons" (selectedLanguageChanged)="selectLanguage($event)" [languages]="languages"></sqx-language-selector>

2
src/Squidex/app/features/content/pages/schemas/schemas-page.component.html

@ -12,7 +12,7 @@
<div class="panel-row">
<div class="search-form">
<input class="form-control form-control-dark" [formControl]="schemasFilter" placeholder="Search for schemas..." />
<input class="form-control form-control-dark" [formControl]="schemasFilter" placeholder="Search for schemas" />
<i class="icon-search"></i>
</div>

4
src/Squidex/appsettings.json

@ -4,9 +4,9 @@
"baseUrl": "http://localhost:5000"
},
"clusterer": {
"type": "none",
"type": "redis",
"redis": {
"connectionString": "redis://localhost:6379"
"connectionString": "localhost:6379"
}
},
"eventStore": {

24
tests/Squidex.Infrastructure.Tests/CQRS/Commands/DefaultDomainObjectRepositoryTests.cs

@ -24,7 +24,6 @@ namespace Squidex.Infrastructure.CQRS.Commands
{
private readonly Mock<IDomainObjectFactory> factory = new Mock<IDomainObjectFactory>();
private readonly Mock<IEventStore> eventStore = new Mock<IEventStore>();
private readonly Mock<IEventPublisher> eventPublisher = new Mock<IEventPublisher>();
private readonly Mock<IStreamNameResolver> streamNameResolver = new Mock<IStreamNameResolver>();
private readonly Mock<EventDataFormatter> eventDataFormatter = new Mock<EventDataFormatter>(new TypeNameRegistry(), null);
private readonly string streamName = Guid.NewGuid().ToString();
@ -40,7 +39,7 @@ namespace Squidex.Infrastructure.CQRS.Commands
factory.Setup(x => x.CreateNew(typeof(MyDomainObject), aggregateId)).Returns(domainObject);
sut = new DefaultDomainObjectRepository(factory.Object, eventStore.Object, eventPublisher.Object, streamNameResolver.Object, eventDataFormatter.Object);
sut = new DefaultDomainObjectRepository(factory.Object, eventStore.Object, streamNameResolver.Object, eventDataFormatter.Object);
}
public sealed class MyEvent : IEvent
@ -74,7 +73,7 @@ namespace Squidex.Infrastructure.CQRS.Commands
[Fact]
public async Task Should_throw_exception_when_event_store_returns_no_events()
{
eventStore.Setup(x => x.GetEventsAsync(streamName)).Returns(Observable.Empty<EventData>());
eventStore.Setup(x => x.GetEventsAsync(streamName)).Returns(Observable.Empty<StoredEvent>());
await Assert.ThrowsAsync<DomainObjectNotFoundException>(() => sut.GetByIdAsync<MyDomainObject>(aggregateId));
}
@ -88,7 +87,13 @@ namespace Squidex.Infrastructure.CQRS.Commands
var event1 = new MyEvent();
var event2 = new MyEvent();
eventStore.Setup(x => x.GetEventsAsync(streamName)).Returns(new[] { eventData1, eventData2 }.ToObservable());
var events = new[]
{
new StoredEvent(0, eventData1),
new StoredEvent(1, eventData2)
};
eventStore.Setup(x => x.GetEventsAsync(streamName)).Returns(events.ToObservable());
eventDataFormatter.Setup(x => x.Parse(eventData1)).Returns(new Envelope<IEvent>(event1));
eventDataFormatter.Setup(x => x.Parse(eventData2)).Returns(new Envelope<IEvent>(event2));
@ -107,7 +112,13 @@ namespace Squidex.Infrastructure.CQRS.Commands
var event1 = new MyEvent();
var event2 = new MyEvent();
eventStore.Setup(x => x.GetEventsAsync(streamName)).Returns(new[] { eventData1, eventData2 }.ToObservable());
var events = new[]
{
new StoredEvent(0, eventData1),
new StoredEvent(1, eventData2)
};
eventStore.Setup(x => x.GetEventsAsync(streamName)).Returns(events.ToObservable());
eventDataFormatter.Setup(x => x.Parse(eventData1)).Returns(new Envelope<IEvent>(event1));
eventDataFormatter.Setup(x => x.Parse(eventData2)).Returns(new Envelope<IEvent>(event2));
@ -137,9 +148,6 @@ namespace Squidex.Infrastructure.CQRS.Commands
await sut.SaveAsync(domainObject, domainObject.GetUncomittedEvents(), commitId);
eventPublisher.Verify(x => x.Publish(eventData1));
eventPublisher.Verify(x => x.Publish(eventData2));
eventStore.VerifyAll();
}

4
tests/Squidex.Infrastructure.Tests/CQRS/Commands/EnrichWithTimestampHandlerTests.cs

@ -14,11 +14,11 @@ namespace Squidex.Infrastructure.CQRS.Commands
{
public sealed class EnrichWithTimestampHandlerTests
{
private sealed class MyNormalCommand : AggregateCommand
private sealed class MyNormalCommand : ICommand
{
}
private sealed class MyTimestampCommand : AggregateCommand, ITimestampCommand
private sealed class MyTimestampCommand : ITimestampCommand
{
public DateTime Timestamp { get; set; }
}

11
tests/Squidex.Infrastructure.Tests/CQRS/EnvelopeExtensionsTests.cs

@ -62,17 +62,6 @@ namespace Squidex.Infrastructure.CQRS
Assert.Equal(commitId, sut.Headers["AggregateId"].ToGuid(culture));
}
[Fact]
public void Should_set_and_get_actor()
{
var actor = new RefToken("subject", "123");
sut.SetActor(actor);
Assert.Equal(actor, sut.Headers.Actor());
Assert.Equal(actor, RefToken.Parse(sut.Headers["Actor"].ToString()));
}
[Fact]
public void Should_set_and_get_event_number()
{

55
tests/Squidex.Infrastructure.Tests/CQRS/Events/EnrichWithActorProcessorTests.cs

@ -1,55 +0,0 @@
// ==========================================================================
// EnrichWithUserProcessorTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Threading.Tasks;
using Squidex.Infrastructure.CQRS.Commands;
using Xunit;
namespace Squidex.Infrastructure.CQRS.Events
{
public class EnrichWithActorProcessorTests
{
public sealed class MyActorCommand : IActorCommand
{
public RefToken Actor { get; set; }
}
public sealed class MyNormalCommand : ICommand
{
}
public sealed class MyEvent : IEvent
{
}
private readonly EnrichWithActorProcessor sut = new EnrichWithActorProcessor();
[Fact]
public async Task Should_not_do_anything_if_not_actor_command()
{
var envelope = new Envelope<IEvent>(new MyEvent());
await sut.ProcessEventAsync(envelope, null, new MyNormalCommand());
Assert.False(envelope.Headers.Contains("User"));
}
[Fact]
public async Task Should_attach_user_to_event_envelope()
{
var actorToken = new RefToken("subject", "123");
var actorCommand = new MyActorCommand { Actor = actorToken };
var envelope = new Envelope<IEvent>(new MyEvent());
await sut.ProcessEventAsync(envelope, null, actorCommand);
Assert.Equal(actorToken, envelope.Headers.Actor());
}
}
}

148
tests/Squidex.Infrastructure.Tests/CQRS/Events/EventReceiverTests.cs

@ -8,6 +8,8 @@
using System;
using System.Collections.Generic;
using System.Reactive.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Moq;
using Xunit;
@ -42,127 +44,117 @@ namespace Squidex.Infrastructure.CQRS.Events
}
}
private readonly Mock<ILiveEventConsumer> liveConsumer1 = new Mock<ILiveEventConsumer>();
private readonly Mock<ILiveEventConsumer> liveConsumer2 = new Mock<ILiveEventConsumer>();
private readonly Mock<IEventCatchConsumer> catchConsumer1 = new Mock<IEventCatchConsumer>();
private readonly Mock<IEventCatchConsumer> catchConsumer2 = new Mock<IEventCatchConsumer>();
private readonly Mock<IEventStream> eventStream = new Mock<IEventStream>();
private readonly Mock<IEventCatchConsumer> eventConsumer = new Mock<IEventCatchConsumer>();
private readonly Mock<IEventNotifier> eventNotifier = new Mock<IEventNotifier>();
private readonly Mock<IEventStore> eventStore = new Mock<IEventStore>();
private readonly Mock<EventDataFormatter> formatter = new Mock<EventDataFormatter>(new TypeNameRegistry(), null);
private readonly EventData eventData = new EventData();
private readonly Envelope<IEvent> envelope = new Envelope<IEvent>(new MyEvent());
private readonly EventData eventData1 = new EventData();
private readonly EventData eventData2 = new EventData();
private readonly EventData eventData3 = new EventData();
private readonly EventData eventData4 = new EventData();
private readonly Envelope<IEvent> envelope1 = new Envelope<IEvent>(new MyEvent());
private readonly Envelope<IEvent> envelope2 = new Envelope<IEvent>(new MyEvent());
private readonly Envelope<IEvent> envelope3 = new Envelope<IEvent>(new MyEvent());
private readonly Envelope<IEvent> envelope4 = new Envelope<IEvent>(new MyEvent());
private readonly EventReceiver sut;
private readonly MyLogger logger = new MyLogger();
private readonly StoredEvent[][] events;
public EventReceiverTests()
{
formatter.Setup(x => x.Parse(eventData)).Returns(envelope);
eventStream.Setup(x => x.Connect("squidex", It.IsAny<Action<EventData>>())).Callback(
new Action<string, Action<EventData>>((queue, callback) =>
events = new []
{
new []
{
callback(eventData);
}));
}
new StoredEvent(3, eventData1),
new StoredEvent(4, eventData1)
},
new[]
{
new StoredEvent(5, eventData1),
new StoredEvent(6, eventData1)
}
};
[Fact]
public void Should_only_connect_once()
{
var sut = CreateSut(true);
sut.Subscribe();
sut.Subscribe();
formatter.Setup(x => x.Parse(eventData1)).Returns(envelope1);
formatter.Setup(x => x.Parse(eventData2)).Returns(envelope2);
formatter.Setup(x => x.Parse(eventData3)).Returns(envelope3);
formatter.Setup(x => x.Parse(eventData4)).Returns(envelope4);
eventStream.Verify(x => x.Connect("squidex", It.IsAny<Action<EventData>>()), Times.Once());
sut = new EventReceiver(formatter.Object, eventStore.Object, eventNotifier.Object, logger);
}
[Fact]
public void Should_invoke_live_consumers()
public void Should_only_connect_once()
{
var sut = CreateSut(false);
sut.Subscribe();
catchConsumer1.Verify(x => x.On(It.IsAny<Envelope<IEvent>>()), Times.Never());
catchConsumer2.Verify(x => x.On(It.IsAny<Envelope<IEvent>>()), Times.Never());
sut.Subscribe(eventConsumer.Object);
sut.Subscribe(eventConsumer.Object);
liveConsumer1.Verify(x => x.On(envelope), Times.Once());
liveConsumer2.Verify(x => x.On(envelope), Times.Once());
Assert.Equal(1, logger.LogCount.Count);
Assert.Equal(1, logger.LogCount[LogLevel.Debug]);
eventConsumer.Verify(x => x.GetLastHandledEventNumber(), Times.Once());
}
[Fact]
public void Should_invoke_catch_consumers()
public void Should_subscribe_to_consumers_and_handle_events()
{
var sut = CreateSut(true);
eventConsumer.Setup(x => x.GetLastHandledEventNumber()).Returns(Task.FromResult(2L));
eventConsumer.Setup(x => x.On(It.IsAny<Envelope<IEvent>>(), It.IsAny<long>())).Returns(Task.FromResult(true));
eventStore.Setup(x => x.GetEventsAsync(2)).Returns(events[0].ToObservable());
eventStore.Setup(x => x.GetEventsAsync(4)).Returns(events[1].ToObservable());
sut.Subscribe();
eventStore.Setup(x => x.GetEventsAsync(It.Is<long>(l => l != 2 && l != 4))).Returns(Observable.Empty<StoredEvent>());
liveConsumer1.Verify(x => x.On(It.IsAny<Envelope<IEvent>>()), Times.Never());
liveConsumer2.Verify(x => x.On(It.IsAny<Envelope<IEvent>>()), Times.Never());
sut.Subscribe(eventConsumer.Object, 20);
catchConsumer1.Verify(x => x.On(envelope), Times.Once());
catchConsumer2.Verify(x => x.On(envelope), Times.Once());
Task.Delay(400).ContinueWith(x => sut.Dispose()).Wait();
Assert.Equal(1, logger.LogCount.Count);
Assert.Equal(1, logger.LogCount[LogLevel.Debug]);
Assert.Equal(4, logger.LogCount[LogLevel.Debug]);
eventConsumer.Verify(x => x.On(It.IsAny<Envelope<IEvent>>(), It.IsAny<long>()), Times.Exactly(4));
}
[Fact]
public void Should_log_if_parsing_event_failed()
public void Should_abort_if_handling_failed()
{
formatter.Setup(x => x.Parse(eventData)).Throws(new InvalidOperationException());
var sut = CreateSut(true);
eventConsumer.Setup(x => x.GetLastHandledEventNumber()).Returns(Task.FromResult(2L));
eventConsumer.Setup(x => x.On(It.IsAny<Envelope<IEvent>>(), It.IsAny<long>())).Throws<InvalidOperationException>();
sut.Subscribe();
eventStore.Setup(x => x.GetEventsAsync(2)).Returns(events[0].ToObservable());
eventStore.Setup(x => x.GetEventsAsync(It.Is<long>(l => l != 2 && l != 4))).Returns(Observable.Empty<StoredEvent>());
catchConsumer1.Verify(x => x.On(It.IsAny<Envelope<IEvent>>()), Times.Never());
catchConsumer2.Verify(x => x.On(It.IsAny<Envelope<IEvent>>()), Times.Never());
sut.Subscribe(eventConsumer.Object, 20);
liveConsumer1.Verify(x => x.On(It.IsAny<Envelope<IEvent>>()), Times.Never());
liveConsumer2.Verify(x => x.On(It.IsAny<Envelope<IEvent>>()), Times.Never());
Task.Delay(400).ContinueWith(x => sut.Dispose()).Wait();
Assert.Equal(1, logger.LogCount.Count);
Assert.Equal(2, logger.LogCount.Count);
Assert.Equal(1, logger.LogCount[LogLevel.Error]);
Assert.Equal(1, logger.LogCount[LogLevel.Critical]);
eventConsumer.Verify(x => x.On(It.IsAny<Envelope<IEvent>>(), It.IsAny<long>()), Times.Exactly(1));
eventStore.Verify(x => x.GetEventsAsync(It.IsAny<long>()), Times.Exactly(1));
}
[Fact]
public void Should_log_if_handling_failed()
public void Should_abort_if_serialization_failed()
{
catchConsumer1.Setup(x => x.On(envelope)).Throws(new InvalidOperationException());
var sut = CreateSut(true);
eventConsumer.Setup(x => x.GetLastHandledEventNumber()).Returns(Task.FromResult(2L));
eventConsumer.Setup(x => x.On(It.IsAny<Envelope<IEvent>>(), It.IsAny<long>())).Throws<InvalidOperationException>();
sut.Subscribe();
eventStore.Setup(x => x.GetEventsAsync(2)).Returns(events[0].ToObservable());
eventStore.Setup(x => x.GetEventsAsync(It.Is<long>(l => l != 2 && l != 4))).Returns(Observable.Empty<StoredEvent>());
catchConsumer1.Verify(x => x.On(envelope), Times.Once());
catchConsumer2.Verify(x => x.On(envelope), Times.Once());
sut.Subscribe(eventConsumer.Object, 20);
liveConsumer1.Verify(x => x.On(It.IsAny<Envelope<IEvent>>()), Times.Never());
liveConsumer2.Verify(x => x.On(It.IsAny<Envelope<IEvent>>()), Times.Never());
Task.Delay(400).ContinueWith(x => sut.Dispose()).Wait();
Assert.Equal(2, logger.LogCount.Count);
Assert.Equal(1, logger.LogCount[LogLevel.Debug]);
Assert.Equal(1, logger.LogCount[LogLevel.Error]);
}
Assert.Equal(1, logger.LogCount[LogLevel.Critical]);
private EventReceiver CreateSut(bool canCatch)
{
return new EventReceiver(
logger,
eventStream.Object,
new[]
{
liveConsumer1.Object,
liveConsumer2.Object
},
new[]
{
catchConsumer1.Object,
catchConsumer2.Object
},
formatter.Object, canCatch);
eventConsumer.Verify(x => x.On(It.IsAny<Envelope<IEvent>>(), It.IsAny<long>()), Times.Exactly(1));
eventStore.Verify(x => x.GetEventsAsync(It.IsAny<long>()), Times.Exactly(1));
}
}
}

82
tests/Squidex.Infrastructure.Tests/CQRS/Replay/ReplayGeneratorTests.cs

@ -1,82 +0,0 @@
// ==========================================================================
// ReplayGeneratorTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Reactive.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Moq;
using Squidex.Infrastructure.CQRS.Events;
using Xunit;
namespace Squidex.Infrastructure.CQRS.Replay
{
public class ReplayGeneratorTests
{
private readonly Mock<IEventStore> eventStore = new Mock<IEventStore>();
private readonly Mock<IEventPublisher> eventPublisher = new Mock<IEventPublisher>();
private readonly Mock<IReplayableStore> store1 = new Mock<IReplayableStore>();
private readonly Mock<IReplayableStore> store2 = new Mock<IReplayableStore>();
private readonly Mock<ILogger<ReplayGenerator>> logger = new Mock<ILogger<ReplayGenerator>>();
private readonly ReplayGenerator sut;
public ReplayGeneratorTests()
{
sut = new ReplayGenerator(logger.Object, eventStore.Object, eventPublisher.Object, new[] { store1.Object, store2.Object });
}
[Fact]
public async Task Should_clear_stores_and_replay_events()
{
var event1 = new EventData();
var event2 = new EventData();
var event3 = new EventData();
eventStore.Setup(x => x.GetEventsAsync()).Returns(new[] { event1, event2, event3 }.ToObservable());
await sut.ReplayAllAsync();
store1.Verify(x => x.ClearAsync(), Times.Once());
store2.Verify(x => x.ClearAsync(), Times.Once());
eventPublisher.Verify(x => x.Publish(event1));
eventPublisher.Verify(x => x.Publish(event2));
eventPublisher.Verify(x => x.Publish(event3));
}
[Fact]
public async Task Should_not_publish_if_clearing_failed()
{
var event1 = new EventData();
var event2 = new EventData();
var event3 = new EventData();
store1.Setup(x => x.ClearAsync()).Throws(new InvalidOperationException());
eventStore.Setup(x => x.GetEventsAsync()).Returns(new[] { event1, event2, event3 }.ToObservable());
await sut.ReplayAllAsync();
store1.Verify(x => x.ClearAsync(), Times.Once());
store2.Verify(x => x.ClearAsync(), Times.Never());
eventStore.Verify(x => x.GetEventsAsync(), Times.Never());
eventPublisher.Verify(x => x.Publish(It.IsAny<EventData>()), Times.Never());
}
[Fact]
public async Task Should_not_throw_if_process_throws()
{
eventStore.Setup(x => x.GetEventsAsync()).Throws(new InvalidOperationException());
await sut.ReplayAllAsync();
eventPublisher.Verify(x => x.Publish(It.IsAny<EventData>()), Times.Never());
}
}
}

22
tests/Squidex.Infrastructure.Tests/LanguageTests.cs

@ -8,22 +8,14 @@
using System;
using System.Linq;
using Newtonsoft.Json;
using Squidex.Infrastructure.Json;
using Squidex.Infrastructure.TestHelpers;
using Xunit;
namespace Squidex.Infrastructure
{
public class LanguageTests
{
private static readonly JsonSerializerSettings serializerSettings = new JsonSerializerSettings();
static LanguageTests()
{
serializerSettings.Converters.Add(new LanguageConverter());
serializerSettings.NullValueHandling = NullValueHandling.Include;
}
[Theory]
[InlineData("")]
[InlineData(" ")]
@ -53,21 +45,13 @@ namespace Squidex.Infrastructure
[Fact]
public void Should_serialize_and_deserialize_null_language()
{
var input = Tuple.Create<Language>(null);
var json = JsonConvert.SerializeObject(input, serializerSettings);
var output = JsonConvert.DeserializeObject<Tuple<Language>>(json, serializerSettings);
Assert.Equal(output.Item1, input.Item1);
JsonHelper.SerializeAndDeserialize<Language>(null, new LanguageConverter());
}
[Fact]
public void Should_serialize_and_deserialize_valid_language()
{
var input = Tuple.Create(Language.DE);
var json = JsonConvert.SerializeObject(input, serializerSettings);
var output = JsonConvert.DeserializeObject<Tuple<Language>>(json, serializerSettings);
Assert.Equal(output.Item1, input.Item1);
Language.DE.SerializeAndDeserialize(new LanguageConverter());
}
[Theory]

148
tests/Squidex.Infrastructure.Tests/NamedIdTest.cs

@ -0,0 +1,148 @@
// ==========================================================================
// NamedIdTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using Squidex.Infrastructure.Json;
using Squidex.Infrastructure.TestHelpers;
using Xunit;
// ReSharper disable RedundantCast
namespace Squidex.Infrastructure
{
public class NamedIdTests
{
[Fact]
public void Should_instantiate_token()
{
var id = Guid.NewGuid();
var namedId = new NamedId<Guid>(id, "my-name");
Assert.Equal(id, namedId.Id);
Assert.Equal("my-name", namedId.Name);
}
[Fact]
public void Should_convert_named_id_to_string()
{
var id = Guid.NewGuid();
var namedId = new NamedId<Guid>(id, "my-name");
Assert.Equal($"{id},my-name", namedId.ToString());
}
[Fact]
public void Should_make_correct_equal_comparisons()
{
var id1 = Guid.NewGuid();
var id2 = Guid.NewGuid();
var token1a = new NamedId<Guid>(id1, "my-name1");
var token1b = new NamedId<Guid>(id1, "my-name1");
var token1c = new NamedId<Guid>(id1, "my-name2");
var token2a = new NamedId<Guid>(id2, "my-name1");
Assert.True(token1a.Equals(token1b));
Assert.False(token1a.Equals(token2a));
Assert.False(token1a.Equals(token1c));
}
[Fact]
public void Should_make_correct_object_equal_comparisons()
{
var id1 = Guid.NewGuid();
var id2 = Guid.NewGuid();
object token1a = new NamedId<Guid>(id1, "my-name1");
object token1b = new NamedId<Guid>(id1, "my-name1");
object token1c = new NamedId<Guid>(id1, "my-name2");
object token2a = new NamedId<Guid>(id2, "my-name1");
Assert.True(token1a.Equals(token1b));
Assert.False(token1a.Equals(token2a));
Assert.False(token1a.Equals(token1c));
}
[Fact]
public void Should_provide_correct_hash_codes()
{
var id1 = Guid.NewGuid();
var id2 = Guid.NewGuid();
object token1a = new NamedId<Guid>(id1, "my-name1");
object token1b = new NamedId<Guid>(id1, "my-name1");
object token1c = new NamedId<Guid>(id1, "my-name2");
object token2a = new NamedId<Guid>(id2, "my-name1");
Assert.Equal(token1a.GetHashCode(), token1b.GetHashCode());
Assert.NotEqual(token1a.GetHashCode(), token2a.GetHashCode());
Assert.NotEqual(token1a.GetHashCode(), token1c.GetHashCode());
}
[Fact]
public void Should_serialize_and_deserialize_null_guid_token()
{
JsonHelper.SerializeAndDeserialize<NamedId<Guid>>(null, new NamedGuidIdConverter());
}
[Fact]
public void Should_serialize_and_deserialize_valid_guid_token()
{
new NamedId<Guid>(Guid.NewGuid(), "my-name").SerializeAndDeserialize(new NamedGuidIdConverter());
}
[Fact]
public void Should_serialize_and_deserialize_null_long_token()
{
JsonHelper.SerializeAndDeserialize<NamedId<long>>(null, new NamedLongIdConverter());
}
[Fact]
public void Should_serialize_and_deserialize_valid_long_token()
{
new NamedId<long>(123, "my-name").SerializeAndDeserialize(new NamedLongIdConverter());
}
[Fact]
public void Should_serialize_and_deserialize_null_string_token()
{
JsonHelper.SerializeAndDeserialize<NamedId<string>>(null, new NamedStringIdConverter());
}
[Fact]
public void Should_serialize_and_deserialize_valid_string_token()
{
new NamedId<string>(Guid.NewGuid().ToString(), "my-name").SerializeAndDeserialize(new NamedStringIdConverter());
}
[Fact]
public void Should_throw_if_string_id_is_not_valid()
{
JsonHelper.DoesNotDeserialize<NamedId<string>>("123", new NamedStringIdConverter());
}
[Fact]
public void Should_throw_if_long_id_is_not_valid()
{
JsonHelper.DoesNotDeserialize<NamedId<long>>("123", new NamedLongIdConverter());
JsonHelper.DoesNotDeserialize<NamedId<long>>("invalid-long,name", new NamedLongIdConverter());
}
[Fact]
public void Should_throw_if_guid_id_is_not_valid()
{
JsonHelper.DoesNotDeserialize<NamedId<Guid>>("123", new NamedGuidIdConverter());
JsonHelper.DoesNotDeserialize<NamedId<Guid>>("invalid-guid,name", new NamedGuidIdConverter());
}
}
}

4
tests/Squidex.Infrastructure.Tests/PropertiesBagTests.cs

@ -39,9 +39,9 @@ namespace Squidex.Infrastructure
serializerSettings.Converters.Add(new PropertiesBagConverter());
var content = JsonConvert.SerializeObject(bag, serializerSettings);
var response = JsonConvert.DeserializeObject<PropertiesBag>(content, serializerSettings);
var output = JsonConvert.DeserializeObject<PropertiesBag>(content, serializerSettings);
Assert.Equal(bag.Count, response.Count);
Assert.Equal(bag.Count, output.Count);
}
[Fact]

37
tests/Squidex.Infrastructure.Tests/RefTokenTests.cs

@ -7,8 +7,8 @@
// ==========================================================================
using System;
using Newtonsoft.Json;
using Squidex.Infrastructure.Json;
using Squidex.Infrastructure.TestHelpers;
using Xunit;
// ReSharper disable RedundantCast
@ -17,14 +17,6 @@ namespace Squidex.Infrastructure
{
public class RefTokenTests
{
private static readonly JsonSerializerSettings serializerSettings = new JsonSerializerSettings();
static RefTokenTests()
{
serializerSettings.Converters.Add(new RefTokenConverter());
serializerSettings.NullValueHandling = NullValueHandling.Include;
}
[Theory]
[InlineData("")]
[InlineData(" ")]
@ -84,24 +76,23 @@ namespace Squidex.Infrastructure
{
var token1a = RefToken.Parse("client:client1");
var token1b = RefToken.Parse("client:client1");
var token2 = RefToken.Parse("client:client2");
var token2a = RefToken.Parse("client:client2");
Assert.True(token1a.Equals(token1b));
Assert.False(token1a.Equals(token2));
Assert.False(token1a.Equals(token2a));
}
[Fact]
public void Should_make_correct_object_equal_comparisons()
{
var token1a = RefToken.Parse("client:client1");
object token1a = RefToken.Parse("client:client1");
object token1b = RefToken.Parse("client:client1");
object token2 = RefToken.Parse("client:client2");
object token2a = RefToken.Parse("client:client2");
Assert.True(token1a.Equals(token1b));
Assert.False(token1a.Equals(token2));
Assert.False(token1a.Equals(token2a));
}
[Fact]
@ -109,31 +100,23 @@ namespace Squidex.Infrastructure
{
var token1a = RefToken.Parse("client:client1");
var token1b = RefToken.Parse("client:client1");
var token2 = RefToken.Parse("client:client2");
var token2a = RefToken.Parse("client:client2");
Assert.Equal(token1a.GetHashCode(), token1b.GetHashCode());
Assert.NotEqual(token1a.GetHashCode(), token2.GetHashCode());
Assert.NotEqual(token1a.GetHashCode(), token2a.GetHashCode());
}
[Fact]
public void Should_serialize_and_deserialize_null_token()
{
var input = Tuple.Create<RefToken>(null);
var json = JsonConvert.SerializeObject(input, serializerSettings);
var output = JsonConvert.DeserializeObject<Tuple<RefToken>>(json, serializerSettings);
Assert.Equal(output.Item1, input.Item1);
JsonHelper.SerializeAndDeserialize<RefToken>(null, new RefTokenConverter());
}
[Fact]
public void Should_serialize_and_deserialize_valid_token()
{
var input = Tuple.Create(RefToken.Parse("client:client1"));
var json = JsonConvert.SerializeObject(input, serializerSettings);
var output = JsonConvert.DeserializeObject<Tuple<RefToken>>(json, serializerSettings);
Assert.Equal(output.Item1, input.Item1);
RefToken.Parse("client:client1").SerializeAndDeserialize(new RefTokenConverter());
}
}
}

40
tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs

@ -0,0 +1,40 @@
// ==========================================================================
// JsonHelper.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using Newtonsoft.Json;
using Xunit;
namespace Squidex.Infrastructure.TestHelpers
{
public static class JsonHelper
{
public static void SerializeAndDeserialize<T>(this T value, JsonConverter converter) where T : class
{
var serializerSettings = new JsonSerializerSettings();
serializerSettings.Converters.Add(converter);
serializerSettings.NullValueHandling = NullValueHandling.Include;
var result = JsonConvert.SerializeObject(Tuple.Create(value), serializerSettings);
var output = JsonConvert.DeserializeObject<Tuple<T>>(result, serializerSettings);
Assert.Equal(value, output.Item1);
}
public static void DoesNotDeserialize<T>(string value, JsonConverter converter) where T : class
{
var serializerSettings = new JsonSerializerSettings();
serializerSettings.Converters.Add(converter);
serializerSettings.NullValueHandling = NullValueHandling.Include;
Assert.Throws<JsonSerializationException>(() => JsonConvert.DeserializeObject<Tuple<T>>($"{{ \"Item1\": \"{value}\" }}"));
}
}
}

114
tests/Squidex.Read.Tests/Apps/CachingAppProviderTests.cs

@ -7,14 +7,11 @@
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
using Moq;
using Squidex.Events.Apps;
using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure;
using Squidex.Read.Apps.Repositories;
using Squidex.Read.Apps.Services.Implementations;
using Squidex.Read.MongoDb.Apps;
@ -32,17 +29,12 @@ namespace Squidex.Read.Apps
private readonly CachingAppProvider sut;
private readonly MongoAppEntity appV1;
private readonly MongoAppEntity appV2;
private readonly Guid appId = Guid.NewGuid();
private readonly string appName = "my-app";
private sealed class MyEvent : IEvent
{
}
private readonly NamedId<Guid> appId = new NamedId<Guid>(Guid.NewGuid(), "my-app");
public CachingAppProviderTests()
{
appV1 = new MongoAppEntity { Name = appName, Id = appId };
appV2 = new MongoAppEntity { Name = appName, Id = appId };
appV1 = new MongoAppEntity { Name = appId.Name, Id = appId.Id };
appV2 = new MongoAppEntity { Name = appId.Name, Id = appId.Id };
sut = new CachingAppProvider(cache, repository.Object);
}
@ -50,110 +42,67 @@ namespace Squidex.Read.Apps
[Fact]
public async Task Should_also_retrieve_app_by_name_if_retrieved_by_id_before()
{
repository.Setup(x => x.FindAppAsync(appId)).Returns(Task.FromResult<IAppEntity>(appV1));
repository.Setup(x => x.FindAppAsync(appId.Id)).Returns(Task.FromResult<IAppEntity>(appV1));
await ProvideAppById(appV1);
await ProvideAppByName(appV1);
repository.Verify(x => x.FindAppAsync(appId), Times.Once());
repository.Verify(x => x.FindAppAsync(appName), Times.Never());
repository.Verify(x => x.FindAppAsync(appId.Id), Times.Once());
repository.Verify(x => x.FindAppAsync(appId.Name), Times.Never());
}
[Fact]
public async Task Should_also_retrieve_app_by_id_if_retrieved_by_name_before()
{
repository.Setup(x => x.FindAppAsync(appName)).Returns(Task.FromResult<IAppEntity>(appV1));
repository.Setup(x => x.FindAppAsync(appId.Name)).Returns(Task.FromResult<IAppEntity>(appV1));
await ProvideAppByName(appV1);
await ProvideAppById(appV1);
repository.Verify(x => x.FindAppAsync(appName), Times.Once());
repository.Verify(x => x.FindAppAsync(appId), Times.Never());
}
[Fact]
public async Task Should_ignore_other_events()
{
repository.Setup(x => x.FindAppAsync(appId)).Returns(Task.FromResult<IAppEntity>(appV1));
await ProvideAppById(appV1);
await RaiseEvent(new MyEvent());
await ProvideAppById(appV1);
repository.Verify(x => x.FindAppAsync(appId), Times.Once());
}
[Fact]
public async Task Should_retrieve_by_id_after_created_event()
{
var apps = ProviderResults(null, appV1);
repository.Setup(x => x.FindAppAsync(appId)).Returns(() => Task.FromResult<IAppEntity>(apps()));
await ProvideAppById(null);
await RaiseEvent(new AppCreated { Name = appName });
await ProvideAppById(appV1);
repository.Verify(x => x.FindAppAsync(appId), Times.Exactly(2));
}
[Fact]
public async Task Should_retrieve_by_name_after_created_event()
{
var apps = ProviderResults(null, appV1);
repository.Setup(x => x.FindAppAsync(appName)).Returns(() => Task.FromResult<IAppEntity>(apps()));
await ProvideAppByName(null);
await RaiseEvent(new AppCreated { Name = appName });
await ProvideAppByName(appV1);
repository.Verify(x => x.FindAppAsync(appName), Times.Exactly(2));
repository.Verify(x => x.FindAppAsync(appId.Name), Times.Once());
repository.Verify(x => x.FindAppAsync(appId.Id), Times.Never());
}
[Theory]
[MemberData(nameof(AppEvents))]
public async Task Should_clear_cache_for_id_after_update_event(IEvent @event)
public async Task Should_clear_cache_for_id_after_update_event()
{
var apps = ProviderResults(appV1, appV2);
repository.Setup(x => x.FindAppAsync(appId)).Returns(() => Task.FromResult<IAppEntity>(apps()));
repository.Setup(x => x.FindAppAsync(appId.Id)).Returns(() => Task.FromResult<IAppEntity>(apps()));
await ProvideAppById(appV1);
await RaiseEvent(@event);
sut.Remove(appId);
await ProvideAppById(appV2);
repository.Verify(x => x.FindAppAsync(appId), Times.Exactly(2));
repository.Verify(x => x.FindAppAsync(appId.Id), Times.Exactly(2));
}
[Theory]
[MemberData(nameof(AppEvents))]
public async Task Should_clear_cache_for_name_after_update_event(IEvent @event)
public async Task Should_clear_cache_for_name_after_update_event()
{
var apps = ProviderResults(appV1, appV2);
repository.Setup(x => x.FindAppAsync(appName)).Returns(() => Task.FromResult<IAppEntity>(apps()));
repository.Setup(x => x.FindAppAsync(appId.Name)).Returns(() => Task.FromResult<IAppEntity>(apps()));
await ProvideAppByName(appV1);
await RaiseEvent(@event);
await ProvideAppByName(appV2);
repository.Verify(x => x.FindAppAsync(appName), Times.Exactly(2));
}
sut.Remove(appId);
private async Task RaiseEvent(IEvent @event)
{
await sut.On(new Envelope<IEvent>(@event).SetAggregateId(appId));
await ProvideAppByName(appV2);
repository.Verify(x => x.FindAppAsync(appId.Name), Times.Exactly(2));
}
private async Task ProvideAppById(IAppEntity app)
{
Assert.Equal(app, await sut.FindAppByIdAsync(appId));
Assert.Equal(app, await sut.FindAppByIdAsync(appId.Id));
}
private async Task ProvideAppByName(IAppEntity app)
{
Assert.Equal(app, await sut.FindAppByNameAsync(appName));
Assert.Equal(app, await sut.FindAppByNameAsync(appId.Name));
}
private static Func<T> ProviderResults<T>(params T[] items)
@ -162,20 +111,5 @@ namespace Squidex.Read.Apps
return () => items[index++];
}
public static IEnumerable<object[]> AppEvents
{
get
{
yield return new object[] { new AppContributorAssigned() };
yield return new object[] { new AppContributorRemoved() };
yield return new object[] { new AppClientAttached() };
yield return new object[] { new AppClientRevoked() };
yield return new object[] { new AppClientRenamed() };
yield return new object[] { new AppLanguageAdded() };
yield return new object[] { new AppLanguageRemoved() };
yield return new object[] { new AppMasterLanguageSet() };
}
}
}
}

114
tests/Squidex.Read.Tests/Schemas/CachingSchemaProviderTests.cs

@ -7,15 +7,11 @@
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
using Moq;
using Squidex.Events;
using Squidex.Events.Schemas;
using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure;
using Squidex.Read.Schemas.Repositories;
using Squidex.Read.Schemas.Services.Implementations;
using Squidex.Read.MongoDb.Schemas;
@ -33,18 +29,13 @@ namespace Squidex.Read.Schemas
private readonly CachingSchemaProvider sut;
private readonly MongoSchemaEntity schemaV1;
private readonly MongoSchemaEntity schemaV2;
private readonly Guid schemaId = Guid.NewGuid();
private readonly Guid appId = Guid.NewGuid();
private readonly string schemaName = "my-schema";
private sealed class MyEvent : IEvent
{
}
private readonly NamedId<Guid> schemaId = new NamedId<Guid>(Guid.NewGuid(), "my-schema");
private readonly NamedId<Guid> appId = new NamedId<Guid>(Guid.NewGuid(), "my-app");
public CachingSchemaProviderTests()
{
schemaV1 = new MongoSchemaEntity { Name = schemaName, Id = schemaId, AppId = appId };
schemaV2 = new MongoSchemaEntity { Name = schemaName, Id = schemaId, AppId = appId };
schemaV1 = new MongoSchemaEntity { Name = schemaId.Name, Id = schemaId.Id, AppId = appId.Id };
schemaV2 = new MongoSchemaEntity { Name = schemaId.Name, Id = schemaId.Id, AppId = appId.Id };
sut = new CachingSchemaProvider(cache, repository.Object);
}
@ -52,110 +43,67 @@ namespace Squidex.Read.Schemas
[Fact]
public async Task Should_also_retrieve_schema_by_name_if_retrieved_by_id_before()
{
repository.Setup(x => x.FindSchemaAsync(schemaId)).Returns(Task.FromResult<ISchemaEntityWithSchema>(schemaV1));
repository.Setup(x => x.FindSchemaAsync(schemaId.Id)).Returns(Task.FromResult<ISchemaEntityWithSchema>(schemaV1));
await ProvideSchemaById(schemaV1);
await ProvideSchemaByName(schemaV1);
repository.Verify(x => x.FindSchemaAsync(schemaId), Times.Once());
repository.Verify(x => x.FindSchemaAsync(appId, schemaName), Times.Never());
repository.Verify(x => x.FindSchemaAsync(schemaId.Id), Times.Once());
repository.Verify(x => x.FindSchemaAsync(appId.Id, schemaId.Name), Times.Never());
}
[Fact]
public async Task Should_also_retrieve_schema_by_id_if_retrieved_by_name_before()
{
repository.Setup(x => x.FindSchemaAsync(appId, schemaName)).Returns(Task.FromResult<ISchemaEntityWithSchema>(schemaV1));
repository.Setup(x => x.FindSchemaAsync(appId.Id, schemaId.Name)).Returns(Task.FromResult<ISchemaEntityWithSchema>(schemaV1));
await ProvideSchemaByName(schemaV1);
await ProvideSchemaById(schemaV1);
repository.Verify(x => x.FindSchemaAsync(appId, schemaName), Times.Once());
repository.Verify(x => x.FindSchemaAsync(schemaId), Times.Never());
}
[Fact]
public async Task Should_ignore_other_events()
{
repository.Setup(x => x.FindSchemaAsync(schemaId)).Returns(Task.FromResult<ISchemaEntityWithSchema>(schemaV1));
await ProvideSchemaById(schemaV1);
await RaiseEvent(new MyEvent());
await ProvideSchemaById(schemaV1);
repository.Verify(x => x.FindSchemaAsync(schemaId), Times.Once());
}
[Fact]
public async Task Should_retrieve_by_id_after_created_event()
{
var schemas = ProviderResults(null, schemaV1);
repository.Setup(x => x.FindSchemaAsync(schemaId)).Returns(() => Task.FromResult<ISchemaEntityWithSchema>(schemas()));
await ProvideSchemaById(null);
await RaiseEvent(new SchemaCreated { Name = schemaName });
await ProvideSchemaById(schemaV1);
repository.Verify(x => x.FindSchemaAsync(schemaId), Times.Exactly(2));
}
[Fact]
public async Task Should_retrieve_by_name_after_created_event()
{
var schemas = ProviderResults(null, schemaV1);
repository.Setup(x => x.FindSchemaAsync(appId, schemaName)).Returns(() => Task.FromResult<ISchemaEntityWithSchema>(schemas()));
await ProvideSchemaByName(null);
await RaiseEvent(new SchemaCreated { Name = schemaName });
await ProvideSchemaByName(schemaV1);
repository.Verify(x => x.FindSchemaAsync(appId, schemaName), Times.Exactly(2));
repository.Verify(x => x.FindSchemaAsync(appId.Id, schemaId.Name), Times.Once());
repository.Verify(x => x.FindSchemaAsync(schemaId.Id), Times.Never());
}
[Theory]
[MemberData(nameof(SchemaEvents))]
public async Task Should_clear_cache_for_id_after_update_event(IEvent @event)
public async Task Should_clear_cache_for_id_after_update_event()
{
var schemas = ProviderResults(schemaV1, schemaV2);
repository.Setup(x => x.FindSchemaAsync(schemaId)).Returns(() => Task.FromResult<ISchemaEntityWithSchema>(schemas()));
repository.Setup(x => x.FindSchemaAsync(schemaId.Id)).Returns(() => Task.FromResult<ISchemaEntityWithSchema>(schemas()));
await ProvideSchemaById(schemaV1);
await RaiseEvent(@event);
sut.Remove(appId, schemaId);
await ProvideSchemaById(schemaV2);
repository.Verify(x => x.FindSchemaAsync(schemaId), Times.Exactly(2));
repository.Verify(x => x.FindSchemaAsync(schemaId.Id), Times.Exactly(2));
}
[Theory]
[MemberData(nameof(SchemaEvents))]
public async Task Should_clear_cache_for_name_after_update_event(IEvent @event)
public async Task Should_clear_cache_for_name_after_update_event()
{
var schemas = ProviderResults(schemaV1, schemaV2);
repository.Setup(x => x.FindSchemaAsync(appId, schemaName)).Returns(() => Task.FromResult<ISchemaEntityWithSchema>(schemas()));
repository.Setup(x => x.FindSchemaAsync(appId.Id, schemaId.Name)).Returns(() => Task.FromResult<ISchemaEntityWithSchema>(schemas()));
await ProvideSchemaByName(schemaV1);
await RaiseEvent(@event);
await ProvideSchemaByName(schemaV2);
repository.Verify(x => x.FindSchemaAsync(appId, schemaName), Times.Exactly(2));
}
sut.Remove(appId, schemaId);
private async Task RaiseEvent(IEvent @event)
{
await sut.On(new Envelope<IEvent>(@event).SetAggregateId(schemaId).SetAppId(appId));
await ProvideSchemaByName(schemaV2);
repository.Verify(x => x.FindSchemaAsync(appId.Id, schemaId.Name), Times.Exactly(2));
}
private async Task ProvideSchemaById(ISchemaEntityWithSchema schema)
{
Assert.Equal(schema, await sut.FindSchemaByIdAsync(schemaId));
Assert.Equal(schema, await sut.FindSchemaByIdAsync(schemaId.Id));
}
private async Task ProvideSchemaByName(ISchemaEntityWithSchema schema)
{
Assert.Equal(schema, await sut.FindSchemaByNameAsync(appId, schemaName));
Assert.Equal(schema, await sut.FindSchemaByNameAsync(appId.Id, schemaId.Name));
}
private static Func<T> ProviderResults<T>(params T[] items)
@ -164,17 +112,5 @@ namespace Squidex.Read.Schemas
return () => items[index++];
}
public static IEnumerable<object[]> SchemaEvents
{
get
{
yield return new object[] { new SchemaDeleted() };
yield return new object[] { new SchemaPublished() };
yield return new object[] { new SchemaUnpublished() };
yield return new object[] { new SchemaUpdated() };
yield return new object[] { new FieldAdded() };
}
}
}
}

67
tests/Squidex.Write.Tests/Apps/AppCommandHandlerTests.cs

@ -11,13 +11,12 @@ using System.Threading.Tasks;
using FluentAssertions;
using Moq;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Read.Apps;
using Squidex.Read.Apps.Repositories;
using Squidex.Read.Users;
using Squidex.Read.Users.Repositories;
using Squidex.Write.Apps.Commands;
using Squidex.Write.Utils;
using Squidex.Write.TestHelpers;
using Xunit;
// ReSharper disable ImplicitlyCapturedClosure
@ -32,17 +31,15 @@ namespace Squidex.Write.Apps
private readonly Mock<IUserRepository> userRepository = new Mock<IUserRepository>();
private readonly AppCommandHandler sut;
private readonly AppDomainObject app;
private readonly RefToken subjectId = new RefToken("subject", Guid.NewGuid().ToString());
private readonly DateTime expiresUtc = DateTime.UtcNow.AddYears(1);
private readonly Language language = Language.DE;
private readonly string contributorId = Guid.NewGuid().ToString();
private readonly string clientSecret = Guid.NewGuid().ToString();
private readonly string clientName = "client";
private readonly string appName = "my-app";
public AppCommandHandlerTests()
{
app = new AppDomainObject(Id, 0);
app = new AppDomainObject(AppId, 0);
sut = new AppCommandHandler(Handler, appRepository.Object, userRepository.Object, keyGenerator.Object);
}
@ -50,10 +47,9 @@ namespace Squidex.Write.Apps
[Fact]
public async Task Create_should_throw_if_a_name_with_same_name_already_exists()
{
var command = new CreateApp { Name = appName, AggregateId = Id, Actor = subjectId };
var context = new CommandContext(command);
var context = CreateContextForCommand(new CreateApp { Name = AppName, AggregateId = AppId });
appRepository.Setup(x => x.FindAppAsync(appName)).Returns(Task.FromResult(new Mock<IAppEntity>().Object)).Verifiable();
appRepository.Setup(x => x.FindAppAsync(AppName)).Returns(Task.FromResult(new Mock<IAppEntity>().Object)).Verifiable();
await TestCreate(app, async _ =>
{
@ -66,17 +62,16 @@ namespace Squidex.Write.Apps
[Fact]
public async Task Create_should_create_app_if_name_is_free()
{
var command = new CreateApp { Name = appName, AggregateId = Id, Actor = subjectId };
var context = new CommandContext(command);
var context = CreateContextForCommand(new CreateApp { Name = AppName, AggregateId = AppId });
appRepository.Setup(x => x.FindAppAsync(appName)).Returns(Task.FromResult<IAppEntity>(null)).Verifiable();
appRepository.Setup(x => x.FindAppAsync(AppName)).Returns(Task.FromResult<IAppEntity>(null)).Verifiable();
await TestCreate(app, async _ =>
{
await sut.HandleAsync(context);
});
Assert.Equal(command.AggregateId, context.Result<Guid>());
Assert.Equal(AppId, context.Result<Guid>());
}
[Fact]
@ -84,10 +79,9 @@ namespace Squidex.Write.Apps
{
CreateApp();
var command = new AssignContributor { AggregateId = Id, ContributorId = contributorId };
var context = new CommandContext(command);
var context = CreateContextForCommand(new AssignContributor { ContributorId = contributorId });
userRepository.Setup(x => x.FindUserByIdAsync(command.ContributorId)).Returns(Task.FromResult<IUserEntity>(null));
userRepository.Setup(x => x.FindUserByIdAsync(contributorId)).Returns(Task.FromResult<IUserEntity>(null));
await TestUpdate(app, async _ =>
{
@ -100,10 +94,9 @@ namespace Squidex.Write.Apps
{
CreateApp();
var command = new AssignContributor { AggregateId = Id, ContributorId = null };
var context = new CommandContext(command);
var context = CreateContextForCommand(new AssignContributor { ContributorId = null });
userRepository.Setup(x => x.FindUserByIdAsync(command.ContributorId)).Returns(Task.FromResult<IUserEntity>(null));
userRepository.Setup(x => x.FindUserByIdAsync(contributorId)).Returns(Task.FromResult<IUserEntity>(null));
await TestUpdate(app, async _ =>
{
@ -116,10 +109,9 @@ namespace Squidex.Write.Apps
{
CreateApp();
var command = new AssignContributor { AggregateId = Id, ContributorId = contributorId };
var context = new CommandContext(command);
var context = CreateContextForCommand(new AssignContributor { ContributorId = contributorId });
userRepository.Setup(x => x.FindUserByIdAsync(command.ContributorId)).Returns(Task.FromResult(new Mock<IUserEntity>().Object));
userRepository.Setup(x => x.FindUserByIdAsync(contributorId)).Returns(Task.FromResult(new Mock<IUserEntity>().Object));
await TestUpdate(app, async _ =>
{
@ -131,10 +123,9 @@ namespace Squidex.Write.Apps
public async Task RemoveContributor_should_update_domain_object()
{
CreateApp()
.AssignContributor(new AssignContributor { ContributorId = contributorId });
.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId }));
var command = new RemoveContributor { AggregateId = Id, ContributorId = contributorId };
var context = new CommandContext(command);
var context = CreateContextForCommand(new RemoveContributor { ContributorId = contributorId });
await TestUpdate(app, async _ =>
{
@ -151,8 +142,7 @@ namespace Squidex.Write.Apps
var timestamp = DateTime.Today;
var command = new AttachClient { Id = clientName, AggregateId = Id, Timestamp = timestamp };
var context = new CommandContext(command);
var context = CreateContextForCommand(new AttachClient { Id = clientName, Timestamp = timestamp });
await TestUpdate(app, async _ =>
{
@ -169,10 +159,9 @@ namespace Squidex.Write.Apps
public async Task RenameClient_should_update_domain_object()
{
CreateApp()
.AttachClient(new AttachClient { Id = clientName }, clientSecret, expiresUtc);
.AttachClient(CreateCommand(new AttachClient { Id = clientName }), clientSecret, expiresUtc);
var command = new RenameClient { AggregateId = Id, Id = clientName, Name = "New Name" };
var context = new CommandContext(command);
var context = CreateContextForCommand(new RenameClient { Id = clientName, Name = "New Name" });
await TestUpdate(app, async _ =>
{
@ -184,10 +173,9 @@ namespace Squidex.Write.Apps
public async Task RevokeClient_should_update_domain_object()
{
CreateApp()
.AttachClient(new AttachClient { Id = clientName }, clientSecret, expiresUtc);
.AttachClient(CreateCommand(new AttachClient { Id = clientName }), clientSecret, expiresUtc);
var command = new RevokeClient { AggregateId = Id, Id = clientName };
var context = new CommandContext(command);
var context = CreateContextForCommand(new RevokeClient { Id = clientName });
await TestUpdate(app, async _ =>
{
@ -200,8 +188,7 @@ namespace Squidex.Write.Apps
{
CreateApp();
var command = new AddLanguage { AggregateId = Id, Language = language };
var context = new CommandContext(command);
var context = CreateContextForCommand(new AddLanguage { Language = language });
await TestUpdate(app, async _ =>
{
@ -213,10 +200,9 @@ namespace Squidex.Write.Apps
public async Task RemoveLanguage_should_update_domain_object()
{
CreateApp()
.AddLanguage(new AddLanguage { AggregateId = Id, Language = language });
.AddLanguage(CreateCommand(new AddLanguage { Language = language }));
var command = new RemoveLanguage { AggregateId = Id, Language = language };
var context = new CommandContext(command);
var context = CreateContextForCommand(new RemoveLanguage { Language = language });
await TestUpdate(app, async _ =>
{
@ -228,10 +214,9 @@ namespace Squidex.Write.Apps
public async Task SetMasterLanguage_should_update_domain_object()
{
CreateApp()
.AddLanguage(new AddLanguage { AggregateId = Id, Language = language });
.AddLanguage(CreateCommand(new AddLanguage { Language = language }));
var command = new SetMasterLanguage { AggregateId = Id, Language = language };
var context = new CommandContext(command);
var context = CreateContextForCommand(new SetMasterLanguage { Language = language });
await TestUpdate(app, async _ =>
{
@ -241,7 +226,7 @@ namespace Squidex.Write.Apps
private AppDomainObject CreateApp()
{
app.Create(new CreateApp { Name = appName, Actor = subjectId });
app.Create(CreateCommand(new CreateApp { Name = AppName }));
return app;
}

332
tests/Squidex.Write.Tests/Apps/AppDomainObjectTests.cs

@ -8,24 +8,21 @@
using System;
using System.Linq;
using FluentAssertions;
using Squidex.Core.Apps;
using Squidex.Events.Apps;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Write.Apps.Commands;
using Squidex.Write.TestHelpers;
using Xunit;
// ReSharper disable ConvertToConstant.Local
namespace Squidex.Write.Apps
{
public class AppDomainObjectTests
public class AppDomainObjectTests : HandlerTestBase<AppDomainObject>
{
private const string TestName = "app";
private readonly AppDomainObject sut;
private readonly RefToken user = new RefToken("subject", Guid.NewGuid().ToString());
private readonly DateTime expiresUtc = DateTime.UtcNow.AddYears(1);
private readonly string contributorId = Guid.NewGuid().ToString();
private readonly string clientSecret = Guid.NewGuid().ToString();
@ -34,7 +31,7 @@ namespace Squidex.Write.Apps
public AppDomainObjectTests()
{
sut = new AppDomainObject(Guid.NewGuid(), 0);
sut = new AppDomainObject(AppId, 0);
}
[Fact]
@ -42,43 +39,53 @@ namespace Squidex.Write.Apps
{
CreateApp();
Assert.Throws<DomainException>(() => sut.Create(new CreateApp { Name = TestName }));
Assert.Throws<DomainException>(() =>
{
sut.Create(CreateCommand(new CreateApp { Name = AppName }));
});
}
[Fact]
public void Create_should_throw_if_command_is_not_valid()
{
Assert.Throws<ValidationException>(() => sut.Create(new CreateApp()));
Assert.Throws<ValidationException>(() =>
{
sut.Create(CreateCommand(new CreateApp()));
});
}
[Fact]
public void Create_should_specify_name_and_owner()
{
sut.Create(new CreateApp { Name = TestName, Actor = user });
sut.Create(CreateCommand(new CreateApp { Name = AppName, Actor = User, AggregateId = AppId }));
Assert.Equal(TestName, sut.Name);
Assert.Equal(AppName, sut.Name);
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new AppCreated { Name = TestName },
new AppContributorAssigned { ContributorId = user.Identifier, Permission = PermissionLevel.Owner },
new AppLanguageAdded { Language = Language.EN },
new AppMasterLanguageSet { Language = Language.EN }
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new AppCreated { Name = AppName }),
CreateEvent(new AppContributorAssigned { ContributorId = User.Identifier, Permission = PermissionLevel.Owner }),
CreateEvent(new AppLanguageAdded { Language = Language.EN }),
CreateEvent(new AppMasterLanguageSet { Language = Language.EN })
);
}
[Fact]
public void AssignContributor_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.AssignContributor(new AssignContributor { ContributorId = contributorId }));
Assert.Throws<DomainException>(() =>
{
sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId }));
});
}
[Fact]
public void AssignContributor_should_throw_if_command_is_not_valid()
{
Assert.Throws<ValidationException>(() => sut.AssignContributor(new AssignContributor()));
Assert.Throws<ValidationException>(() =>
{
sut.AssignContributor(CreateCommand(new AssignContributor()));
});
}
[Fact]
@ -86,16 +93,22 @@ namespace Squidex.Write.Apps
{
CreateApp();
Assert.Throws<ValidationException>(() => sut.AssignContributor(new AssignContributor { ContributorId = user.Identifier, Permission = PermissionLevel.Editor }));
Assert.Throws<ValidationException>(() =>
{
sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = User.Identifier, Permission = PermissionLevel.Editor }));
});
}
[Fact]
public void AssignContributor_should_throw_if_user_already_contributor()
{
CreateApp();
sut.AssignContributor(new AssignContributor { ContributorId = contributorId, Permission = PermissionLevel.Editor });
sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId, Permission = PermissionLevel.Editor }));
Assert.Throws<ValidationException>(() => sut.AssignContributor(new AssignContributor { ContributorId = contributorId, Permission = PermissionLevel.Editor }));
Assert.Throws<ValidationException>(() =>
{
sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId, Permission = PermissionLevel.Editor }));
});
}
[Fact]
@ -103,26 +116,30 @@ namespace Squidex.Write.Apps
{
CreateApp();
sut.AssignContributor(new AssignContributor { ContributorId = contributorId, Permission = PermissionLevel.Editor });
sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId, Permission = PermissionLevel.Editor }));
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new AppContributorAssigned { ContributorId = contributorId, Permission = PermissionLevel.Editor }
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new AppContributorAssigned { ContributorId = contributorId, Permission = PermissionLevel.Editor })
);
}
[Fact]
public void RemoveContributor_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.RemoveContributor(new RemoveContributor { ContributorId = contributorId }));
Assert.Throws<DomainException>(() =>
{
sut.RemoveContributor(CreateCommand(new RemoveContributor { ContributorId = contributorId }));
});
}
[Fact]
public void RemoveContributor_should_throw_if_command_is_not_valid()
{
Assert.Throws<ValidationException>(() => sut.RemoveContributor(new RemoveContributor()));
Assert.Throws<ValidationException>(() =>
{
sut.RemoveContributor(CreateCommand(new RemoveContributor()));
});
}
[Fact]
@ -130,7 +147,10 @@ namespace Squidex.Write.Apps
{
CreateApp();
Assert.Throws<ValidationException>(() => sut.RemoveContributor(new RemoveContributor { ContributorId = user.Identifier }));
Assert.Throws<ValidationException>(() =>
{
sut.RemoveContributor(CreateCommand(new RemoveContributor { ContributorId = User.Identifier }));
});
}
[Fact]
@ -138,7 +158,10 @@ namespace Squidex.Write.Apps
{
CreateApp();
Assert.Throws<DomainObjectNotFoundException>(() => sut.RemoveContributor(new RemoveContributor { ContributorId = "not-found" }));
Assert.Throws<DomainObjectNotFoundException>(() =>
{
sut.RemoveContributor(CreateCommand(new RemoveContributor { ContributorId = "not-found" }));
});
}
[Fact]
@ -146,21 +169,22 @@ namespace Squidex.Write.Apps
{
CreateApp();
sut.AssignContributor(new AssignContributor { ContributorId = contributorId, Permission = PermissionLevel.Editor });
sut.RemoveContributor(new RemoveContributor { ContributorId = contributorId });
sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId, Permission = PermissionLevel.Editor }));
sut.RemoveContributor(CreateCommand(new RemoveContributor { ContributorId = contributorId }));
sut.GetUncomittedEvents().Select(x => x.Payload).Skip(1).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new AppContributorRemoved { ContributorId = contributorId }
});
sut.GetUncomittedEvents().Skip(1)
.ShouldHaveSameEvents(
CreateEvent(new AppContributorRemoved { ContributorId = contributorId })
);
}
[Fact]
public void AttachClient_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.AttachClient(new AttachClient { Id = clientId }, clientSecret, expiresUtc));
Assert.Throws<DomainException>(() =>
{
sut.AttachClient(CreateCommand(new AttachClient { Id = clientId }), clientSecret, expiresUtc);
});
}
[Fact]
@ -168,8 +192,15 @@ namespace Squidex.Write.Apps
{
CreateApp();
Assert.Throws<ValidationException>(() => sut.AttachClient(new AttachClient(), clientSecret, expiresUtc));
Assert.Throws<ValidationException>(() => sut.AttachClient(new AttachClient { Id = string.Empty }, clientSecret, expiresUtc));
Assert.Throws<ValidationException>(() =>
{
sut.AttachClient(CreateCommand(new AttachClient()), clientSecret, expiresUtc);
});
Assert.Throws<ValidationException>(() =>
{
sut.AttachClient(CreateCommand(new AttachClient { Id = string.Empty }), clientSecret, expiresUtc);
});
}
[Fact]
@ -177,9 +208,12 @@ namespace Squidex.Write.Apps
{
CreateApp();
sut.AttachClient(new AttachClient { Id = clientId }, clientSecret, expiresUtc);
sut.AttachClient(CreateCommand(new AttachClient { Id = clientId }), clientSecret, expiresUtc);
Assert.Throws<ValidationException>(() => sut.AttachClient(new AttachClient { Id = clientId }, clientSecret, expiresUtc));
Assert.Throws<ValidationException>(() =>
{
sut.AttachClient(CreateCommand(new AttachClient { Id = clientId }), clientSecret, expiresUtc);
});
}
[Fact]
@ -189,20 +223,21 @@ namespace Squidex.Write.Apps
CreateApp();
sut.AttachClient(new AttachClient { Id = clientId, Timestamp = now }, clientSecret, expiresUtc);
sut.AttachClient(CreateCommand(new AttachClient { Id = clientId, Timestamp = now }), clientSecret, expiresUtc);
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new AppClientAttached { Id = clientId, Secret = clientSecret, ExpiresUtc = expiresUtc }
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new AppClientAttached { Id = clientId, Secret = clientSecret, ExpiresUtc = expiresUtc })
);
}
[Fact]
public void RevokeClient_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.RevokeClient(new RevokeClient { Id = "not-found" }));
Assert.Throws<DomainException>(() =>
{
sut.RevokeClient(CreateCommand(new RevokeClient { Id = "not-found" }));
});
}
[Fact]
@ -210,8 +245,15 @@ namespace Squidex.Write.Apps
{
CreateApp();
Assert.Throws<ValidationException>(() => sut.RevokeClient(new RevokeClient()));
Assert.Throws<ValidationException>(() => sut.RevokeClient(new RevokeClient { Id = string.Empty }));
Assert.Throws<ValidationException>(() =>
{
sut.RevokeClient(CreateCommand(new RevokeClient()));
});
Assert.Throws<ValidationException>(() =>
{
sut.RevokeClient(CreateCommand(new RevokeClient { Id = string.Empty }));
});
}
[Fact]
@ -219,29 +261,33 @@ namespace Squidex.Write.Apps
{
CreateApp();
Assert.Throws<DomainObjectNotFoundException>(() => sut.RevokeClient(new RevokeClient { Id = "not-found" }));
Assert.Throws<DomainObjectNotFoundException>(() =>
{
sut.RevokeClient(CreateCommand(new RevokeClient { Id = "not-found" }));
});
}
[Fact]
public void RevokeClient_should_create_events()
{
CreateApp();
CreateClient();
sut.AttachClient(new AttachClient { Id = clientId }, clientSecret, expiresUtc);
sut.RevokeClient(new RevokeClient { Id = clientId });
sut.RevokeClient(CreateCommand(new RevokeClient { Id = clientId }));
sut.GetUncomittedEvents().Select(x => x.Payload).Skip(1).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new AppClientRevoked { Id = clientSecret }
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new AppClientRevoked { Id = clientId })
);
}
[Fact]
public void RenameClient_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.RenameClient(new RenameClient { Id = "not-found", Name = clientNewName }));
Assert.Throws<DomainException>(() =>
{
sut.RenameClient(CreateCommand(new RenameClient { Id = "not-found", Name = clientNewName }));
});
}
[Fact]
@ -249,8 +295,15 @@ namespace Squidex.Write.Apps
{
CreateApp();
Assert.Throws<ValidationException>(() => sut.RenameClient(new RenameClient()));
Assert.Throws<ValidationException>(() => sut.RenameClient(new RenameClient { Id = string.Empty }));
Assert.Throws<ValidationException>(() =>
{
sut.RenameClient(CreateCommand(new RenameClient()));
});
Assert.Throws<ValidationException>(() =>
{
sut.RenameClient(CreateCommand(new RenameClient { Id = string.Empty }));
});
}
[Fact]
@ -258,40 +311,47 @@ namespace Squidex.Write.Apps
{
CreateApp();
Assert.Throws<DomainObjectNotFoundException>(() => sut.RenameClient(new RenameClient { Id = "not-found", Name = clientNewName }));
Assert.Throws<DomainObjectNotFoundException>(() =>
{
sut.RenameClient(CreateCommand(new RenameClient { Id = "not-found", Name = clientNewName }));
});
}
[Fact]
public void RenameClient_should_throw_if_same_client_name()
{
CreateApp();
CreateClient();
sut.AttachClient(new AttachClient { Id = clientId }, clientSecret, expiresUtc);
sut.RenameClient(new RenameClient { Id = clientId, Name = clientNewName });
sut.RenameClient(CreateCommand(new RenameClient { Id = clientId, Name = clientNewName }));
Assert.Throws<ValidationException>(() => sut.RenameClient(new RenameClient { Id = clientId, Name = clientNewName }));
Assert.Throws<ValidationException>(() =>
{
sut.RenameClient(CreateCommand(new RenameClient { Id = clientId, Name = clientNewName }));
});
}
[Fact]
public void RenameClient_should_create_events()
{
CreateApp();
CreateClient();
sut.AttachClient(new AttachClient { Id = clientId }, clientSecret, expiresUtc);
sut.RenameClient(new RenameClient { Id = clientId, Name = clientNewName });
sut.RenameClient(CreateCommand(new RenameClient { Id = clientId, Name = clientNewName }));
sut.GetUncomittedEvents().Select(x => x.Payload).Skip(1).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new AppClientRenamed { Id = clientId, Name = clientNewName }
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new AppClientRenamed { Id = clientId, Name = clientNewName })
);
}
[Fact]
public void AddLanguage_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.AddLanguage(new AddLanguage { Language = Language.DE }));
Assert.Throws<DomainException>(() =>
{
sut.AddLanguage(CreateCommand(new AddLanguage { Language = Language.DE }));
});
}
[Fact]
@ -299,7 +359,10 @@ namespace Squidex.Write.Apps
{
CreateApp();
Assert.Throws<ValidationException>(() => sut.AddLanguage(new AddLanguage()));
Assert.Throws<ValidationException>(() =>
{
sut.AddLanguage(CreateCommand(new AddLanguage()));
});
}
[Fact]
@ -307,7 +370,10 @@ namespace Squidex.Write.Apps
{
CreateApp();
Assert.Throws<ValidationException>(() => sut.AddLanguage(new AddLanguage { Language = Language.EN }));
Assert.Throws<ValidationException>(() =>
{
sut.AddLanguage(CreateCommand(new AddLanguage { Language = Language.EN }));
});
}
[Fact]
@ -315,20 +381,21 @@ namespace Squidex.Write.Apps
{
CreateApp();
sut.AddLanguage(new AddLanguage { Language = Language.DE });
sut.AddLanguage(CreateCommand(new AddLanguage { Language = Language.DE }));
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new AppLanguageAdded { Language = Language.DE }
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new AppLanguageAdded { Language = Language.DE })
);
}
[Fact]
public void RemoveLanguage_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.RemoveLanguage(new RemoveLanguage { Language = Language.EN }));
Assert.Throws<DomainException>(() =>
{
sut.RemoveLanguage(CreateCommand(new RemoveLanguage { Language = Language.EN }));
});
}
[Fact]
@ -336,7 +403,10 @@ namespace Squidex.Write.Apps
{
CreateApp();
Assert.Throws<ValidationException>(() => sut.RemoveLanguage(new RemoveLanguage()));
Assert.Throws<ValidationException>(() =>
{
sut.RemoveLanguage(CreateCommand(new RemoveLanguage()));
});
}
[Fact]
@ -344,7 +414,10 @@ namespace Squidex.Write.Apps
{
CreateApp();
Assert.Throws<DomainObjectNotFoundException>(() => sut.RemoveLanguage(new RemoveLanguage { Language = Language.DE }));
Assert.Throws<DomainObjectNotFoundException>(() =>
{
sut.RemoveLanguage(CreateCommand(new RemoveLanguage { Language = Language.DE }));
});
}
[Fact]
@ -352,29 +425,33 @@ namespace Squidex.Write.Apps
{
CreateApp();
Assert.Throws<ValidationException>(() => sut.RemoveLanguage(new RemoveLanguage { Language = Language.EN }));
Assert.Throws<ValidationException>(() =>
{
sut.RemoveLanguage(CreateCommand(new RemoveLanguage { Language = Language.EN }));
});
}
[Fact]
public void RemoveLanguage_should_create_events()
{
CreateApp();
CreateLanguage();
sut.AddLanguage(new AddLanguage { Language = Language.DE });
sut.RemoveLanguage(new RemoveLanguage { Language = Language.DE });
sut.RemoveLanguage(CreateCommand(new RemoveLanguage { Language = Language.DE }));
sut.GetUncomittedEvents().Select(x => x.Payload).Skip(1).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new AppLanguageRemoved { Language = Language.DE }
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new AppLanguageRemoved { Language = Language.DE })
);
}
[Fact]
public void SetMasterLanguage_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.SetMasterLanguage(new SetMasterLanguage { Language = Language.EN }));
Assert.Throws<DomainException>(() =>
{
sut.SetMasterLanguage(CreateCommand(new SetMasterLanguage { Language = Language.EN }));
});
}
[Fact]
@ -382,7 +459,10 @@ namespace Squidex.Write.Apps
{
CreateApp();
Assert.Throws<ValidationException>(() => sut.SetMasterLanguage(new SetMasterLanguage()));
Assert.Throws<ValidationException>(() =>
{
sut.SetMasterLanguage(CreateCommand(new SetMasterLanguage()));
});
}
[Fact]
@ -390,7 +470,10 @@ namespace Squidex.Write.Apps
{
CreateApp();
Assert.Throws<DomainObjectNotFoundException>(() => sut.SetMasterLanguage(new SetMasterLanguage { Language = Language.DE }));
Assert.Throws<DomainObjectNotFoundException>(() =>
{
sut.SetMasterLanguage(CreateCommand(new SetMasterLanguage { Language = Language.DE }));
});
}
[Fact]
@ -398,28 +481,43 @@ namespace Squidex.Write.Apps
{
CreateApp();
Assert.Throws<ValidationException>(() => sut.SetMasterLanguage(new SetMasterLanguage { Language = Language.EN }));
Assert.Throws<ValidationException>(() =>
{
sut.SetMasterLanguage(CreateCommand(new SetMasterLanguage { Language = Language.EN }));
});
}
[Fact]
public void SetMasterLanguage_should_create_events()
{
CreateApp();
CreateLanguage();
sut.AddLanguage(new AddLanguage { Language = Language.DE });
sut.SetMasterLanguage(new SetMasterLanguage { Language = Language.DE });
sut.SetMasterLanguage(CreateCommand(new SetMasterLanguage { Language = Language.DE }));
sut.GetUncomittedEvents().Select(x => x.Payload).Skip(1).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new AppMasterLanguageSet { Language = Language.DE }
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new AppMasterLanguageSet { Language = Language.DE })
);
}
private void CreateApp()
{
sut.Create(new CreateApp { Name = TestName, Actor = user });
sut.Create(CreateCommand(new CreateApp { Name = AppName }));
((IAggregate)sut).ClearUncommittedEvents();
}
private void CreateClient()
{
sut.AttachClient(CreateCommand(new AttachClient { Id = clientId }), clientSecret, expiresUtc);
((IAggregate)sut).ClearUncommittedEvents();
}
private void CreateLanguage()
{
sut.AddLanguage(CreateCommand(new AddLanguage { Language = Language.DE }));
((IAggregate)sut).ClearUncommittedEvents();
}

45
tests/Squidex.Write.Tests/Contents/ContentCommandHandlerTests.cs

@ -12,13 +12,12 @@ using Moq;
using Squidex.Core.Contents;
using Squidex.Core.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Read.Apps;
using Squidex.Read.Apps.Services;
using Squidex.Read.Schemas;
using Squidex.Read.Schemas.Services;
using Squidex.Write.Contents.Commands;
using Squidex.Write.Utils;
using Squidex.Write.TestHelpers;
using Xunit;
// ReSharper disable ConvertToConstant.Local
@ -33,9 +32,8 @@ namespace Squidex.Write.Contents
private readonly Mock<IAppProvider> appProvider = new Mock<IAppProvider>();
private readonly Mock<ISchemaEntityWithSchema> schemaEntity = new Mock<ISchemaEntityWithSchema>();
private readonly Mock<IAppEntity> appEntity = new Mock<IAppEntity>();
private readonly Guid schemaId = Guid.NewGuid();
private readonly Guid appId = Guid.NewGuid();
private readonly ContentData data = new ContentData().AddField("my-field", new ContentFieldData().SetValue(1));
private readonly Guid contentId = Guid.NewGuid();
public ContentCommandHandlerTests()
{
@ -44,22 +42,21 @@ namespace Squidex.Write.Contents
.AddOrUpdateField(new NumberField(1, "my-field",
new NumberFieldProperties { IsRequired = true }));
content = new ContentDomainObject(Id, 0);
content = new ContentDomainObject(contentId, 0);
sut = new ContentCommandHandler(Handler, appProvider.Object, schemaProvider.Object);
appEntity.Setup(x => x.Languages).Returns(new[] { Language.DE });
appProvider.Setup(x => x.FindAppByIdAsync(appId)).Returns(Task.FromResult(appEntity.Object));
appProvider.Setup(x => x.FindAppByIdAsync(AppId)).Returns(Task.FromResult(appEntity.Object));
schemaEntity.Setup(x => x.Schema).Returns(schema);
schemaProvider.Setup(x => x.FindSchemaByIdAsync(schemaId)).Returns(Task.FromResult(schemaEntity.Object));
schemaProvider.Setup(x => x.FindSchemaByIdAsync(SchemaId)).Returns(Task.FromResult(schemaEntity.Object));
}
[Fact]
public async Task Create_should_throw_exception_if_data_is_not_valid()
{
var command = new CreateContent { AggregateId = Id, AppId = appId, SchemaId = schemaId, Data = new ContentData() };
var context = new CommandContext(command);
var context = CreateContextForCommand(new CreateContent { ContentId = contentId, Data = new ContentData() });
await TestCreate(content, async _ =>
{
@ -70,15 +67,14 @@ namespace Squidex.Write.Contents
[Fact]
public async Task Create_should_create_content()
{
var command = new CreateContent { AggregateId = Id, AppId = appId, SchemaId = schemaId, Data = data };
var context = new CommandContext(command);
var context = CreateContextForCommand(new CreateContent { ContentId = contentId, Data = data });
await TestCreate(content, async _ =>
{
await sut.HandleAsync(context);
});
Assert.Equal(Id, context.Result<Guid>());
Assert.Equal(contentId, context.Result<Guid>());
}
[Fact]
@ -86,8 +82,7 @@ namespace Squidex.Write.Contents
{
CreateContent();
var command = new UpdateContent { AggregateId = Id, AppId = appId, SchemaId = schemaId, Data = new ContentData() };
var context = new CommandContext(command);
var context = CreateContextForCommand(new UpdateContent { ContentId = contentId, Data = new ContentData() });
await TestUpdate(content, async _ =>
{
@ -100,8 +95,7 @@ namespace Squidex.Write.Contents
{
CreateContent();
var command = new UpdateContent { AggregateId = Id, AppId = appId, SchemaId = schemaId, Data = data };
var context = new CommandContext(command);
var context = CreateContextForCommand(new UpdateContent { ContentId = contentId, Data = data });
await TestUpdate(content, async _ =>
{
@ -114,8 +108,7 @@ namespace Squidex.Write.Contents
{
CreateContent();
var command = new PatchContent { AggregateId = Id, AppId = appId, SchemaId = schemaId, Data = new ContentData() };
var context = new CommandContext(command);
var context = CreateContextForCommand(new PatchContent { ContentId = contentId, Data = new ContentData() });
await TestUpdate(content, async _ =>
{
@ -126,10 +119,11 @@ namespace Squidex.Write.Contents
[Fact]
public async Task Patch_should_update_domain_object()
{
var otherContent = new ContentData().AddField("my-field", new ContentFieldData().SetValue(3));
CreateContent();
var command = new PatchContent { AggregateId = Id, AppId = appId, SchemaId = schemaId, Data = data };
var context = new CommandContext(command);
var context = CreateContextForCommand(new PatchContent { ContentId = contentId, Data = otherContent });
await TestUpdate(content, async _ =>
{
@ -142,8 +136,7 @@ namespace Squidex.Write.Contents
{
CreateContent();
var command = new PublishContent { AggregateId = Id, AppId = appId, SchemaId = schemaId };
var context = new CommandContext(command);
var context = CreateContextForCommand(new PublishContent { ContentId = contentId });
await TestUpdate(content, async _ =>
{
@ -156,8 +149,7 @@ namespace Squidex.Write.Contents
{
CreateContent();
var command = new UnpublishContent { AggregateId = Id, AppId = appId, SchemaId = schemaId };
var context = new CommandContext(command);
var context = CreateContextForCommand(new UnpublishContent { ContentId = contentId });
await TestUpdate(content, async _ =>
{
@ -170,12 +162,11 @@ namespace Squidex.Write.Contents
{
CreateContent();
var command = new DeleteContent { AggregateId = Id };
var context = new CommandContext(command);
var command = CreateContextForCommand(new DeleteContent { ContentId = contentId });
await TestUpdate(content, async _ =>
{
await sut.HandleAsync(context);
await sut.HandleAsync(command);
});
}

184
tests/Squidex.Write.Tests/Contents/ContentDomainObjectTests.cs

@ -7,23 +7,21 @@
// ==========================================================================
using System;
using System.Linq;
using FluentAssertions;
using Squidex.Core.Contents;
using Squidex.Events.Contents;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Write.Contents.Commands;
using Squidex.Write.TestHelpers;
using Xunit;
// ReSharper disable ConvertToConstant.Local
namespace Squidex.Write.Contents
{
public class ContentDomainObjectTests
public class ContentDomainObjectTests : HandlerTestBase<ContentDomainObject>
{
private readonly Guid appId = Guid.NewGuid();
private readonly ContentDomainObject sut;
private readonly ContentData data =
new ContentData()
@ -36,9 +34,11 @@ namespace Squidex.Write.Contents
new ContentFieldData()
.AddValue("iv", 2));
public Guid ContentId { get; } = Guid.NewGuid();
public ContentDomainObjectTests()
{
sut = new ContentDomainObject(Guid.NewGuid(), 0);
sut = new ContentDomainObject(ContentId, 0);
}
[Fact]
@ -46,32 +46,39 @@ namespace Squidex.Write.Contents
{
sut.Create(new CreateContent { Data = data });
Assert.Throws<DomainException>(() => sut.Create(new CreateContent { Data = data }));
Assert.Throws<DomainException>(() =>
{
sut.Create(CreateContentCommand(new CreateContent { Data = data }));
});
}
[Fact]
public void Create_should_throw_if_command_is_not_valid()
{
Assert.Throws<ValidationException>(() => sut.Create(new CreateContent()));
Assert.Throws<ValidationException>(() =>
{
sut.Create(CreateContentCommand(new CreateContent()));
});
}
[Fact]
public void Create_should_create_events()
{
sut.Create(new CreateContent { Data = data, AppId = appId });
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new ContentCreated { Data = data }
});
sut.Create(CreateContentCommand(new CreateContent { Data = data }));
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateContentEvent(new ContentCreated { Data = data })
);
}
[Fact]
public void Update_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.Update(new UpdateContent { Data = data }));
Assert.Throws<DomainException>(() =>
{
sut.Update(CreateContentCommand(new UpdateContent { Data = data }));
});
}
[Fact]
@ -80,7 +87,10 @@ namespace Squidex.Write.Contents
CreateContent();
DeleteContent();
Assert.Throws<ValidationException>(() => sut.Update(new UpdateContent()));
Assert.Throws<ValidationException>(() =>
{
sut.Update(CreateContentCommand(new UpdateContent()));
});
}
[Fact]
@ -88,7 +98,10 @@ namespace Squidex.Write.Contents
{
CreateContent();
Assert.Throws<ValidationException>(() => sut.Update(new UpdateContent()));
Assert.Throws<ValidationException>(() =>
{
sut.Update(CreateContentCommand(new UpdateContent()));
});
}
[Fact]
@ -97,14 +110,12 @@ namespace Squidex.Write.Contents
CreateContent();
UpdateContent();
sut.Update(new UpdateContent { Data = otherData });
sut.Update(CreateContentCommand(new UpdateContent { Data = otherData }));
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new ContentUpdated { Data = otherData }
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateContentEvent(new ContentUpdated { Data = otherData })
);
}
[Fact]
@ -113,15 +124,18 @@ namespace Squidex.Write.Contents
CreateContent();
UpdateContent();
sut.Update(new UpdateContent { Data = data });
sut.Update(CreateContentCommand(new UpdateContent { Data = data }));
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray().ShouldBeEquivalentTo(new IEvent[0]);
sut.GetUncomittedEvents().Should().BeEmpty();
}
[Fact]
public void Patch_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.Patch(new PatchContent { Data = data }));
Assert.Throws<DomainException>(() =>
{
sut.Patch(CreateContentCommand(new PatchContent { Data = data }));
});
}
[Fact]
@ -130,7 +144,10 @@ namespace Squidex.Write.Contents
CreateContent();
DeleteContent();
Assert.Throws<ValidationException>(() => sut.Patch(new PatchContent()));
Assert.Throws<ValidationException>(() =>
{
sut.Patch(CreateContentCommand(new PatchContent()));
});
}
[Fact]
@ -138,7 +155,10 @@ namespace Squidex.Write.Contents
{
CreateContent();
Assert.Throws<ValidationException>(() => sut.Patch(new PatchContent()));
Assert.Throws<ValidationException>(() =>
{
sut.Patch(CreateContentCommand(new PatchContent()));
});
}
[Fact]
@ -147,14 +167,12 @@ namespace Squidex.Write.Contents
CreateContent();
UpdateContent();
sut.Patch(new PatchContent { Data = otherData });
sut.Patch(CreateContentCommand(new PatchContent { Data = otherData }));
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new ContentUpdated { Data = data.MergeInto(otherData) }
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateContentEvent(new ContentUpdated { Data = otherData })
);
}
[Fact]
@ -163,15 +181,18 @@ namespace Squidex.Write.Contents
CreateContent();
UpdateContent();
sut.Patch(new PatchContent { Data = data });
sut.Patch(CreateContentCommand(new PatchContent { Data = data }));
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray().Should().BeEmpty();
sut.GetUncomittedEvents().Should().BeEmpty();
}
[Fact]
public void Publish_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.Publish(new PublishContent()));
Assert.Throws<DomainException>(() =>
{
sut.Publish(CreateContentCommand(new PublishContent()));
});
}
[Fact]
@ -180,7 +201,10 @@ namespace Squidex.Write.Contents
CreateContent();
DeleteContent();
Assert.Throws<DomainException>(() => sut.Publish(new PublishContent()));
Assert.Throws<DomainException>(() =>
{
sut.Publish(CreateContentCommand(new PublishContent()));
});
}
[Fact]
@ -188,22 +212,23 @@ namespace Squidex.Write.Contents
{
CreateContent();
sut.Publish(new PublishContent());
sut.Publish(CreateContentCommand(new PublishContent()));
Assert.True(sut.IsPublished);
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new ContentPublished()
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateContentEvent(new ContentPublished())
);
}
[Fact]
public void Unpublish_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.Unpublish(new UnpublishContent()));
Assert.Throws<DomainException>(() =>
{
sut.Unpublish(CreateContentCommand(new UnpublishContent()));
});
}
[Fact]
@ -212,7 +237,10 @@ namespace Squidex.Write.Contents
CreateContent();
DeleteContent();
Assert.Throws<DomainException>(() => sut.Unpublish(new UnpublishContent()));
Assert.Throws<DomainException>(() =>
{
sut.Unpublish(CreateContentCommand(new UnpublishContent()));
});
}
[Fact]
@ -221,22 +249,23 @@ namespace Squidex.Write.Contents
CreateContent();
PublishContent();
sut.Unpublish(new UnpublishContent());
sut.Unpublish(CreateContentCommand(new UnpublishContent()));
Assert.False(sut.IsPublished);
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new ContentUnpublished()
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateContentEvent(new ContentUnpublished())
);
}
[Fact]
public void Delete_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.Delete(new DeleteContent()));
Assert.Throws<DomainException>(() =>
{
sut.Delete(CreateContentCommand(new DeleteContent()));
});
}
[Fact]
@ -245,7 +274,10 @@ namespace Squidex.Write.Contents
CreateContent();
DeleteContent();
Assert.Throws<DomainException>(() => sut.Delete(new DeleteContent()));
Assert.Throws<DomainException>(() =>
{
sut.Delete(CreateContentCommand(new DeleteContent()));
});
}
[Fact]
@ -253,44 +285,56 @@ namespace Squidex.Write.Contents
{
CreateContent();
sut.Delete(new DeleteContent());
sut.Delete(CreateContentCommand(new DeleteContent()));
Assert.True(sut.IsDeleted);
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new ContentDeleted()
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateContentEvent(new ContentDeleted())
);
}
private void CreateContent()
{
sut.Create(new CreateContent { Data = data, AppId = appId });
sut.Create(CreateContentCommand(new CreateContent { Data = data }));
((IAggregate)sut).ClearUncommittedEvents();
}
private void UpdateContent()
{
sut.Update(new UpdateContent { Data = data, AppId = appId });
sut.Update(CreateContentCommand(new UpdateContent { Data = data }));
((IAggregate)sut).ClearUncommittedEvents();
}
private void PublishContent()
{
sut.Publish(new PublishContent());
sut.Publish(CreateContentCommand(new PublishContent()));
((IAggregate)sut).ClearUncommittedEvents();
}
private void DeleteContent()
{
sut.Delete(new DeleteContent());
sut.Delete(CreateContentCommand(new DeleteContent()));
((IAggregate)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);
}
}
}

71
tests/Squidex.Write.Tests/EnrichWithAppIdProcessorTests.cs

@ -1,71 +0,0 @@
// ==========================================================================
// EnrichWithAppIdProcessorTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Threading.Tasks;
using Squidex.Events;
using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Write.Apps;
using Xunit;
namespace Squidex.Write
{
public class EnrichWithAppIdProcessorTests
{
public sealed class MyAppCommand : AppAggregateCommand
{
}
public sealed class MyNormalCommand : ICommand
{
}
public sealed class MyEvent : IEvent
{
}
private readonly EnrichWithAppIdProcessor sut = new EnrichWithAppIdProcessor();
[Fact]
public async Task Should_not_do_anything_if_not_app_command()
{
var envelope = new Envelope<IEvent>(new MyEvent());
await sut.ProcessEventAsync(envelope, null, new MyNormalCommand());
Assert.False(envelope.Headers.Contains("AppId"));
}
[Fact]
public async Task Should_attach_app_id_from_domain_object()
{
var appId = Guid.NewGuid();
var envelope = new Envelope<IEvent>(new MyEvent());
await sut.ProcessEventAsync(envelope, new AppDomainObject(appId, 1), new MyNormalCommand());
Assert.Equal(appId, envelope.Headers.AppId());
}
[Fact]
public async Task Should_attach_app_id_to_event_envelope()
{
var appId = Guid.NewGuid();
var appCommand = new MyAppCommand { AggregateId = appId };
var envelope = new Envelope<IEvent>(new MyEvent());
await sut.ProcessEventAsync(envelope, null, appCommand);
Assert.Equal(appId, envelope.Headers.AppId());
}
}
}

74
tests/Squidex.Write.Tests/EnrichWithSchemaIdProcessorTests.cs

@ -1,74 +0,0 @@
// ==========================================================================
// EnrichWithSchemaIdProcessorTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Threading.Tasks;
using Squidex.Core.Schemas;
using Squidex.Events;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Write.Schemas;
using Xunit;
namespace Squidex.Write
{
public class EnrichWithSchemaIdProcessorTests
{
public sealed class MySchemaCommand : SchemaAggregateCommand
{
}
public sealed class MyNormalCommand : ICommand
{
}
public sealed class MyEvent : IEvent
{
}
private readonly FieldRegistry registry = new FieldRegistry(new TypeNameRegistry());
private readonly EnrichWithSchemaIdProcessor sut = new EnrichWithSchemaIdProcessor();
[Fact]
public async Task Should_not_do_anything_if_not_app_command()
{
var envelope = new Envelope<IEvent>(new MyEvent());
await sut.ProcessEventAsync(envelope, null, new MyNormalCommand());
Assert.False(envelope.Headers.Contains("SchemaId"));
}
[Fact]
public async Task Should_attach_app_id_from_domain_object()
{
var appId = Guid.NewGuid();
var envelope = new Envelope<IEvent>(new MyEvent());
await sut.ProcessEventAsync(envelope, new SchemaDomainObject(appId, 1, registry), new MyNormalCommand());
Assert.Equal(appId, envelope.Headers.SchemaId());
}
[Fact]
public async Task Should_attach_app_id_to_event_envelope()
{
var appId = Guid.NewGuid();
var appCommand = new MySchemaCommand { AggregateId = appId };
var envelope = new Envelope<IEvent>(new MyEvent());
await sut.ProcessEventAsync(envelope, null, appCommand);
Assert.Equal(appId, envelope.Headers.SchemaId());
}
}
}

59
tests/Squidex.Write.Tests/Schemas/SchemaCommandHandlerTests.cs

@ -6,16 +6,14 @@
// All rights reserved.
// ==========================================================================
using System;
using System.Threading.Tasks;
using Moq;
using Squidex.Core.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Read.Schemas;
using Squidex.Read.Schemas.Services;
using Squidex.Write.Schemas.Commands;
using Squidex.Write.Utils;
using Squidex.Write.TestHelpers;
using Xunit;
// ReSharper disable ConvertToConstant.Local
@ -28,13 +26,11 @@ namespace Squidex.Write.Schemas
private readonly SchemaCommandHandler sut;
private readonly SchemaDomainObject schema;
private readonly FieldRegistry registry = new FieldRegistry(new TypeNameRegistry());
private readonly Guid appId = Guid.NewGuid();
private readonly string fieldName = "age";
private readonly string schemaName = "users";
public SchemaCommandHandlerTests()
{
schema = new SchemaDomainObject(Id, 0, registry);
schema = new SchemaDomainObject(SchemaId, 0, registry);
sut = new SchemaCommandHandler(Handler, schemaProvider.Object);
}
@ -42,10 +38,9 @@ namespace Squidex.Write.Schemas
[Fact]
public async Task Create_should_throw_if_a_name_with_same_name_already_exists()
{
var command = new CreateSchema { Name = schemaName, AppId = appId, AggregateId = Id };
var context = new CommandContext(command);
var context = CreateContextForCommand(new CreateSchema { Name = SchemaName, SchemaId = SchemaId });
schemaProvider.Setup(x => x.FindSchemaByNameAsync(appId, schemaName)).Returns(Task.FromResult(new Mock<ISchemaEntityWithSchema>().Object)).Verifiable();
schemaProvider.Setup(x => x.FindSchemaByNameAsync(AppId, SchemaName)).Returns(Task.FromResult(new Mock<ISchemaEntityWithSchema>().Object)).Verifiable();
await TestCreate(schema, async _ =>
{
@ -58,17 +53,16 @@ namespace Squidex.Write.Schemas
[Fact]
public async Task Create_should_create_schema_if_name_is_free()
{
var command = new CreateSchema { Name = schemaName, AppId = appId, AggregateId = Id };
var context = new CommandContext(command);
var context = CreateContextForCommand(new CreateSchema { Name = SchemaName, SchemaId = SchemaId });
schemaProvider.Setup(x => x.FindSchemaByNameAsync(Id, schemaName)).Returns(Task.FromResult<ISchemaEntityWithSchema>(null)).Verifiable();
schemaProvider.Setup(x => x.FindSchemaByNameAsync(AppId, SchemaName)).Returns(Task.FromResult<ISchemaEntityWithSchema>(null)).Verifiable();
await TestCreate(schema, async _ =>
{
await sut.HandleAsync(context);
});
Assert.Equal(command.Name, context.Result<string>());
Assert.Equal(SchemaName, context.Result<string>());
}
[Fact]
@ -76,8 +70,7 @@ namespace Squidex.Write.Schemas
{
CreateSchema();
var command = new UpdateSchema { AggregateId = Id, Properties = new SchemaProperties() };
var context = new CommandContext(command);
var context = CreateContextForCommand(new UpdateSchema { Properties = new SchemaProperties() });
await TestUpdate(schema, async _ =>
{
@ -90,8 +83,7 @@ namespace Squidex.Write.Schemas
{
CreateSchema();
var command = new PublishSchema { AggregateId = Id };
var context = new CommandContext(command);
var context = CreateContextForCommand(new PublishSchema());
await TestUpdate(schema, async _ =>
{
@ -105,8 +97,7 @@ namespace Squidex.Write.Schemas
CreateSchema();
PublishSchema();
var command = new UnpublishSchema { AggregateId = Id };
var context = new CommandContext(command);
var context = CreateContextForCommand(new UnpublishSchema());
await TestUpdate(schema, async _ =>
{
@ -119,8 +110,7 @@ namespace Squidex.Write.Schemas
{
CreateSchema();
var command = new DeleteSchema { AggregateId = Id };
var context = new CommandContext(command);
var context = CreateContextForCommand(new DeleteSchema());
await TestUpdate(schema, async _ =>
{
@ -133,8 +123,7 @@ namespace Squidex.Write.Schemas
{
CreateSchema();
var command = new AddField { AggregateId = Id, Name = fieldName, Properties = new NumberFieldProperties() };
var context = new CommandContext(command);
var context = CreateContextForCommand(new AddField { Name = fieldName, Properties = new NumberFieldProperties() });
await TestUpdate(schema, async _ =>
{
@ -150,8 +139,7 @@ namespace Squidex.Write.Schemas
CreateSchema();
CreateField();
var command = new UpdateField { AggregateId = Id, FieldId = 1, Properties = new NumberFieldProperties() };
var context = new CommandContext(command);
var context = CreateContextForCommand(new UpdateField { FieldId = 1, Properties = new NumberFieldProperties() });
await TestUpdate(schema, async _ =>
{
@ -165,8 +153,7 @@ namespace Squidex.Write.Schemas
CreateSchema();
CreateField();
var command = new HideField { AggregateId = Id, FieldId = 1 };
var context = new CommandContext(command);
var context = CreateContextForCommand(new HideField { FieldId = 1 });
await TestUpdate(schema, async _ =>
{
@ -180,8 +167,7 @@ namespace Squidex.Write.Schemas
CreateSchema();
CreateField();
var command = new ShowField { AggregateId = Id, FieldId = 1 };
var context = new CommandContext(command);
var context = CreateContextForCommand(new ShowField { FieldId = 1 });
await TestUpdate(schema, async _ =>
{
@ -195,8 +181,7 @@ namespace Squidex.Write.Schemas
CreateSchema();
CreateField();
var command = new DisableField { AggregateId = Id, FieldId = 1 };
var context = new CommandContext(command);
var context = CreateContextForCommand(new DisableField { FieldId = 1 });
await TestUpdate(schema, async _ =>
{
@ -210,8 +195,7 @@ namespace Squidex.Write.Schemas
CreateSchema();
CreateField();
var command = new EnableField { AggregateId = Id, FieldId = 1 };
var context = new CommandContext(command);
var context = CreateContextForCommand(new EnableField { FieldId = 1 });
await TestUpdate(schema, async _ =>
{
@ -225,8 +209,7 @@ namespace Squidex.Write.Schemas
CreateSchema();
CreateField();
var command = new DeleteField { AggregateId = Id, FieldId = 1 };
var context = new CommandContext(command);
var context = CreateContextForCommand(new DeleteField { FieldId = 1 });
await TestUpdate(schema, async _ =>
{
@ -236,17 +219,17 @@ namespace Squidex.Write.Schemas
private void CreateSchema()
{
schema.Create(new CreateSchema { Name = schemaName });
schema.Create(CreateCommand(new CreateSchema { Name = SchemaName }));
}
private void PublishSchema()
{
schema.Publish(new PublishSchema());
schema.Publish(CreateCommand(new PublishSchema()));
}
private void CreateField()
{
schema.AddField(new AddField { Name = fieldName, Properties = new NumberFieldProperties() });
schema.AddField(CreateCommand(new AddField { Name = fieldName, Properties = new NumberFieldProperties() }));
}
}
}

332
tests/Squidex.Write.Tests/Schemas/SchemaDomainObjectTests.cs

@ -6,47 +6,52 @@
// All rights reserved.
// ==========================================================================
using System;
using System.Linq;
using FluentAssertions;
using Squidex.Core.Schemas;
using Squidex.Events.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Write.Schemas.Commands;
using Squidex.Write.TestHelpers;
using Xunit;
// ReSharper disable ConvertToConstant.Local
namespace Squidex.Write.Schemas
{
public class SchemaDomainObjectTests
public class SchemaDomainObjectTests : HandlerTestBase<SchemaDomainObject>
{
private readonly Guid appId = Guid.NewGuid();
private readonly string fieldName = "age";
private readonly string appName = "schema";
private readonly NamedId<long> fieldId;
private readonly SchemaDomainObject sut;
public SchemaDomainObjectTests()
{
fieldId = new NamedId<long>(1, fieldName);
var fieldRegistry = new FieldRegistry(new TypeNameRegistry());
sut = new SchemaDomainObject(Guid.NewGuid(), 0, fieldRegistry);
sut = new SchemaDomainObject(SchemaId, 0, fieldRegistry);
}
[Fact]
public void Create_should_throw_if_created()
{
sut.Create(new CreateSchema { Name = appName });
sut.Create(new CreateSchema { Name = SchemaName });
Assert.Throws<DomainException>(() => sut.Create(new CreateSchema { Name = appName }));
Assert.Throws<DomainException>(() =>
{
sut.Create(CreateCommand(new CreateSchema { Name = SchemaName }));
});
}
[Fact]
public void Create_should_throw_if_command_is_not_valid()
{
Assert.Throws<ValidationException>(() => sut.Create(new CreateSchema()));
Assert.Throws<ValidationException>(() =>
{
sut.Create(CreateCommand(new CreateSchema()));
});
}
[Fact]
@ -54,22 +59,22 @@ namespace Squidex.Write.Schemas
{
var properties = new SchemaProperties();
sut.Create(new CreateSchema { Name = appName, AppId = appId, Properties = properties });
sut.Create(CreateCommand(new CreateSchema { Name = SchemaName, Properties = properties }));
Assert.Equal("schema", sut.Schema.Name);
Assert.Equal(SchemaName, sut.Schema.Name);
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new SchemaCreated { Name = appName, Properties = properties }
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new SchemaCreated { Name = SchemaName, Properties = properties })
);
}
[Fact]
public void Update_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.Update(new UpdateSchema { Properties = new SchemaProperties() }));
Assert.Throws<DomainException>(() =>
{
sut.Update(CreateCommand(new UpdateSchema { Properties = new SchemaProperties() }));
});
}
[Fact]
@ -78,7 +83,10 @@ namespace Squidex.Write.Schemas
CreateSchema();
DeleteSchema();
Assert.Throws<ValidationException>(() => sut.Update(new UpdateSchema()));
Assert.Throws<ValidationException>(() =>
{
sut.Update(CreateCommand(new UpdateSchema()));
});
}
[Fact]
@ -86,7 +94,10 @@ namespace Squidex.Write.Schemas
{
CreateSchema();
Assert.Throws<ValidationException>(() => sut.Update(new UpdateSchema()));
Assert.Throws<ValidationException>(() =>
{
sut.Update(CreateCommand(new UpdateSchema()));
});
}
[Fact]
@ -96,22 +107,23 @@ namespace Squidex.Write.Schemas
CreateSchema();
sut.Update(new UpdateSchema { Properties = properties });
sut.Update(CreateCommand(new UpdateSchema { Properties = properties }));
Assert.Equal(properties, sut.Schema.Properties);
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new SchemaUpdated { Properties = properties }
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new SchemaUpdated { Properties = properties })
);
}
[Fact]
public void Publish_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.Publish(new PublishSchema()));
Assert.Throws<DomainException>(() =>
{
sut.Publish(CreateCommand(new PublishSchema()));
});
}
[Fact]
@ -120,7 +132,10 @@ namespace Squidex.Write.Schemas
CreateSchema();
DeleteSchema();
Assert.Throws<DomainException>(() => sut.Publish(new PublishSchema()));
Assert.Throws<DomainException>(() =>
{
sut.Publish(CreateCommand(new PublishSchema()));
});
}
[Fact]
@ -128,22 +143,23 @@ namespace Squidex.Write.Schemas
{
CreateSchema();
sut.Publish(new PublishSchema());
sut.Publish(CreateCommand(new PublishSchema()));
Assert.True(sut.Schema.IsPublished);
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new SchemaPublished()
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new SchemaPublished())
);
}
[Fact]
public void Unpublish_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.Unpublish(new UnpublishSchema()));
Assert.Throws<DomainException>(() =>
{
sut.Unpublish(CreateCommand(new UnpublishSchema()));
});
}
[Fact]
@ -152,7 +168,10 @@ namespace Squidex.Write.Schemas
CreateSchema();
DeleteSchema();
Assert.Throws<DomainException>(() => sut.Unpublish(new UnpublishSchema()));
Assert.Throws<DomainException>(() =>
{
sut.Unpublish(CreateCommand(new UnpublishSchema()));
});
}
[Fact]
@ -161,22 +180,23 @@ namespace Squidex.Write.Schemas
CreateSchema();
PublishSchema();
sut.Unpublish(new UnpublishSchema());
sut.Unpublish(CreateCommand(new UnpublishSchema()));
Assert.False(sut.Schema.IsPublished);
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new SchemaUnpublished()
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new SchemaUnpublished())
);
}
[Fact]
public void Delete_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.Delete(new DeleteSchema()));
Assert.Throws<DomainException>(() =>
{
sut.Delete(CreateCommand(new DeleteSchema()));
});
}
[Fact]
@ -185,7 +205,10 @@ namespace Squidex.Write.Schemas
CreateSchema();
DeleteSchema();
Assert.Throws<DomainException>(() => sut.Delete(new DeleteSchema()));
Assert.Throws<DomainException>(() =>
{
sut.Delete(CreateCommand(new DeleteSchema()));
});
}
[Fact]
@ -193,28 +216,32 @@ namespace Squidex.Write.Schemas
{
CreateSchema();
sut.Delete(new DeleteSchema());
sut.Delete(CreateCommand(new DeleteSchema()));
Assert.True(sut.IsDeleted);
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new SchemaDeleted()
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new SchemaDeleted())
);
}
[Fact]
public void AddField_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.AddField(new AddField { Name = fieldName, Properties = new NumberFieldProperties() }));
Assert.Throws<DomainException>(() =>
{
sut.AddField(CreateCommand(new AddField { Name = fieldName, Properties = new NumberFieldProperties() }));
});
}
[Fact]
public void AddField_should_throw_if_command_is_not_valid()
{
Assert.Throws<ValidationException>(() => sut.AddField(new AddField()));
Assert.Throws<ValidationException>(() =>
{
sut.AddField(CreateCommand(new AddField()));
});
}
[Fact]
@ -223,7 +250,10 @@ namespace Squidex.Write.Schemas
CreateSchema();
DeleteSchema();
Assert.Throws<DomainException>(() => sut.AddField(new AddField { Name = fieldName, Properties = new NumberFieldProperties() }));
Assert.Throws<DomainException>(() =>
{
sut.AddField(CreateCommand(new AddField { Name = fieldName, Properties = new NumberFieldProperties() }));
});
}
[Fact]
@ -233,28 +263,32 @@ namespace Squidex.Write.Schemas
CreateSchema();
sut.AddField(new AddField { Name = fieldName, Properties = properties });
sut.AddField(CreateCommand(new AddField { Name = fieldName, Properties = properties }));
Assert.Equal(properties, sut.Schema.Fields[1].RawProperties);
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new FieldAdded { Name = fieldName, FieldId = 1, Properties = properties }
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new FieldAdded { Name = fieldName, FieldId = fieldId, Properties = properties })
);
}
[Fact]
public void UpdateField_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.UpdateField(new UpdateField { FieldId = 1, Properties = new NumberFieldProperties() }));
Assert.Throws<DomainException>(() =>
{
sut.UpdateField(CreateCommand(new UpdateField { FieldId = 1, Properties = new NumberFieldProperties() }));
});
}
[Fact]
public void UpdateField_should_throw_if_command_is_not_valid()
{
Assert.Throws<ValidationException>(() => sut.UpdateField(new UpdateField()));
Assert.Throws<ValidationException>(() =>
{
sut.UpdateField(CreateCommand(new UpdateField()));
});
}
[Fact]
@ -262,7 +296,10 @@ namespace Squidex.Write.Schemas
{
CreateSchema();
Assert.Throws<DomainObjectNotFoundException>(() => sut.UpdateField(new UpdateField { FieldId = 1, Properties = new NumberFieldProperties() }));
Assert.Throws<DomainObjectNotFoundException>(() =>
{
sut.UpdateField(CreateCommand(new UpdateField { FieldId = 1, Properties = new NumberFieldProperties() }));
});
}
[Fact]
@ -271,7 +308,10 @@ namespace Squidex.Write.Schemas
CreateSchema();
DeleteSchema();
Assert.Throws<DomainException>(() => sut.UpdateField(new UpdateField { FieldId = 1, Properties = new NumberFieldProperties() }));
Assert.Throws<DomainException>(() =>
{
sut.UpdateField(CreateCommand(new UpdateField { FieldId = 1, Properties = new NumberFieldProperties() }));
});
}
[Fact]
@ -282,22 +322,23 @@ namespace Squidex.Write.Schemas
CreateSchema();
CreateField();
sut.UpdateField(new UpdateField { FieldId = 1, Properties = properties });
sut.UpdateField(CreateCommand(new UpdateField { FieldId = 1, Properties = properties }));
Assert.Equal(properties, sut.Schema.Fields[1].RawProperties);
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new FieldUpdated { FieldId = 1, Properties = properties }
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new FieldUpdated { FieldId = fieldId, Properties = properties })
);
}
[Fact]
public void HideField_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.HideField(new HideField { FieldId = 1 }));
Assert.Throws<DomainException>(() =>
{
sut.HideField(CreateCommand(new HideField { FieldId = 1 }));
});
}
[Fact]
@ -305,7 +346,10 @@ namespace Squidex.Write.Schemas
{
CreateSchema();
Assert.Throws<DomainObjectNotFoundException>(() => sut.HideField(new HideField { FieldId = 2 }));
Assert.Throws<DomainObjectNotFoundException>(() =>
{
sut.HideField(CreateCommand(new HideField { FieldId = 2 }));
});
}
[Fact]
@ -314,7 +358,10 @@ namespace Squidex.Write.Schemas
CreateSchema();
DeleteSchema();
Assert.Throws<DomainException>(() => sut.HideField(new HideField { FieldId = 1 }));
Assert.Throws<DomainException>(() =>
{
sut.HideField(CreateCommand(new HideField { FieldId = 1 }));
});
}
[Fact]
@ -323,22 +370,23 @@ namespace Squidex.Write.Schemas
CreateSchema();
CreateField();
sut.HideField(new HideField { FieldId = 1 });
sut.HideField(CreateCommand(new HideField { FieldId = 1 }));
Assert.True(sut.Schema.Fields[1].IsHidden);
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new FieldHidden { FieldId = 1 }
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new FieldHidden { FieldId = fieldId })
);
}
[Fact]
public void ShowField_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.ShowField(new ShowField { FieldId = 1 }));
Assert.Throws<DomainException>(() =>
{
sut.ShowField(CreateCommand(new ShowField { FieldId = 1 }));
});
}
[Fact]
@ -346,7 +394,10 @@ namespace Squidex.Write.Schemas
{
CreateSchema();
Assert.Throws<DomainObjectNotFoundException>(() => sut.ShowField(new ShowField { FieldId = 2 }));
Assert.Throws<DomainObjectNotFoundException>(() =>
{
sut.ShowField(CreateCommand(new ShowField { FieldId = 2 }));
});
}
[Fact]
@ -355,7 +406,10 @@ namespace Squidex.Write.Schemas
CreateSchema();
DeleteSchema();
Assert.Throws<DomainException>(() => sut.ShowField(new ShowField { FieldId = 1 }));
Assert.Throws<DomainException>(() =>
{
sut.ShowField(CreateCommand(new ShowField { FieldId = 1 }));
});
}
[Fact]
@ -364,23 +418,24 @@ namespace Squidex.Write.Schemas
CreateSchema();
CreateField();
sut.HideField(new HideField { FieldId = 1 });
sut.ShowField(new ShowField { FieldId = 1 });
sut.HideField(CreateCommand(new HideField { FieldId = 1 }));
sut.ShowField(CreateCommand(new ShowField { FieldId = 1 }));
Assert.False(sut.Schema.Fields[1].IsHidden);
sut.GetUncomittedEvents().Select(x => x.Payload).Skip(1).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new FieldShown { FieldId = 1 }
});
sut.GetUncomittedEvents().Skip(1)
.ShouldHaveSameEvents(
CreateEvent(new FieldShown { FieldId = fieldId })
);
}
[Fact]
public void DisableField_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.DisableField(new DisableField { FieldId = 1 }));
Assert.Throws<DomainException>(() =>
{
sut.DisableField(CreateCommand(new DisableField { FieldId = 1 }));
});
}
[Fact]
@ -388,7 +443,10 @@ namespace Squidex.Write.Schemas
{
CreateSchema();
Assert.Throws<DomainObjectNotFoundException>(() => sut.DisableField(new DisableField { FieldId = 2 }));
Assert.Throws<DomainObjectNotFoundException>(() =>
{
sut.DisableField(CreateCommand(new DisableField { FieldId = 2 }));
});
}
[Fact]
@ -397,7 +455,10 @@ namespace Squidex.Write.Schemas
CreateSchema();
DeleteSchema();
Assert.Throws<DomainException>(() => sut.DisableField(new DisableField { FieldId = 1 }));
Assert.Throws<DomainException>(() =>
{
sut.DisableField(CreateCommand(new DisableField { FieldId = 1 }));
});
}
[Fact]
@ -406,22 +467,23 @@ namespace Squidex.Write.Schemas
CreateSchema();
CreateField();
sut.DisableField(new DisableField { FieldId = 1 });
sut.DisableField(CreateCommand(new DisableField { FieldId = 1 }));
Assert.True(sut.Schema.Fields[1].IsDisabled);
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new FieldDisabled { FieldId = 1 }
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new FieldDisabled { FieldId = fieldId })
);
}
[Fact]
public void EnableField_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.EnableField(new EnableField { FieldId = 1 }));
Assert.Throws<DomainException>(() =>
{
sut.EnableField(CreateCommand(new EnableField { FieldId = 1 }));
});
}
[Fact]
@ -429,7 +491,10 @@ namespace Squidex.Write.Schemas
{
CreateSchema();
Assert.Throws<DomainObjectNotFoundException>(() => sut.EnableField(new EnableField { FieldId = 2 }));
Assert.Throws<DomainObjectNotFoundException>(() =>
{
sut.EnableField(CreateCommand(new EnableField { FieldId = 2 }));
});
}
[Fact]
@ -438,7 +503,10 @@ namespace Squidex.Write.Schemas
CreateSchema();
DeleteSchema();
Assert.Throws<DomainException>(() => sut.EnableField(new EnableField { FieldId = 1 }));
Assert.Throws<DomainException>(() =>
{
sut.EnableField(CreateCommand(new EnableField { FieldId = 1 }));
});
}
[Fact]
@ -447,23 +515,24 @@ namespace Squidex.Write.Schemas
CreateSchema();
CreateField();
sut.DisableField(new DisableField { FieldId = 1 });
sut.EnableField(new EnableField { FieldId = 1 });
sut.DisableField(CreateCommand(new DisableField { FieldId = 1 }));
sut.EnableField(CreateCommand(new EnableField { FieldId = 1 }));
Assert.False(sut.Schema.Fields[1].IsDisabled);
sut.GetUncomittedEvents().Select(x => x.Payload).Skip(1).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new FieldEnabled { FieldId = 1 }
});
sut.GetUncomittedEvents().Skip(1)
.ShouldHaveSameEvents(
CreateEvent(new FieldEnabled { FieldId = fieldId })
);
}
[Fact]
public void DeleteField_should_throw_if_not_created()
{
Assert.Throws<DomainException>(() => sut.DeleteField(new DeleteField { FieldId = 1 }));
Assert.Throws<DomainException>(() =>
{
sut.DeleteField(CreateCommand(new DeleteField { FieldId = 1 }));
});
}
[Fact]
@ -472,7 +541,10 @@ namespace Squidex.Write.Schemas
CreateSchema();
DeleteSchema();
Assert.Throws<DomainException>(() => sut.DeleteField(new DeleteField { FieldId = 1 }));
Assert.Throws<DomainException>(() =>
{
sut.DeleteField(CreateCommand(new DeleteField { FieldId = 1 }));
});
}
[Fact]
@ -481,16 +553,14 @@ namespace Squidex.Write.Schemas
CreateSchema();
CreateField();
sut.DeleteField(new DeleteField { FieldId = 1 });
sut.DeleteField(CreateCommand(new DeleteField { FieldId = 1 }));
Assert.False(sut.Schema.Fields.ContainsKey(1));
sut.GetUncomittedEvents().Select(x => x.Payload).ToArray()
.ShouldBeEquivalentTo(
new IEvent[]
{
new FieldDeleted { FieldId = 1 }
});
sut.GetUncomittedEvents()
.ShouldHaveSameEvents(
CreateEvent(new FieldDeleted { FieldId = fieldId })
);
}
private void CreateField()
@ -502,21 +572,21 @@ namespace Squidex.Write.Schemas
private void CreateSchema()
{
sut.Create(new CreateSchema { Name = appName, AppId = appId });
sut.Create(CreateCommand(new CreateSchema { Name = SchemaName }));
((IAggregate)sut).ClearUncommittedEvents();
}
private void PublishSchema()
{
sut.Publish(new PublishSchema());
sut.Publish(CreateCommand(new PublishSchema()));
((IAggregate)sut).ClearUncommittedEvents();
}
private void DeleteSchema()
{
sut.Delete(new DeleteSchema());
sut.Delete(CreateCommand(new DeleteSchema()));
((IAggregate)sut).ClearUncommittedEvents();
}

31
tests/Squidex.Write.Tests/TestHelpers/AssertHelper.cs

@ -0,0 +1,31 @@
// ==========================================================================
// AssertHelper.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Write.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++)
{
((object)source[i]).ShouldBeEquivalentTo(others[i], o => o.IncludingAllDeclaredProperties());
}
}
}
}

71
tests/Squidex.Write.Tests/Utils/HandlerTestBase.cs → tests/Squidex.Write.Tests/TestHelpers/HandlerTestBase.cs

@ -8,10 +8,12 @@
using System;
using System.Threading.Tasks;
using Squidex.Events;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Commands;
namespace Squidex.Write.Utils
namespace Squidex.Write.TestHelpers
{
public abstract class HandlerTestBase<T> where T : DomainObject
{
@ -46,11 +48,25 @@ namespace Squidex.Write.Utils
}
private readonly MockupHandler handler = new MockupHandler();
private readonly Guid id = Guid.NewGuid();
protected Guid Id
protected RefToken User { get; } = new RefToken("subject", Guid.NewGuid().ToString());
protected Guid AppId { get; } = Guid.NewGuid();
protected Guid SchemaId { get; } = Guid.NewGuid();
protected string AppName { get; } = "my-app";
protected string SchemaName { get; } = "my-schema";
protected NamedId<Guid> AppNamedId
{
get { return id; }
get { return new NamedId<Guid>(AppId, AppName); }
}
protected NamedId<Guid> SchemaNamedId
{
get { return new NamedId<Guid>(SchemaId, SchemaName); }
}
protected IAggregateHandler Handler
@ -58,6 +74,11 @@ namespace Squidex.Write.Utils
get { return handler; }
}
protected CommandContext CreateContextForCommand<TCommand>(TCommand command) where TCommand : SquidexCommand
{
return new CommandContext(CreateCommand(command));
}
public async Task TestCreate(T domainObject, Func<T, Task> action, bool shouldCreate = true)
{
handler.Init(domainObject);
@ -81,5 +102,47 @@ namespace Squidex.Write.Utils
throw new InvalidOperationException("Create not called");
}
}
protected virtual TCommand CreateCommand<TCommand>(TCommand command) where TCommand : SquidexCommand
{
command.Actor = User;
var appCommand = command as AppCommand;
if (appCommand != null)
{
appCommand.AppId = AppNamedId;
}
var schemaCommand = command as SchemaCommand;
if (schemaCommand != null)
{
schemaCommand.SchemaId = SchemaNamedId;
}
return command;
}
protected virtual TEvent CreateEvent<TEvent>(TEvent @event) where TEvent : SquidexEvent
{
@event.Actor = User;
var appEvent = @event as AppEvent;
if (appEvent != null)
{
appEvent.AppId = AppNamedId;
}
var schemaEvent = @event as SchemaEvent;
if (schemaEvent != null)
{
schemaEvent.SchemaId = SchemaNamedId;
}
return @event;
}
}
}
Loading…
Cancel
Save