mirror of https://github.com/Squidex/squidex.git
65 changed files with 2 additions and 8074 deletions
@ -1,31 +0,0 @@ |
|||
// ==========================================================================
|
|||
// IBenchmark.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
namespace Benchmarks |
|||
{ |
|||
public abstract class Benchmark |
|||
{ |
|||
public virtual void Initialize() |
|||
{ |
|||
} |
|||
|
|||
public virtual void RunInitialize() |
|||
{ |
|||
} |
|||
|
|||
public virtual void RunCleanup() |
|||
{ |
|||
} |
|||
|
|||
public virtual void Cleanup() |
|||
{ |
|||
} |
|||
|
|||
public abstract long Run(); |
|||
} |
|||
} |
|||
@ -1,26 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
<PropertyGroup> |
|||
<OutputType>Exe</OutputType> |
|||
<TargetFramework>netcoreapp2.0</TargetFramework> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\Squidex.Domain.Apps.Read\Squidex.Domain.Apps.Read.csproj" /> |
|||
<ProjectReference Include="..\..\src\Squidex.Infrastructure.MongoDb\Squidex.Infrastructure.MongoDb.csproj" /> |
|||
<ProjectReference Include="..\..\src\Squidex.Infrastructure\Squidex.Infrastructure.csproj" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<PackageReference Include="MongoDB.Driver" Version="2.4.4" /> |
|||
<PackageReference Include="NodaTime.Serialization.JsonNet" Version="2.0.0" /> |
|||
<PackageReference Include="RefactoringEssentials" Version="5.4.0" /> |
|||
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2" /> |
|||
<PackageReference Include="System.ValueTuple" Version="4.4.0" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Reference Include="Microsoft.Extensions.DependencyInjection"> |
|||
<HintPath>C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.extensions.dependencyinjection\2.0.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.dll</HintPath> |
|||
</Reference> |
|||
</ItemGroup> |
|||
<PropertyGroup> |
|||
<CodeAnalysisRuleSet>..\..\Squidex.ruleset</CodeAnalysisRuleSet> |
|||
</PropertyGroup> |
|||
</Project> |
|||
@ -1,96 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Program.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics; |
|||
using System.Linq; |
|||
using Benchmarks.Tests; |
|||
|
|||
namespace Benchmarks |
|||
{ |
|||
public static class Program |
|||
{ |
|||
private static readonly List<(string Name, Benchmark Benchmark)> Benchmarks = new Benchmark[] |
|||
{ |
|||
new AppendToEventStore(), |
|||
new AppendToEventStoreWithManyWriters(), |
|||
new HandleEvents(), |
|||
new HandleEventsWithManyWriters(), |
|||
new ReadSchemaState() |
|||
}.Select(x => (x.GetType().Name, x)).ToList(); |
|||
|
|||
public static void Main(string[] args) |
|||
{ |
|||
var name = "ReadSchemaState"; |
|||
|
|||
var selected = Benchmarks.Find(x => x.Name == name); |
|||
|
|||
if (selected.Benchmark == null) |
|||
{ |
|||
Console.WriteLine($"'{name}' is not a valid benchmark, please try: "); |
|||
|
|||
foreach (var b in Benchmarks) |
|||
{ |
|||
Console.WriteLine($" * {b.Name}"); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
const int numRuns = 3; |
|||
|
|||
try |
|||
{ |
|||
var elapsed = 0d; |
|||
var count = 0L; |
|||
|
|||
Console.WriteLine($"{selected.Name}: Initialized"); |
|||
|
|||
selected.Benchmark.Initialize(); |
|||
|
|||
for (var run = 0; run < numRuns; run++) |
|||
{ |
|||
try |
|||
{ |
|||
selected.Benchmark.RunInitialize(); |
|||
|
|||
var watch = Stopwatch.StartNew(); |
|||
|
|||
count += selected.Benchmark.Run(); |
|||
|
|||
watch.Stop(); |
|||
|
|||
elapsed += watch.ElapsedMilliseconds; |
|||
|
|||
Console.WriteLine($"{selected.Name}: Run {run + 1} finished"); |
|||
} |
|||
finally |
|||
{ |
|||
selected.Benchmark.RunCleanup(); |
|||
} |
|||
} |
|||
|
|||
var averageElapsed = TimeSpan.FromMilliseconds(elapsed / numRuns); |
|||
var averageSeconds = Math.Round(count / (numRuns * averageElapsed.TotalSeconds), 2); |
|||
|
|||
Console.WriteLine($"{selected.Name}: Completed after {averageElapsed}, {averageSeconds} items/s"); |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
Console.WriteLine($"Benchmark failed with '{e.Message}'"); |
|||
} |
|||
finally |
|||
{ |
|||
selected.Benchmark.Cleanup(); |
|||
} |
|||
} |
|||
|
|||
Console.ReadLine(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,7 +0,0 @@ |
|||
{ |
|||
"profiles": { |
|||
"Benchmarks": { |
|||
"commandName": "Project" |
|||
} |
|||
} |
|||
} |
|||
@ -1,145 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Services.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Benchmarks.Tests.TestData; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using MongoDB.Driver; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Converters; |
|||
using NodaTime; |
|||
using NodaTime.Serialization.JsonNet; |
|||
using Squidex.Domain.Apps.Core.Apps.Json; |
|||
using Squidex.Domain.Apps.Core.Rules.Json; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Core.Schemas.Json; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.EventSourcing; |
|||
using Squidex.Infrastructure.Json; |
|||
using Squidex.Infrastructure.Log; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
using Squidex.Infrastructure.States; |
|||
|
|||
namespace Benchmarks |
|||
{ |
|||
public static class Services |
|||
{ |
|||
public static IServiceProvider Create() |
|||
{ |
|||
var services = new ServiceCollection(); |
|||
|
|||
services.AddSingleton(CreateTypeNameRegistry()); |
|||
|
|||
services.AddSingleton<FieldRegistry>(); |
|||
|
|||
services.AddTransient<MyAppState>(); |
|||
|
|||
services.AddSingleton<IMongoClient>( |
|||
new MongoClient("mongodb://localhost")); |
|||
|
|||
services.AddSingleton<ISemanticLog>( |
|||
new SemanticLog(new ILogChannel[0], new ILogAppender[0], () => new JsonLogWriter())); |
|||
|
|||
services.AddSingleton<IMemoryCache>( |
|||
new MemoryCache(Options.Create(new MemoryCacheOptions()))); |
|||
|
|||
services.AddSingleton<IPubSub, |
|||
InMemoryPubSub>(); |
|||
|
|||
services.AddSingleton<IEventNotifier, |
|||
DefaultEventNotifier>(); |
|||
|
|||
services.AddSingleton<IEventStore, |
|||
MongoEventStore>(); |
|||
|
|||
services.AddSingleton<IEventDataFormatter, |
|||
JsonEventDataFormatter>(); |
|||
|
|||
services.AddSingleton<ISnapshotStore, |
|||
MongoSnapshotStore>(); |
|||
|
|||
services.AddSingleton<IStateFactory, |
|||
StateFactory>(); |
|||
|
|||
services.AddSingleton<IStreamNameResolver, |
|||
DefaultStreamNameResolver>(); |
|||
|
|||
services.AddSingleton<JsonSerializer>(c => |
|||
JsonSerializer.Create(c.GetRequiredService<JsonSerializerSettings>())); |
|||
|
|||
services.AddSingleton<JsonSerializerSettings>(c => |
|||
CreateJsonSerializerSettings(c.GetRequiredService<TypeNameRegistry>(), c.GetRequiredService<FieldRegistry>())); |
|||
|
|||
services.AddSingleton(c => |
|||
c.GetRequiredService<IMongoClient>().GetDatabase(Guid.NewGuid().ToString())); |
|||
|
|||
return services.BuildServiceProvider(); |
|||
} |
|||
|
|||
public static void Cleanup(this IServiceProvider services) |
|||
{ |
|||
var mongoClient = services.GetRequiredService<IMongoClient>(); |
|||
var mongoDatabase = services.GetRequiredService<IMongoDatabase>(); |
|||
|
|||
mongoClient.DropDatabase(mongoDatabase.DatabaseNamespace.DatabaseName); |
|||
|
|||
if (services is IDisposable disposable) |
|||
{ |
|||
disposable.Dispose(); |
|||
} |
|||
} |
|||
|
|||
private static TypeNameRegistry CreateTypeNameRegistry() |
|||
{ |
|||
var result = new TypeNameRegistry(); |
|||
|
|||
result.Map(typeof(MyEvent)); |
|||
|
|||
return result; |
|||
} |
|||
|
|||
private static JsonSerializerSettings CreateJsonSerializerSettings(TypeNameRegistry typeNameRegistry, FieldRegistry fieldRegistry) |
|||
{ |
|||
var settings = new JsonSerializerSettings(); |
|||
|
|||
settings.SerializationBinder = new TypeNameSerializationBinder(typeNameRegistry); |
|||
|
|||
settings.ContractResolver = new ConverterContractResolver( |
|||
new AppClientsConverter(), |
|||
new AppContributorsConverter(), |
|||
new ClaimsPrincipalConverter(), |
|||
new InstantConverter(), |
|||
new LanguageConverter(), |
|||
new LanguagesConfigConverter(), |
|||
new NamedGuidIdConverter(), |
|||
new NamedLongIdConverter(), |
|||
new NamedStringIdConverter(), |
|||
new PropertiesBagConverter<EnvelopeHeaders>(), |
|||
new PropertiesBagConverter<PropertiesBag>(), |
|||
new RefTokenConverter(), |
|||
new RuleConverter(), |
|||
new SchemaConverter(fieldRegistry), |
|||
new StringEnumConverter()); |
|||
|
|||
settings.NullValueHandling = NullValueHandling.Ignore; |
|||
|
|||
settings.DateFormatHandling = DateFormatHandling.IsoDateFormat; |
|||
settings.DateParseHandling = DateParseHandling.None; |
|||
|
|||
settings.TypeNameHandling = TypeNameHandling.Auto; |
|||
|
|||
settings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb); |
|||
|
|||
BsonJsonConvention.Register(JsonSerializer.Create(settings)); |
|||
|
|||
return settings; |
|||
} |
|||
} |
|||
} |
|||
@ -1,53 +0,0 @@ |
|||
// ==========================================================================
|
|||
// AppendToEventStore.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Benchmarks.Utils; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Squidex.Infrastructure.EventSourcing; |
|||
|
|||
namespace Benchmarks.Tests |
|||
{ |
|||
public sealed class AppendToEventStore : Benchmark |
|||
{ |
|||
private IServiceProvider services; |
|||
private IEventStore eventStore; |
|||
|
|||
public override void RunInitialize() |
|||
{ |
|||
services = Services.Create(); |
|||
|
|||
eventStore = services.GetRequiredService<IEventStore>(); |
|||
} |
|||
|
|||
public override long Run() |
|||
{ |
|||
const long numCommits = 100; |
|||
const long numStreams = 20; |
|||
|
|||
for (var streamId = 0; streamId < numStreams; streamId++) |
|||
{ |
|||
var eventOffset = -1; |
|||
var streamName = streamId.ToString(); |
|||
|
|||
for (var commitId = 0; commitId < numCommits; commitId++) |
|||
{ |
|||
eventStore.AppendEventsAsync(Guid.NewGuid(), streamName, eventOffset, new[] { Helper.CreateEventData() }).Wait(); |
|||
eventOffset++; |
|||
} |
|||
} |
|||
|
|||
return numCommits * numStreams; |
|||
} |
|||
|
|||
public override void RunCleanup() |
|||
{ |
|||
services.Cleanup(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,52 +0,0 @@ |
|||
// ==========================================================================
|
|||
// AppendToEventStoreWithManyWriters.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Benchmarks.Utils; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Squidex.Infrastructure.EventSourcing; |
|||
|
|||
namespace Benchmarks.Tests |
|||
{ |
|||
public sealed class AppendToEventStoreWithManyWriters : Benchmark |
|||
{ |
|||
private IServiceProvider services; |
|||
private IEventStore eventStore; |
|||
|
|||
public override void RunInitialize() |
|||
{ |
|||
services = Services.Create(); |
|||
|
|||
eventStore = services.GetRequiredService<IEventStore>(); |
|||
} |
|||
|
|||
public override long Run() |
|||
{ |
|||
const long numCommits = 200; |
|||
const long numStreams = 100; |
|||
|
|||
Parallel.For(0, numStreams, streamId => |
|||
{ |
|||
var streamName = streamId.ToString(); |
|||
|
|||
for (var commitId = 0; commitId < numCommits; commitId++) |
|||
{ |
|||
eventStore.AppendEventsAsync(Guid.NewGuid(), streamName, new[] { Helper.CreateEventData() }).Wait(); |
|||
} |
|||
}); |
|||
|
|||
return numCommits * numStreams; |
|||
} |
|||
|
|||
public override void RunCleanup() |
|||
{ |
|||
services.Cleanup(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,63 +0,0 @@ |
|||
// ==========================================================================
|
|||
// HandleEvents.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Benchmarks.Tests.TestData; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Squidex.Infrastructure.EventSourcing; |
|||
using Squidex.Infrastructure.EventSourcing.Grains; |
|||
using Squidex.Infrastructure.States; |
|||
|
|||
namespace Benchmarks.Tests |
|||
{ |
|||
public sealed class HandleEvents : Benchmark |
|||
{ |
|||
private const int NumEvents = 5000; |
|||
private IServiceProvider services; |
|||
private IEventStore eventStore; |
|||
private IEventDataFormatter eventDataFormatter; |
|||
private EventConsumerGrain eventConsumerGrain; |
|||
private MyEventConsumer eventConsumer; |
|||
|
|||
public override void RunInitialize() |
|||
{ |
|||
services = Services.Create(); |
|||
|
|||
eventConsumer = new MyEventConsumer(NumEvents); |
|||
|
|||
eventStore = services.GetRequiredService<IEventStore>(); |
|||
|
|||
eventDataFormatter = services.GetRequiredService<IEventDataFormatter>(); |
|||
eventConsumerGrain = services.GetRequiredService<EventConsumerGrain>(); |
|||
|
|||
eventConsumerGrain.ActivateAsync("Test", services.GetRequiredService<IStore>()).Wait(); |
|||
eventConsumerGrain.Activate(eventConsumer); |
|||
} |
|||
|
|||
public override long Run() |
|||
{ |
|||
var streamName = Guid.NewGuid().ToString(); |
|||
|
|||
for (var eventId = 0; eventId < NumEvents; eventId++) |
|||
{ |
|||
var eventData = eventDataFormatter.ToEventData(new Envelope<IEvent>(new MyEvent { EventNumber = eventId + 1 }), Guid.NewGuid()); |
|||
|
|||
eventStore.AppendEventsAsync(Guid.NewGuid(), streamName, eventId - 1, new[] { eventData }).Wait(); |
|||
} |
|||
|
|||
eventConsumer.WaitAndVerify(); |
|||
|
|||
return NumEvents; |
|||
} |
|||
|
|||
public override void RunCleanup() |
|||
{ |
|||
services.Cleanup(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,70 +0,0 @@ |
|||
// ==========================================================================
|
|||
// HandleEventsWithManyWriters.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Benchmarks.Tests.TestData; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Squidex.Infrastructure.EventSourcing; |
|||
using Squidex.Infrastructure.EventSourcing.Grains; |
|||
using Squidex.Infrastructure.States; |
|||
|
|||
namespace Benchmarks.Tests |
|||
{ |
|||
public sealed class HandleEventsWithManyWriters : Benchmark |
|||
{ |
|||
private const int NumCommits = 200; |
|||
private const int NumStreams = 10; |
|||
private IServiceProvider services; |
|||
private IEventStore eventStore; |
|||
private IEventDataFormatter eventDataFormatter; |
|||
private EventConsumerGrain eventConsumerGrain; |
|||
private MyEventConsumer eventConsumer; |
|||
|
|||
public override void RunInitialize() |
|||
{ |
|||
services = Services.Create(); |
|||
|
|||
eventConsumer = new MyEventConsumer(NumStreams * NumCommits); |
|||
|
|||
eventStore = services.GetRequiredService<IEventStore>(); |
|||
eventDataFormatter = services.GetRequiredService<IEventDataFormatter>(); |
|||
|
|||
eventConsumerGrain = services.GetRequiredService<EventConsumerGrain>(); |
|||
|
|||
eventConsumerGrain.ActivateAsync("Test", services.GetRequiredService<IStore>()).Wait(); |
|||
eventConsumerGrain.Activate(eventConsumer); |
|||
} |
|||
|
|||
public override long Run() |
|||
{ |
|||
Parallel.For(0, NumStreams, streamId => |
|||
{ |
|||
var eventOffset = -1; |
|||
var streamName = streamId.ToString(); |
|||
|
|||
for (var commitId = 0; commitId < NumCommits; commitId++) |
|||
{ |
|||
var eventData = eventDataFormatter.ToEventData(new Envelope<IEvent>(new MyEvent()), Guid.NewGuid()); |
|||
|
|||
eventStore.AppendEventsAsync(Guid.NewGuid(), streamName, eventOffset - 1, new[] { eventData }).Wait(); |
|||
eventOffset++; |
|||
} |
|||
}); |
|||
|
|||
eventConsumer.WaitAndVerify(); |
|||
|
|||
return NumStreams * NumCommits; |
|||
} |
|||
|
|||
public override void RunCleanup() |
|||
{ |
|||
services.Cleanup(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,102 +0,0 @@ |
|||
// ==========================================================================
|
|||
// ReadSchemaState.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Immutable; |
|||
using Benchmarks.Tests.TestData; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using NodaTime; |
|||
using Squidex.Domain.Apps.Core; |
|||
using Squidex.Domain.Apps.Core.Rules; |
|||
using Squidex.Domain.Apps.Core.Rules.Actions; |
|||
using Squidex.Domain.Apps.Core.Rules.Triggers; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Read.State.Grains; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.States; |
|||
|
|||
namespace Benchmarks.Tests |
|||
{ |
|||
public class ReadSchemaState : Benchmark |
|||
{ |
|||
private IServiceProvider services; |
|||
private MyAppState grain; |
|||
|
|||
public override void Initialize() |
|||
{ |
|||
services = Services.Create(); |
|||
|
|||
grain = services.GetRequiredService<IStateFactory>().GetSynchronizedAsync<MyAppState>("DEFAULT").Result; |
|||
|
|||
var state = new AppStateGrainState |
|||
{ |
|||
App = new JsonAppEntity |
|||
{ |
|||
Id = Guid.NewGuid() |
|||
} |
|||
}; |
|||
|
|||
state.Schemas = ImmutableDictionary<Guid, JsonSchemaEntity>.Empty; |
|||
|
|||
for (var i = 1; i <= 100; i++) |
|||
{ |
|||
var schema = new JsonSchemaEntity |
|||
{ |
|||
Id = Guid.NewGuid(), |
|||
Created = SystemClock.Instance.GetCurrentInstant(), |
|||
CreatedBy = new RefToken("user", "1"), |
|||
LastModified = SystemClock.Instance.GetCurrentInstant(), |
|||
LastModifiedBy = new RefToken("user", "1"), |
|||
SchemaDef = new Schema("Name") |
|||
}; |
|||
|
|||
for (var j = 1; j < 30; j++) |
|||
{ |
|||
schema.SchemaDef = schema.SchemaDef.AddField(new StringField(j, j.ToString(), Partitioning.Invariant)); |
|||
} |
|||
|
|||
state.Schemas = state.Schemas.Add(schema.Id, schema); |
|||
} |
|||
|
|||
state.Rules = ImmutableDictionary<Guid, JsonRuleEntity>.Empty; |
|||
|
|||
for (var i = 0; i < 100; i++) |
|||
{ |
|||
var rule = new JsonRuleEntity |
|||
{ |
|||
Id = Guid.NewGuid(), |
|||
Created = SystemClock.Instance.GetCurrentInstant(), |
|||
CreatedBy = new RefToken("user", "1"), |
|||
LastModified = SystemClock.Instance.GetCurrentInstant(), |
|||
LastModifiedBy = new RefToken("user", "1"), |
|||
RuleDef = new Rule(new ContentChangedTrigger(), new WebhookAction()) |
|||
}; |
|||
|
|||
state.Rules = state.Rules.Add(rule.Id, rule); |
|||
} |
|||
|
|||
grain.SetState(state); |
|||
grain.WriteStateAsync().Wait(); |
|||
} |
|||
|
|||
public override long Run() |
|||
{ |
|||
for (var i = 0; i < 10; i++) |
|||
{ |
|||
grain.ReadStateAsync().Wait(); |
|||
} |
|||
|
|||
return 10; |
|||
} |
|||
|
|||
public override void Cleanup() |
|||
{ |
|||
services.Cleanup(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,42 +0,0 @@ |
|||
// ==========================================================================
|
|||
// MyAppState.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
using Squidex.Domain.Apps.Read.State.Grains; |
|||
using Squidex.Infrastructure.States; |
|||
|
|||
namespace Benchmarks.Tests.TestData |
|||
{ |
|||
public sealed class MyAppState : IStatefulObject |
|||
{ |
|||
private IPersistence<AppStateGrainState> persistence; |
|||
private AppStateGrainState state; |
|||
|
|||
public Task ActivateAsync(string key, IStore store) |
|||
{ |
|||
persistence = store.WithSnapshots<MyAppState, AppStateGrainState>(key, s => state = s); |
|||
|
|||
return persistence.ReadAsync(); |
|||
} |
|||
|
|||
public void SetState(AppStateGrainState state) |
|||
{ |
|||
this.state = state; |
|||
} |
|||
|
|||
public Task WriteStateAsync() |
|||
{ |
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task ReadStateAsync() |
|||
{ |
|||
return persistence.ReadAsync(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,19 +0,0 @@ |
|||
// ==========================================================================
|
|||
// MyEvent.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.EventSourcing; |
|||
|
|||
namespace Benchmarks.Tests.TestData |
|||
{ |
|||
[TypeName("MyEvent")] |
|||
public sealed class MyEvent : IEvent |
|||
{ |
|||
public int EventNumber { get; set; } |
|||
} |
|||
} |
|||
@ -1,79 +0,0 @@ |
|||
// ==========================================================================
|
|||
// MyEventConsumer.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Squidex.Infrastructure.EventSourcing; |
|||
using Squidex.Infrastructure.Tasks; |
|||
|
|||
namespace Benchmarks.Tests.TestData |
|||
{ |
|||
public sealed class MyEventConsumer : IEventConsumer |
|||
{ |
|||
private readonly TaskCompletionSource<object> completion = new TaskCompletionSource<object>(); |
|||
private readonly int numEvents; |
|||
|
|||
public List<int> EventNumbers { get; } = new List<int>(); |
|||
|
|||
public string Name |
|||
{ |
|||
get { return typeof(MyEventConsumer).Name; } |
|||
} |
|||
|
|||
public string EventsFilter |
|||
{ |
|||
get { return string.Empty; } |
|||
} |
|||
|
|||
public MyEventConsumer(int numEvents) |
|||
{ |
|||
this.numEvents = numEvents; |
|||
} |
|||
|
|||
public Task ClearAsync() |
|||
{ |
|||
return TaskHelper.Done; |
|||
} |
|||
|
|||
public void WaitAndVerify() |
|||
{ |
|||
completion.Task.Wait(); |
|||
|
|||
if (EventNumbers.Count != numEvents) |
|||
{ |
|||
throw new InvalidOperationException($"{EventNumbers.Count} Events have been handled"); |
|||
} |
|||
|
|||
for (var i = 0; i < EventNumbers.Count; i++) |
|||
{ |
|||
var value = EventNumbers[i]; |
|||
|
|||
if (value != i + 1) |
|||
{ |
|||
throw new InvalidOperationException($"Event[{i}] != value"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public Task On(Envelope<IEvent> @event) |
|||
{ |
|||
if (@event.Payload is MyEvent myEvent) |
|||
{ |
|||
EventNumbers.Add(myEvent.EventNumber); |
|||
|
|||
if (myEvent.EventNumber == numEvents) |
|||
{ |
|||
completion.SetResult(true); |
|||
} |
|||
} |
|||
|
|||
return TaskHelper.Done; |
|||
} |
|||
} |
|||
} |
|||
@ -1,21 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Helper.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Squidex.Infrastructure.EventSourcing; |
|||
|
|||
namespace Benchmarks.Utils |
|||
{ |
|||
public static class Helper |
|||
{ |
|||
public static EventData CreateEventData() |
|||
{ |
|||
return new EventData { EventId = Guid.NewGuid(), Metadata = "EventMetdata", Payload = "EventPayload", Type = "MyEvent" }; |
|||
} |
|||
} |
|||
} |
|||
@ -1,51 +0,0 @@ |
|||
// ==========================================================================
|
|||
// AppEventTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Domain.Apps.Entities.TestHelpers; |
|||
using Squidex.Domain.Apps.Events; |
|||
using Squidex.Domain.Apps.Events.Apps; |
|||
using Squidex.Domain.Apps.Events.Apps.Old; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
#pragma warning disable CS0612 // Type or member is obsolete
|
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Apps |
|||
{ |
|||
public class AppEventTests |
|||
{ |
|||
private readonly RefToken actor = new RefToken("User", Guid.NewGuid().ToString()); |
|||
private readonly NamedId<Guid> appId = new NamedId<Guid>(Guid.NewGuid(), "my-app"); |
|||
|
|||
[Fact] |
|||
public void Should_migrate_client_changed_as_reader_to_client_updated() |
|||
{ |
|||
var source = CreateEvent(new AppClientChanged { IsReader = true }); |
|||
|
|||
source.Migrate().ShouldBeSameEvent(CreateEvent(new AppClientUpdated { Permission = AppClientPermission.Reader })); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_migrate_client_changed_as_writer_to_client_updated() |
|||
{ |
|||
var source = CreateEvent(new AppClientChanged { IsReader = false }); |
|||
|
|||
source.Migrate().ShouldBeSameEvent(CreateEvent(new AppClientUpdated { Permission = AppClientPermission.Editor })); |
|||
} |
|||
|
|||
private T CreateEvent<T>(T contentEvent) where T : AppEvent |
|||
{ |
|||
contentEvent.Actor = actor; |
|||
contentEvent.AppId = appId; |
|||
|
|||
return contentEvent; |
|||
} |
|||
} |
|||
} |
|||
@ -1,70 +0,0 @@ |
|||
// ==========================================================================
|
|||
// ContentEventTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Domain.Apps.Entities.TestHelpers; |
|||
using Squidex.Domain.Apps.Events.Contents; |
|||
using Squidex.Domain.Apps.Events.Contents.Old; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
#pragma warning disable CS0612 // Type or member is obsolete
|
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Contents |
|||
{ |
|||
public class ContentEventTests |
|||
{ |
|||
private readonly RefToken actor = new RefToken("User", Guid.NewGuid().ToString()); |
|||
private readonly NamedId<Guid> appId = new NamedId<Guid>(Guid.NewGuid(), "my-app"); |
|||
private readonly NamedId<Guid> schemaId = new NamedId<Guid>(Guid.NewGuid(), "my-schema"); |
|||
private readonly Guid contentId = Guid.NewGuid(); |
|||
|
|||
[Fact] |
|||
public void Should_migrate_content_published_to_content_status_changed() |
|||
{ |
|||
var source = CreateEvent(new ContentPublished()); |
|||
|
|||
source.Migrate().ShouldBeSameEvent(CreateEvent(new ContentStatusChanged { Status = Status.Published })); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_migrate_content_unpublished_to_content_status_changed() |
|||
{ |
|||
var source = CreateEvent(new ContentUnpublished()); |
|||
|
|||
source.Migrate().ShouldBeSameEvent(CreateEvent(new ContentStatusChanged { Status = Status.Draft })); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_migrate_content_restored_to_content_status_changed() |
|||
{ |
|||
var source = CreateEvent(new ContentRestored()); |
|||
|
|||
source.Migrate().ShouldBeSameEvent(CreateEvent(new ContentStatusChanged { Status = Status.Draft })); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_migrate_content_archived_to_content_status_changed() |
|||
{ |
|||
var source = CreateEvent(new ContentArchived()); |
|||
|
|||
source.Migrate().ShouldBeSameEvent(CreateEvent(new ContentStatusChanged { Status = Status.Archived })); |
|||
} |
|||
|
|||
private T CreateEvent<T>(T contentEvent) where T : ContentEvent |
|||
{ |
|||
contentEvent.Actor = actor; |
|||
contentEvent.AppId = appId; |
|||
contentEvent.SchemaId = schemaId; |
|||
contentEvent.ContentId = contentId; |
|||
|
|||
return contentEvent; |
|||
} |
|||
} |
|||
} |
|||
@ -1,150 +0,0 @@ |
|||
// ==========================================================================
|
|||
// ConfigAppLimitsProviderTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Linq; |
|||
using FakeItEasy; |
|||
using FluentAssertions; |
|||
using Squidex.Domain.Apps.Read.Apps.Services.Implementations; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Read.Apps |
|||
{ |
|||
public class ConfigAppLimitsProviderTests |
|||
{ |
|||
private static readonly ConfigAppLimitsPlan InfinitePlan = new ConfigAppLimitsPlan |
|||
{ |
|||
Id = "infinite", |
|||
Name = "Infinite", |
|||
MaxApiCalls = -1, |
|||
MaxAssetSize = -1, |
|||
MaxContributors = -1 |
|||
}; |
|||
|
|||
private static readonly ConfigAppLimitsPlan FreePlan = new ConfigAppLimitsPlan |
|||
{ |
|||
Id = "free", |
|||
Name = "Free", |
|||
MaxApiCalls = 50000, |
|||
MaxAssetSize = 1024 * 1024 * 10, |
|||
MaxContributors = 2 |
|||
}; |
|||
|
|||
private static readonly ConfigAppLimitsPlan BasicPlan = new ConfigAppLimitsPlan |
|||
{ |
|||
Id = "basic", |
|||
Name = "Basic", |
|||
MaxApiCalls = 150000, |
|||
MaxAssetSize = 1024 * 1024 * 2, |
|||
MaxContributors = 5 |
|||
}; |
|||
|
|||
private static readonly ConfigAppLimitsPlan[] Plans = { BasicPlan, FreePlan }; |
|||
|
|||
[Fact] |
|||
public void Should_return_plans() |
|||
{ |
|||
var sut = new ConfigAppPlansProvider(Plans); |
|||
|
|||
Plans.OrderBy(x => x.MaxApiCalls).ShouldBeEquivalentTo(sut.GetAvailablePlans()); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(null)] |
|||
[InlineData("my-plan")] |
|||
public void Should_return_infinite_if_nothing_configured(string planId) |
|||
{ |
|||
var sut = new ConfigAppPlansProvider(Enumerable.Empty<ConfigAppLimitsPlan>()); |
|||
|
|||
var plan = sut.GetPlanForApp(CreateApp(planId)); |
|||
|
|||
plan.ShouldBeEquivalentTo(InfinitePlan); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_return_fitting_app_plan() |
|||
{ |
|||
var sut = new ConfigAppPlansProvider(Plans); |
|||
|
|||
var plan = sut.GetPlanForApp(CreateApp("basic")); |
|||
|
|||
plan.ShouldBeEquivalentTo(BasicPlan); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_smallest_plan_if_none_fits() |
|||
{ |
|||
var sut = new ConfigAppPlansProvider(Plans); |
|||
|
|||
var plan = sut.GetPlanForApp(CreateApp("enterprise")); |
|||
|
|||
plan.ShouldBeEquivalentTo(FreePlan); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_return_second_plan_for_upgrade_if_plan_is_null() |
|||
{ |
|||
var sut = new ConfigAppPlansProvider(Plans); |
|||
|
|||
var upgradePlan = sut.GetPlanUpgrade(null); |
|||
|
|||
upgradePlan.ShouldBeEquivalentTo(BasicPlan); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_return_second_plan_for_upgrade_if_plan_not_found() |
|||
{ |
|||
var sut = new ConfigAppPlansProvider(Plans); |
|||
|
|||
var upgradePlan = sut.GetPlanUpgradeForApp(CreateApp("enterprise")); |
|||
|
|||
upgradePlan.ShouldBeEquivalentTo(BasicPlan); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_not_return_plan_for_upgrade_if_plan_is_highest_plan() |
|||
{ |
|||
var sut = new ConfigAppPlansProvider(Plans); |
|||
|
|||
var upgradePlan = sut.GetPlanUpgradeForApp(CreateApp("basic")); |
|||
|
|||
Assert.Null(upgradePlan); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_return_next_plan_if_plan_is_upgradeable() |
|||
{ |
|||
var sut = new ConfigAppPlansProvider(Plans); |
|||
|
|||
var upgradePlan = sut.GetPlanUpgradeForApp(CreateApp("free")); |
|||
|
|||
upgradePlan.ShouldBeEquivalentTo(BasicPlan); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_check_plan_exists() |
|||
{ |
|||
var sut = new ConfigAppPlansProvider(Plans); |
|||
|
|||
Assert.True(sut.IsConfiguredPlan("basic")); |
|||
Assert.True(sut.IsConfiguredPlan("free")); |
|||
|
|||
Assert.False(sut.IsConfiguredPlan("infinite")); |
|||
Assert.False(sut.IsConfiguredPlan("invalid")); |
|||
Assert.False(sut.IsConfiguredPlan(null)); |
|||
} |
|||
|
|||
private static IAppEntity CreateApp(string plan) |
|||
{ |
|||
var app = A.Dummy<IAppEntity>(); |
|||
|
|||
A.CallTo(() => app.PlanId).Returns(plan); |
|||
|
|||
return app; |
|||
} |
|||
} |
|||
} |
|||
@ -1,38 +0,0 @@ |
|||
// ==========================================================================
|
|||
// NoopAppPlanBillingManagerTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Squidex.Domain.Apps.Read.Apps.Services.Implementations; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Read.Apps |
|||
{ |
|||
public class NoopAppPlanBillingManagerTests |
|||
{ |
|||
private readonly NoopAppPlanBillingManager sut = new NoopAppPlanBillingManager(); |
|||
|
|||
[Fact] |
|||
public void Should_not_have_portal() |
|||
{ |
|||
Assert.False(sut.HasPortal); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_do_nothing_when_changing_plan() |
|||
{ |
|||
await sut.ChangePlanAsync(null, Guid.Empty, null, null); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_return_portal_link() |
|||
{ |
|||
Assert.Equal(string.Empty, await sut.GetPortalLinkAsync(null)); |
|||
} |
|||
} |
|||
} |
|||
@ -1,220 +0,0 @@ |
|||
// ==========================================================================
|
|||
// ContentQueryServiceTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Security.Claims; |
|||
using System.Threading.Tasks; |
|||
using FakeItEasy; |
|||
using Microsoft.OData.UriParser; |
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Domain.Apps.Core.Scripting; |
|||
using Squidex.Domain.Apps.Read.Apps; |
|||
using Squidex.Domain.Apps.Read.Contents.Edm; |
|||
using Squidex.Domain.Apps.Read.Contents.Repositories; |
|||
using Squidex.Domain.Apps.Read.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Security; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Read.Contents |
|||
{ |
|||
public class ContentQueryServiceTests |
|||
{ |
|||
private readonly IContentRepository contentRepository = A.Fake<IContentRepository>(); |
|||
private readonly IScriptEngine scriptEngine = A.Fake<IScriptEngine>(); |
|||
private readonly ISchemaEntity schema = A.Fake<ISchemaEntity>(); |
|||
private readonly IContentEntity content = A.Fake<IContentEntity>(); |
|||
private readonly IAppEntity app = A.Fake<IAppEntity>(); |
|||
private readonly IAppProvider appProvider = A.Fake<IAppProvider>(); |
|||
private readonly Guid appId = Guid.NewGuid(); |
|||
private readonly Guid schemaId = Guid.NewGuid(); |
|||
private readonly Guid contentId = Guid.NewGuid(); |
|||
private readonly string appName = "my-app"; |
|||
private readonly NamedContentData data = new NamedContentData(); |
|||
private readonly NamedContentData transformedData = new NamedContentData(); |
|||
private readonly ClaimsPrincipal user; |
|||
private readonly ClaimsIdentity identity = new ClaimsIdentity(); |
|||
private readonly EdmModelBuilder modelBuilder = A.Fake<EdmModelBuilder>(); |
|||
private readonly ContentQueryService sut; |
|||
|
|||
public ContentQueryServiceTests() |
|||
{ |
|||
user = new ClaimsPrincipal(identity); |
|||
|
|||
A.CallTo(() => app.Id).Returns(appId); |
|||
A.CallTo(() => app.Name).Returns(appName); |
|||
|
|||
A.CallTo(() => content.Id).Returns(contentId); |
|||
A.CallTo(() => content.Data).Returns(data); |
|||
A.CallTo(() => content.Status).Returns(Status.Published); |
|||
|
|||
sut = new ContentQueryService(contentRepository, appProvider, scriptEngine, modelBuilder); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_schema_from_id_if_string_is_guid() |
|||
{ |
|||
A.CallTo(() => appProvider.GetSchemaAsync(appName, schemaId, false)) |
|||
.Returns(schema); |
|||
|
|||
var result = await sut.FindSchemaAsync(app, schemaId.ToString()); |
|||
|
|||
Assert.Equal(schema, result); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_schema_from_name_if_string_not_guid() |
|||
{ |
|||
A.CallTo(() => appProvider.GetSchemaAsync(appName, "my-schema", false)) |
|||
.Returns(schema); |
|||
|
|||
var result = await sut.FindSchemaAsync(app, "my-schema"); |
|||
|
|||
Assert.Equal(schema, result); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_throw_if_schema_not_found() |
|||
{ |
|||
A.CallTo(() => appProvider.GetSchemaAsync(appName, "my-schema", false)) |
|||
.Returns((ISchemaEntity)null); |
|||
|
|||
await Assert.ThrowsAsync<DomainObjectNotFoundException>(() => sut.FindSchemaAsync(app, "my-schema")); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_content_from_repository_and_transform() |
|||
{ |
|||
A.CallTo(() => appProvider.GetSchemaAsync(appName, schemaId, false)) |
|||
.Returns(schema); |
|||
A.CallTo(() => contentRepository.FindContentAsync(app, schema, contentId)) |
|||
.Returns(content); |
|||
|
|||
A.CallTo(() => schema.ScriptQuery) |
|||
.Returns("<script-query>"); |
|||
|
|||
A.CallTo(() => scriptEngine.Transform(A<ScriptContext>.That.Matches(x => x.User == user && x.ContentId == contentId && ReferenceEquals(x.Data, data)), "<query-script>")) |
|||
.Returns(transformedData); |
|||
|
|||
var result = await sut.FindContentAsync(app, schemaId.ToString(), user, contentId); |
|||
|
|||
Assert.Equal(schema, result.Schema); |
|||
Assert.Equal(data, result.Content.Data); |
|||
Assert.Equal(content.Id, result.Content.Id); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_throw_if_content_to_find_does_not_exist() |
|||
{ |
|||
A.CallTo(() => appProvider.GetSchemaAsync(appName, schemaId, false)) |
|||
.Returns(schema); |
|||
A.CallTo(() => contentRepository.FindContentAsync(app, schema, contentId)) |
|||
.Returns((IContentEntity)null); |
|||
|
|||
await Assert.ThrowsAsync<DomainObjectNotFoundException>(async () => await sut.FindContentAsync(app, schemaId.ToString(), user, contentId)); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_contents_with_ids_from_repository_and_transform() |
|||
{ |
|||
await TestManyIdRequest(true, false, new HashSet<Guid> { Guid.NewGuid() }, Status.Draft, Status.Published); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_non_archived_contents_from_repository_and_transform() |
|||
{ |
|||
await TestManyRequest(true, false, Status.Draft, Status.Published); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_archived_contents_from_repository_and_transform() |
|||
{ |
|||
await TestManyRequest(true, true, Status.Archived); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_draft_contents_from_repository_and_transform() |
|||
{ |
|||
await TestManyRequest(false, false, Status.Published); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_draft_contents_from_repository_and_transform_when_requesting_archive_as_non_frontend() |
|||
{ |
|||
await TestManyRequest(false, true, Status.Published); |
|||
} |
|||
|
|||
private async Task TestManyRequest(bool isFrontend, bool archive, params Status[] status) |
|||
{ |
|||
SetupClaims(isFrontend); |
|||
|
|||
SetupFakeWithOdataQuery(status); |
|||
SetupFakeWithScripting(); |
|||
|
|||
var result = await sut.QueryWithCountAsync(app, schemaId.ToString(), user, archive, string.Empty); |
|||
|
|||
Assert.Equal(123, result.Total); |
|||
Assert.Equal(schema, result.Schema); |
|||
Assert.Equal(data, result.Items[0].Data); |
|||
Assert.Equal(content.Id, result.Items[0].Id); |
|||
} |
|||
|
|||
private async Task TestManyIdRequest(bool isFrontend, bool archive, HashSet<Guid> ids, params Status[] status) |
|||
{ |
|||
SetupClaims(isFrontend); |
|||
|
|||
SetupFakeWithIdQuery(status, ids); |
|||
SetupFakeWithScripting(); |
|||
|
|||
var result = await sut.QueryWithCountAsync(app, schemaId.ToString(), user, archive, ids); |
|||
|
|||
Assert.Equal(123, result.Total); |
|||
Assert.Equal(schema, result.Schema); |
|||
Assert.Equal(data, result.Items[0].Data); |
|||
Assert.Equal(content.Id, result.Items[0].Id); |
|||
} |
|||
|
|||
private void SetupClaims(bool isFrontend) |
|||
{ |
|||
if (isFrontend) |
|||
{ |
|||
identity.AddClaim(new Claim(OpenIdClaims.ClientId, "squidex-frontend")); |
|||
} |
|||
} |
|||
|
|||
private void SetupFakeWithIdQuery(Status[] status, HashSet<Guid> ids) |
|||
{ |
|||
A.CallTo(() => appProvider.GetSchemaAsync(appName, schemaId, false)) |
|||
.Returns(schema); |
|||
A.CallTo(() => contentRepository.QueryAsync(app, schema, A<Status[]>.That.IsSameSequenceAs(status), ids)) |
|||
.Returns(new List<IContentEntity> { content }); |
|||
A.CallTo(() => contentRepository.CountAsync(app, schema, A<Status[]>.That.IsSameSequenceAs(status), ids)) |
|||
.Returns(123); |
|||
} |
|||
|
|||
private void SetupFakeWithOdataQuery(Status[] status) |
|||
{ |
|||
A.CallTo(() => appProvider.GetSchemaAsync(appName, schemaId, false)) |
|||
.Returns(schema); |
|||
A.CallTo(() => contentRepository.QueryAsync(app, schema, A<Status[]>.That.IsSameSequenceAs(status), A<ODataUriParser>.Ignored)) |
|||
.Returns(new List<IContentEntity> { content }); |
|||
A.CallTo(() => contentRepository.CountAsync(app, schema, A<Status[]>.That.IsSameSequenceAs(status), A<ODataUriParser>.Ignored)) |
|||
.Returns(123); |
|||
} |
|||
|
|||
private void SetupFakeWithScripting() |
|||
{ |
|||
A.CallTo(() => schema.ScriptQuery) |
|||
.Returns("<script-query>"); |
|||
|
|||
A.CallTo(() => scriptEngine.Transform(A<ScriptContext>.That.Matches(x => x.User == user && x.ContentId == contentId && ReferenceEquals(x.Data, data)), "<query-script>")) |
|||
.Returns(transformedData); |
|||
} |
|||
} |
|||
} |
|||
@ -1,689 +0,0 @@ |
|||
// ==========================================================================
|
|||
// GraphQLTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Security.Claims; |
|||
using System.Threading.Tasks; |
|||
using FakeItEasy; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using Microsoft.Extensions.Options; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Linq; |
|||
using NodaTime.Extensions; |
|||
using Squidex.Domain.Apps.Core; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Read.Apps; |
|||
using Squidex.Domain.Apps.Read.Assets; |
|||
using Squidex.Domain.Apps.Read.Assets.Repositories; |
|||
using Squidex.Domain.Apps.Read.Contents.GraphQL; |
|||
using Squidex.Domain.Apps.Read.Contents.TestData; |
|||
using Squidex.Domain.Apps.Read.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
#pragma warning disable SA1311 // Static readonly fields must begin with upper-case letter
|
|||
|
|||
namespace Squidex.Domain.Apps.Read.Contents |
|||
{ |
|||
public class GraphQLTests |
|||
{ |
|||
private static readonly Guid schemaId = Guid.NewGuid(); |
|||
private static readonly Guid appId = Guid.NewGuid(); |
|||
private static readonly string appName = "my-app"; |
|||
private readonly Schema schemaDef; |
|||
private readonly IContentQueryService contentQuery = A.Fake<IContentQueryService>(); |
|||
private readonly IAssetRepository assetRepository = A.Fake<IAssetRepository>(); |
|||
private readonly ISchemaEntity schema = A.Fake<ISchemaEntity>(); |
|||
private readonly IMemoryCache cache = new MemoryCache(Options.Create(new MemoryCacheOptions())); |
|||
private readonly IAppProvider appProvider = A.Fake<IAppProvider>(); |
|||
private readonly IAppEntity app = A.Dummy<IAppEntity>(); |
|||
private readonly ClaimsPrincipal user = new ClaimsPrincipal(); |
|||
private readonly IGraphQLService sut; |
|||
|
|||
public GraphQLTests() |
|||
{ |
|||
schemaDef = |
|||
new Schema("my-schema") |
|||
.AddField(new JsonField(1, "my-json", Partitioning.Invariant, |
|||
new JsonFieldProperties())) |
|||
.AddField(new StringField(2, "my-string", Partitioning.Language, |
|||
new StringFieldProperties())) |
|||
.AddField(new NumberField(3, "my-number", Partitioning.Invariant, |
|||
new NumberFieldProperties())) |
|||
.AddField(new AssetsField(4, "my-assets", Partitioning.Invariant, |
|||
new AssetsFieldProperties())) |
|||
.AddField(new BooleanField(5, "my-boolean", Partitioning.Invariant, |
|||
new BooleanFieldProperties())) |
|||
.AddField(new DateTimeField(6, "my-datetime", Partitioning.Invariant, |
|||
new DateTimeFieldProperties())) |
|||
.AddField(new ReferencesField(7, "my-references", Partitioning.Invariant, |
|||
new ReferencesFieldProperties { SchemaId = schemaId })) |
|||
.AddField(new ReferencesField(9, "my-invalid", Partitioning.Invariant, |
|||
new ReferencesFieldProperties { SchemaId = Guid.NewGuid() })) |
|||
.AddField(new GeolocationField(10, "my-geolocation", Partitioning.Invariant, |
|||
new GeolocationFieldProperties())) |
|||
.AddField(new TagsField(11, "my-tags", Partitioning.Invariant, |
|||
new TagsFieldProperties())); |
|||
|
|||
A.CallTo(() => app.Id).Returns(appId); |
|||
A.CallTo(() => app.Name).Returns(appName); |
|||
A.CallTo(() => app.LanguagesConfig).Returns(LanguagesConfig.Build(Language.DE)); |
|||
|
|||
A.CallTo(() => schema.Id).Returns(schemaId); |
|||
A.CallTo(() => schema.Name).Returns(schemaDef.Name); |
|||
A.CallTo(() => schema.SchemaDef).Returns(schemaDef); |
|||
A.CallTo(() => schema.IsPublished).Returns(true); |
|||
A.CallTo(() => schema.ScriptQuery).Returns("<script-query>"); |
|||
|
|||
var allSchemas = new List<ISchemaEntity> { schema }; |
|||
|
|||
A.CallTo(() => appProvider.GetSchemasAsync(appName)).Returns(allSchemas); |
|||
|
|||
sut = new CachingGraphQLService(cache, appProvider, assetRepository, contentQuery, new FakeUrlGenerator()); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(null)] |
|||
[InlineData("")] |
|||
[InlineData(" ")] |
|||
public async Task Should_return_empty_object_for_empty_query(string query) |
|||
{ |
|||
var result = await sut.QueryAsync(app, user, new GraphQLQuery { Query = query }); |
|||
|
|||
var expected = new |
|||
{ |
|||
data = new |
|||
{ |
|||
} |
|||
}; |
|||
|
|||
AssertJson(expected, new { data = result.Data }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_multiple_assets_when_querying_assets() |
|||
{ |
|||
const string query = @"
|
|||
query { |
|||
queryAssets(search: ""my-query"", top: 30, skip: 5) { |
|||
id |
|||
version |
|||
created |
|||
createdBy |
|||
lastModified |
|||
lastModifiedBy |
|||
url |
|||
thumbnailUrl |
|||
sourceUrl |
|||
mimeType |
|||
fileName |
|||
fileSize |
|||
fileVersion |
|||
isImage |
|||
pixelWidth |
|||
pixelHeight |
|||
} |
|||
}";
|
|||
|
|||
var asset = CreateAsset(Guid.NewGuid()); |
|||
|
|||
var assets = new List<IAssetEntity> { asset }; |
|||
|
|||
A.CallTo(() => assetRepository.QueryAsync(app.Id, null, null, "my-query", 30, 5)) |
|||
.Returns(assets); |
|||
|
|||
var result = await sut.QueryAsync(app, user, new GraphQLQuery { Query = query }); |
|||
|
|||
var expected = new |
|||
{ |
|||
data = new |
|||
{ |
|||
queryAssets = new dynamic[] |
|||
{ |
|||
new |
|||
{ |
|||
id = asset.Id, |
|||
version = 1, |
|||
created = asset.Created.ToDateTimeUtc(), |
|||
createdBy = "subject:user1", |
|||
lastModified = asset.LastModified.ToDateTimeUtc(), |
|||
lastModifiedBy = "subject:user2", |
|||
url = $"assets/{asset.Id}", |
|||
thumbnailUrl = $"assets/{asset.Id}?width=100", |
|||
sourceUrl = $"assets/source/{asset.Id}", |
|||
mimeType = "image/png", |
|||
fileName = "MyFile.png", |
|||
fileSize = 1024, |
|||
fileVersion = 123, |
|||
isImage = true, |
|||
pixelWidth = 800, |
|||
pixelHeight = 600 |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
AssertJson(expected, new { data = result.Data }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_single_asset_when_finding_asset() |
|||
{ |
|||
var assetId = Guid.NewGuid(); |
|||
var asset = CreateAsset(Guid.NewGuid()); |
|||
|
|||
var query = $@"
|
|||
query {{ |
|||
findAsset(id: ""{assetId}"") {{ |
|||
id |
|||
version |
|||
created |
|||
createdBy |
|||
lastModified |
|||
lastModifiedBy |
|||
url |
|||
thumbnailUrl |
|||
sourceUrl |
|||
mimeType |
|||
fileName |
|||
fileSize |
|||
fileVersion |
|||
isImage |
|||
pixelWidth |
|||
pixelHeight |
|||
}} |
|||
}}";
|
|||
|
|||
A.CallTo(() => assetRepository.FindAssetAsync(assetId)) |
|||
.Returns(asset); |
|||
|
|||
var result = await sut.QueryAsync(app, user, new GraphQLQuery { Query = query }); |
|||
|
|||
var expected = new |
|||
{ |
|||
data = new |
|||
{ |
|||
findAsset = new |
|||
{ |
|||
id = asset.Id, |
|||
version = 1, |
|||
created = asset.Created.ToDateTimeUtc(), |
|||
createdBy = "subject:user1", |
|||
lastModified = asset.LastModified.ToDateTimeUtc(), |
|||
lastModifiedBy = "subject:user2", |
|||
url = $"assets/{asset.Id}", |
|||
thumbnailUrl = $"assets/{asset.Id}?width=100", |
|||
sourceUrl = $"assets/source/{asset.Id}", |
|||
mimeType = "image/png", |
|||
fileName = "MyFile.png", |
|||
fileSize = 1024, |
|||
fileVersion = 123, |
|||
isImage = true, |
|||
pixelWidth = 800, |
|||
pixelHeight = 600 |
|||
} |
|||
} |
|||
}; |
|||
|
|||
AssertJson(expected, new { data = result.Data }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_multiple_contents_when_querying_contents() |
|||
{ |
|||
const string query = @"
|
|||
query { |
|||
queryMySchemaContents(top: 30, skip: 5) { |
|||
id |
|||
version |
|||
created |
|||
createdBy |
|||
lastModified |
|||
lastModifiedBy |
|||
url |
|||
data { |
|||
myString { |
|||
de |
|||
} |
|||
myNumber { |
|||
iv |
|||
} |
|||
myBoolean { |
|||
iv |
|||
} |
|||
myDatetime { |
|||
iv |
|||
} |
|||
myJson { |
|||
iv |
|||
} |
|||
myGeolocation { |
|||
iv |
|||
} |
|||
myTags { |
|||
iv |
|||
} |
|||
} |
|||
} |
|||
}";
|
|||
|
|||
var content = CreateContent(Guid.NewGuid(), Guid.Empty, Guid.Empty); |
|||
|
|||
var contents = new List<IContentEntity> { content }; |
|||
|
|||
A.CallTo(() => contentQuery.QueryWithCountAsync(app, schema.Id.ToString(), user, false, "?$top=30&$skip=5")) |
|||
.Returns((schema, 0L, (IReadOnlyList<IContentEntity>)contents)); |
|||
|
|||
var result = await sut.QueryAsync(app, user, new GraphQLQuery { Query = query }); |
|||
|
|||
var expected = new |
|||
{ |
|||
data = new |
|||
{ |
|||
queryMySchemaContents = new dynamic[] |
|||
{ |
|||
new |
|||
{ |
|||
id = content.Id, |
|||
version = 1, |
|||
created = content.Created.ToDateTimeUtc(), |
|||
createdBy = "subject:user1", |
|||
lastModified = content.LastModified.ToDateTimeUtc(), |
|||
lastModifiedBy = "subject:user2", |
|||
url = $"contents/my-schema/{content.Id}", |
|||
data = new |
|||
{ |
|||
myString = new |
|||
{ |
|||
de = "value" |
|||
}, |
|||
myNumber = new |
|||
{ |
|||
iv = 1 |
|||
}, |
|||
myBoolean = new |
|||
{ |
|||
iv = true |
|||
}, |
|||
myDatetime = new |
|||
{ |
|||
iv = content.LastModified.ToDateTimeUtc() |
|||
}, |
|||
myJson = new |
|||
{ |
|||
iv = new |
|||
{ |
|||
value = 1 |
|||
} |
|||
}, |
|||
myGeolocation = new |
|||
{ |
|||
iv = new |
|||
{ |
|||
latitude = 10, |
|||
longitude = 20 |
|||
} |
|||
}, |
|||
myTags = new |
|||
{ |
|||
iv = new[] |
|||
{ |
|||
"tag1", |
|||
"tag2" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
AssertJson(expected, new { data = result.Data }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_return_single_content_when_finding_content() |
|||
{ |
|||
var contentId = Guid.NewGuid(); |
|||
var content = CreateContent(contentId, Guid.Empty, Guid.Empty); |
|||
|
|||
var query = $@"
|
|||
query {{ |
|||
findMySchemaContent(id: ""{contentId}"") {{ |
|||
id |
|||
version |
|||
created |
|||
createdBy |
|||
lastModified |
|||
lastModifiedBy |
|||
url |
|||
data {{ |
|||
myString {{ |
|||
de |
|||
}} |
|||
myNumber {{ |
|||
iv |
|||
}} |
|||
myBoolean {{ |
|||
iv |
|||
}} |
|||
myDatetime {{ |
|||
iv |
|||
}} |
|||
myJson {{ |
|||
iv |
|||
}} |
|||
myGeolocation {{ |
|||
iv |
|||
}} |
|||
myTags {{ |
|||
iv |
|||
}} |
|||
}} |
|||
}} |
|||
}}";
|
|||
|
|||
A.CallTo(() => contentQuery.FindContentAsync(app, schema.Id.ToString(), user, contentId)) |
|||
.Returns((schema, content)); |
|||
|
|||
var result = await sut.QueryAsync(app, user, new GraphQLQuery { Query = query }); |
|||
|
|||
var expected = new |
|||
{ |
|||
data = new |
|||
{ |
|||
findMySchemaContent = new |
|||
{ |
|||
id = content.Id, |
|||
version = 1, |
|||
created = content.Created.ToDateTimeUtc(), |
|||
createdBy = "subject:user1", |
|||
lastModified = content.LastModified.ToDateTimeUtc(), |
|||
lastModifiedBy = "subject:user2", |
|||
url = $"contents/my-schema/{content.Id}", |
|||
data = new |
|||
{ |
|||
myString = new |
|||
{ |
|||
de = "value" |
|||
}, |
|||
myNumber = new |
|||
{ |
|||
iv = 1 |
|||
}, |
|||
myBoolean = new |
|||
{ |
|||
iv = true |
|||
}, |
|||
myDatetime = new |
|||
{ |
|||
iv = content.LastModified.ToDateTimeUtc() |
|||
}, |
|||
myJson = new |
|||
{ |
|||
iv = new |
|||
{ |
|||
value = 1 |
|||
} |
|||
}, |
|||
myGeolocation = new |
|||
{ |
|||
iv = new |
|||
{ |
|||
latitude = 10, |
|||
longitude = 20 |
|||
} |
|||
}, |
|||
myTags = new |
|||
{ |
|||
iv = new[] |
|||
{ |
|||
"tag1", |
|||
"tag2" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
AssertJson(expected, new { data = result.Data }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_also_fetch_referenced_contents_when_field_is_included_in_query() |
|||
{ |
|||
var contentRefId = Guid.NewGuid(); |
|||
var contentRef = CreateContent(contentRefId, Guid.Empty, Guid.Empty); |
|||
|
|||
var contentId = Guid.NewGuid(); |
|||
var content = CreateContent(contentId, contentRefId, Guid.Empty); |
|||
|
|||
var query = $@"
|
|||
query {{ |
|||
findMySchemaContent(id: ""{contentId}"") {{ |
|||
id |
|||
data {{ |
|||
myReferences {{ |
|||
iv {{ |
|||
id |
|||
}} |
|||
}} |
|||
}} |
|||
}} |
|||
}}";
|
|||
|
|||
var refContents = new List<IContentEntity> { contentRef }; |
|||
|
|||
A.CallTo(() => contentQuery.FindContentAsync(app, schema.Id.ToString(), user, contentId)) |
|||
.Returns((schema, content)); |
|||
|
|||
A.CallTo(() => contentQuery.QueryWithCountAsync(app, schema.Id.ToString(), user, false, A<HashSet<Guid>>.That.Matches(x => x.Contains(contentRefId)))) |
|||
.Returns((schema, 0L, (IReadOnlyList<IContentEntity>)refContents)); |
|||
|
|||
var result = await sut.QueryAsync(app, user, new GraphQLQuery { Query = query }); |
|||
|
|||
var expected = new |
|||
{ |
|||
data = new |
|||
{ |
|||
findMySchemaContent = new |
|||
{ |
|||
id = content.Id, |
|||
data = new |
|||
{ |
|||
myReferences = new |
|||
{ |
|||
iv = new[] |
|||
{ |
|||
new |
|||
{ |
|||
id = contentRefId |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
AssertJson(expected, new { data = result.Data }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_also_fetch_referenced_assets_when_field_is_included_in_query() |
|||
{ |
|||
var assetRefId = Guid.NewGuid(); |
|||
var assetRef = CreateAsset(assetRefId); |
|||
|
|||
var contentId = Guid.NewGuid(); |
|||
var content = CreateContent(contentId, Guid.Empty, assetRefId); |
|||
|
|||
var query = $@"
|
|||
query {{ |
|||
findMySchemaContent(id: ""{contentId}"") {{ |
|||
id |
|||
data {{ |
|||
myAssets {{ |
|||
iv {{ |
|||
id |
|||
}} |
|||
}} |
|||
}} |
|||
}} |
|||
}}";
|
|||
|
|||
var refAssets = new List<IAssetEntity> { assetRef }; |
|||
|
|||
A.CallTo(() => contentQuery.FindContentAsync(app, schema.Id.ToString(), user, contentId)) |
|||
.Returns((schema, content)); |
|||
|
|||
A.CallTo(() => assetRepository.QueryAsync(app.Id, null, A<HashSet<Guid>>.That.Matches(x => x.Contains(assetRefId)), null, int.MaxValue, 0)) |
|||
.Returns(refAssets); |
|||
|
|||
var result = await sut.QueryAsync(app, user, new GraphQLQuery { Query = query }); |
|||
|
|||
var expected = new |
|||
{ |
|||
data = new |
|||
{ |
|||
findMySchemaContent = new |
|||
{ |
|||
id = content.Id, |
|||
data = new |
|||
{ |
|||
myAssets = new |
|||
{ |
|||
iv = new[] |
|||
{ |
|||
new |
|||
{ |
|||
id = assetRefId |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
AssertJson(expected, new { data = result.Data }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_return_data_when_field_not_part_of_content() |
|||
{ |
|||
var contentId = Guid.NewGuid(); |
|||
var content = CreateContent(contentId, Guid.Empty, Guid.Empty, new NamedContentData()); |
|||
|
|||
var query = $@"
|
|||
query {{ |
|||
findMySchemaContent(id: ""{contentId}"") {{ |
|||
id |
|||
version |
|||
created |
|||
createdBy |
|||
lastModified |
|||
lastModifiedBy |
|||
url |
|||
data {{ |
|||
myInvalid {{ |
|||
iv |
|||
}} |
|||
}} |
|||
}} |
|||
}}";
|
|||
|
|||
A.CallTo(() => contentQuery.FindContentAsync(app, schema.Id.ToString(), user, contentId)) |
|||
.Returns((schema, content)); |
|||
|
|||
var result = await sut.QueryAsync(app, user, new GraphQLQuery { Query = query }); |
|||
|
|||
var expected = new |
|||
{ |
|||
data = (object)null |
|||
}; |
|||
|
|||
AssertJson(expected, new { data = result.Data }); |
|||
} |
|||
|
|||
private static IContentEntity CreateContent(Guid id, Guid refId, Guid assetId, NamedContentData data = null) |
|||
{ |
|||
var now = DateTime.UtcNow.ToInstant(); |
|||
|
|||
data = data ?? |
|||
new NamedContentData() |
|||
.AddField("my-json", |
|||
new ContentFieldData().AddValue("iv", JToken.FromObject(new { value = 1 }))) |
|||
.AddField("my-string", |
|||
new ContentFieldData().AddValue("de", "value")) |
|||
.AddField("my-assets", |
|||
new ContentFieldData().AddValue("iv", JToken.FromObject(new[] { assetId }))) |
|||
.AddField("my-number", |
|||
new ContentFieldData().AddValue("iv", 1)) |
|||
.AddField("my-boolean", |
|||
new ContentFieldData().AddValue("iv", true)) |
|||
.AddField("my-datetime", |
|||
new ContentFieldData().AddValue("iv", now.ToDateTimeUtc())) |
|||
.AddField("my-tags", |
|||
new ContentFieldData().AddValue("iv", JToken.FromObject(new[] { "tag1", "tag2" }))) |
|||
.AddField("my-references", |
|||
new ContentFieldData().AddValue("iv", JToken.FromObject(new[] { refId }))) |
|||
.AddField("my-geolocation", |
|||
new ContentFieldData().AddValue("iv", JToken.FromObject(new { latitude = 10, longitude = 20 }))); |
|||
|
|||
var content = new FakeContentEntity |
|||
{ |
|||
Id = id, |
|||
Version = 1, |
|||
Created = now, |
|||
CreatedBy = new RefToken("subject", "user1"), |
|||
LastModified = now, |
|||
LastModifiedBy = new RefToken("subject", "user2"), |
|||
Data = data |
|||
}; |
|||
|
|||
return content; |
|||
} |
|||
|
|||
private static IAssetEntity CreateAsset(Guid id) |
|||
{ |
|||
var now = DateTime.UtcNow.ToInstant(); |
|||
|
|||
var asset = new FakeAssetEntity |
|||
{ |
|||
Id = id, |
|||
Version = 1, |
|||
Created = now, |
|||
CreatedBy = new RefToken("subject", "user1"), |
|||
LastModified = now, |
|||
LastModifiedBy = new RefToken("subject", "user2"), |
|||
FileName = "MyFile.png", |
|||
FileSize = 1024, |
|||
FileVersion = 123, |
|||
MimeType = "image/png", |
|||
IsImage = true, |
|||
PixelWidth = 800, |
|||
PixelHeight = 600 |
|||
}; |
|||
|
|||
return asset; |
|||
} |
|||
|
|||
private static void AssertJson(object expected, object result) |
|||
{ |
|||
var resultJson = JsonConvert.SerializeObject(result, Formatting.Indented); |
|||
var expectJson = JsonConvert.SerializeObject(expected, Formatting.Indented); |
|||
|
|||
Assert.Equal(expectJson, resultJson); |
|||
} |
|||
} |
|||
} |
|||
@ -1,392 +0,0 @@ |
|||
// ==========================================================================
|
|||
// ODataQueryTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Immutable; |
|||
using FakeItEasy; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using Microsoft.Extensions.Options; |
|||
using Microsoft.OData.Edm; |
|||
using MongoDB.Bson.Serialization; |
|||
using MongoDB.Driver; |
|||
using Squidex.Domain.Apps.Core; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Read.Apps; |
|||
using Squidex.Domain.Apps.Read.Contents.Edm; |
|||
using Squidex.Domain.Apps.Read.MongoDb.Contents; |
|||
using Squidex.Domain.Apps.Read.MongoDb.Contents.Visitors; |
|||
using Squidex.Domain.Apps.Read.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Read.Contents |
|||
{ |
|||
public class ODataQueryTests |
|||
{ |
|||
private readonly Schema schemaDef; |
|||
private readonly IBsonSerializerRegistry registry = BsonSerializer.SerializerRegistry; |
|||
private readonly IBsonSerializer<MongoContentEntity> serializer = BsonSerializer.SerializerRegistry.GetSerializer<MongoContentEntity>(); |
|||
private readonly IEdmModel edmModel; |
|||
private readonly LanguagesConfig languagesConfig = LanguagesConfig.Build(Language.EN, Language.DE); |
|||
|
|||
static ODataQueryTests() |
|||
{ |
|||
InstantSerializer.Register(); |
|||
} |
|||
|
|||
public ODataQueryTests() |
|||
{ |
|||
schemaDef = |
|||
new Schema("user") |
|||
.AddField(new StringField(1, "firstName", Partitioning.Language, |
|||
new StringFieldProperties { Label = "FirstName", IsRequired = true, AllowedValues = ImmutableList.Create("1", "2") })) |
|||
.AddField(new StringField(2, "lastName", Partitioning.Language, |
|||
new StringFieldProperties { Hints = "Last Name", Editor = StringFieldEditor.Input })) |
|||
.AddField(new BooleanField(3, "isAdmin", Partitioning.Invariant, |
|||
new BooleanFieldProperties())) |
|||
.AddField(new NumberField(4, "age", Partitioning.Invariant, |
|||
new NumberFieldProperties { MinValue = 1, MaxValue = 10 })) |
|||
.AddField(new DateTimeField(5, "birthday", Partitioning.Invariant, |
|||
new DateTimeFieldProperties())) |
|||
.AddField(new AssetsField(6, "pictures", Partitioning.Invariant, |
|||
new AssetsFieldProperties())) |
|||
.AddField(new ReferencesField(7, "friends", Partitioning.Invariant, |
|||
new ReferencesFieldProperties())) |
|||
.AddField(new StringField(8, "dashed-field", Partitioning.Invariant, |
|||
new StringFieldProperties())) |
|||
.Update(new SchemaProperties { Hints = "The User" }); |
|||
|
|||
var builder = new EdmModelBuilder(new MemoryCache(Options.Create(new MemoryCacheOptions()))); |
|||
|
|||
var schema = A.Dummy<ISchemaEntity>(); |
|||
A.CallTo(() => schema.Id).Returns(Guid.NewGuid()); |
|||
A.CallTo(() => schema.Version).Returns(3); |
|||
A.CallTo(() => schema.SchemaDef).Returns(schemaDef); |
|||
|
|||
var app = A.Dummy<IAppEntity>(); |
|||
A.CallTo(() => app.Id).Returns(Guid.NewGuid()); |
|||
A.CallTo(() => app.Version).Returns(3); |
|||
A.CallTo(() => app.LanguagesConfig).Returns(languagesConfig); |
|||
|
|||
edmModel = builder.BuildEdmModel(schema, app); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_parse_query() |
|||
{ |
|||
var parser = edmModel.ParseQuery("$filter=data/firstName/de eq 'Sebastian'"); |
|||
|
|||
Assert.NotNull(parser); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_make_query_with_underscore_field() |
|||
{ |
|||
var i = F("$filter=data/dashed_field/iv eq 'Value'"); |
|||
var o = C("{ 'do.8.iv' : 'Value' }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_not_operator() |
|||
{ |
|||
var i = F("$filter=not endswith(data/firstName/de, 'Sebastian')"); |
|||
var o = C("{ 'do.1.de' : { '$not' : /Sebastian$/i } }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_starts_with_query() |
|||
{ |
|||
var i = F("$filter=startswith(data/firstName/de, 'Sebastian')"); |
|||
var o = C("{ 'do.1.de' : /^Sebastian/i }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_ends_with_query() |
|||
{ |
|||
var i = F("$filter=endswith(data/firstName/de, 'Sebastian')"); |
|||
var o = C("{ 'do.1.de' : /Sebastian$/i }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_contains_query() |
|||
{ |
|||
var i = F("$filter=contains(data/firstName/de, 'Sebastian')"); |
|||
var o = C("{ 'do.1.de' : /Sebastian/i }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_contains_query_with_equals() |
|||
{ |
|||
var i = F("$filter=contains(data/firstName/de, 'Sebastian') eq true"); |
|||
var o = C("{ 'do.1.de' : /Sebastian/i }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_negated_contains_query_with_equals() |
|||
{ |
|||
var i = F("$filter=contains(data/firstName/de, 'Sebastian') eq false"); |
|||
var o = C("{ 'do.1.de' : { '$not' : /Sebastian/i } }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_negated_contains_query_and_other() |
|||
{ |
|||
var i = F("$filter=contains(data/firstName/de, 'Sebastian') eq false and data/isAdmin/iv eq true"); |
|||
var o = C("{ 'do.1.de' : { '$not' : /Sebastian/i }, 'do.3.iv' : true }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_string_equals_query() |
|||
{ |
|||
var i = F("$filter=data/firstName/de eq 'Sebastian'"); |
|||
var o = C("{ 'do.1.de' : 'Sebastian' }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_datetime_equals_query() |
|||
{ |
|||
var i = F("$filter=data/birthday/iv eq 1988-01-19T12:00:00Z"); |
|||
var o = C("{ 'do.5.iv' : ISODate(\"1988-01-19T12:00:00Z\") }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_boolean_equals_query() |
|||
{ |
|||
var i = F("$filter=data/isAdmin/iv eq true"); |
|||
var o = C("{ 'do.3.iv' : true }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_string_not_equals_query() |
|||
{ |
|||
var i = F("$filter=data/firstName/de ne 'Sebastian'"); |
|||
var o = C("{ '$or' : [{ 'do.1.de' : { '$exists' : false } }, { 'do.1.de' : { '$ne' : 'Sebastian' } }] }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_number_less_than_query() |
|||
{ |
|||
var i = F("$filter=data/age/iv lt 1"); |
|||
var o = C("{ 'do.4.iv' : { '$lt' : 1.0 } }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_number_less_equals_query() |
|||
{ |
|||
var i = F("$filter=data/age/iv le 1"); |
|||
var o = C("{ 'do.4.iv' : { '$lte' : 1.0 } }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_number_greater_than_query() |
|||
{ |
|||
var i = F("$filter=data/age/iv gt 1"); |
|||
var o = C("{ 'do.4.iv' : { '$gt' : 1.0 } }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_number_greater_equals_query() |
|||
{ |
|||
var i = F("$filter=data/age/iv ge 1"); |
|||
var o = C("{ 'do.4.iv' : { '$gte' : 1.0 } }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_equals_query_for_assets() |
|||
{ |
|||
var i = F("$filter=data/pictures/iv eq 'guid'"); |
|||
var o = C("{ 'do.6.iv' : 'guid' }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_equals_query_for_references() |
|||
{ |
|||
var i = F("$filter=data/friends/iv eq 'guid'"); |
|||
var o = C("{ 'do.7.iv' : 'guid' }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_and_query() |
|||
{ |
|||
var i = F("$filter=data/age/iv eq 1 and data/age/iv eq 2"); |
|||
var o = C("{ '$and' : [{ 'do.4.iv' : 1.0 }, { 'do.4.iv' : 2.0 }] }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_or_query() |
|||
{ |
|||
var i = F("$filter=data/age/iv eq 1 or data/age/iv eq 2"); |
|||
var o = C("{ '$or' : [{ 'do.4.iv' : 1.0 }, { 'do.4.iv' : 2.0 }] }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_full_text_query() |
|||
{ |
|||
var i = F("$search=Hello my World"); |
|||
var o = C("{ '$text' : { '$search' : 'Hello my World' } }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_full_text_query_with_and() |
|||
{ |
|||
var i = F("$search=A and B"); |
|||
var o = C("{ '$text' : { '$search' : 'A and B' } }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_convert_orderby_with_single_statements() |
|||
{ |
|||
var i = S("$orderby=data/age/iv desc"); |
|||
var o = C("{ 'do.4.iv' : -1 }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_convert_orderby_with_multiple_statements() |
|||
{ |
|||
var i = S("$orderby=data/age/iv, data/firstName/en desc"); |
|||
var o = C("{ 'do.4.iv' : 1, 'do.1.en' : -1 }"); |
|||
|
|||
Assert.Equal(o, i); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_set_top() |
|||
{ |
|||
var parser = edmModel.ParseQuery("$top=3"); |
|||
var cursor = A.Fake<IFindFluent<MongoContentEntity, MongoContentEntity>>(); |
|||
|
|||
cursor.Take(parser); |
|||
|
|||
A.CallTo(() => cursor.Limit(3)).MustHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_set_max_top_if_larger() |
|||
{ |
|||
var parser = edmModel.ParseQuery("$top=300"); |
|||
var cursor = A.Fake<IFindFluent<MongoContentEntity, MongoContentEntity>>(); |
|||
|
|||
cursor.Take(parser); |
|||
|
|||
A.CallTo(() => cursor.Limit(200)).MustHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_set_default_top() |
|||
{ |
|||
var parser = edmModel.ParseQuery(string.Empty); |
|||
var cursor = A.Fake<IFindFluent<MongoContentEntity, MongoContentEntity>>(); |
|||
|
|||
cursor.Take(parser); |
|||
|
|||
A.CallTo(() => cursor.Limit(20)).MustHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_set_skip() |
|||
{ |
|||
var parser = edmModel.ParseQuery("$skip=3"); |
|||
var cursor = A.Fake<IFindFluent<MongoContentEntity, MongoContentEntity>>(); |
|||
|
|||
cursor.Skip(parser); |
|||
|
|||
A.CallTo(() => cursor.Skip(3)).MustHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_not_set_skip() |
|||
{ |
|||
var parser = edmModel.ParseQuery(string.Empty); |
|||
var cursor = A.Fake<IFindFluent<MongoContentEntity, MongoContentEntity>>(); |
|||
|
|||
cursor.Take(parser); |
|||
|
|||
A.CallTo(() => cursor.Skip(A<int>.Ignored)).MustNotHaveHappened(); |
|||
} |
|||
|
|||
private static string C(string value) |
|||
{ |
|||
return value.Replace('\'', '"'); |
|||
} |
|||
|
|||
private string S(string value) |
|||
{ |
|||
var parser = edmModel.ParseQuery(value); |
|||
var cursor = A.Fake<IFindFluent<MongoContentEntity, MongoContentEntity>>(); |
|||
|
|||
var i = string.Empty; |
|||
|
|||
A.CallTo(() => cursor.Sort(A<SortDefinition<MongoContentEntity>>.Ignored)) |
|||
.Invokes((SortDefinition<MongoContentEntity> sortDefinition) => |
|||
{ |
|||
i = sortDefinition.Render(serializer, registry).ToString(); |
|||
}); |
|||
|
|||
cursor.Sort(parser, schemaDef); |
|||
|
|||
return i; |
|||
} |
|||
|
|||
private string F(string value) |
|||
{ |
|||
var parser = edmModel.ParseQuery(value); |
|||
|
|||
var query = FilterBuilder.Build(parser, schemaDef).Render(serializer, registry).ToString(); |
|||
|
|||
return query; |
|||
} |
|||
} |
|||
} |
|||
@ -1,50 +0,0 @@ |
|||
// ==========================================================================
|
|||
// MockupAssetEntity.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using NodaTime; |
|||
using Squidex.Domain.Apps.Read.Assets; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Read.Contents.TestData |
|||
{ |
|||
public sealed class FakeAssetEntity : IAssetEntity |
|||
{ |
|||
public Guid Id { get; set; } |
|||
|
|||
public Guid AppId { get; set; } |
|||
|
|||
public Guid AssetId { get; set; } |
|||
|
|||
public Instant Created { get; set; } |
|||
|
|||
public Instant LastModified { get; set; } |
|||
|
|||
public RefToken CreatedBy { get; set; } |
|||
|
|||
public RefToken LastModifiedBy { get; set; } |
|||
|
|||
public long Version { get; set; } |
|||
|
|||
public string MimeType { get; set; } |
|||
|
|||
public string FileName { get; set; } |
|||
|
|||
public long FileSize { get; set; } |
|||
|
|||
public long FileVersion { get; set; } |
|||
|
|||
public bool IsImage { get; set; } |
|||
|
|||
public bool IsDeleted { get; set; } |
|||
|
|||
public int? PixelWidth { get; set; } |
|||
|
|||
public int? PixelHeight { get; set; } |
|||
} |
|||
} |
|||
@ -1,33 +0,0 @@ |
|||
// ==========================================================================
|
|||
// FakeContentEntity.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using NodaTime; |
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Read.Contents.TestData |
|||
{ |
|||
public sealed class FakeContentEntity : IContentEntity |
|||
{ |
|||
public Guid Id { get; set; } |
|||
public Guid AppId { get; set; } |
|||
|
|||
public long Version { get; set; } |
|||
|
|||
public Instant Created { get; set; } |
|||
public Instant LastModified { get; set; } |
|||
|
|||
public RefToken CreatedBy { get; set; } |
|||
public RefToken LastModifiedBy { get; set; } |
|||
|
|||
public NamedContentData Data { get; set; } |
|||
|
|||
public Status Status { get; set; } |
|||
} |
|||
} |
|||
@ -1,40 +0,0 @@ |
|||
// ==========================================================================
|
|||
// FakeUrlGenerator.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Read.Apps; |
|||
using Squidex.Domain.Apps.Read.Assets; |
|||
using Squidex.Domain.Apps.Read.Contents.GraphQL; |
|||
using Squidex.Domain.Apps.Read.Schemas; |
|||
|
|||
namespace Squidex.Domain.Apps.Read.Contents.TestData |
|||
{ |
|||
public sealed class FakeUrlGenerator : IGraphQLUrlGenerator |
|||
{ |
|||
public bool CanGenerateAssetSourceUrl { get; } = true; |
|||
|
|||
public string GenerateAssetUrl(IAppEntity app, IAssetEntity asset) |
|||
{ |
|||
return $"assets/{asset.Id}"; |
|||
} |
|||
|
|||
public string GenerateAssetThumbnailUrl(IAppEntity app, IAssetEntity asset) |
|||
{ |
|||
return $"assets/{asset.Id}?width=100"; |
|||
} |
|||
|
|||
public string GenerateAssetSourceUrl(IAppEntity app, IAssetEntity asset) |
|||
{ |
|||
return $"assets/source/{asset.Id}"; |
|||
} |
|||
|
|||
public string GenerateContentUrl(IAppEntity app, ISchemaEntity schema, IContentEntity content) |
|||
{ |
|||
return $"contents/{schema.Name}/{content.Id}"; |
|||
} |
|||
} |
|||
} |
|||
@ -1,99 +0,0 @@ |
|||
// ==========================================================================
|
|||
// RuleDequeuerGrainTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using FakeItEasy; |
|||
using NodaTime; |
|||
using Squidex.Domain.Apps.Core.HandleRules; |
|||
using Squidex.Domain.Apps.Core.Rules; |
|||
using Squidex.Domain.Apps.Read.Rules.Repositories; |
|||
using Squidex.Infrastructure.Log; |
|||
using Xunit; |
|||
|
|||
#pragma warning disable RECS0165 // Asynchronous methods should return a Task instead of void
|
|||
|
|||
namespace Squidex.Domain.Apps.Read.Rules |
|||
{ |
|||
public class RuleDequeuerTests |
|||
{ |
|||
private readonly IClock clock = A.Fake<IClock>(); |
|||
private readonly ISemanticLog log = A.Fake<ISemanticLog>(); |
|||
private readonly IAppProvider appProvider = A.Fake<IAppProvider>(); |
|||
private readonly IRuleEventRepository ruleEventRepository = A.Fake<IRuleEventRepository>(); |
|||
private readonly RuleService ruleService = A.Fake<RuleService>(); |
|||
private readonly RuleDequeuer sut; |
|||
private readonly Instant now = SystemClock.Instance.GetCurrentInstant(); |
|||
|
|||
public RuleDequeuerTests() |
|||
{ |
|||
A.CallTo(() => clock.GetCurrentInstant()).Returns(now); |
|||
|
|||
sut = new RuleDequeuer( |
|||
ruleService, |
|||
ruleEventRepository, |
|||
log, |
|||
clock); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0, 0, RuleResult.Success, RuleJobResult.Success)] |
|||
[InlineData(0, 5, RuleResult.Timeout, RuleJobResult.Retry)] |
|||
[InlineData(1, 60, RuleResult.Timeout, RuleJobResult.Retry)] |
|||
[InlineData(2, 360, RuleResult.Failed, RuleJobResult.Retry)] |
|||
[InlineData(3, 720, RuleResult.Failed, RuleJobResult.Retry)] |
|||
[InlineData(4, 0, RuleResult.Failed, RuleJobResult.Failed)] |
|||
public async Task Should_set_next_attempt_based_on_num_calls(int calls, int minutes, RuleResult result, RuleJobResult jobResult) |
|||
{ |
|||
var actionData = new RuleJobData(); |
|||
var actionName = "MyAction"; |
|||
|
|||
var @event = CreateEvent(calls, actionName, actionData); |
|||
|
|||
var requestElapsed = TimeSpan.FromMinutes(1); |
|||
var requestDump = "Dump"; |
|||
|
|||
A.CallTo(() => ruleService.InvokeAsync(@event.Job.ActionName, @event.Job.ActionData)) |
|||
.Returns((requestDump, result, requestElapsed)); |
|||
|
|||
Instant? nextCall = null; |
|||
|
|||
if (minutes > 0) |
|||
{ |
|||
nextCall = now.Plus(Duration.FromMinutes(minutes)); |
|||
} |
|||
|
|||
await sut.HandleAsync(@event); |
|||
|
|||
sut.Dispose(); |
|||
|
|||
A.CallTo(() => ruleEventRepository.MarkSentAsync(@event.Id, requestDump, result, jobResult, requestElapsed, nextCall)) |
|||
.MustHaveHappened(); |
|||
} |
|||
|
|||
private IRuleEventEntity CreateEvent(int numCalls, string actionName, RuleJobData actionData) |
|||
{ |
|||
var @event = A.Fake<IRuleEventEntity>(); |
|||
|
|||
var job = new RuleJob |
|||
{ |
|||
RuleId = Guid.NewGuid(), |
|||
ActionData = actionData, |
|||
ActionName = actionName, |
|||
Created = now |
|||
}; |
|||
|
|||
A.CallTo(() => @event.Id).Returns(Guid.NewGuid()); |
|||
A.CallTo(() => @event.Job).Returns(job); |
|||
A.CallTo(() => @event.Created).Returns(now); |
|||
A.CallTo(() => @event.NumCalls).Returns(numCalls); |
|||
|
|||
return @event; |
|||
} |
|||
} |
|||
} |
|||
@ -1,102 +0,0 @@ |
|||
// ==========================================================================
|
|||
// RuleEnqueuerTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using FakeItEasy; |
|||
using NodaTime; |
|||
using Squidex.Domain.Apps.Core.HandleRules; |
|||
using Squidex.Domain.Apps.Core.Rules; |
|||
using Squidex.Domain.Apps.Core.Rules.Actions; |
|||
using Squidex.Domain.Apps.Core.Rules.Triggers; |
|||
using Squidex.Domain.Apps.Events.Contents; |
|||
using Squidex.Domain.Apps.Read.Rules.Repositories; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.EventSourcing; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Read.Rules |
|||
{ |
|||
public class RuleEnqueuerTests |
|||
{ |
|||
private readonly IAppProvider appProvider = A.Fake<IAppProvider>(); |
|||
private readonly IRuleEventRepository ruleEventRepository = A.Fake<IRuleEventRepository>(); |
|||
private readonly RuleService ruleService = A.Fake<RuleService>(); |
|||
private readonly Instant now = SystemClock.Instance.GetCurrentInstant(); |
|||
private readonly NamedId<Guid> appId = new NamedId<Guid>(Guid.NewGuid(), "my-app"); |
|||
private readonly RuleEnqueuer sut; |
|||
|
|||
public RuleEnqueuerTests() |
|||
{ |
|||
sut = new RuleEnqueuer( |
|||
ruleEventRepository, |
|||
appProvider, |
|||
ruleService); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_return_contents_filter_for_events_filter() |
|||
{ |
|||
Assert.Equal(".*", sut.EventsFilter); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_return_type_name_for_name() |
|||
{ |
|||
Assert.Equal(typeof(RuleEnqueuer).Name, sut.Name); |
|||
} |
|||
|
|||
[Fact] |
|||
public Task Should_do_nothing_on_clear() |
|||
{ |
|||
return sut.ClearAsync(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_update_repositories_on_with_jobs_from_sender() |
|||
{ |
|||
var @event = Envelope.Create(new ContentCreated { AppId = appId }); |
|||
|
|||
var rule1 = new Rule(new ContentChangedTrigger(), new WebhookAction { Url = new Uri("https://squidex.io") }); |
|||
var rule2 = new Rule(new ContentChangedTrigger(), new WebhookAction { Url = new Uri("https://squidex.io") }); |
|||
var rule3 = new Rule(new ContentChangedTrigger(), new WebhookAction { Url = new Uri("https://squidex.io") }); |
|||
|
|||
var job1 = new RuleJob { Created = now }; |
|||
var job2 = new RuleJob { Created = now }; |
|||
|
|||
var ruleEntity1 = A.Fake<IRuleEntity>(); |
|||
var ruleEntity2 = A.Fake<IRuleEntity>(); |
|||
var ruleEntity3 = A.Fake<IRuleEntity>(); |
|||
|
|||
A.CallTo(() => ruleEntity1.RuleDef).Returns(rule1); |
|||
A.CallTo(() => ruleEntity2.RuleDef).Returns(rule2); |
|||
A.CallTo(() => ruleEntity3.RuleDef).Returns(rule3); |
|||
|
|||
A.CallTo(() => appProvider.GetRulesAsync(appId.Name)) |
|||
.Returns(new List<IRuleEntity> { ruleEntity1, ruleEntity2, ruleEntity3 }); |
|||
|
|||
A.CallTo(() => ruleService.CreateJob(rule1, @event)) |
|||
.Returns(job1); |
|||
|
|||
A.CallTo(() => ruleService.CreateJob(rule2, @event)) |
|||
.Returns(job2); |
|||
|
|||
A.CallTo(() => ruleService.CreateJob(rule3, @event)) |
|||
.Returns(null); |
|||
|
|||
await sut.On(@event); |
|||
|
|||
A.CallTo(() => ruleEventRepository.EnqueueAsync(job1, now)) |
|||
.MustHaveHappened(); |
|||
|
|||
A.CallTo(() => ruleEventRepository.EnqueueAsync(job2, now)) |
|||
.MustHaveHappened(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,37 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
<PropertyGroup> |
|||
<OutputType>Exe</OutputType> |
|||
<TargetFramework>netcoreapp2.0</TargetFramework> |
|||
<RootNamespace>Squidex.Domain.Apps.Read</RootNamespace> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<Compile Remove="MongoDb\**" /> |
|||
<EmbeddedResource Remove="MongoDb\**" /> |
|||
<None Remove="MongoDb\**" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\Squidex.Domain.Apps.Core.Model\Squidex.Domain.Apps.Core.Model.csproj" /> |
|||
<ProjectReference Include="..\..\src\Squidex.Domain.Apps.Core.Operations\Squidex.Domain.Apps.Core.Operations.csproj" /> |
|||
<ProjectReference Include="..\..\src\Squidex.Domain.Apps.Events\Squidex.Domain.Apps.Events.csproj" /> |
|||
<ProjectReference Include="..\..\src\Squidex.Infrastructure\Squidex.Infrastructure.csproj" /> |
|||
<ProjectReference Include="..\..\src\Squidex.Domain.Apps.Read\Squidex.Domain.Apps.Read.csproj" /> |
|||
<ProjectReference Include="..\..\src\Squidex.Domain.Apps.Read.MongoDb\Squidex.Domain.Apps.Read.MongoDb.csproj" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<PackageReference Include="FakeItEasy" Version="4.2.0" /> |
|||
<PackageReference Include="FluentAssertions" Version="4.19.4" /> |
|||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" /> |
|||
<PackageReference Include="MongoDB.Driver" Version="2.4.4" /> |
|||
<PackageReference Include="RefactoringEssentials" Version="5.4.0" /> |
|||
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2" /> |
|||
<PackageReference Include="System.ValueTuple" Version="4.4.0" /> |
|||
<PackageReference Include="xunit" Version="2.3.1" /> |
|||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="2.0.0" /> |
|||
</ItemGroup> |
|||
<PropertyGroup> |
|||
<CodeAnalysisRuleSet>..\..\Squidex.ruleset</CodeAnalysisRuleSet> |
|||
</PropertyGroup> |
|||
</Project> |
|||
@ -1,244 +0,0 @@ |
|||
// ==========================================================================
|
|||
// AppCommandMiddlewareTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using FakeItEasy; |
|||
using Squidex.Domain.Apps.Read; |
|||
using Squidex.Domain.Apps.Read.Apps; |
|||
using Squidex.Domain.Apps.Read.Apps.Services; |
|||
using Squidex.Domain.Apps.Read.Apps.Services.Implementations; |
|||
using Squidex.Domain.Apps.Write.Apps.Commands; |
|||
using Squidex.Domain.Apps.Write.TestHelpers; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Commands; |
|||
using Squidex.Shared.Users; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Apps |
|||
{ |
|||
public class AppCommandMiddlewareTests : HandlerTestBase<AppDomainObject> |
|||
{ |
|||
private readonly IAppProvider appProvider = A.Fake<IAppProvider>(); |
|||
private readonly IAppPlansProvider appPlansProvider = A.Fake<IAppPlansProvider>(); |
|||
private readonly IAppPlanBillingManager appPlansBillingManager = A.Fake<IAppPlanBillingManager>(); |
|||
private readonly IUserResolver userResolver = A.Fake<IUserResolver>(); |
|||
private readonly AppCommandMiddleware sut; |
|||
private readonly AppDomainObject app; |
|||
private readonly Language language = Language.DE; |
|||
private readonly string contributorId = Guid.NewGuid().ToString(); |
|||
private readonly string clientName = "client"; |
|||
|
|||
public AppCommandMiddlewareTests() |
|||
{ |
|||
app = new AppDomainObject(AppId, -1); |
|||
|
|||
A.CallTo(() => appProvider.GetAppAsync(AppName)) |
|||
.Returns((IAppEntity)null); |
|||
|
|||
A.CallTo(() => userResolver.FindByIdAsync(contributorId)) |
|||
.Returns(A.Fake<IUser>()); |
|||
|
|||
sut = new AppCommandMiddleware(Handler, appProvider, appPlansProvider, appPlansBillingManager, userResolver); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Create_should_create_domain_object() |
|||
{ |
|||
var context = CreateContextForCommand(new CreateApp { Name = AppName, AppId = AppId }); |
|||
|
|||
await TestCreate(app, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
|
|||
Assert.Equal(AppId, context.Result<EntityCreatedResult<Guid>>().IdOrValue); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task AssignContributor_should_assign_if_user_found() |
|||
{ |
|||
A.CallTo(() => appPlansProvider.GetPlan(null)) |
|||
.Returns(new ConfigAppLimitsPlan { MaxContributors = -1 }); |
|||
|
|||
CreateApp(); |
|||
|
|||
var context = CreateContextForCommand(new AssignContributor { ContributorId = contributorId }); |
|||
|
|||
await TestUpdate(app, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task RemoveContributor_should_update_domain_object() |
|||
{ |
|||
CreateApp() |
|||
.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId })); |
|||
|
|||
var context = CreateContextForCommand(new RemoveContributor { ContributorId = contributorId }); |
|||
|
|||
await TestUpdate(app, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task AttachClient_should_update_domain_object() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
var context = CreateContextForCommand(new AttachClient { Id = clientName }); |
|||
|
|||
await TestUpdate(app, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task RenameClient_should_update_domain_object() |
|||
{ |
|||
CreateApp() |
|||
.AttachClient(CreateCommand(new AttachClient { Id = clientName })); |
|||
|
|||
var context = CreateContextForCommand(new UpdateClient { Id = clientName, Name = "New Name" }); |
|||
|
|||
await TestUpdate(app, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task RevokeClient_should_update_domain_object() |
|||
{ |
|||
CreateApp() |
|||
.AttachClient(CreateCommand(new AttachClient { Id = clientName })); |
|||
|
|||
var context = CreateContextForCommand(new RevokeClient { Id = clientName }); |
|||
|
|||
await TestUpdate(app, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task ChangePlan_should_update_domain_object() |
|||
{ |
|||
A.CallTo(() => appPlansProvider.IsConfiguredPlan("my-plan")) |
|||
.Returns(true); |
|||
|
|||
CreateApp(); |
|||
|
|||
var context = CreateContextForCommand(new ChangePlan { PlanId = "my-plan" }); |
|||
|
|||
await TestUpdate(app, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
|
|||
A.CallTo(() => appPlansBillingManager.ChangePlanAsync(User.Identifier, app.Id, app.Name, "my-plan")).MustHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task ChangePlan_should_not_make_update_for_redirect_result() |
|||
{ |
|||
A.CallTo(() => appPlansProvider.IsConfiguredPlan("my-plan")) |
|||
.Returns(true); |
|||
|
|||
A.CallTo(() => appPlansBillingManager.ChangePlanAsync(User.Identifier, app.Id, app.Name, "my-plan")) |
|||
.Returns(CreateRedirectResult()); |
|||
|
|||
CreateApp(); |
|||
|
|||
var context = CreateContextForCommand(new ChangePlan { PlanId = "my-plan" }); |
|||
|
|||
await TestUpdate(app, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
|
|||
Assert.Null(app.Plan); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task ChangePlan_should_not_call_billing_manager_for_callback() |
|||
{ |
|||
A.CallTo(() => appPlansProvider.IsConfiguredPlan("my-plan")) |
|||
.Returns(true); |
|||
|
|||
CreateApp(); |
|||
|
|||
var context = CreateContextForCommand(new ChangePlan { PlanId = "my-plan", FromCallback = true }); |
|||
|
|||
await TestUpdate(app, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
|
|||
A.CallTo(() => appPlansBillingManager.ChangePlanAsync(User.Identifier, app.Id, app.Name, "my-plan")).MustNotHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task AddLanguage_should_update_domain_object() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
var context = CreateContextForCommand(new AddLanguage { Language = language }); |
|||
|
|||
await TestUpdate(app, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task RemoveLanguage_should_update_domain_object() |
|||
{ |
|||
CreateApp() |
|||
.AddLanguage(CreateCommand(new AddLanguage { Language = language })); |
|||
|
|||
var context = CreateContextForCommand(new RemoveLanguage { Language = language }); |
|||
|
|||
await TestUpdate(app, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task UpdateLanguage_should_update_domain_object() |
|||
{ |
|||
CreateApp() |
|||
.AddLanguage(CreateCommand(new AddLanguage { Language = language })); |
|||
|
|||
var context = CreateContextForCommand(new UpdateLanguage { Language = language }); |
|||
|
|||
await TestUpdate(app, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
private AppDomainObject CreateApp() |
|||
{ |
|||
app.Create(CreateCommand(new CreateApp { Name = AppName })); |
|||
|
|||
return app; |
|||
} |
|||
|
|||
private static Task<IChangePlanResult> CreateRedirectResult() |
|||
{ |
|||
return Task.FromResult<IChangePlanResult>(new RedirectToCheckoutResult(new Uri("http://squidex.io"))); |
|||
} |
|||
} |
|||
} |
|||
@ -1,288 +0,0 @@ |
|||
// ==========================================================================
|
|||
// AppDomainObjectTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Domain.Apps.Events.Apps; |
|||
using Squidex.Domain.Apps.Write.Apps.Commands; |
|||
using Squidex.Domain.Apps.Write.TestHelpers; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Commands; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Apps |
|||
{ |
|||
public class AppDomainObjectTests : HandlerTestBase<AppDomainObject> |
|||
{ |
|||
private readonly AppDomainObject sut; |
|||
private readonly string contributorId = Guid.NewGuid().ToString(); |
|||
private readonly string clientId = "client"; |
|||
private readonly string clientNewName = "My Client"; |
|||
private readonly string planId = "premium"; |
|||
|
|||
public AppDomainObjectTests() |
|||
{ |
|||
sut = new AppDomainObject(AppId, 0); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_throw_exception_if_created() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Create(CreateCommand(new CreateApp { Name = AppName })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_specify_name_and_owner() |
|||
{ |
|||
sut.Create(CreateCommand(new CreateApp { Name = AppName, Actor = User, AppId = AppId })); |
|||
|
|||
Assert.Equal(AppName, sut.Name); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new AppCreated { Name = AppName }), |
|||
CreateEvent(new AppContributorAssigned { ContributorId = User.Identifier, Permission = AppContributorPermission.Owner }), |
|||
CreateEvent(new AppLanguageAdded { Language = Language.EN }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ChangePlan_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.ChangePlan(CreateCommand(new ChangePlan { PlanId = planId })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ChangePlan_should_create_events() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
sut.ChangePlan(CreateCommand(new ChangePlan { PlanId = planId })); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new AppPlanChanged { PlanId = planId }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void AssignContributor_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void AssignContributor_should_create_events() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId, Permission = AppContributorPermission.Editor })); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new AppContributorAssigned { ContributorId = contributorId, Permission = AppContributorPermission.Editor }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void RemoveContributor_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.RemoveContributor(CreateCommand(new RemoveContributor { ContributorId = contributorId })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void RemoveContributor_should_create_events_and_remove_contributor() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId, Permission = AppContributorPermission.Editor })); |
|||
sut.RemoveContributor(CreateCommand(new RemoveContributor { ContributorId = contributorId })); |
|||
|
|||
sut.GetUncomittedEvents().Skip(1) |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new AppContributorRemoved { ContributorId = contributorId }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void AttachClient_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.AttachClient(CreateCommand(new AttachClient { Id = clientId })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void AttachClient_should_create_events() |
|||
{ |
|||
var command = new AttachClient { Id = clientId }; |
|||
|
|||
CreateApp(); |
|||
|
|||
sut.AttachClient(CreateCommand(command)); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new AppClientAttached { Id = clientId, Secret = command.Secret }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void RevokeClient_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.RevokeClient(CreateCommand(new RevokeClient { Id = "not-found" })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void RevokeClient_should_create_events() |
|||
{ |
|||
CreateApp(); |
|||
CreateClient(); |
|||
|
|||
sut.RevokeClient(CreateCommand(new RevokeClient { Id = clientId })); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new AppClientRevoked { Id = clientId }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateClient_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.UpdateClient(CreateCommand(new UpdateClient { Id = "not-found", Name = clientNewName })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateClient_should_create_events() |
|||
{ |
|||
CreateApp(); |
|||
CreateClient(); |
|||
|
|||
sut.UpdateClient(CreateCommand(new UpdateClient { Id = clientId, Name = clientNewName, Permission = AppClientPermission.Developer })); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new AppClientRenamed { Id = clientId, Name = clientNewName }), |
|||
CreateEvent(new AppClientUpdated { Id = clientId, Permission = AppClientPermission.Developer }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void AddLanguage_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.AddLanguage(CreateCommand(new AddLanguage { Language = Language.DE })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void AddLanguage_should_create_events() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
sut.AddLanguage(CreateCommand(new AddLanguage { Language = Language.DE })); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new AppLanguageAdded { Language = Language.DE }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void RemoveLanguage_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.RemoveLanguage(CreateCommand(new RemoveLanguage { Language = Language.EN })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void RemoveLanguage_should_create_events() |
|||
{ |
|||
CreateApp(); |
|||
CreateLanguage(Language.DE); |
|||
|
|||
sut.RemoveLanguage(CreateCommand(new RemoveLanguage { Language = Language.DE })); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new AppLanguageRemoved { Language = Language.DE }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateLanguage_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.UpdateLanguage(CreateCommand(new UpdateLanguage { Language = Language.EN })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateLanguage_should_create_events() |
|||
{ |
|||
CreateApp(); |
|||
CreateLanguage(Language.DE); |
|||
|
|||
sut.UpdateLanguage(CreateCommand(new UpdateLanguage { Language = Language.DE, Fallback = new List<Language> { Language.EN } })); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new AppLanguageUpdated { Language = Language.DE, Fallback = new List<Language> { Language.EN } }) |
|||
); |
|||
} |
|||
|
|||
private void CreateApp() |
|||
{ |
|||
sut.Create(CreateCommand(new CreateApp { Name = AppName })); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
|
|||
private void CreateClient() |
|||
{ |
|||
sut.AttachClient(CreateCommand(new AttachClient { Id = clientId })); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
|
|||
private void CreateLanguage(Language language) |
|||
{ |
|||
sut.AddLanguage(CreateCommand(new AddLanguage { Language = language })); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,51 +0,0 @@ |
|||
// ==========================================================================
|
|||
// AppEventTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Domain.Apps.Events; |
|||
using Squidex.Domain.Apps.Events.Apps; |
|||
using Squidex.Domain.Apps.Events.Apps.Old; |
|||
using Squidex.Domain.Apps.Write.TestHelpers; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
#pragma warning disable CS0612 // Type or member is obsolete
|
|||
|
|||
namespace Squidex.Domain.Apps.Write.Apps |
|||
{ |
|||
public class AppEventTests |
|||
{ |
|||
private readonly RefToken actor = new RefToken("User", Guid.NewGuid().ToString()); |
|||
private readonly NamedId<Guid> appId = new NamedId<Guid>(Guid.NewGuid(), "my-app"); |
|||
|
|||
[Fact] |
|||
public void Should_migrate_client_changed_as_reader_to_client_updated() |
|||
{ |
|||
var source = CreateEvent(new AppClientChanged { IsReader = true }); |
|||
|
|||
source.Migrate().ShouldBeSameEvent(CreateEvent(new AppClientUpdated { Permission = AppClientPermission.Reader })); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_migrate_client_changed_as_writer_to_client_updated() |
|||
{ |
|||
var source = CreateEvent(new AppClientChanged { IsReader = false }); |
|||
|
|||
source.Migrate().ShouldBeSameEvent(CreateEvent(new AppClientUpdated { Permission = AppClientPermission.Editor })); |
|||
} |
|||
|
|||
private T CreateEvent<T>(T contentEvent) where T : AppEvent |
|||
{ |
|||
contentEvent.Actor = actor; |
|||
contentEvent.AppId = appId; |
|||
|
|||
return contentEvent; |
|||
} |
|||
} |
|||
} |
|||
@ -1,142 +0,0 @@ |
|||
// ==========================================================================
|
|||
// GuardAppClientsTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Domain.Apps.Write.Apps.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
#pragma warning disable SA1310 // Field names must not contain underscore
|
|||
|
|||
namespace Squidex.Domain.Apps.Write.Apps.Guards |
|||
{ |
|||
public class GuardAppClientsTests |
|||
{ |
|||
private readonly AppClients clients_0 = AppClients.Empty; |
|||
|
|||
[Fact] |
|||
public void CanAttach_should_throw_execption_if_client_id_is_null() |
|||
{ |
|||
var command = new AttachClient(); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppClients.CanAttach(clients_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanAttach_should_throw_exception_if_client_already_exists() |
|||
{ |
|||
var command = new AttachClient { Id = "android" }; |
|||
|
|||
var clients_1 = clients_0.Add("android", "secret"); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppClients.CanAttach(clients_1, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanAttach_should_not_throw_exception_if_client_is_free() |
|||
{ |
|||
var command = new AttachClient { Id = "ios" }; |
|||
|
|||
var clients_1 = clients_0.Add("android", "secret"); |
|||
|
|||
GuardAppClients.CanAttach(clients_1, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanRevoke_should_throw_execption_if_client_id_is_null() |
|||
{ |
|||
var command = new RevokeClient(); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppClients.CanRevoke(clients_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanRevoke_should_throw_exception_if_client_is_not_found() |
|||
{ |
|||
var command = new RevokeClient { Id = "ios" }; |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppClients.CanRevoke(clients_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanRevoke_should_not_throw_exception_if_client_is_found() |
|||
{ |
|||
var command = new RevokeClient { Id = "ios" }; |
|||
|
|||
var clients_1 = clients_0.Add("ios", "secret"); |
|||
|
|||
GuardAppClients.CanRevoke(clients_1, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUpdate_should_throw_execption_if_client_id_is_null() |
|||
{ |
|||
var command = new UpdateClient(); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateClient_should_throw_exception_if_client_is_not_found() |
|||
{ |
|||
var command = new UpdateClient { Id = "ios", Name = "iOS" }; |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppClients.CanUpdate(clients_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateClient_should_throw_exception_if_client_has_no_name_and_permission() |
|||
{ |
|||
var command = new UpdateClient { Id = "ios" }; |
|||
|
|||
var clients_1 = clients_0.Add("ios", "secret"); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients_1, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateClient_should_throw_exception_if_client_has_invalid_permission() |
|||
{ |
|||
var command = new UpdateClient { Id = "ios", Permission = (AppClientPermission)10 }; |
|||
|
|||
var clients_1 = clients_0.Add("ios", "secret"); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients_1, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateClient_should_throw_exception_if_client_has_same_name() |
|||
{ |
|||
var command = new UpdateClient { Id = "ios", Name = "ios" }; |
|||
|
|||
var clients_1 = clients_0.Add("ios", "secret"); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients_1, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateClient_should_throw_exception_if_client_has_same_permission() |
|||
{ |
|||
var command = new UpdateClient { Id = "ios", Permission = AppClientPermission.Editor }; |
|||
|
|||
var clients_1 = clients_0.Add("ios", "secret"); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients_1, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateClient_should_not_throw_exception_if_command_is_valid() |
|||
{ |
|||
var command = new UpdateClient { Id = "ios", Name = "iOS", Permission = AppClientPermission.Reader }; |
|||
|
|||
var clients_1 = clients_0.Add("ios", "secret"); |
|||
|
|||
GuardAppClients.CanUpdate(clients_1, command); |
|||
} |
|||
} |
|||
} |
|||
@ -1,158 +0,0 @@ |
|||
// ==========================================================================
|
|||
// GuardAppContributorsTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
using FakeItEasy; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Domain.Apps.Read.Apps.Services; |
|||
using Squidex.Domain.Apps.Write.Apps.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Shared.Users; |
|||
using Xunit; |
|||
|
|||
#pragma warning disable SA1310 // Field names must not contain underscore
|
|||
|
|||
namespace Squidex.Domain.Apps.Write.Apps.Guards |
|||
{ |
|||
public class GuardAppContributorsTests |
|||
{ |
|||
private readonly IUserResolver users = A.Fake<IUserResolver>(); |
|||
private readonly IAppLimitsPlan appPlan = A.Fake<IAppLimitsPlan>(); |
|||
private readonly AppContributors contributors_0 = AppContributors.Empty; |
|||
|
|||
public GuardAppContributorsTests() |
|||
{ |
|||
A.CallTo(() => users.FindByIdAsync(A<string>.Ignored)) |
|||
.Returns(A.Fake<IUser>()); |
|||
|
|||
A.CallTo(() => appPlan.MaxContributors) |
|||
.Returns(10); |
|||
} |
|||
|
|||
[Fact] |
|||
public Task CanAssign_should_throw_exception_if_contributor_id_is_null() |
|||
{ |
|||
var command = new AssignContributor(); |
|||
|
|||
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan)); |
|||
} |
|||
|
|||
[Fact] |
|||
public Task CanAssign_should_throw_exception_if_permission_not_valid() |
|||
{ |
|||
var command = new AssignContributor { ContributorId = "1", Permission = (AppContributorPermission)10 }; |
|||
|
|||
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan)); |
|||
} |
|||
|
|||
[Fact] |
|||
public Task CanAssign_should_throw_exception_if_user_already_exists_with_same_permission() |
|||
{ |
|||
var command = new AssignContributor { ContributorId = "1" }; |
|||
|
|||
var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Owner); |
|||
|
|||
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors_1, command, users, appPlan)); |
|||
} |
|||
|
|||
[Fact] |
|||
public Task CanAssign_should_throw_exception_if_user_not_found() |
|||
{ |
|||
A.CallTo(() => users.FindByIdAsync(A<string>.Ignored)) |
|||
.Returns(Task.FromResult<IUser>(null)); |
|||
|
|||
var command = new AssignContributor { ContributorId = "1", Permission = (AppContributorPermission)10 }; |
|||
|
|||
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan)); |
|||
} |
|||
|
|||
[Fact] |
|||
public Task CanAssign_should_throw_exception_if_contributor_max_reached() |
|||
{ |
|||
A.CallTo(() => appPlan.MaxContributors) |
|||
.Returns(2); |
|||
|
|||
var command = new AssignContributor { ContributorId = "3" }; |
|||
|
|||
var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Owner); |
|||
var contributors_2 = contributors_1.Assign("2", AppContributorPermission.Editor); |
|||
|
|||
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors_2, command, users, appPlan)); |
|||
} |
|||
|
|||
[Fact] |
|||
public Task CanAssign_should_not_throw_exception_if_user_found() |
|||
{ |
|||
var command = new AssignContributor { ContributorId = "1" }; |
|||
|
|||
return GuardAppContributors.CanAssign(contributors_0, command, users, appPlan); |
|||
} |
|||
|
|||
[Fact] |
|||
public Task CanAssign_should_not_throw_exception_if_contributor_has_another_permission() |
|||
{ |
|||
var command = new AssignContributor { ContributorId = "1" }; |
|||
|
|||
var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Editor); |
|||
|
|||
return GuardAppContributors.CanAssign(contributors_1, command, users, appPlan); |
|||
} |
|||
|
|||
[Fact] |
|||
public Task CanAssign_should_not_throw_exception_if_contributor_max_reached_but_permission_changed() |
|||
{ |
|||
A.CallTo(() => appPlan.MaxContributors) |
|||
.Returns(2); |
|||
|
|||
var command = new AssignContributor { ContributorId = "1" }; |
|||
|
|||
var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Editor); |
|||
var contributors_2 = contributors_1.Assign("2", AppContributorPermission.Editor); |
|||
|
|||
return GuardAppContributors.CanAssign(contributors_2, command, users, appPlan); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanRemove_should_throw_exception_if_contributor_id_is_null() |
|||
{ |
|||
var command = new RemoveContributor(); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppContributors.CanRemove(contributors_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanRemove_should_throw_exception_if_contributor_not_found() |
|||
{ |
|||
var command = new RemoveContributor { ContributorId = "1" }; |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppContributors.CanRemove(contributors_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanRemove_should_throw_exception_if_contributor_is_only_owner() |
|||
{ |
|||
var command = new RemoveContributor { ContributorId = "1" }; |
|||
|
|||
var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Owner); |
|||
var contributors_2 = contributors_1.Assign("2", AppContributorPermission.Editor); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppContributors.CanRemove(contributors_2, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanRemove_should_not_throw_exception_if_contributor_not_only_owner() |
|||
{ |
|||
var command = new RemoveContributor { ContributorId = "1" }; |
|||
|
|||
var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Owner); |
|||
var contributors_2 = contributors_1.Assign("2", AppContributorPermission.Owner); |
|||
|
|||
GuardAppContributors.CanRemove(contributors_2, command); |
|||
} |
|||
} |
|||
} |
|||
@ -1,131 +0,0 @@ |
|||
// ==========================================================================
|
|||
// GuardAppLanguagesTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Domain.Apps.Write.Apps.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
#pragma warning disable SA1310 // Field names must not contain underscore
|
|||
|
|||
namespace Squidex.Domain.Apps.Write.Apps.Guards |
|||
{ |
|||
public class GuardAppLanguagesTests |
|||
{ |
|||
private readonly LanguagesConfig languages_0 = LanguagesConfig.Build(Language.DE); |
|||
|
|||
[Fact] |
|||
public void CanAddLanguage_should_throw_exception_if_language_is_null() |
|||
{ |
|||
var command = new AddLanguage(); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanAdd(languages_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanAddLanguage_should_throw_exception_if_language_already_added() |
|||
{ |
|||
var command = new AddLanguage { Language = Language.DE }; |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanAdd(languages_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanAddLanguage_should_not_throw_exception_if_language_valid() |
|||
{ |
|||
var command = new AddLanguage { Language = Language.EN }; |
|||
|
|||
GuardAppLanguages.CanAdd(languages_0, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanRemoveLanguage_should_throw_exception_if_language_is_null() |
|||
{ |
|||
var command = new RemoveLanguage(); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanRemove(languages_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanRemoveLanguage_should_throw_exception_if_language_not_found() |
|||
{ |
|||
var command = new RemoveLanguage { Language = Language.EN }; |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppLanguages.CanRemove(languages_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanRemoveLanguage_should_throw_exception_if_language_is_master() |
|||
{ |
|||
var command = new RemoveLanguage { Language = Language.DE }; |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanRemove(languages_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanRemoveLanguage_should_not_throw_exception_if_language_is_valid() |
|||
{ |
|||
var command = new RemoveLanguage { Language = Language.EN }; |
|||
|
|||
var languages_1 = languages_0.Set(new LanguageConfig(Language.EN)); |
|||
|
|||
GuardAppLanguages.CanRemove(languages_1, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUpdateLanguage_should_throw_exception_if_language_is_null() |
|||
{ |
|||
var command = new UpdateLanguage(); |
|||
|
|||
var languages_1 = languages_0.Set(new LanguageConfig(Language.EN)); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanUpdate(languages_1, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUpdateLanguage_should_throw_exception_if_language_is_optional_and_master() |
|||
{ |
|||
var command = new UpdateLanguage { Language = Language.DE, IsOptional = true }; |
|||
|
|||
var languages_1 = languages_0.Set(new LanguageConfig(Language.EN)); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanUpdate(languages_1, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUpdateLanguage_should_throw_exception_if_language_has_invalid_fallback() |
|||
{ |
|||
var command = new UpdateLanguage { Language = Language.DE, Fallback = new List<Language> { Language.IT } }; |
|||
|
|||
var languages_1 = languages_0.Set(new LanguageConfig(Language.EN)); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanUpdate(languages_1, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUpdateLanguage_should_throw_exception_if_not_found() |
|||
{ |
|||
var command = new UpdateLanguage { Language = Language.IT }; |
|||
|
|||
var languages_1 = languages_0.Set(new LanguageConfig(Language.EN)); |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppLanguages.CanUpdate(languages_1, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUpdateLanguage_should_not_throw_exception_if_language_is_valid() |
|||
{ |
|||
var command = new UpdateLanguage { Language = Language.DE, Fallback = new List<Language> { Language.EN } }; |
|||
|
|||
var languages_1 = languages_0.Set(new LanguageConfig(Language.EN)); |
|||
|
|||
GuardAppLanguages.CanUpdate(languages_1, command); |
|||
} |
|||
} |
|||
} |
|||
@ -1,120 +0,0 @@ |
|||
// ==========================================================================
|
|||
// GuardAppTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
using FakeItEasy; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Domain.Apps.Read; |
|||
using Squidex.Domain.Apps.Read.Apps; |
|||
using Squidex.Domain.Apps.Read.Apps.Services; |
|||
using Squidex.Domain.Apps.Write.Apps.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Shared.Users; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Apps.Guards |
|||
{ |
|||
public class GuardAppTests |
|||
{ |
|||
private readonly IAppProvider apps = A.Fake<IAppProvider>(); |
|||
private readonly IUserResolver users = A.Fake<IUserResolver>(); |
|||
private readonly IAppPlansProvider appPlans = A.Fake<IAppPlansProvider>(); |
|||
|
|||
public GuardAppTests() |
|||
{ |
|||
A.CallTo(() => apps.GetAppAsync("new-app")) |
|||
.Returns(Task.FromResult<IAppEntity>(null)); |
|||
|
|||
A.CallTo(() => users.FindByIdAsync(A<string>.Ignored)) |
|||
.Returns(A.Fake<IUser>()); |
|||
|
|||
A.CallTo(() => appPlans.GetPlan("free")) |
|||
.Returns(A.Fake<IAppLimitsPlan>()); |
|||
} |
|||
|
|||
[Fact] |
|||
public Task CanCreate_should_throw_exception_if_name_already_in_use() |
|||
{ |
|||
A.CallTo(() => apps.GetAppAsync("new-app")) |
|||
.Returns(A.Fake<IAppEntity>()); |
|||
|
|||
var command = new CreateApp { Name = "new-app" }; |
|||
|
|||
return Assert.ThrowsAsync<ValidationException>(() => GuardApp.CanCreate(command, apps)); |
|||
} |
|||
|
|||
[Fact] |
|||
public Task CanCreate_should_throw_exception_if_name_not_valid() |
|||
{ |
|||
var command = new CreateApp { Name = "INVALID NAME" }; |
|||
|
|||
return Assert.ThrowsAsync<ValidationException>(() => GuardApp.CanCreate(command, apps)); |
|||
} |
|||
|
|||
[Fact] |
|||
public Task CanCreate_should_not_throw_exception_if_app_name_is_free() |
|||
{ |
|||
var command = new CreateApp { Name = "new-app" }; |
|||
|
|||
return GuardApp.CanCreate(command, apps); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanChangePlan_should_throw_exception_if_plan_id_null() |
|||
{ |
|||
var command = new ChangePlan { Actor = new RefToken("user", "me") }; |
|||
|
|||
AppPlan plan = null; |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardApp.CanChangePlan(command, plan, appPlans)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanChangePlan_should_throw_exception_if_plan_not_found() |
|||
{ |
|||
A.CallTo(() => appPlans.GetPlan("free")) |
|||
.Returns(null); |
|||
|
|||
var command = new ChangePlan { PlanId = "free", Actor = new RefToken("user", "me") }; |
|||
|
|||
AppPlan plan = null; |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardApp.CanChangePlan(command, plan, appPlans)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanChangePlan_should_throw_exception_if_plan_was_configured_from_another_user() |
|||
{ |
|||
var command = new ChangePlan { PlanId = "free", Actor = new RefToken("user", "me") }; |
|||
|
|||
var plan = new AppPlan(new RefToken("user", "other"), "premium"); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardApp.CanChangePlan(command, plan, appPlans)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanChangePlan_should_throw_exception_if_plan_is_the_same() |
|||
{ |
|||
var command = new ChangePlan { PlanId = "free", Actor = new RefToken("user", "me") }; |
|||
|
|||
var plan = new AppPlan(new RefToken("user", "me"), "free"); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardApp.CanChangePlan(command, plan, appPlans)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanChangePlan_should_not_throw_exception_if_same_user_but_other_plan() |
|||
{ |
|||
var command = new ChangePlan { PlanId = "free", Actor = new RefToken("user", "me") }; |
|||
|
|||
var plan = new AppPlan(new RefToken("user", "me"), "premium"); |
|||
|
|||
GuardApp.CanChangePlan(command, plan, appPlans); |
|||
} |
|||
} |
|||
} |
|||
@ -1,139 +0,0 @@ |
|||
// ==========================================================================
|
|||
// AssetCommandMiddlewareTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.IO; |
|||
using System.Threading.Tasks; |
|||
using FakeItEasy; |
|||
using Squidex.Domain.Apps.Write.Assets.Commands; |
|||
using Squidex.Domain.Apps.Write.TestHelpers; |
|||
using Squidex.Infrastructure.Assets; |
|||
using Squidex.Infrastructure.Commands; |
|||
using Squidex.Infrastructure.Tasks; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Assets |
|||
{ |
|||
public class AssetCommandMiddlewareTests : HandlerTestBase<AssetDomainObject> |
|||
{ |
|||
private readonly IAssetThumbnailGenerator assetThumbnailGenerator = A.Fake<IAssetThumbnailGenerator>(); |
|||
private readonly IAssetStore assetStore = A.Fake<IAssetStore>(); |
|||
private readonly AssetCommandMiddleware sut; |
|||
private readonly AssetDomainObject asset; |
|||
private readonly Guid assetId = Guid.NewGuid(); |
|||
private readonly Stream stream = new MemoryStream(); |
|||
private readonly ImageInfo image = new ImageInfo(2048, 2048); |
|||
private readonly AssetFile file; |
|||
|
|||
public AssetCommandMiddlewareTests() |
|||
{ |
|||
file = new AssetFile("my-image.png", "image/png", 1024, () => stream); |
|||
|
|||
asset = new AssetDomainObject(assetId, -1); |
|||
|
|||
sut = new AssetCommandMiddleware(Handler, assetStore, assetThumbnailGenerator); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Create_should_create_domain_object() |
|||
{ |
|||
var context = CreateContextForCommand(new CreateAsset { AssetId = assetId, File = file }); |
|||
|
|||
SetupStore(0, context.ContextId); |
|||
SetupImageInfo(); |
|||
|
|||
await TestCreate(asset, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
|
|||
Assert.Equal(assetId, context.Result<EntityCreatedResult<Guid>>().IdOrValue); |
|||
|
|||
VerifyStore(0, context.ContextId); |
|||
VerifyImageInfo(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Update_should_update_domain_object() |
|||
{ |
|||
var context = CreateContextForCommand(new UpdateAsset { AssetId = assetId, File = file }); |
|||
|
|||
SetupStore(1, context.ContextId); |
|||
SetupImageInfo(); |
|||
|
|||
CreateAsset(); |
|||
|
|||
await TestUpdate(asset, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
|
|||
VerifyStore(1, context.ContextId); |
|||
VerifyImageInfo(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Rename_should_update_domain_object() |
|||
{ |
|||
CreateAsset(); |
|||
|
|||
var context = CreateContextForCommand(new RenameAsset { AssetId = assetId, FileName = "my-new-image.png" }); |
|||
|
|||
await TestUpdate(asset, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Delete_should_update_domain_object() |
|||
{ |
|||
CreateAsset(); |
|||
|
|||
var command = CreateContextForCommand(new DeleteAsset { AssetId = assetId }); |
|||
|
|||
await TestUpdate(asset, async _ => |
|||
{ |
|||
await sut.HandleAsync(command); |
|||
}); |
|||
} |
|||
|
|||
private void CreateAsset() |
|||
{ |
|||
asset.Create(new CreateAsset { File = file }); |
|||
} |
|||
|
|||
private void SetupImageInfo() |
|||
{ |
|||
A.CallTo(() => assetThumbnailGenerator.GetImageInfoAsync(stream)) |
|||
.Returns(image); |
|||
} |
|||
|
|||
private void SetupStore(long version, Guid commitId) |
|||
{ |
|||
A.CallTo(() => assetStore.UploadTemporaryAsync(commitId.ToString(), stream)) |
|||
.Returns(TaskHelper.Done); |
|||
A.CallTo(() => assetStore.CopyTemporaryAsync(commitId.ToString(), assetId.ToString(), version, null)) |
|||
.Returns(TaskHelper.Done); |
|||
A.CallTo(() => assetStore.DeleteTemporaryAsync(commitId.ToString())) |
|||
.Returns(TaskHelper.Done); |
|||
} |
|||
|
|||
private void VerifyImageInfo() |
|||
{ |
|||
A.CallTo(() => assetThumbnailGenerator.GetImageInfoAsync(stream)).MustHaveHappened(); |
|||
} |
|||
|
|||
private void VerifyStore(long version, Guid commitId) |
|||
{ |
|||
A.CallTo(() => assetStore.UploadTemporaryAsync(commitId.ToString(), stream)).MustHaveHappened(); |
|||
A.CallTo(() => assetStore.CopyTemporaryAsync(commitId.ToString(), assetId.ToString(), version, null)).MustHaveHappened(); |
|||
A.CallTo(() => assetStore.DeleteTemporaryAsync(commitId.ToString())).MustHaveHappened(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,213 +0,0 @@ |
|||
// ==========================================================================
|
|||
// AssetDomainObjectTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.IO; |
|||
using Squidex.Domain.Apps.Events.Assets; |
|||
using Squidex.Domain.Apps.Write.Assets.Commands; |
|||
using Squidex.Domain.Apps.Write.TestHelpers; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Assets; |
|||
using Squidex.Infrastructure.Commands; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Assets |
|||
{ |
|||
public class AssetDomainObjectTests : HandlerTestBase<AssetDomainObject> |
|||
{ |
|||
private readonly AssetDomainObject sut; |
|||
private readonly ImageInfo image = new ImageInfo(2048, 2048); |
|||
private readonly AssetFile file = new AssetFile("my-image.png", "image/png", 1024, () => new MemoryStream()); |
|||
|
|||
public Guid AssetId { get; } = Guid.NewGuid(); |
|||
|
|||
public AssetDomainObjectTests() |
|||
{ |
|||
sut = new AssetDomainObject(AssetId, 0); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_throw_exception_if_created() |
|||
{ |
|||
sut.Create(new CreateAsset { File = file }); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Create(CreateAssetCommand(new CreateAsset { File = file })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_create_events() |
|||
{ |
|||
sut.Create(CreateAssetCommand(new CreateAsset { File = file, ImageInfo = image })); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateAssetEvent(new AssetCreated |
|||
{ |
|||
IsImage = true, |
|||
FileName = file.FileName, |
|||
FileSize = file.FileSize, |
|||
FileVersion = 0, |
|||
MimeType = file.MimeType, |
|||
PixelWidth = image.PixelWidth, |
|||
PixelHeight = image.PixelHeight |
|||
}) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Update(CreateAssetCommand(new UpdateAsset { File = file })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_throw_exception_if_asset_is_deleted() |
|||
{ |
|||
CreateAsset(); |
|||
DeleteAsset(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Update(CreateAssetCommand(new UpdateAsset())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_create_events() |
|||
{ |
|||
CreateAsset(); |
|||
|
|||
sut.Update(CreateAssetCommand(new UpdateAsset { File = file, ImageInfo = image })); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateAssetEvent(new AssetUpdated |
|||
{ |
|||
IsImage = true, |
|||
FileSize = file.FileSize, |
|||
FileVersion = 1, |
|||
MimeType = file.MimeType, |
|||
PixelWidth = image.PixelWidth, |
|||
PixelHeight = image.PixelHeight |
|||
}) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rename_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Rename(CreateAssetCommand(new RenameAsset { FileName = "new-file.png" })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rename_should_throw_exception_if_asset_is_deleted() |
|||
{ |
|||
CreateAsset(); |
|||
DeleteAsset(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Update(CreateAssetCommand(new UpdateAsset())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rename_should_create_events() |
|||
{ |
|||
CreateAsset(); |
|||
|
|||
sut.Rename(CreateAssetCommand(new RenameAsset { FileName = "my-new-image.png" })); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateAssetEvent(new AssetRenamed { FileName = "my-new-image.png" }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Delete_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Delete(CreateAssetCommand(new DeleteAsset())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Delete_should_throw_exception_if_already_deleted() |
|||
{ |
|||
CreateAsset(); |
|||
DeleteAsset(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Delete(CreateAssetCommand(new DeleteAsset())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Delete_should_create_events_with_total_file_size() |
|||
{ |
|||
CreateAsset(); |
|||
UpdateAsset(); |
|||
|
|||
sut.Delete(CreateAssetCommand(new DeleteAsset())); |
|||
|
|||
Assert.True(sut.IsDeleted); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateAssetEvent(new AssetDeleted { DeletedSize = 2048 }) |
|||
); |
|||
} |
|||
|
|||
private void CreateAsset() |
|||
{ |
|||
sut.Create(CreateAssetCommand(new CreateAsset { File = file })); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
|
|||
private void UpdateAsset() |
|||
{ |
|||
sut.Update(CreateAssetCommand(new UpdateAsset { File = file })); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
|
|||
private void DeleteAsset() |
|||
{ |
|||
sut.Delete(CreateAssetCommand(new DeleteAsset())); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
|
|||
protected T CreateAssetEvent<T>(T @event) where T : AssetEvent |
|||
{ |
|||
@event.AssetId = AssetId; |
|||
|
|||
return CreateEvent(@event); |
|||
} |
|||
|
|||
protected T CreateAssetCommand<T>(T command) where T : AssetAggregateCommand |
|||
{ |
|||
command.AssetId = AssetId; |
|||
|
|||
return CreateCommand(command); |
|||
} |
|||
} |
|||
} |
|||
@ -1,65 +0,0 @@ |
|||
// ==========================================================================
|
|||
// GuardAssetTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Write.Assets.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Assets.Guards |
|||
{ |
|||
public class GuardAssetTests |
|||
{ |
|||
[Fact] |
|||
public void CanRename_should_throw_exception_if_name_not_defined() |
|||
{ |
|||
var command = new RenameAsset(); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAsset.CanRename(command, "asset-name")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanRename_should_throw_exception_if_name_are_the_same() |
|||
{ |
|||
var command = new RenameAsset { FileName = "asset-name" }; |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAsset.CanRename(command, "asset-name")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanRename_not_should_throw_exception_if_name_are_different() |
|||
{ |
|||
var command = new RenameAsset { FileName = "new-name" }; |
|||
|
|||
GuardAsset.CanRename(command, "asset-name"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanCreate_should_not_throw_exception() |
|||
{ |
|||
var command = new CreateAsset(); |
|||
|
|||
GuardAsset.CanCreate(command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUpdate_should_not_throw_exception() |
|||
{ |
|||
var command = new UpdateAsset(); |
|||
|
|||
GuardAsset.CanUpdate(command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanDelete_should_not_throw_exception() |
|||
{ |
|||
var command = new DeleteAsset(); |
|||
|
|||
GuardAsset.CanDelete(command); |
|||
} |
|||
} |
|||
} |
|||
@ -1,247 +0,0 @@ |
|||
// ==========================================================================
|
|||
// ContentCommandMiddlewareTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Security.Claims; |
|||
using System.Threading.Tasks; |
|||
using FakeItEasy; |
|||
using Squidex.Domain.Apps.Core; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Core.Scripting; |
|||
using Squidex.Domain.Apps.Read; |
|||
using Squidex.Domain.Apps.Read.Apps; |
|||
using Squidex.Domain.Apps.Read.Assets.Repositories; |
|||
using Squidex.Domain.Apps.Read.Contents.Repositories; |
|||
using Squidex.Domain.Apps.Read.Schemas; |
|||
using Squidex.Domain.Apps.Write.Contents.Commands; |
|||
using Squidex.Domain.Apps.Write.TestHelpers; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Commands; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Contents |
|||
{ |
|||
public class ContentCommandMiddlewareTests : HandlerTestBase<ContentDomainObject> |
|||
{ |
|||
private readonly ContentCommandMiddleware sut; |
|||
private readonly ContentDomainObject content; |
|||
private readonly ISchemaEntity schema = A.Fake<ISchemaEntity>(); |
|||
private readonly IScriptEngine scriptEngine = A.Fake<IScriptEngine>(); |
|||
private readonly IAppProvider appProvider = A.Fake<IAppProvider>(); |
|||
private readonly IAppEntity app = A.Fake<IAppEntity>(); |
|||
private readonly ClaimsPrincipal user = new ClaimsPrincipal(); |
|||
private readonly LanguagesConfig languagesConfig = LanguagesConfig.Build(Language.DE); |
|||
private readonly Guid contentId = Guid.NewGuid(); |
|||
|
|||
private readonly NamedContentData invalidData = |
|||
new NamedContentData() |
|||
.AddField("my-field1", new ContentFieldData() |
|||
.AddValue(null)) |
|||
.AddField("my-field2", new ContentFieldData() |
|||
.AddValue(1)); |
|||
private readonly NamedContentData data = |
|||
new NamedContentData() |
|||
.AddField("my-field1", new ContentFieldData() |
|||
.AddValue(1)) |
|||
.AddField("my-field2", new ContentFieldData() |
|||
.AddValue(1)); |
|||
private readonly NamedContentData patch = |
|||
new NamedContentData() |
|||
.AddField("my-field1", new ContentFieldData() |
|||
.AddValue(1)); |
|||
|
|||
public ContentCommandMiddlewareTests() |
|||
{ |
|||
var schemaDef = |
|||
new Schema("my-schema") |
|||
.AddField(new NumberField(1, "my-field1", Partitioning.Invariant, |
|||
new NumberFieldProperties { IsRequired = true })) |
|||
.AddField(new NumberField(2, "my-field2", Partitioning.Invariant, |
|||
new NumberFieldProperties { IsRequired = false })); |
|||
|
|||
content = new ContentDomainObject(contentId, -1); |
|||
|
|||
sut = new ContentCommandMiddleware(Handler, appProvider, A.Dummy<IAssetRepository>(), scriptEngine, A.Dummy<IContentRepository>()); |
|||
|
|||
A.CallTo(() => app.LanguagesConfig).Returns(languagesConfig); |
|||
|
|||
A.CallTo(() => appProvider.GetAppAsync(AppName)).Returns(app); |
|||
|
|||
A.CallTo(() => schema.SchemaDef).Returns(schemaDef); |
|||
A.CallTo(() => schema.ScriptCreate).Returns("<create-script>"); |
|||
A.CallTo(() => schema.ScriptChange).Returns("<change-script>"); |
|||
A.CallTo(() => schema.ScriptUpdate).Returns("<update-script>"); |
|||
A.CallTo(() => schema.ScriptDelete).Returns("<delete-script>"); |
|||
|
|||
A.CallTo(() => appProvider.GetAppWithSchemaAsync(AppName, SchemaId)).Returns((app, schema)); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Create_should_throw_exception_if_data_is_not_valid() |
|||
{ |
|||
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored)) |
|||
.Returns(invalidData); |
|||
|
|||
var context = CreateContextForCommand(new CreateContent { ContentId = contentId, Data = invalidData, User = user }); |
|||
|
|||
await TestCreate(content, async _ => |
|||
{ |
|||
await Assert.ThrowsAsync<ValidationException>(() => sut.HandleAsync(context)); |
|||
}, false); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Create_should_create_content() |
|||
{ |
|||
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored)) |
|||
.Returns(data); |
|||
|
|||
var context = CreateContextForCommand(new CreateContent { ContentId = contentId, Data = data, User = user }); |
|||
|
|||
await TestCreate(content, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
|
|||
Assert.Equal(data, context.Result<EntityCreatedResult<NamedContentData>>().IdOrValue); |
|||
|
|||
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<create-script>")).MustHaveHappened(); |
|||
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<change-script>")).MustNotHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Create_should_also_invoke_publish_script_when_publishing() |
|||
{ |
|||
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored)) |
|||
.Returns(data); |
|||
|
|||
var context = CreateContextForCommand(new CreateContent { ContentId = contentId, Data = data, User = user, Publish = true }); |
|||
|
|||
await TestCreate(content, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
|
|||
Assert.Equal(data, context.Result<EntityCreatedResult<NamedContentData>>().IdOrValue); |
|||
|
|||
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<create-script>")).MustHaveHappened(); |
|||
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<change-script>")).MustHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Update_should_throw_exception_if_data_is_not_valid() |
|||
{ |
|||
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored)) |
|||
.Returns(invalidData); |
|||
|
|||
CreateContent(); |
|||
|
|||
var context = CreateContextForCommand(new UpdateContent { ContentId = contentId, Data = invalidData, User = user }); |
|||
|
|||
await TestUpdate(content, async _ => |
|||
{ |
|||
await Assert.ThrowsAsync<ValidationException>(() => sut.HandleAsync(context)); |
|||
}, false); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Update_should_update_domain_object() |
|||
{ |
|||
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored)) |
|||
.Returns(data); |
|||
|
|||
CreateContent(); |
|||
|
|||
var context = CreateContextForCommand(new UpdateContent { ContentId = contentId, Data = data, User = user }); |
|||
|
|||
await TestUpdate(content, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
|
|||
Assert.Equal(data, context.Result<ContentDataChangedResult>().Data); |
|||
|
|||
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<update-script>")).MustHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Patch_should_throw_exception_if_data_is_not_valid() |
|||
{ |
|||
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored)) |
|||
.Returns(invalidData); |
|||
|
|||
CreateContent(); |
|||
|
|||
var context = CreateContextForCommand(new PatchContent { ContentId = contentId, Data = invalidData, User = user }); |
|||
|
|||
await TestUpdate(content, async _ => |
|||
{ |
|||
await Assert.ThrowsAsync<ValidationException>(() => sut.HandleAsync(context)); |
|||
}, false); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Patch_should_update_domain_object() |
|||
{ |
|||
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored)) |
|||
.Returns(data); |
|||
|
|||
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, A<string>.Ignored)).Returns(patch); |
|||
|
|||
CreateContent(); |
|||
|
|||
var context = CreateContextForCommand(new PatchContent { ContentId = contentId, Data = patch, User = user }); |
|||
|
|||
await TestUpdate(content, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
|
|||
Assert.NotNull(context.Result<ContentDataChangedResult>().Data); |
|||
|
|||
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<update-script>")).MustHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task ChangeStatus_should_publish_domain_object() |
|||
{ |
|||
CreateContent(); |
|||
|
|||
var context = CreateContextForCommand(new ChangeContentStatus { ContentId = contentId, User = user, Status = Status.Published }); |
|||
|
|||
await TestUpdate(content, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
|
|||
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<change-script>")).MustHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Delete_should_update_domain_object() |
|||
{ |
|||
CreateContent(); |
|||
|
|||
var command = CreateContextForCommand(new DeleteContent { ContentId = contentId, User = user }); |
|||
|
|||
await TestUpdate(content, async _ => |
|||
{ |
|||
await sut.HandleAsync(command); |
|||
}); |
|||
|
|||
A.CallTo(() => scriptEngine.Execute(A<ScriptContext>.Ignored, "<delete-script>")).MustHaveHappened(); |
|||
} |
|||
|
|||
private void CreateContent() |
|||
{ |
|||
content.Create(new CreateContent { Data = data }); |
|||
} |
|||
} |
|||
} |
|||
@ -1,280 +0,0 @@ |
|||
// ==========================================================================
|
|||
// ContentDomainObjectTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using FluentAssertions; |
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Domain.Apps.Events.Contents; |
|||
using Squidex.Domain.Apps.Write.Contents.Commands; |
|||
using Squidex.Domain.Apps.Write.TestHelpers; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Commands; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Contents |
|||
{ |
|||
public class ContentDomainObjectTests : HandlerTestBase<ContentDomainObject> |
|||
{ |
|||
private readonly ContentDomainObject sut; |
|||
private readonly NamedContentData data = |
|||
new NamedContentData() |
|||
.AddField("field1", |
|||
new ContentFieldData() |
|||
.AddValue("iv", 1)); |
|||
private readonly NamedContentData otherData = |
|||
new NamedContentData() |
|||
.AddField("field2", |
|||
new ContentFieldData() |
|||
.AddValue("iv", 2)); |
|||
|
|||
public Guid ContentId { get; } = Guid.NewGuid(); |
|||
|
|||
public ContentDomainObjectTests() |
|||
{ |
|||
sut = new ContentDomainObject(ContentId, 0); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_throw_exception_if_created() |
|||
{ |
|||
sut.Create(new CreateContent { Data = data }); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Create(CreateContentCommand(new CreateContent { Data = data })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_create_events() |
|||
{ |
|||
sut.Create(CreateContentCommand(new CreateContent { Data = data })); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateContentEvent(new ContentCreated { Data = data }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_also_publish_if_set_to_true() |
|||
{ |
|||
sut.Create(CreateContentCommand(new CreateContent { Data = data, Publish = true })); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateContentEvent(new ContentCreated { Data = data }), |
|||
CreateContentEvent(new ContentStatusChanged { Status = Status.Published }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Update(CreateContentCommand(new UpdateContent { Data = data })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_throw_exception_if_content_is_deleted() |
|||
{ |
|||
CreateContent(); |
|||
DeleteContent(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Update(CreateContentCommand(new UpdateContent())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_create_events() |
|||
{ |
|||
CreateContent(); |
|||
|
|||
sut.Update(CreateContentCommand(new UpdateContent { Data = otherData })); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateContentEvent(new ContentUpdated { Data = otherData }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_not_create_event_for_same_data() |
|||
{ |
|||
CreateContent(); |
|||
UpdateContent(); |
|||
|
|||
sut.Update(CreateContentCommand(new UpdateContent { Data = data })); |
|||
|
|||
sut.GetUncomittedEvents().Should().BeEmpty(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Patch_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Patch(CreateContentCommand(new PatchContent { Data = data })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Patch_should_throw_exception_if_content_is_deleted() |
|||
{ |
|||
CreateContent(); |
|||
DeleteContent(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Patch(CreateContentCommand(new PatchContent())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Patch_should_create_events() |
|||
{ |
|||
CreateContent(); |
|||
|
|||
sut.Patch(CreateContentCommand(new PatchContent { Data = otherData })); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateContentEvent(new ContentUpdated { Data = otherData }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Patch_should_not_create_event_for_same_data() |
|||
{ |
|||
CreateContent(); |
|||
UpdateContent(); |
|||
|
|||
sut.Patch(CreateContentCommand(new PatchContent { Data = data })); |
|||
|
|||
sut.GetUncomittedEvents().Should().BeEmpty(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ChangeStatus_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.ChangeStatus(CreateContentCommand(new ChangeContentStatus())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ChangeStatus_should_throw_exception_if_content_is_deleted() |
|||
{ |
|||
CreateContent(); |
|||
DeleteContent(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.ChangeStatus(CreateContentCommand(new ChangeContentStatus())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ChangeStatus_should_refresh_properties_and_create_events() |
|||
{ |
|||
CreateContent(); |
|||
|
|||
sut.ChangeStatus(CreateContentCommand(new ChangeContentStatus { Status = Status.Published })); |
|||
|
|||
Assert.Equal(Status.Published, sut.Status); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateContentEvent(new ContentStatusChanged { Status = Status.Published }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Delete_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Delete(CreateContentCommand(new DeleteContent())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Delete_should_throw_exception_if_already_deleted() |
|||
{ |
|||
CreateContent(); |
|||
DeleteContent(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Delete(CreateContentCommand(new DeleteContent())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Delete_should_update_properties_and_create_events() |
|||
{ |
|||
CreateContent(); |
|||
|
|||
sut.Delete(CreateContentCommand(new DeleteContent())); |
|||
|
|||
Assert.True(sut.IsDeleted); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateContentEvent(new ContentDeleted()) |
|||
); |
|||
} |
|||
|
|||
private void CreateContent() |
|||
{ |
|||
sut.Create(CreateContentCommand(new CreateContent { Data = data })); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
|
|||
private void UpdateContent() |
|||
{ |
|||
sut.Update(CreateContentCommand(new UpdateContent { Data = data })); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
|
|||
private void ChangeStatus(Status status) |
|||
{ |
|||
sut.ChangeStatus(CreateContentCommand(new ChangeContentStatus { Status = status })); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
|
|||
private void 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); |
|||
} |
|||
} |
|||
} |
|||
@ -1,70 +0,0 @@ |
|||
// ==========================================================================
|
|||
// SchemaEventTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Domain.Apps.Events.Contents; |
|||
using Squidex.Domain.Apps.Events.Contents.Old; |
|||
using Squidex.Domain.Apps.Write.TestHelpers; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
#pragma warning disable CS0612 // Type or member is obsolete
|
|||
|
|||
namespace Squidex.Domain.Apps.Write.Contents |
|||
{ |
|||
public class ContentEventTests |
|||
{ |
|||
private readonly RefToken actor = new RefToken("User", Guid.NewGuid().ToString()); |
|||
private readonly NamedId<Guid> appId = new NamedId<Guid>(Guid.NewGuid(), "my-app"); |
|||
private readonly NamedId<Guid> schemaId = new NamedId<Guid>(Guid.NewGuid(), "my-schema"); |
|||
private readonly Guid contentId = Guid.NewGuid(); |
|||
|
|||
[Fact] |
|||
public void Should_migrate_content_published_to_content_status_changed() |
|||
{ |
|||
var source = CreateEvent(new ContentPublished()); |
|||
|
|||
source.Migrate().ShouldBeSameEvent(CreateEvent(new ContentStatusChanged { Status = Status.Published })); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_migrate_content_unpublished_to_content_status_changed() |
|||
{ |
|||
var source = CreateEvent(new ContentUnpublished()); |
|||
|
|||
source.Migrate().ShouldBeSameEvent(CreateEvent(new ContentStatusChanged { Status = Status.Draft })); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_migrate_content_restored_to_content_status_changed() |
|||
{ |
|||
var source = CreateEvent(new ContentRestored()); |
|||
|
|||
source.Migrate().ShouldBeSameEvent(CreateEvent(new ContentStatusChanged { Status = Status.Draft })); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_migrate_content_archived_to_content_status_changed() |
|||
{ |
|||
var source = CreateEvent(new ContentArchived()); |
|||
|
|||
source.Migrate().ShouldBeSameEvent(CreateEvent(new ContentStatusChanged { Status = Status.Archived })); |
|||
} |
|||
|
|||
private T CreateEvent<T>(T contentEvent) where T : ContentEvent |
|||
{ |
|||
contentEvent.Actor = actor; |
|||
contentEvent.AppId = appId; |
|||
contentEvent.SchemaId = schemaId; |
|||
contentEvent.ContentId = contentId; |
|||
|
|||
return contentEvent; |
|||
} |
|||
} |
|||
} |
|||
@ -1,140 +0,0 @@ |
|||
// ==========================================================================
|
|||
// ContentVersionLoaderTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using FakeItEasy; |
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Domain.Apps.Events.Contents; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.EventSourcing; |
|||
using Squidex.Infrastructure.States; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Contents |
|||
{ |
|||
public class ContentVersionLoaderTests |
|||
{ |
|||
private readonly IEventStore eventStore = A.Fake<IEventStore>(); |
|||
private readonly IEventDataFormatter formatter = A.Fake<IEventDataFormatter>(); |
|||
private readonly IStreamNameResolver nameResolver = A.Fake<IStreamNameResolver>(); |
|||
private readonly Guid id = Guid.NewGuid(); |
|||
private readonly Guid appId = Guid.NewGuid(); |
|||
private readonly string streamName = Guid.NewGuid().ToString(); |
|||
private readonly ContentVersionLoader sut; |
|||
|
|||
public ContentVersionLoaderTests() |
|||
{ |
|||
A.CallTo(() => nameResolver.GetStreamName(typeof(ContentDomainObject), id.ToString())) |
|||
.Returns(streamName); |
|||
|
|||
sut = new ContentVersionLoader(eventStore, nameResolver, formatter); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_throw_exception_when_event_store_returns_no_events() |
|||
{ |
|||
A.CallTo(() => eventStore.GetEventsAsync(streamName, 0)) |
|||
.Returns(new List<StoredEvent>()); |
|||
|
|||
await Assert.ThrowsAsync<DomainObjectNotFoundException>(() => sut.LoadAsync(appId, id, -1)); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_throw_exception_when_version_not_found() |
|||
{ |
|||
A.CallTo(() => eventStore.GetEventsAsync(streamName, 0)) |
|||
.Returns(new List<StoredEvent>()); |
|||
|
|||
await Assert.ThrowsAsync<DomainObjectNotFoundException>(() => sut.LoadAsync(appId, id, 3)); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_throw_exception_when_content_is_from_another_event() |
|||
{ |
|||
var eventData1 = new EventData(); |
|||
|
|||
var event1 = new ContentCreated { Data = new NamedContentData(), AppId = new NamedId<Guid>(Guid.NewGuid(), "my-app") }; |
|||
|
|||
var events = new List<StoredEvent> |
|||
{ |
|||
new StoredEvent("0", 0, eventData1) |
|||
}; |
|||
|
|||
A.CallTo(() => eventStore.GetEventsAsync(streamName, 0)) |
|||
.Returns(events); |
|||
|
|||
A.CallTo(() => formatter.Parse(eventData1, true)) |
|||
.Returns(new Envelope<IEvent>(event1)); |
|||
|
|||
await Assert.ThrowsAsync<DomainObjectNotFoundException>(() => sut.LoadAsync(appId, id, 0)); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_load_content_from_created_event() |
|||
{ |
|||
var eventData1 = new EventData(); |
|||
var eventData2 = new EventData(); |
|||
|
|||
var event1 = new ContentCreated { Data = new NamedContentData(), AppId = new NamedId<Guid>(appId, "my-app") }; |
|||
var event2 = new ContentStatusChanged(); |
|||
|
|||
var events = new List<StoredEvent> |
|||
{ |
|||
new StoredEvent("0", 0, eventData1), |
|||
new StoredEvent("1", 1, eventData2) |
|||
}; |
|||
|
|||
A.CallTo(() => eventStore.GetEventsAsync(streamName, 0)) |
|||
.Returns(events); |
|||
|
|||
A.CallTo(() => formatter.Parse(eventData1, true)) |
|||
.Returns(new Envelope<IEvent>(event1)); |
|||
A.CallTo(() => formatter.Parse(eventData2, true)) |
|||
.Returns(new Envelope<IEvent>(event2)); |
|||
|
|||
var data = await sut.LoadAsync(appId, id, 3); |
|||
|
|||
Assert.Same(event1.Data, data); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_load_content_from_correct_version() |
|||
{ |
|||
var eventData1 = new EventData(); |
|||
var eventData2 = new EventData(); |
|||
var eventData3 = new EventData(); |
|||
|
|||
var event1 = new ContentCreated { Data = new NamedContentData(), AppId = new NamedId<Guid>(appId, "my-app") }; |
|||
var event2 = new ContentUpdated { Data = new NamedContentData() }; |
|||
var event3 = new ContentUpdated { Data = new NamedContentData() }; |
|||
|
|||
var events = new List<StoredEvent> |
|||
{ |
|||
new StoredEvent("0", 0, eventData1), |
|||
new StoredEvent("1", 1, eventData2), |
|||
new StoredEvent("2", 2, eventData3) |
|||
}; |
|||
|
|||
A.CallTo(() => eventStore.GetEventsAsync(streamName, 0)) |
|||
.Returns(events); |
|||
|
|||
A.CallTo(() => formatter.Parse(eventData1, true)) |
|||
.Returns(new Envelope<IEvent>(event1)); |
|||
A.CallTo(() => formatter.Parse(eventData2, true)) |
|||
.Returns(new Envelope<IEvent>(event2)); |
|||
A.CallTo(() => formatter.Parse(eventData3, true)) |
|||
.Returns(new Envelope<IEvent>(event3)); |
|||
|
|||
var data = await sut.LoadAsync(appId, id, 1); |
|||
|
|||
Assert.Equal(event2.Data, data); |
|||
} |
|||
} |
|||
} |
|||
@ -1,99 +0,0 @@ |
|||
// ==========================================================================
|
|||
// GuardContentTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Domain.Apps.Write.Contents.Commands; |
|||
using Squidex.Domain.Apps.Write.Contents.Guards; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Contents.Guard |
|||
{ |
|||
public class GuardContentTests |
|||
{ |
|||
[Fact] |
|||
public void CanCreate_should_throw_exception_if_data_is_null() |
|||
{ |
|||
var command = new CreateContent(); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardContent.CanCreate(command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanCreate_should_not_throw_exception_if_data_is_not_null() |
|||
{ |
|||
var command = new CreateContent { Data = new NamedContentData() }; |
|||
|
|||
GuardContent.CanCreate(command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUpdate_should_throw_exception_if_data_is_null() |
|||
{ |
|||
var command = new UpdateContent(); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardContent.CanUpdate(command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUpdate_should_not_throw_exception_if_data_is_not_null() |
|||
{ |
|||
var command = new UpdateContent { Data = new NamedContentData() }; |
|||
|
|||
GuardContent.CanUpdate(command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanPatch_should_throw_exception_if_data_is_null() |
|||
{ |
|||
var command = new PatchContent(); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardContent.CanPatch(command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanPatch_should_not_throw_exception_if_data_is_not_null() |
|||
{ |
|||
var command = new PatchContent { Data = new NamedContentData() }; |
|||
|
|||
GuardContent.CanPatch(command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanChangeContentStatus_should_throw_exception_if_status_not_valid() |
|||
{ |
|||
var command = new ChangeContentStatus { Status = (Status)10 }; |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardContent.CanChangeContentStatus(Status.Archived, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanChangeContentStatus_should_throw_exception_if_status_flow_not_valid() |
|||
{ |
|||
var command = new ChangeContentStatus { Status = Status.Published }; |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardContent.CanChangeContentStatus(Status.Archived, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanChangeContentStatus_not_should_throw_exception_if_status_flow_valid() |
|||
{ |
|||
var command = new ChangeContentStatus { Status = Status.Published }; |
|||
|
|||
GuardContent.CanChangeContentStatus(Status.Draft, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanPatch_should_not_throw_exception() |
|||
{ |
|||
var command = new DeleteContent(); |
|||
|
|||
GuardContent.CanDelete(command); |
|||
} |
|||
} |
|||
} |
|||
@ -1,48 +0,0 @@ |
|||
// ==========================================================================
|
|||
// WebhookActionTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Squidex.Domain.Apps.Core.Rules.Actions; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Rules.Guards.Actions |
|||
{ |
|||
public sealed class WebhookActionTests |
|||
{ |
|||
[Fact] |
|||
public async Task Should_add_error_if_url_is_null() |
|||
{ |
|||
var action = new WebhookAction { Url = null }; |
|||
|
|||
var errors = await RuleActionValidator.ValidateAsync(action); |
|||
|
|||
Assert.NotEmpty(errors); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_add_error_if_url_is_relative() |
|||
{ |
|||
var action = new WebhookAction { Url = new Uri("/invalid", UriKind.Relative) }; |
|||
|
|||
var errors = await RuleActionValidator.ValidateAsync(action); |
|||
|
|||
Assert.NotEmpty(errors); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_add_error_if_url_is_absolute() |
|||
{ |
|||
var action = new WebhookAction { Url = new Uri("https://squidex.io", UriKind.Absolute) }; |
|||
|
|||
var errors = await RuleActionValidator.ValidateAsync(action); |
|||
|
|||
Assert.Empty(errors); |
|||
} |
|||
} |
|||
} |
|||
@ -1,168 +0,0 @@ |
|||
// ==========================================================================
|
|||
// GuardRuleTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Immutable; |
|||
using System.Threading.Tasks; |
|||
using FakeItEasy; |
|||
using Squidex.Domain.Apps.Core.Rules; |
|||
using Squidex.Domain.Apps.Core.Rules.Actions; |
|||
using Squidex.Domain.Apps.Core.Rules.Triggers; |
|||
using Squidex.Domain.Apps.Read; |
|||
using Squidex.Domain.Apps.Read.Schemas; |
|||
using Squidex.Domain.Apps.Write.Rules.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
#pragma warning disable SA1310 // Field names must not contain underscore
|
|||
|
|||
namespace Squidex.Domain.Apps.Write.Rules.Guards |
|||
{ |
|||
public class GuardRuleTests |
|||
{ |
|||
private readonly Uri validUrl = new Uri("https://squidex.io"); |
|||
private readonly Rule rule_0 = new Rule(new ContentChangedTrigger(), new WebhookAction()); |
|||
private readonly NamedId<Guid> appId = new NamedId<Guid>(Guid.NewGuid(), "my-app"); |
|||
private readonly IAppProvider appProvider = A.Fake<IAppProvider>(); |
|||
|
|||
public GuardRuleTests() |
|||
{ |
|||
A.CallTo(() => appProvider.GetSchemaAsync(appId.Name, A<Guid>.Ignored, false)) |
|||
.Returns(A.Fake<ISchemaEntity>()); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task CanCreate_should_throw_exception_if_trigger_null() |
|||
{ |
|||
var command = CreateCommand(new CreateRule |
|||
{ |
|||
Trigger = null, |
|||
Action = new WebhookAction |
|||
{ |
|||
Url = validUrl |
|||
} |
|||
}); |
|||
|
|||
await Assert.ThrowsAsync<ValidationException>(() => GuardRule.CanCreate(command, appProvider)); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task CanCreate_should_throw_exception_if_action_null() |
|||
{ |
|||
var command = CreateCommand(new CreateRule |
|||
{ |
|||
Trigger = new ContentChangedTrigger |
|||
{ |
|||
Schemas = ImmutableList<ContentChangedTriggerSchema>.Empty |
|||
}, |
|||
Action = null |
|||
}); |
|||
|
|||
await Assert.ThrowsAsync<ValidationException>(() => GuardRule.CanCreate(command, appProvider)); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task CanCreate_should_not_throw_exception_if_trigger_and_action_valid() |
|||
{ |
|||
var command = CreateCommand(new CreateRule |
|||
{ |
|||
Trigger = new ContentChangedTrigger |
|||
{ |
|||
Schemas = ImmutableList<ContentChangedTriggerSchema>.Empty |
|||
}, |
|||
Action = new WebhookAction |
|||
{ |
|||
Url = validUrl |
|||
} |
|||
}); |
|||
|
|||
await GuardRule.CanCreate(command, appProvider); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task CanUpdate_should_throw_exception_if_action_and_trigger_are_null() |
|||
{ |
|||
var command = new UpdateRule(); |
|||
|
|||
await Assert.ThrowsAsync<ValidationException>(() => GuardRule.CanUpdate(command, appProvider)); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task CanUpdate_should_not_throw_exception_if_trigger_and_action_valid() |
|||
{ |
|||
var command = CreateCommand(new UpdateRule |
|||
{ |
|||
Trigger = new ContentChangedTrigger |
|||
{ |
|||
Schemas = ImmutableList<ContentChangedTriggerSchema>.Empty |
|||
}, |
|||
Action = new WebhookAction |
|||
{ |
|||
Url = validUrl |
|||
} |
|||
}); |
|||
|
|||
await GuardRule.CanUpdate(command, appProvider); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanEnable_should_throw_exception_if_rule_enabled() |
|||
{ |
|||
var command = new EnableRule(); |
|||
|
|||
var rule_1 = rule_0.Enable(); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardRule.CanEnable(command, rule_1)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanEnable_should_not_throw_exception_if_rule_disabled() |
|||
{ |
|||
var command = new EnableRule(); |
|||
|
|||
var rule_1 = rule_0.Disable(); |
|||
|
|||
GuardRule.CanEnable(command, rule_1); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanDisable_should_throw_exception_if_rule_disabled() |
|||
{ |
|||
var command = new DisableRule(); |
|||
|
|||
var rule_1 = rule_0.Disable(); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardRule.CanDisable(command, rule_1)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanDisable_should_not_throw_exception_if_rule_enabled() |
|||
{ |
|||
var command = new DisableRule(); |
|||
|
|||
var rule_1 = rule_0.Enable(); |
|||
|
|||
GuardRule.CanDisable(command, rule_1); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanDelete_should_not_throw_exception() |
|||
{ |
|||
var command = new DeleteRule(); |
|||
|
|||
GuardRule.CanDelete(command); |
|||
} |
|||
|
|||
private T CreateCommand<T>(T command) where T : AppCommand |
|||
{ |
|||
command.AppId = appId; |
|||
|
|||
return command; |
|||
} |
|||
} |
|||
} |
|||
@ -1,84 +0,0 @@ |
|||
// ==========================================================================
|
|||
// ContentChangedTriggerTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Immutable; |
|||
using System.Threading.Tasks; |
|||
using FakeItEasy; |
|||
using Squidex.Domain.Apps.Core.Rules.Triggers; |
|||
using Squidex.Domain.Apps.Read; |
|||
using Squidex.Domain.Apps.Read.Schemas; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Rules.Guards.Triggers |
|||
{ |
|||
public class ContentChangedTriggerTests |
|||
{ |
|||
private readonly IAppProvider appProvider = A.Fake<IAppProvider>(); |
|||
private readonly string appName = "my-app"; |
|||
|
|||
[Fact] |
|||
public async Task Should_add_error_if_schemas_ids_are_not_valid() |
|||
{ |
|||
A.CallTo(() => appProvider.GetSchemaAsync(appName, A<Guid>.Ignored, false)) |
|||
.Returns(Task.FromResult<ISchemaEntity>(null)); |
|||
|
|||
var trigger = new ContentChangedTrigger |
|||
{ |
|||
Schemas = ImmutableList.Create( |
|||
new ContentChangedTriggerSchema() |
|||
) |
|||
}; |
|||
|
|||
var errors = await RuleTriggerValidator.ValidateAsync(appName, trigger, appProvider); |
|||
|
|||
Assert.NotEmpty(errors); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_add_error_if_schemas_is_null() |
|||
{ |
|||
var trigger = new ContentChangedTrigger(); |
|||
|
|||
var errors = await RuleTriggerValidator.ValidateAsync(appName, trigger, appProvider); |
|||
|
|||
Assert.Empty(errors); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_add_error_if_schemas_is_empty() |
|||
{ |
|||
var trigger = new ContentChangedTrigger |
|||
{ |
|||
Schemas = ImmutableList<ContentChangedTriggerSchema>.Empty |
|||
}; |
|||
|
|||
var errors = await RuleTriggerValidator.ValidateAsync(appName, trigger, appProvider); |
|||
|
|||
Assert.Empty(errors); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_add_error_if_schemas_ids_are_valid() |
|||
{ |
|||
A.CallTo(() => appProvider.GetSchemaAsync(appName, A<Guid>.Ignored, false)) |
|||
.Returns(A.Fake<ISchemaEntity>()); |
|||
|
|||
var trigger = new ContentChangedTrigger |
|||
{ |
|||
Schemas = ImmutableList.Create( |
|||
new ContentChangedTriggerSchema() |
|||
) |
|||
}; |
|||
|
|||
var errors = await RuleTriggerValidator.ValidateAsync(appName, trigger, appProvider); |
|||
|
|||
Assert.Empty(errors); |
|||
} |
|||
} |
|||
} |
|||
@ -1,117 +0,0 @@ |
|||
// ==========================================================================
|
|||
// RuleCommandMiddlewareTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using FakeItEasy; |
|||
using Squidex.Domain.Apps.Core.Rules; |
|||
using Squidex.Domain.Apps.Core.Rules.Actions; |
|||
using Squidex.Domain.Apps.Core.Rules.Triggers; |
|||
using Squidex.Domain.Apps.Read; |
|||
using Squidex.Domain.Apps.Read.Schemas; |
|||
using Squidex.Domain.Apps.Write.Rules.Commands; |
|||
using Squidex.Domain.Apps.Write.TestHelpers; |
|||
using Squidex.Infrastructure.Commands; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Rules |
|||
{ |
|||
public class RuleCommandMiddlewareTests : HandlerTestBase<RuleDomainObject> |
|||
{ |
|||
private readonly IAppProvider appProvider = A.Fake<IAppProvider>(); |
|||
private readonly RuleCommandMiddleware sut; |
|||
private readonly RuleDomainObject rule; |
|||
private readonly RuleTrigger ruleTrigger = new ContentChangedTrigger(); |
|||
private readonly RuleAction ruleAction = new WebhookAction { Url = new Uri("https://squidex.io") }; |
|||
private readonly Guid ruleId = Guid.NewGuid(); |
|||
|
|||
public RuleCommandMiddlewareTests() |
|||
{ |
|||
A.CallTo(() => appProvider.GetSchemaAsync(A<string>.Ignored, A<Guid>.Ignored, false)) |
|||
.Returns(A.Fake<ISchemaEntity>()); |
|||
|
|||
rule = new RuleDomainObject(ruleId, -1); |
|||
|
|||
sut = new RuleCommandMiddleware(Handler, appProvider); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Create_should_create_domain_object() |
|||
{ |
|||
var context = CreateContextForCommand(new CreateRule { Trigger = ruleTrigger, Action = ruleAction }); |
|||
|
|||
await TestCreate(rule, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Update_should_update_domain_object() |
|||
{ |
|||
var context = CreateContextForCommand(new UpdateRule { Trigger = ruleTrigger, Action = ruleAction }); |
|||
|
|||
CreateRule(); |
|||
|
|||
await TestUpdate(rule, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Enable_should_update_domain_object() |
|||
{ |
|||
CreateRule(); |
|||
DisableRule(); |
|||
|
|||
var command = CreateContextForCommand(new EnableRule { RuleId = ruleId }); |
|||
|
|||
await TestUpdate(rule, async _ => |
|||
{ |
|||
await sut.HandleAsync(command); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Disable_should_update_domain_object() |
|||
{ |
|||
CreateRule(); |
|||
|
|||
var command = CreateContextForCommand(new DisableRule { RuleId = ruleId }); |
|||
|
|||
await TestUpdate(rule, async _ => |
|||
{ |
|||
await sut.HandleAsync(command); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Delete_should_update_domain_object() |
|||
{ |
|||
CreateRule(); |
|||
|
|||
var command = CreateContextForCommand(new DeleteRule { RuleId = ruleId }); |
|||
|
|||
await TestUpdate(rule, async _ => |
|||
{ |
|||
await sut.HandleAsync(command); |
|||
}); |
|||
} |
|||
|
|||
private void DisableRule() |
|||
{ |
|||
rule.Disable(new DisableRule()); |
|||
} |
|||
|
|||
private void CreateRule() |
|||
{ |
|||
rule.Create(new CreateRule { Trigger = ruleTrigger, Action = ruleAction }); |
|||
} |
|||
} |
|||
} |
|||
@ -1,240 +0,0 @@ |
|||
// ==========================================================================
|
|||
// RuleDomainObjectTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Immutable; |
|||
using Squidex.Domain.Apps.Core.Rules; |
|||
using Squidex.Domain.Apps.Core.Rules.Actions; |
|||
using Squidex.Domain.Apps.Core.Rules.Triggers; |
|||
using Squidex.Domain.Apps.Events.Rules; |
|||
using Squidex.Domain.Apps.Write.Rules.Commands; |
|||
using Squidex.Domain.Apps.Write.TestHelpers; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Commands; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Rules |
|||
{ |
|||
public class RuleDomainObjectTests : HandlerTestBase<RuleDomainObject> |
|||
{ |
|||
private readonly RuleTrigger ruleTrigger = new ContentChangedTrigger(); |
|||
private readonly RuleAction ruleAction = new WebhookAction { Url = new Uri("https://squidex.io") }; |
|||
private readonly RuleDomainObject sut; |
|||
|
|||
public Guid RuleId { get; } = Guid.NewGuid(); |
|||
|
|||
public RuleDomainObjectTests() |
|||
{ |
|||
sut = new RuleDomainObject(RuleId, 0); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_throw_exception_if_created() |
|||
{ |
|||
sut.Create(new CreateRule { Trigger = ruleTrigger, Action = ruleAction }); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Create(CreateRuleCommand(new CreateRule { Trigger = ruleTrigger, Action = ruleAction })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_create_events() |
|||
{ |
|||
var command = new CreateRule { Trigger = ruleTrigger, Action = ruleAction }; |
|||
|
|||
sut.Create(CreateRuleCommand(command)); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateRuleEvent(new RuleCreated { Trigger = ruleTrigger, Action = ruleAction }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Update(CreateRuleCommand(new UpdateRule { Trigger = ruleTrigger, Action = ruleAction })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_throw_exception_if_rule_is_deleted() |
|||
{ |
|||
CreateRule(); |
|||
DeleteRule(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Update(CreateRuleCommand(new UpdateRule { Trigger = ruleTrigger, Action = ruleAction })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_create_events() |
|||
{ |
|||
var newTrigger = new ContentChangedTrigger |
|||
{ |
|||
Schemas = ImmutableList<ContentChangedTriggerSchema>.Empty |
|||
}; |
|||
|
|||
var newAction = new WebhookAction |
|||
{ |
|||
Url = new Uri("https://squidex.io/v2") |
|||
}; |
|||
|
|||
CreateRule(); |
|||
|
|||
var command = new UpdateRule { Trigger = newTrigger, Action = newAction }; |
|||
|
|||
sut.Update(CreateRuleCommand(command)); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateRuleEvent(new RuleUpdated { Trigger = newTrigger, Action = newAction }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Enable_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Enable(CreateRuleCommand(new EnableRule())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Enable_should_throw_exception_if_rule_is_deleted() |
|||
{ |
|||
CreateRule(); |
|||
DeleteRule(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Enable(CreateRuleCommand(new EnableRule())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Enable_should_create_events() |
|||
{ |
|||
CreateRule(); |
|||
|
|||
var command = new EnableRule(); |
|||
|
|||
sut.Enable(CreateRuleCommand(command)); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateRuleEvent(new RuleEnabled()) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Disable_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Disable(CreateRuleCommand(new DisableRule())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Disable_should_throw_exception_if_rule_is_deleted() |
|||
{ |
|||
CreateRule(); |
|||
DeleteRule(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Disable(CreateRuleCommand(new DisableRule())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Disable_should_create_events() |
|||
{ |
|||
CreateRule(); |
|||
|
|||
var command = new DisableRule(); |
|||
|
|||
sut.Disable(CreateRuleCommand(command)); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateRuleEvent(new RuleDisabled()) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Delete_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Delete(CreateRuleCommand(new DeleteRule())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Delete_should_throw_exception_if_already_deleted() |
|||
{ |
|||
CreateRule(); |
|||
DeleteRule(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Delete(CreateRuleCommand(new DeleteRule())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Delete_should_update_create_events() |
|||
{ |
|||
CreateRule(); |
|||
|
|||
sut.Delete(CreateRuleCommand(new DeleteRule())); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateRuleEvent(new RuleDeleted()) |
|||
); |
|||
} |
|||
|
|||
private void CreateRule() |
|||
{ |
|||
sut.Create(CreateRuleCommand(new CreateRule { Trigger = ruleTrigger, Action = ruleAction })); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
|
|||
private void DeleteRule() |
|||
{ |
|||
sut.Delete(CreateRuleCommand(new DeleteRule())); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
|
|||
protected T CreateRuleEvent<T>(T @event) where T : RuleEvent |
|||
{ |
|||
@event.RuleId = RuleId; |
|||
|
|||
return CreateEvent(@event); |
|||
} |
|||
|
|||
protected T CreateRuleCommand<T>(T command) where T : RuleAggregateCommand |
|||
{ |
|||
command.RuleId = RuleId; |
|||
|
|||
return CreateCommand(command); |
|||
} |
|||
} |
|||
} |
|||
@ -1,104 +0,0 @@ |
|||
// ==========================================================================
|
|||
// AssetsFieldPropertiesTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using FluentAssertions; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas.Guards.FieldProperties |
|||
{ |
|||
public class AssetsFieldPropertiesTests |
|||
{ |
|||
[Fact] |
|||
public void Should_add_error_if_min_items_greater_than_max_items() |
|||
{ |
|||
var sut = new AssetsFieldProperties { MinItems = 10, MaxItems = 5 }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Max items must be greater than min items.", "MinItems", "MaxItems") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_min_width_greater_than_max_width() |
|||
{ |
|||
var sut = new AssetsFieldProperties { MinWidth = 10, MaxWidth = 5 }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Max width must be greater than min width.", "MinWidth", "MaxWidth") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_min_height_greater_than_max_height() |
|||
{ |
|||
var sut = new AssetsFieldProperties { MinHeight = 10, MaxHeight = 5 }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Max height must be greater than min height.", "MinHeight", "MaxHeight") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_min_size_greater_than_max_size() |
|||
{ |
|||
var sut = new AssetsFieldProperties { MinSize = 10, MaxSize = 5 }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Max size must be greater than min size.", "MinSize", "MaxSize") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_only_aspect_width_is_defined() |
|||
{ |
|||
var sut = new AssetsFieldProperties { AspectWidth = 10 }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Aspect width and height must be defined.", "AspectWidth", "AspectHeight") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_only_aspect_height_is_defined() |
|||
{ |
|||
var sut = new AssetsFieldProperties { AspectHeight = 10 }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Aspect width and height must be defined.", "AspectWidth", "AspectHeight") |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -1,34 +0,0 @@ |
|||
// ==========================================================================
|
|||
// BooleanFieldPropertiesTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using FluentAssertions; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas.Guards.FieldProperties |
|||
{ |
|||
public class BooleanFieldPropertiesTests |
|||
{ |
|||
[Fact] |
|||
public void Should_add_error_if_editor_is_not_valid() |
|||
{ |
|||
var sut = new BooleanFieldProperties { Editor = (BooleanFieldEditor)123 }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Editor is not a valid value.", "Editor") |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -1,126 +0,0 @@ |
|||
// ==========================================================================
|
|||
// DateTimeFieldPropertiesTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using FluentAssertions; |
|||
using NodaTime; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas.Guards.FieldProperties |
|||
{ |
|||
public class DateTimeFieldPropertiesTests |
|||
{ |
|||
[Fact] |
|||
public void Should_not_add_error_if_sut_is_valid() |
|||
{ |
|||
var sut = new DateTimeFieldProperties |
|||
{ |
|||
MinValue = FutureDays(10), |
|||
MaxValue = FutureDays(20), |
|||
DefaultValue = FutureDays(15) |
|||
}; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
Assert.Empty(errors); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_default_value_is_less_than_min() |
|||
{ |
|||
var sut = new DateTimeFieldProperties { MinValue = FutureDays(10), DefaultValue = FutureDays(5) }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Default value must be greater than min value.", "DefaultValue") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_default_value_is_greater_than_min() |
|||
{ |
|||
var sut = new DateTimeFieldProperties { MaxValue = FutureDays(10), DefaultValue = FutureDays(15) }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Default value must be less than max value.", "DefaultValue") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_min_greater_than_max() |
|||
{ |
|||
var sut = new DateTimeFieldProperties { MinValue = FutureDays(10), MaxValue = FutureDays(5) }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Max value must be greater than min value.", "MinValue", "MaxValue") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_editor_is_not_valid() |
|||
{ |
|||
var sut = new DateTimeFieldProperties { Editor = (DateTimeFieldEditor)123 }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Editor is not a valid value.", "Editor") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_calculated_default_value_is_not_valid() |
|||
{ |
|||
var sut = new DateTimeFieldProperties { CalculatedDefaultValue = (DateTimeCalculatedDefaultValue)123 }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Calculated default value is not valid.", "CalculatedDefaultValue") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_calculated_default_value_default_value_is_defined() |
|||
{ |
|||
var sut = new DateTimeFieldProperties { CalculatedDefaultValue = DateTimeCalculatedDefaultValue.Now, DefaultValue = FutureDays(10) }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Calculated default value and default value cannot be used together.", "CalculatedDefaultValue", "DefaultValue") |
|||
}); |
|||
} |
|||
|
|||
private static Instant FutureDays(int days) |
|||
{ |
|||
return Instant.FromDateTimeUtc(DateTime.UtcNow.Date.AddDays(days)); |
|||
} |
|||
} |
|||
} |
|||
@ -1,34 +0,0 @@ |
|||
// ==========================================================================
|
|||
// GeolocationPropertiesTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using FluentAssertions; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas.Guards.FieldProperties |
|||
{ |
|||
public class GeolocationFieldPropertiesTests |
|||
{ |
|||
[Fact] |
|||
public void Should_add_error_if_editor_is_not_valid() |
|||
{ |
|||
var sut = new GeolocationFieldProperties { Editor = (GeolocationFieldEditor)123 }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Editor is not a valid value.", "Editor") |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -1,27 +0,0 @@ |
|||
// ==========================================================================
|
|||
// JsonFieldPropertiesTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Linq; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas.Guards.FieldProperties |
|||
{ |
|||
public class JsonFieldPropertiesTests |
|||
{ |
|||
[Fact] |
|||
public void Should_add_error_if_editor_is_not_valid() |
|||
{ |
|||
var sut = new JsonFieldProperties(); |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
Assert.Empty(errors); |
|||
} |
|||
} |
|||
} |
|||
@ -1,134 +0,0 @@ |
|||
// ==========================================================================
|
|||
// NumberFieldPropertiesTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Collections.Immutable; |
|||
using System.Linq; |
|||
using FluentAssertions; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas.Guards.FieldProperties |
|||
{ |
|||
public class NumberFieldPropertiesTests |
|||
{ |
|||
[Fact] |
|||
public void Should_not_add_error_if_sut_is_valid() |
|||
{ |
|||
var sut = new NumberFieldProperties |
|||
{ |
|||
MinValue = 0, |
|||
MaxValue = 100, |
|||
DefaultValue = 5 |
|||
}; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
Assert.Empty(errors); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_default_value_is_less_than_min() |
|||
{ |
|||
var sut = new NumberFieldProperties { MinValue = 10, DefaultValue = 5 }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Default value must be greater than min value.", "DefaultValue") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_default_value_is_greater_than_min() |
|||
{ |
|||
var sut = new NumberFieldProperties { MaxValue = 0, DefaultValue = 5 }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Default value must be less than max value.", "DefaultValue") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_min_greater_than_max() |
|||
{ |
|||
var sut = new NumberFieldProperties { MinValue = 10, MaxValue = 5 }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Max value must be greater than min value.", "MinValue", "MaxValue") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_allowed_values_and_max_value_is_specified() |
|||
{ |
|||
var sut = new NumberFieldProperties { MaxValue = 10, AllowedValues = ImmutableList.Create(4d) }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Either allowed values or min and max value can be defined.", "AllowedValues", "MinValue", "MaxValue") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_allowed_values_and_min_value_is_specified() |
|||
{ |
|||
var sut = new NumberFieldProperties { MinValue = 10, AllowedValues = ImmutableList.Create(4d) }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Either allowed values or min and max value can be defined.", "AllowedValues", "MinValue", "MaxValue") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_radio_button_has_no_allowed_values() |
|||
{ |
|||
var sut = new NumberFieldProperties { Editor = NumberFieldEditor.Radio }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Radio buttons or dropdown list need allowed values.", "AllowedValues") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_editor_is_not_valid() |
|||
{ |
|||
var sut = new NumberFieldProperties { Editor = (NumberFieldEditor)123 }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Editor is not a valid value.", "Editor") |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -1,34 +0,0 @@ |
|||
// ==========================================================================
|
|||
// ReferencesFieldPropertiesTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using FluentAssertions; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas.Guards.FieldProperties |
|||
{ |
|||
public class ReferencesFieldPropertiesTests |
|||
{ |
|||
[Fact] |
|||
public void Should_add_error_if_min_greater_than_max() |
|||
{ |
|||
var sut = new ReferencesFieldProperties { MinItems = 10, MaxItems = 5 }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Max items must be greater than min items.", "MinItems", "MaxItems") |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -1,105 +0,0 @@ |
|||
// ==========================================================================
|
|||
// StringFieldPropertiesTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Collections.Immutable; |
|||
using System.Linq; |
|||
using FluentAssertions; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas.Guards.FieldProperties |
|||
{ |
|||
public class StringFieldPropertiesTests |
|||
{ |
|||
[Fact] |
|||
public void Should_add_error_if_min_greater_than_max() |
|||
{ |
|||
var sut = new StringFieldProperties { MinLength = 10, MaxLength = 5 }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Max length must be greater than min length.", "MinLength", "MaxLength") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_allowed_values_and_max_value_is_specified() |
|||
{ |
|||
var sut = new StringFieldProperties { MinLength = 10, AllowedValues = ImmutableList.Create("4") }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Either allowed values or min and max length can be defined.", "AllowedValues", "MinLength", "MaxLength") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_allowed_values_and_min_value_is_specified() |
|||
{ |
|||
var sut = new StringFieldProperties { MaxLength = 10, AllowedValues = ImmutableList.Create("4") }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Either allowed values or min and max length can be defined.", "AllowedValues", "MinLength", "MaxLength") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_radio_button_has_no_allowed_values() |
|||
{ |
|||
var sut = new StringFieldProperties { Editor = StringFieldEditor.Radio }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Radio buttons or dropdown list need allowed values.", "AllowedValues") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_editor_is_not_valid() |
|||
{ |
|||
var sut = new StringFieldProperties { Editor = (StringFieldEditor)123 }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Editor is not a valid value.", "Editor") |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_add_error_if_pattern_is_not_valid_regex() |
|||
{ |
|||
var sut = new StringFieldProperties { Pattern = "[0-9{1}" }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Pattern is not a valid expression.", "Pattern") |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -1,34 +0,0 @@ |
|||
// ==========================================================================
|
|||
// TagsFieldPropertiesTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using FluentAssertions; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas.Guards.FieldProperties |
|||
{ |
|||
public class TagsFieldPropertiesTests |
|||
{ |
|||
[Fact] |
|||
public void Should_add_error_if_min_greater_than_max() |
|||
{ |
|||
var sut = new TagsFieldProperties { MinItems = 10, MaxItems = 5 }; |
|||
|
|||
var errors = FieldPropertiesValidator.Validate(sut).ToList(); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new List<ValidationError> |
|||
{ |
|||
new ValidationError("Max items must be greater than min items.", "MinItems", "MaxItems") |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -1,247 +0,0 @@ |
|||
// ==========================================================================
|
|||
// GuardSchemaFieldTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Write.Schemas.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
#pragma warning disable SA1310 // Field names must not contain underscore
|
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas.Guards |
|||
{ |
|||
public class GuardSchemaFieldTests |
|||
{ |
|||
private readonly Schema schema_0; |
|||
private readonly StringFieldProperties validProperties = new StringFieldProperties(); |
|||
private readonly StringFieldProperties invalidProperties = new StringFieldProperties { MinLength = 10, MaxLength = 5 }; |
|||
|
|||
public GuardSchemaFieldTests() |
|||
{ |
|||
schema_0 = |
|||
new Schema("my-schema") |
|||
.AddField(new StringField(1, "field1", Partitioning.Invariant)) |
|||
.AddField(new StringField(2, "field2", Partitioning.Invariant)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanHide_should_throw_exception_if_already_hidden() |
|||
{ |
|||
var command = new HideField { FieldId = 1 }; |
|||
|
|||
var schema_1 = schema_0.HideField(1); |
|||
|
|||
Assert.Throws<DomainException>(() => GuardSchemaField.CanHide(schema_1, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanHide_should_throw_exception_if_not_found() |
|||
{ |
|||
var command = new HideField { FieldId = 3 }; |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanHide(schema_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanHide_hould_not_throw_exception_if_visible() |
|||
{ |
|||
var command = new HideField { FieldId = 1 }; |
|||
|
|||
GuardSchemaField.CanHide(schema_0, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanDisable_should_throw_exception_if_already_disabled() |
|||
{ |
|||
var command = new DisableField { FieldId = 1 }; |
|||
|
|||
var schema_1 = schema_0.DisableField(1); |
|||
|
|||
Assert.Throws<DomainException>(() => GuardSchemaField.CanDisable(schema_1, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanDisable_should_throw_exception_if_not_found() |
|||
{ |
|||
var command = new DisableField { FieldId = 3 }; |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanDisable(schema_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanDisable_Should_not_throw_exception_if_enabled() |
|||
{ |
|||
var command = new DisableField { FieldId = 1 }; |
|||
|
|||
GuardSchemaField.CanDisable(schema_0, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanShow_should_throw_exception_if_already_shown() |
|||
{ |
|||
var command = new ShowField { FieldId = 1 }; |
|||
|
|||
Assert.Throws<DomainException>(() => GuardSchemaField.CanShow(schema_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanShow_should_throw_exception_if_not_found() |
|||
{ |
|||
var command = new ShowField { FieldId = 3 }; |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanShow(schema_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanShow_should_not_throw_exception_if_hidden() |
|||
{ |
|||
var command = new ShowField { FieldId = 1 }; |
|||
|
|||
var schema_1 = schema_0.HideField(1); |
|||
|
|||
GuardSchemaField.CanShow(schema_1, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanEnable_should_throw_exception_if_already_enabled() |
|||
{ |
|||
var command = new EnableField { FieldId = 1 }; |
|||
|
|||
Assert.Throws<DomainException>(() => GuardSchemaField.CanEnable(schema_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanEnable_should_throw_exception_if_not_found() |
|||
{ |
|||
var command = new EnableField { FieldId = 3 }; |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanEnable(schema_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanEnable_should_not_throw_exception_if_disabled() |
|||
{ |
|||
var command = new EnableField { FieldId = 1 }; |
|||
|
|||
var schema_1 = schema_0.DisableField(1); |
|||
|
|||
GuardSchemaField.CanEnable(schema_1, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanLock_should_throw_exception_if_already_locked() |
|||
{ |
|||
var command = new LockField { FieldId = 1 }; |
|||
|
|||
var schema_1 = schema_0.LockField(1); |
|||
|
|||
Assert.Throws<DomainException>(() => GuardSchemaField.CanLock(schema_1, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void LockField_should_throw_exception_if_not_found() |
|||
{ |
|||
var command = new LockField { FieldId = 3 }; |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanLock(schema_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanLock_should_not_throw_exception_if_not_locked() |
|||
{ |
|||
var command = new LockField { FieldId = 1 }; |
|||
|
|||
GuardSchemaField.CanLock(schema_0, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanDelete_should_throw_exception_if_not_found() |
|||
{ |
|||
var command = new DeleteField { FieldId = 3 }; |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanDelete(schema_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanDelete_should_throw_exception_if_locked() |
|||
{ |
|||
var command = new DeleteField { FieldId = 1 }; |
|||
|
|||
var schema_1 = schema_0.LockField(1); |
|||
|
|||
Assert.Throws<DomainException>(() => GuardSchemaField.CanDelete(schema_1, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanDelete_should_not_throw_exception_if_not_locked() |
|||
{ |
|||
var command = new DeleteField { FieldId = 1 }; |
|||
|
|||
GuardSchemaField.CanDelete(schema_0, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUpdate_should_throw_exception_if_locked() |
|||
{ |
|||
var command = new UpdateField { FieldId = 1, Properties = new StringFieldProperties() }; |
|||
|
|||
var schema_1 = schema_0.LockField(1); |
|||
|
|||
Assert.Throws<DomainException>(() => GuardSchemaField.CanUpdate(schema_1, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUpdate_should_not_throw_exception_if_not_locked() |
|||
{ |
|||
var command = new UpdateField { FieldId = 1, Properties = new StringFieldProperties() }; |
|||
|
|||
GuardSchemaField.CanUpdate(schema_0, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanAdd_should_throw_exception_if_field_already_exists() |
|||
{ |
|||
var command = new AddField { Name = "field1", Properties = new StringFieldProperties() }; |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardSchemaField.CanAdd(schema_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanAdd_should_throw_exception_if_name_not_valid() |
|||
{ |
|||
var command = new AddField { Name = "INVALID_NAME", Properties = validProperties }; |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardSchemaField.CanAdd(schema_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanAdd_should_throw_exception_if_properties_not_valid() |
|||
{ |
|||
var command = new AddField { Name = "field3", Properties = invalidProperties }; |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardSchemaField.CanAdd(schema_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanAdd_should_throw_exception_if_partitioning_not_valid() |
|||
{ |
|||
var command = new AddField { Name = "field3", Partitioning = "INVALID_PARTITIONING", Properties = validProperties }; |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardSchemaField.CanAdd(schema_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanAdd_should_not_throw_exception_if_field_not_exists() |
|||
{ |
|||
var command = new AddField { Name = "field3", Properties = new StringFieldProperties() }; |
|||
|
|||
GuardSchemaField.CanAdd(schema_0, command); |
|||
} |
|||
} |
|||
} |
|||
@ -1,201 +0,0 @@ |
|||
// ==========================================================================
|
|||
// GuardSchemaTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using FakeItEasy; |
|||
using Squidex.Domain.Apps.Core; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Read; |
|||
using Squidex.Domain.Apps.Read.Schemas; |
|||
using Squidex.Domain.Apps.Write.Schemas.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
#pragma warning disable SA1310 // Field names must not contain underscore
|
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas.Guards |
|||
{ |
|||
public class GuardSchemaTests |
|||
{ |
|||
private readonly IAppProvider appProvider = A.Fake<IAppProvider>(); |
|||
private readonly Schema schema_0; |
|||
private readonly NamedId<Guid> appId = new NamedId<Guid>(Guid.NewGuid(), "my-app"); |
|||
|
|||
public GuardSchemaTests() |
|||
{ |
|||
schema_0 = |
|||
new Schema("my-schema") |
|||
.AddField(new StringField(1, "field1", Partitioning.Invariant)) |
|||
.AddField(new StringField(2, "field2", Partitioning.Invariant)); |
|||
|
|||
A.CallTo(() => appProvider.GetSchemaAsync(A<string>.Ignored, "new-schema", false)) |
|||
.Returns(Task.FromResult<ISchemaEntity>(null)); |
|||
} |
|||
|
|||
[Fact] |
|||
public Task CanCreate_should_throw_exception_if_name_not_valid() |
|||
{ |
|||
var command = new CreateSchema { AppId = appId, Name = "INVALID NAME" }; |
|||
|
|||
return Assert.ThrowsAsync<ValidationException>(() => GuardSchema.CanCreate(command, appProvider)); |
|||
} |
|||
|
|||
[Fact] |
|||
public Task CanCreate_should_throw_exception_if_name_already_in_use() |
|||
{ |
|||
A.CallTo(() => appProvider.GetSchemaAsync(A<string>.Ignored, "new-schema", false)) |
|||
.Returns(Task.FromResult(A.Fake<ISchemaEntity>())); |
|||
|
|||
var command = new CreateSchema { AppId = appId, Name = "new-schema" }; |
|||
|
|||
return Assert.ThrowsAsync<ValidationException>(() => GuardSchema.CanCreate(command, appProvider)); |
|||
} |
|||
|
|||
[Fact] |
|||
public Task CanCreate_should_throw_exception_if_fields_not_valid() |
|||
{ |
|||
var command = new CreateSchema |
|||
{ |
|||
AppId = appId, |
|||
Fields = new List<CreateSchemaField> |
|||
{ |
|||
new CreateSchemaField |
|||
{ |
|||
Name = null, |
|||
Properties = null, |
|||
Partitioning = "invalid" |
|||
}, |
|||
new CreateSchemaField |
|||
{ |
|||
Name = null, |
|||
Properties = InvalidProperties(), |
|||
Partitioning = "invalid" |
|||
} |
|||
}, |
|||
Name = "new-schema" |
|||
}; |
|||
|
|||
return Assert.ThrowsAsync<ValidationException>(() => GuardSchema.CanCreate(command, appProvider)); |
|||
} |
|||
|
|||
[Fact] |
|||
public Task CanCreate_should_throw_exception_if_fields_contain_duplicate_names() |
|||
{ |
|||
var command = new CreateSchema |
|||
{ |
|||
AppId = appId, |
|||
Fields = new List<CreateSchemaField> |
|||
{ |
|||
new CreateSchemaField |
|||
{ |
|||
Name = "field1", |
|||
Properties = ValidProperties(), |
|||
Partitioning = "invariant" |
|||
}, |
|||
new CreateSchemaField |
|||
{ |
|||
Name = "field1", |
|||
Properties = ValidProperties(), |
|||
Partitioning = "invariant" |
|||
} |
|||
}, |
|||
Name = "new-schema" |
|||
}; |
|||
|
|||
return Assert.ThrowsAsync<ValidationException>(() => GuardSchema.CanCreate(command, appProvider)); |
|||
} |
|||
|
|||
[Fact] |
|||
public Task CanCreate_should_not_throw_exception_if_command_is_valid() |
|||
{ |
|||
var command = new CreateSchema { AppId = appId, Name = "new-schema" }; |
|||
|
|||
return GuardSchema.CanCreate(command, appProvider); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanPublish_should_throw_exception_if_already_published() |
|||
{ |
|||
var command = new PublishSchema(); |
|||
|
|||
var schema_1 = schema_0.Publish(); |
|||
|
|||
Assert.Throws<DomainException>(() => GuardSchema.CanPublish(schema_1, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanPublish_should_not_throw_exception_if_not_published() |
|||
{ |
|||
var command = new PublishSchema(); |
|||
|
|||
GuardSchema.CanPublish(schema_0, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUnpublish_should_throw_exception_if_already_unpublished() |
|||
{ |
|||
var command = new UnpublishSchema(); |
|||
|
|||
Assert.Throws<DomainException>(() => GuardSchema.CanUnpublish(schema_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUnpublish_should_not_throw_exception_if_already_published() |
|||
{ |
|||
var command = new UnpublishSchema(); |
|||
|
|||
var schema_1 = schema_0.Publish(); |
|||
|
|||
GuardSchema.CanUnpublish(schema_1, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanReorder_should_throw_exception_if_field_ids_contains_invalid_id() |
|||
{ |
|||
var command = new ReorderFields { FieldIds = new List<long> { 1, 3 } }; |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardSchema.CanReorder(schema_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanReorder_should_throw_exception_if_field_ids_do_not_covers_all_fields() |
|||
{ |
|||
var command = new ReorderFields { FieldIds = new List<long> { 1 } }; |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardSchema.CanReorder(schema_0, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanReorder_should_not_throw_exception_if_field_ids_are_valid() |
|||
{ |
|||
var command = new ReorderFields { FieldIds = new List<long> { 1, 2 } }; |
|||
|
|||
GuardSchema.CanReorder(schema_0, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanDelete_should_not_throw_exception() |
|||
{ |
|||
var command = new DeleteSchema(); |
|||
|
|||
GuardSchema.CanDelete(schema_0, command); |
|||
} |
|||
|
|||
private static StringFieldProperties ValidProperties() |
|||
{ |
|||
return new StringFieldProperties { MinLength = 10, MaxLength = 20 }; |
|||
} |
|||
|
|||
private static StringFieldProperties InvalidProperties() |
|||
{ |
|||
return new StringFieldProperties { MinLength = 20, MaxLength = 10 }; |
|||
} |
|||
} |
|||
} |
|||
@ -1,278 +0,0 @@ |
|||
// ==========================================================================
|
|||
// SchemaCommandMiddlewareTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using FakeItEasy; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Read; |
|||
using Squidex.Domain.Apps.Read.Schemas; |
|||
using Squidex.Domain.Apps.Write.Schemas.Commands; |
|||
using Squidex.Domain.Apps.Write.TestHelpers; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Commands; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas |
|||
{ |
|||
public class SchemaCommandMiddlewareTests : HandlerTestBase<SchemaDomainObject> |
|||
{ |
|||
private readonly IAppProvider appProvider = A.Fake<IAppProvider>(); |
|||
private readonly SchemaCommandMiddleware sut; |
|||
private readonly SchemaDomainObject schema; |
|||
private readonly FieldRegistry registry = new FieldRegistry(new TypeNameRegistry()); |
|||
private readonly string fieldName = "age"; |
|||
|
|||
public SchemaCommandMiddlewareTests() |
|||
{ |
|||
schema = new SchemaDomainObject(SchemaId, -1, registry); |
|||
|
|||
sut = new SchemaCommandMiddleware(Handler, appProvider); |
|||
|
|||
A.CallTo(() => appProvider.GetSchemaAsync(AppName, SchemaName, false)) |
|||
.Returns((ISchemaEntity)null); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Create_should_create_schema_domain_object() |
|||
{ |
|||
var context = CreateContextForCommand(new CreateSchema { Name = SchemaName, SchemaId = SchemaId }); |
|||
|
|||
await TestCreate(schema, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
|
|||
Assert.Equal(SchemaId, context.Result<EntityCreatedResult<Guid>>().IdOrValue); |
|||
|
|||
A.CallTo(() => appProvider.GetSchemaAsync(AppName, SchemaName, false)).MustHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task UpdateSchema_should_update_domain_object() |
|||
{ |
|||
CreateSchema(); |
|||
|
|||
var context = CreateContextForCommand(new UpdateSchema { Properties = new SchemaProperties() }); |
|||
|
|||
await TestUpdate(schema, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task ReorderSchema_should_update_domain_object() |
|||
{ |
|||
CreateSchema(); |
|||
|
|||
var context = CreateContextForCommand(new ReorderFields { FieldIds = new List<long>() }); |
|||
|
|||
await TestUpdate(schema, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task PublishSchema_should_update_domain_object() |
|||
{ |
|||
CreateSchema(); |
|||
|
|||
var context = CreateContextForCommand(new PublishSchema()); |
|||
|
|||
await TestUpdate(schema, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task UnpublishSchema_should_update_domain_object() |
|||
{ |
|||
CreateSchema(); |
|||
PublishSchema(); |
|||
|
|||
var context = CreateContextForCommand(new UnpublishSchema()); |
|||
|
|||
await TestUpdate(schema, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task ConfigureScripts_should_update_domain_object() |
|||
{ |
|||
CreateSchema(); |
|||
|
|||
var context = CreateContextForCommand(new ConfigureScripts()); |
|||
|
|||
await TestUpdate(schema, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task DeleteSchema_should_update_domain_object() |
|||
{ |
|||
CreateSchema(); |
|||
|
|||
var context = CreateContextForCommand(new DeleteSchema()); |
|||
|
|||
await TestUpdate(schema, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Add_should_update_domain_object() |
|||
{ |
|||
CreateSchema(); |
|||
|
|||
var context = CreateContextForCommand(new AddField { Name = fieldName, Properties = new NumberFieldProperties() }); |
|||
|
|||
await TestUpdate(schema, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
|
|||
Assert.Equal(1, context.Result<EntityCreatedResult<long>>().IdOrValue); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task UpdateField_should_update_domain_object() |
|||
{ |
|||
CreateSchema(); |
|||
CreateField(); |
|||
|
|||
var context = CreateContextForCommand(new UpdateField { FieldId = 1, Properties = new NumberFieldProperties() }); |
|||
|
|||
await TestUpdate(schema, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task LockField_should_update_domain_object() |
|||
{ |
|||
CreateSchema(); |
|||
CreateField(); |
|||
|
|||
var context = CreateContextForCommand(new LockField { FieldId = 1 }); |
|||
|
|||
await TestUpdate(schema, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task HideField_should_update_domain_object() |
|||
{ |
|||
CreateSchema(); |
|||
CreateField(); |
|||
|
|||
var context = CreateContextForCommand(new HideField { FieldId = 1 }); |
|||
|
|||
await TestUpdate(schema, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task ShowField_should_update_domain_object() |
|||
{ |
|||
CreateSchema(); |
|||
CreateField(); |
|||
|
|||
HideField(); |
|||
|
|||
var context = CreateContextForCommand(new ShowField { FieldId = 1 }); |
|||
|
|||
await TestUpdate(schema, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task DisableField_should_update_domain_object() |
|||
{ |
|||
CreateSchema(); |
|||
CreateField(); |
|||
|
|||
var context = CreateContextForCommand(new DisableField { FieldId = 1 }); |
|||
|
|||
await TestUpdate(schema, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task EnableField_should_update_domain_object() |
|||
{ |
|||
CreateSchema(); |
|||
CreateField(); |
|||
|
|||
DisableField(); |
|||
|
|||
var context = CreateContextForCommand(new EnableField { FieldId = 1 }); |
|||
|
|||
await TestUpdate(schema, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task DeleteField_should_update_domain_object() |
|||
{ |
|||
CreateSchema(); |
|||
CreateField(); |
|||
|
|||
var context = CreateContextForCommand(new DeleteField { FieldId = 1 }); |
|||
|
|||
await TestUpdate(schema, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
private void CreateSchema() |
|||
{ |
|||
schema.Create(CreateCommand(new CreateSchema { Name = SchemaName })); |
|||
} |
|||
|
|||
private void PublishSchema() |
|||
{ |
|||
schema.Publish(CreateCommand(new PublishSchema())); |
|||
} |
|||
|
|||
private void CreateField() |
|||
{ |
|||
schema.Add(CreateCommand(new AddField { Name = fieldName, Properties = new NumberFieldProperties() })); |
|||
} |
|||
|
|||
private void HideField() |
|||
{ |
|||
schema.HideField(CreateCommand(new HideField { FieldId = 1 })); |
|||
} |
|||
|
|||
private void DisableField() |
|||
{ |
|||
schema.DisableField(CreateCommand(new DisableField { FieldId = 1 })); |
|||
} |
|||
} |
|||
} |
|||
@ -1,656 +0,0 @@ |
|||
// ==========================================================================
|
|||
// SchemaDomainObjectTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Events.Schemas; |
|||
using Squidex.Domain.Apps.Write.Schemas.Commands; |
|||
using Squidex.Domain.Apps.Write.TestHelpers; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Commands; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas |
|||
{ |
|||
public class SchemaDomainObjectTests : HandlerTestBase<SchemaDomainObject> |
|||
{ |
|||
private readonly string fieldName = "age"; |
|||
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(SchemaId, 0, fieldRegistry); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_throw_exception_if_created() |
|||
{ |
|||
sut.Create(new CreateSchema { Name = SchemaName }); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Create(CreateCommand(new CreateSchema { Name = SchemaName })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_create_schema_and_create_events() |
|||
{ |
|||
var properties = new SchemaProperties(); |
|||
|
|||
sut.Create(CreateCommand(new CreateSchema { Name = SchemaName, Properties = properties })); |
|||
|
|||
Assert.Equal(SchemaName, sut.Schema.Name); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new SchemaCreated { Name = SchemaName, Properties = properties }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_create_schema_with_initial_fields() |
|||
{ |
|||
var properties = new SchemaProperties(); |
|||
|
|||
var fields = new List<CreateSchemaField> |
|||
{ |
|||
new CreateSchemaField { Name = "field1", Properties = ValidProperties() }, |
|||
new CreateSchemaField { Name = "field2", Properties = ValidProperties() } |
|||
}; |
|||
|
|||
sut.Create(CreateCommand(new CreateSchema { Name = SchemaName, Properties = properties, Fields = fields })); |
|||
|
|||
var @event = (SchemaCreated)sut.GetUncomittedEvents().Single().Payload; |
|||
|
|||
Assert.Equal(SchemaName, sut.Schema.Name); |
|||
Assert.Equal(2, @event.Fields.Count); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Update(CreateCommand(new UpdateSchema { Properties = new SchemaProperties() })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_throw_exception_if_schema_is_deleted() |
|||
{ |
|||
CreateSchema(); |
|||
DeleteSchema(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Update(CreateCommand(new UpdateSchema { Properties = new SchemaProperties() })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_refresh_properties_and_create_events() |
|||
{ |
|||
var properties = new SchemaProperties(); |
|||
|
|||
CreateSchema(); |
|||
|
|||
sut.Update(CreateCommand(new UpdateSchema { Properties = properties })); |
|||
|
|||
Assert.Equal(properties, sut.Schema.Properties); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new SchemaUpdated { Properties = properties }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ConfigureScripts_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.ConfigureScripts(CreateCommand(new ConfigureScripts())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ConfigureScripts_should_throw_exception_if_schema_is_deleted() |
|||
{ |
|||
CreateSchema(); |
|||
DeleteSchema(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.ConfigureScripts(CreateCommand(new ConfigureScripts())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ConfigureScripts_should_create_events() |
|||
{ |
|||
CreateSchema(); |
|||
|
|||
sut.ConfigureScripts(CreateCommand(new ConfigureScripts |
|||
{ |
|||
ScriptQuery = "<script-query>", |
|||
ScriptCreate = "<script-create>", |
|||
ScriptUpdate = "<script-update>", |
|||
ScriptDelete = "<script-delete>", |
|||
ScriptChange = "<script-change>" |
|||
})); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new ScriptsConfigured |
|||
{ |
|||
ScriptQuery = "<script-query>", |
|||
ScriptCreate = "<script-create>", |
|||
ScriptUpdate = "<script-update>", |
|||
ScriptDelete = "<script-delete>", |
|||
ScriptChange = "<script-change>" |
|||
}) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Reorder_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Reorder(CreateCommand(new ReorderFields { FieldIds = new List<long>() })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Reorder_should_throw_exception_if_schema_is_deleted() |
|||
{ |
|||
CreateSchema(); |
|||
DeleteSchema(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Reorder(CreateCommand(new ReorderFields { FieldIds = new List<long>() })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Reorder_should_refresh_properties_and_create_events() |
|||
{ |
|||
var fieldIds = new List<long> { 1, 2 }; |
|||
|
|||
CreateSchema(); |
|||
|
|||
sut.Add(new AddField { Name = "field1", Properties = ValidProperties() }); |
|||
sut.Add(new AddField { Name = "field2", Properties = ValidProperties() }); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
|
|||
sut.Reorder(CreateCommand(new ReorderFields { FieldIds = fieldIds })); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new SchemaFieldsReordered { FieldIds = fieldIds }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Publish_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Publish(CreateCommand(new PublishSchema())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Publish_should_throw_exception_if_schema_is_deleted() |
|||
{ |
|||
CreateSchema(); |
|||
DeleteSchema(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Publish(CreateCommand(new PublishSchema())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Publish_should_refresh_properties_and_create_events() |
|||
{ |
|||
CreateSchema(); |
|||
|
|||
sut.Publish(CreateCommand(new PublishSchema())); |
|||
|
|||
Assert.True(sut.Schema.IsPublished); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new SchemaPublished()) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Unpublish_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Unpublish(CreateCommand(new UnpublishSchema())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Unpublish_should_throw_exception_if_schema_is_deleted() |
|||
{ |
|||
CreateSchema(); |
|||
DeleteSchema(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Unpublish(CreateCommand(new UnpublishSchema())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Unpublish_should_refresh_properties_and_create_events() |
|||
{ |
|||
CreateSchema(); |
|||
PublishSchema(); |
|||
|
|||
sut.Unpublish(CreateCommand(new UnpublishSchema())); |
|||
|
|||
Assert.False(sut.Schema.IsPublished); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new SchemaUnpublished()) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Delete_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Delete(CreateCommand(new DeleteSchema())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Delete_should_throw_exception_if_already_deleted() |
|||
{ |
|||
CreateSchema(); |
|||
DeleteSchema(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Delete(CreateCommand(new DeleteSchema())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Delete_should_refresh_properties_and_create_events() |
|||
{ |
|||
CreateSchema(); |
|||
|
|||
sut.Delete(CreateCommand(new DeleteSchema())); |
|||
|
|||
Assert.True(sut.IsDeleted); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new SchemaDeleted()) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void AddField_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Add(CreateCommand(new AddField { Name = fieldName, Properties = ValidProperties() })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void AddField_should_throw_exception_if_schema_is_deleted() |
|||
{ |
|||
CreateSchema(); |
|||
DeleteSchema(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Add(CreateCommand(new AddField { Name = fieldName, Properties = new NumberFieldProperties() })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Add_should_update_schema_and_create_events() |
|||
{ |
|||
var properties = new NumberFieldProperties(); |
|||
|
|||
CreateSchema(); |
|||
|
|||
sut.Add(CreateCommand(new AddField { Name = fieldName, Properties = properties })); |
|||
|
|||
Assert.Equal(properties, sut.Schema.FieldsById[1].RawProperties); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new FieldAdded { Name = fieldName, FieldId = fieldId, Properties = properties }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateField_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.UpdateField(CreateCommand(new UpdateField { FieldId = 1, Properties = new NumberFieldProperties() })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateField_should_throw_exception_if_schema_is_deleted() |
|||
{ |
|||
CreateSchema(); |
|||
DeleteSchema(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.UpdateField(CreateCommand(new UpdateField { FieldId = 1, Properties = new NumberFieldProperties() })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateField_should_update_schema_and_create_events() |
|||
{ |
|||
var properties = new NumberFieldProperties(); |
|||
|
|||
CreateSchema(); |
|||
CreateField(); |
|||
|
|||
sut.UpdateField(CreateCommand(new UpdateField { FieldId = 1, Properties = properties })); |
|||
|
|||
Assert.Equal(properties, sut.Schema.FieldsById[1].RawProperties); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new FieldUpdated { FieldId = fieldId, Properties = properties }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void LockField_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.LockField(CreateCommand(new LockField { FieldId = 1 })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void LockField_should_throw_exception_if_schema_is_deleted() |
|||
{ |
|||
CreateSchema(); |
|||
DeleteSchema(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.LockField(CreateCommand(new LockField { FieldId = 1 })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void LockField_should_update_schema_and_create_events() |
|||
{ |
|||
CreateSchema(); |
|||
CreateField(); |
|||
|
|||
sut.LockField(CreateCommand(new LockField { FieldId = 1 })); |
|||
|
|||
Assert.False(sut.Schema.FieldsById[1].IsDisabled); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new FieldLocked { FieldId = fieldId }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void HideField_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.HideField(CreateCommand(new HideField { FieldId = 1 })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void HideField_should_throw_exception_if_schema_is_deleted() |
|||
{ |
|||
CreateSchema(); |
|||
DeleteSchema(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.HideField(CreateCommand(new HideField { FieldId = 1 })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void HideField_should_update_schema_and_create_events() |
|||
{ |
|||
CreateSchema(); |
|||
CreateField(); |
|||
|
|||
sut.HideField(CreateCommand(new HideField { FieldId = 1 })); |
|||
|
|||
Assert.True(sut.Schema.FieldsById[1].IsHidden); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new FieldHidden { FieldId = fieldId }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ShowField_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.ShowField(CreateCommand(new ShowField { FieldId = 1 })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ShowField_should_throw_exception_if_schema_is_deleted() |
|||
{ |
|||
CreateSchema(); |
|||
DeleteSchema(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.ShowField(CreateCommand(new ShowField { FieldId = 1 })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ShowField_should_update_schema_and_create_events() |
|||
{ |
|||
CreateSchema(); |
|||
CreateField(); |
|||
|
|||
sut.HideField(CreateCommand(new HideField { FieldId = 1 })); |
|||
sut.ShowField(CreateCommand(new ShowField { FieldId = 1 })); |
|||
|
|||
Assert.False(sut.Schema.FieldsById[1].IsHidden); |
|||
|
|||
sut.GetUncomittedEvents().Skip(1) |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new FieldShown { FieldId = fieldId }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void DisableField_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.DisableField(CreateCommand(new DisableField { FieldId = 1 })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void DisableField_should_throw_exception_if_schema_is_deleted() |
|||
{ |
|||
CreateSchema(); |
|||
DeleteSchema(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.DisableField(CreateCommand(new DisableField { FieldId = 1 })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void DisableField_should_update_schema_and_create_events() |
|||
{ |
|||
CreateSchema(); |
|||
CreateField(); |
|||
|
|||
sut.DisableField(CreateCommand(new DisableField { FieldId = 1 })); |
|||
|
|||
Assert.True(sut.Schema.FieldsById[1].IsDisabled); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new FieldDisabled { FieldId = fieldId }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void EnableField_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.EnableField(CreateCommand(new EnableField { FieldId = 1 })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void EnableField_should_throw_exception_if_schema_is_deleted() |
|||
{ |
|||
CreateSchema(); |
|||
DeleteSchema(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.EnableField(CreateCommand(new EnableField { FieldId = 1 })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void EnableField_should_update_schema_and_create_events() |
|||
{ |
|||
CreateSchema(); |
|||
CreateField(); |
|||
|
|||
sut.DisableField(CreateCommand(new DisableField { FieldId = 1 })); |
|||
sut.EnableField(CreateCommand(new EnableField { FieldId = 1 })); |
|||
|
|||
Assert.False(sut.Schema.FieldsById[1].IsDisabled); |
|||
|
|||
sut.GetUncomittedEvents().Skip(1) |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new FieldEnabled { FieldId = fieldId }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void DeleteField_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.DeleteField(CreateCommand(new DeleteField { FieldId = 1 })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void DeleteField_should_throw_exception_if_schema_is_deleted() |
|||
{ |
|||
CreateSchema(); |
|||
DeleteSchema(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.DeleteField(CreateCommand(new DeleteField { FieldId = 1 })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void DeleteField_should_update_schema_and_create_events() |
|||
{ |
|||
CreateSchema(); |
|||
CreateField(); |
|||
|
|||
sut.DeleteField(CreateCommand(new DeleteField { FieldId = 1 })); |
|||
|
|||
Assert.False(sut.Schema.FieldsById.ContainsKey(1)); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateEvent(new FieldDeleted { FieldId = fieldId }) |
|||
); |
|||
} |
|||
|
|||
private void CreateField() |
|||
{ |
|||
sut.Add(new AddField { Name = fieldName, Properties = new NumberFieldProperties() }); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
|
|||
private void CreateSchema() |
|||
{ |
|||
sut.Create(CreateCommand(new CreateSchema { Name = SchemaName })); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
|
|||
private void PublishSchema() |
|||
{ |
|||
sut.Publish(CreateCommand(new PublishSchema())); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
|
|||
private void DeleteSchema() |
|||
{ |
|||
sut.Delete(CreateCommand(new DeleteSchema())); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
|
|||
private static StringFieldProperties ValidProperties() |
|||
{ |
|||
return new StringFieldProperties { MinLength = 10, MaxLength = 20 }; |
|||
} |
|||
|
|||
private static StringFieldProperties InvalidProperties() |
|||
{ |
|||
return new StringFieldProperties { MinLength = 20, MaxLength = 10 }; |
|||
} |
|||
} |
|||
} |
|||
@ -1,29 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
<PropertyGroup> |
|||
<OutputType>Exe</OutputType> |
|||
<TargetFramework>netcoreapp2.0</TargetFramework> |
|||
<RootNamespace>Squidex.Domain.Apps.Write</RootNamespace> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\Squidex.Domain.Apps.Core.Model\Squidex.Domain.Apps.Core.Model.csproj" /> |
|||
<ProjectReference Include="..\..\src\Squidex.Domain.Apps.Core.Operations\Squidex.Domain.Apps.Core.Operations.csproj" /> |
|||
<ProjectReference Include="..\..\src\Squidex.Domain.Apps.Write\Squidex.Domain.Apps.Write.csproj" /> |
|||
<ProjectReference Include="..\..\src\Squidex.Infrastructure\Squidex.Infrastructure.csproj" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<PackageReference Include="FakeItEasy" Version="4.2.0" /> |
|||
<PackageReference Include="FluentAssertions" Version="4.19.4" /> |
|||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" /> |
|||
<PackageReference Include="RefactoringEssentials" Version="5.4.0" /> |
|||
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2" /> |
|||
<PackageReference Include="System.ValueTuple" Version="4.4.0" /> |
|||
<PackageReference Include="xunit" Version="2.3.1" /> |
|||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="2.0.0" /> |
|||
</ItemGroup> |
|||
<PropertyGroup> |
|||
<CodeAnalysisRuleSet>..\..\Squidex.ruleset</CodeAnalysisRuleSet> |
|||
</PropertyGroup> |
|||
</Project> |
|||
@ -1,45 +0,0 @@ |
|||
// ==========================================================================
|
|||
// AssertHelper.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using FluentAssertions; |
|||
using Squidex.Infrastructure.EventSourcing; |
|||
|
|||
namespace Squidex.Domain.Apps.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++) |
|||
{ |
|||
var lhs = source[i]; |
|||
var rhs = others[i]; |
|||
|
|||
lhs.ShouldBeSameEvent(rhs); |
|||
} |
|||
} |
|||
|
|||
public static void ShouldBeSameEvent(this IEvent lhs, IEvent rhs) |
|||
{ |
|||
lhs.Should().BeOfType(rhs.GetType()); |
|||
|
|||
((object)lhs).ShouldBeEquivalentTo(rhs, o => o.IncludingAllDeclaredProperties()); |
|||
} |
|||
|
|||
public static void ShouldBeSameEventType(this IEvent lhs, IEvent rhs) |
|||
{ |
|||
lhs.Should().BeOfType(rhs.GetType()); |
|||
} |
|||
} |
|||
} |
|||
@ -1,162 +0,0 @@ |
|||
// ==========================================================================
|
|||
// HandlerTestBase.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Squidex.Domain.Apps.Events; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Commands; |
|||
|
|||
#pragma warning disable IDE0019 // Use pattern matching
|
|||
|
|||
namespace Squidex.Domain.Apps.Write.TestHelpers |
|||
{ |
|||
public abstract class HandlerTestBase<T> where T : DomainObjectBase |
|||
{ |
|||
private sealed class MockupHandler : IAggregateHandler |
|||
{ |
|||
private T domainObject; |
|||
|
|||
public bool IsCreated { get; private set; } |
|||
public bool IsUpdated { get; private set; } |
|||
|
|||
public void Init(T newDomainObject) |
|||
{ |
|||
domainObject = newDomainObject; |
|||
|
|||
IsCreated = false; |
|||
IsUpdated = false; |
|||
} |
|||
|
|||
public async Task<V> CreateAsync<V>(CommandContext context, Func<V, Task> creator) where V : class, IAggregate |
|||
{ |
|||
IsCreated = true; |
|||
|
|||
var @do = domainObject as V; |
|||
|
|||
await creator(domainObject as V); |
|||
|
|||
return @do; |
|||
} |
|||
|
|||
public async Task<V> UpdateAsync<V>(CommandContext context, Func<V, Task> updater) where V : class, IAggregate |
|||
{ |
|||
IsUpdated = true; |
|||
|
|||
var @do = domainObject as V; |
|||
|
|||
await updater(domainObject as V); |
|||
|
|||
return @do; |
|||
} |
|||
} |
|||
|
|||
private readonly MockupHandler handler = new MockupHandler(); |
|||
|
|||
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 new NamedId<Guid>(AppId, AppName); } |
|||
} |
|||
|
|||
protected NamedId<Guid> SchemaNamedId |
|||
{ |
|||
get { return new NamedId<Guid>(SchemaId, SchemaName); } |
|||
} |
|||
|
|||
protected IAggregateHandler Handler |
|||
{ |
|||
get { return handler; } |
|||
} |
|||
|
|||
protected CommandContext CreateContextForCommand<TCommand>(TCommand command) where TCommand : SquidexCommand |
|||
{ |
|||
return new CommandContext(CreateCommand(command)); |
|||
} |
|||
|
|||
protected async Task TestCreate(T domainObject, Func<T, Task> action, bool shouldCreate = true) |
|||
{ |
|||
handler.Init(domainObject); |
|||
|
|||
await action(domainObject); |
|||
|
|||
if (!handler.IsCreated && shouldCreate) |
|||
{ |
|||
throw new InvalidOperationException("Create not called."); |
|||
} |
|||
} |
|||
|
|||
protected async Task TestUpdate(T domainObject, Func<T, Task> action, bool shouldUpdate = true) |
|||
{ |
|||
handler.Init(domainObject); |
|||
|
|||
await action(domainObject); |
|||
|
|||
if (!handler.IsUpdated && shouldUpdate) |
|||
{ |
|||
throw new InvalidOperationException("Update not called."); |
|||
} |
|||
} |
|||
|
|||
protected TCommand CreateCommand<TCommand>(TCommand command) where TCommand : SquidexCommand |
|||
{ |
|||
if (command.Actor == null) |
|||
{ |
|||
command.Actor = User; |
|||
} |
|||
|
|||
var appCommand = command as AppCommand; |
|||
|
|||
if (appCommand != null && appCommand.AppId == null) |
|||
{ |
|||
appCommand.AppId = AppNamedId; |
|||
} |
|||
|
|||
var schemaCommand = command as SchemaCommand; |
|||
|
|||
if (schemaCommand != null && schemaCommand.SchemaId == null) |
|||
{ |
|||
schemaCommand.SchemaId = SchemaNamedId; |
|||
} |
|||
|
|||
return command; |
|||
} |
|||
|
|||
protected 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; |
|||
} |
|||
} |
|||
} |
|||
|
|||
#pragma warning restore IDE0019 // Use pattern matching
|
|||
Loading…
Reference in new issue