mirror of https://github.com/Squidex/squidex.git
76 changed files with 1399 additions and 3933 deletions
@ -0,0 +1,27 @@ |
|||
// ==========================================================================
|
|||
// PartitioningExtensions.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Squidex.Domain.Apps.Core |
|||
{ |
|||
public static class PartitioningExtensions |
|||
{ |
|||
private static readonly HashSet<string> AllowedPartitions = new HashSet<string>(StringComparer.OrdinalIgnoreCase) |
|||
{ |
|||
Partitioning.Language.Key, |
|||
Partitioning.Invariant.Key |
|||
}; |
|||
|
|||
public static bool IsValidPartitioning(this string value) |
|||
{ |
|||
return value == null || AllowedPartitions.Contains(value); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,72 @@ |
|||
// ==========================================================================
|
|||
// MongoAppRepository_EventHandling.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
|
|||
namespace Squidex.Domain.Apps.Events.Apps.Utils |
|||
{ |
|||
public static class AppEventDispatcher |
|||
{ |
|||
public static void Apply(this AppContributors contributors, AppContributorRemoved @event) |
|||
{ |
|||
contributors.Remove(@event.ContributorId); |
|||
} |
|||
|
|||
public static void Apply(this AppContributors contributors, AppContributorAssigned @event) |
|||
{ |
|||
contributors.Assign(@event.ContributorId, @event.Permission); |
|||
} |
|||
|
|||
public static void Apply(this LanguagesConfig languagesConfig, AppLanguageAdded @event) |
|||
{ |
|||
languagesConfig.Set(new LanguageConfig(@event.Language)); |
|||
} |
|||
|
|||
public static void Apply(this LanguagesConfig languagesConfig, AppLanguageRemoved @event) |
|||
{ |
|||
languagesConfig.Remove(@event.Language); |
|||
} |
|||
|
|||
public static void Apply(this AppClients clients, AppClientAttached @event) |
|||
{ |
|||
clients.Add(@event.Id, @event.Secret); |
|||
} |
|||
|
|||
public static void Apply(this AppClients clients, AppClientRevoked @event) |
|||
{ |
|||
clients.Revoke(@event.Id); |
|||
} |
|||
|
|||
public static void Apply(this AppClients clients, AppClientRenamed @event) |
|||
{ |
|||
if (clients.Clients.TryGetValue(@event.Id, out var client)) |
|||
{ |
|||
client.Rename(@event.Name); |
|||
} |
|||
} |
|||
|
|||
public static void Apply(this AppClients clients, AppClientUpdated @event) |
|||
{ |
|||
if (clients.Clients.TryGetValue(@event.Id, out var client)) |
|||
{ |
|||
client.Update(@event.Permission); |
|||
} |
|||
} |
|||
|
|||
public static void Apply(this LanguagesConfig languagesConfig, AppLanguageUpdated @event) |
|||
{ |
|||
languagesConfig.Set(new LanguageConfig(@event.Language, @event.IsOptional, @event.Fallback)); |
|||
|
|||
if (@event.IsMaster) |
|||
{ |
|||
languagesConfig.MakeMaster(@event.Language); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,43 +0,0 @@ |
|||
// ==========================================================================
|
|||
// MongoAppEntityClient.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using MongoDB.Bson.Serialization.Attributes; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Domain.Apps.Read.Apps; |
|||
|
|||
namespace Squidex.Domain.Apps.Read.MongoDb.Apps |
|||
{ |
|||
public sealed class MongoAppEntityClient : IAppClientEntity |
|||
{ |
|||
[BsonRequired] |
|||
[BsonElement] |
|||
public string Id { get; set; } |
|||
|
|||
[BsonRequired] |
|||
[BsonElement] |
|||
public string Secret { get; set; } |
|||
|
|||
[BsonRequired] |
|||
[BsonElement] |
|||
public string Name { get; set; } |
|||
|
|||
[BsonRequired] |
|||
[BsonElement] |
|||
public AppClientPermission Permission { get; set; } |
|||
|
|||
string IAppClientEntity.Name |
|||
{ |
|||
get { return !string.IsNullOrWhiteSpace(Name) ? Name : Id; } |
|||
} |
|||
|
|||
public MongoAppEntityClient() |
|||
{ |
|||
Permission = AppClientPermission.Editor; |
|||
} |
|||
} |
|||
} |
|||
@ -1,21 +0,0 @@ |
|||
// ==========================================================================
|
|||
// MongoAppEntityContributor.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using MongoDB.Bson.Serialization.Attributes; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Domain.Apps.Read.Apps; |
|||
|
|||
namespace Squidex.Domain.Apps.Read.MongoDb.Apps |
|||
{ |
|||
public sealed class MongoAppEntityContributor : IAppContributorEntity |
|||
{ |
|||
[BsonRequired] |
|||
[BsonElement] |
|||
public AppContributorPermission Permission { get; set; } |
|||
} |
|||
} |
|||
@ -1,28 +0,0 @@ |
|||
// ==========================================================================
|
|||
// MongoAppEntityLanguage.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using MongoDB.Bson.Serialization.Attributes; |
|||
|
|||
namespace Squidex.Domain.Apps.Read.MongoDb.Apps |
|||
{ |
|||
public sealed class MongoAppEntityLanguage |
|||
{ |
|||
[BsonRequired] |
|||
[BsonElement] |
|||
public string Iso2Code { get; set; } |
|||
|
|||
[BsonRequired] |
|||
[BsonElement] |
|||
public bool IsOptional { get; set; } |
|||
|
|||
[BsonRequired] |
|||
[BsonElement] |
|||
public List<string> Fallback { get; set; } |
|||
} |
|||
} |
|||
@ -1,56 +0,0 @@ |
|||
// ==========================================================================
|
|||
// AppClient.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Apps |
|||
{ |
|||
public sealed class AppClient |
|||
{ |
|||
private readonly string name; |
|||
private readonly string secret; |
|||
private readonly AppClientPermission permission; |
|||
|
|||
public AppClient(string secret, string name, AppClientPermission permission) |
|||
{ |
|||
Guard.NotNullOrEmpty(name, nameof(name)); |
|||
Guard.NotNullOrEmpty(secret, nameof(secret)); |
|||
Guard.Enum(permission, nameof(permission)); |
|||
|
|||
this.name = name; |
|||
this.secret = secret; |
|||
this.permission = permission; |
|||
} |
|||
|
|||
public AppClient Update(AppClientPermission newPermission, Func<string> message) |
|||
{ |
|||
if (permission == newPermission) |
|||
{ |
|||
var error = new ValidationError("Client has already the permission.", "IsReader"); |
|||
|
|||
throw new ValidationException(message(), error); |
|||
} |
|||
|
|||
return new AppClient(secret, name, newPermission); |
|||
} |
|||
|
|||
public AppClient Rename(string newName, Func<string> message) |
|||
{ |
|||
if (string.Equals(name, newName)) |
|||
{ |
|||
var error = new ValidationError("Client already has the name.", "Id"); |
|||
|
|||
throw new ValidationException(message(), error); |
|||
} |
|||
|
|||
return new AppClient(secret, newName, permission); |
|||
} |
|||
} |
|||
} |
|||
@ -1,66 +0,0 @@ |
|||
// ==========================================================================
|
|||
// AppClients.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Apps |
|||
{ |
|||
public class AppClients |
|||
{ |
|||
private readonly Dictionary<string, AppClient> clients = new Dictionary<string, AppClient>(); |
|||
|
|||
public void Add(string id, string secret) |
|||
{ |
|||
ThrowIfFound(id, () => "Cannot add client"); |
|||
|
|||
clients[id] = new AppClient(secret, id, AppClientPermission.Editor); |
|||
} |
|||
|
|||
public void Rename(string clientId, string name) |
|||
{ |
|||
ThrowIfNotFound(clientId); |
|||
|
|||
clients[clientId] = clients[clientId].Rename(name, () => "Cannot rename client"); |
|||
} |
|||
|
|||
public void Update(string clientId, AppClientPermission permission) |
|||
{ |
|||
ThrowIfNotFound(clientId); |
|||
|
|||
clients[clientId] = clients[clientId].Update(permission, () => "Cannot update client"); |
|||
} |
|||
|
|||
public void Revoke(string clientId) |
|||
{ |
|||
ThrowIfNotFound(clientId); |
|||
|
|||
clients.Remove(clientId); |
|||
} |
|||
|
|||
private void ThrowIfNotFound(string clientId) |
|||
{ |
|||
if (!clients.ContainsKey(clientId)) |
|||
{ |
|||
throw new DomainObjectNotFoundException(clientId, "Contributors", typeof(AppDomainObject)); |
|||
} |
|||
} |
|||
|
|||
private void ThrowIfFound(string clientId, Func<string> message) |
|||
{ |
|||
if (clients.ContainsKey(clientId)) |
|||
{ |
|||
var error = new ValidationError("Client id is alreay part of the app.", "Id"); |
|||
|
|||
throw new ValidationException(message(), error); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,78 +0,0 @@ |
|||
// ==========================================================================
|
|||
// AppContributors.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.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Apps |
|||
{ |
|||
public class AppContributors |
|||
{ |
|||
private readonly Dictionary<string, AppContributorPermission> contributors = new Dictionary<string, AppContributorPermission>(); |
|||
|
|||
public int Count |
|||
{ |
|||
get { return contributors.Count; } |
|||
} |
|||
|
|||
public void Assign(string contributorId, AppContributorPermission permission) |
|||
{ |
|||
string Message() => "Cannot assign contributor"; |
|||
|
|||
ThrowIfFound(contributorId, permission, Message); |
|||
ThrowIfNoOwner(c => c[contributorId] = permission, Message); |
|||
|
|||
contributors[contributorId] = permission; |
|||
} |
|||
|
|||
public void Remove(string contributorId) |
|||
{ |
|||
string Message() => "Cannot remove contributor"; |
|||
|
|||
ThrowIfNotFound(contributorId); |
|||
ThrowIfNoOwner(c => c.Remove(contributorId), Message); |
|||
|
|||
contributors.Remove(contributorId); |
|||
} |
|||
|
|||
private void ThrowIfNotFound(string contributorId) |
|||
{ |
|||
if (!contributors.ContainsKey(contributorId)) |
|||
{ |
|||
throw new DomainObjectNotFoundException(contributorId, "Contributors", typeof(AppDomainObject)); |
|||
} |
|||
} |
|||
|
|||
private void ThrowIfFound(string contributorId, AppContributorPermission permission, Func<string> message) |
|||
{ |
|||
if (contributors.TryGetValue(contributorId, out var currentPermission) && currentPermission == permission) |
|||
{ |
|||
var error = new ValidationError("Contributor is already part of the app with same permissions.", "ContributorId"); |
|||
|
|||
throw new ValidationException(message(), error); |
|||
} |
|||
} |
|||
|
|||
private void ThrowIfNoOwner(Action<Dictionary<string, AppContributorPermission>> change, Func<string> message) |
|||
{ |
|||
var contributorsCopy = new Dictionary<string, AppContributorPermission>(contributors); |
|||
|
|||
change(contributorsCopy); |
|||
|
|||
if (contributorsCopy.All(x => x.Value != AppContributorPermission.Owner)) |
|||
{ |
|||
var error = new ValidationError("Contributor is the last owner.", "ContributorId"); |
|||
|
|||
throw new ValidationException(message(), error); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,69 @@ |
|||
// ==========================================================================
|
|||
// GuardContent.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.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Contents.Guards |
|||
{ |
|||
public static class GuardContent |
|||
{ |
|||
public static void CanCreate(CreateContent command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
Validate.It(() => "Cannot created content.", error => |
|||
{ |
|||
if (command.Data == null) |
|||
{ |
|||
error(new ValidationError("Data cannot be null.", nameof(command.Data))); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public static void CanCreate(UpdateContent command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
Validate.It(() => "Cannot update content.", error => |
|||
{ |
|||
if (command.Data == null) |
|||
{ |
|||
error(new ValidationError("Data cannot be null.", nameof(command.Data))); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public static void CanCreate(PatchContent command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
Validate.It(() => "Cannot patch content.", error => |
|||
{ |
|||
if (command.Data == null) |
|||
{ |
|||
error(new ValidationError("Data cannot be null.", nameof(command.Data))); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public static void CanChangeStatus(Status status, ChangeContentStatus command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
Validate.It(() => "Cannot change status.", error => |
|||
{ |
|||
if (!StatusFlow.Exists(command.Status) || !StatusFlow.CanChange(status, command.Status)) |
|||
{ |
|||
error(new ValidationError($"Content cannot be changed from status {status} to {command.Status}.", nameof(command.Status))); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,130 @@ |
|||
// ==========================================================================
|
|||
// GuardSchema.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Squidex.Domain.Apps.Core; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Read.Schemas.Services; |
|||
using Squidex.Domain.Apps.Write.Schemas.Commands; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas.Guards |
|||
{ |
|||
public static class GuardSchema |
|||
{ |
|||
public static Task CanCreate(CreateSchema command, ISchemaProvider schemas) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
return Validate.It(() => "Cannot create schema.", async error => |
|||
{ |
|||
if (!command.Name.IsSlug()) |
|||
{ |
|||
error(new ValidationError("Name must be a valid slug.", nameof(command.Name))); |
|||
} |
|||
|
|||
if (await schemas.FindSchemaByNameAsync(command.AppId.Id, command.Name) != null) |
|||
{ |
|||
error(new ValidationError($"A schema with name '{command.Name}' already exists", nameof(command.Name))); |
|||
} |
|||
|
|||
if (command.Fields != null && command.Fields.Any()) |
|||
{ |
|||
var index = 0; |
|||
|
|||
foreach (var field in command.Fields) |
|||
{ |
|||
var prefix = $"Fields.{index}"; |
|||
|
|||
if (!field.Partitioning.IsValidPartitioning()) |
|||
{ |
|||
error(new ValidationError("Partitioning is not valid.", $"{prefix}.{nameof(field.Partitioning)}")); |
|||
} |
|||
|
|||
if (!field.Name.IsPropertyName()) |
|||
{ |
|||
error(new ValidationError("Name must be a valid property name.", $"{prefix}.{nameof(field.Name)}")); |
|||
} |
|||
|
|||
if (field.Properties == null) |
|||
{ |
|||
error(new ValidationError("Properties must be defined.", $"{prefix}.{nameof(field.Properties)}")); |
|||
} |
|||
|
|||
var propertyErrors = FieldPropertiesValidator.Validate(field.Properties); |
|||
|
|||
foreach (var propertyError in propertyErrors) |
|||
{ |
|||
error(propertyError); |
|||
} |
|||
} |
|||
|
|||
if (command.Fields.Select(x => x.Name).Distinct().Count() != command.Fields.Count) |
|||
{ |
|||
error(new ValidationError("Fields cannot have duplicate names.", nameof(command.Fields))); |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public static void CanReorder(Schema schema, ReorderFields command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
Validate.It(() => "Cannot reorder schema fields.", error => |
|||
{ |
|||
if (command.FieldIds == null) |
|||
{ |
|||
error(new ValidationError("Field ids must be specified.", nameof(command.FieldIds))); |
|||
} |
|||
|
|||
if (command.FieldIds.Count != schema.Fields.Count || command.FieldIds.Any(x => !schema.FieldsById.ContainsKey(x))) |
|||
{ |
|||
error(new ValidationError("Ids must cover all fields.", nameof(command.FieldIds))); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public static void CanPublish(Schema schema, PublishSchema command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
if (schema.IsPublished) |
|||
{ |
|||
throw new DomainException("Schema is already published."); |
|||
} |
|||
} |
|||
|
|||
public static void CanUnpublish(Schema schema, UnpublishSchema command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
if (!schema.IsPublished) |
|||
{ |
|||
throw new DomainException("Schema is not published."); |
|||
} |
|||
} |
|||
|
|||
public static void CanUpdate(Schema schema, UpdateSchema command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
} |
|||
|
|||
public static void CanConfigureScripts(Schema schema, ConfigureScripts command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
} |
|||
|
|||
public static void CanDelete(Schema schema, DeleteSchema command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,160 @@ |
|||
// ==========================================================================
|
|||
// SchemaFieldGuard.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; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas.Guards |
|||
{ |
|||
public static class GuardSchemaField |
|||
{ |
|||
public static void CanAdd(Schema schema, AddField command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
Validate.It(() => "Cannot add a new field.", error => |
|||
{ |
|||
if (!command.Partitioning.IsValidPartitioning()) |
|||
{ |
|||
error(new ValidationError("Partitioning is not valid.", nameof(command.Partitioning))); |
|||
} |
|||
|
|||
if (!command.Name.IsPropertyName()) |
|||
{ |
|||
error(new ValidationError("Name must be a valid property name.", nameof(command.Name))); |
|||
} |
|||
|
|||
if (command.Properties == null) |
|||
{ |
|||
error(new ValidationError("Properties must be defined.", nameof(command.Properties))); |
|||
} |
|||
|
|||
var propertyErrors = FieldPropertiesValidator.Validate(command.Properties); |
|||
|
|||
foreach (var propertyError in propertyErrors) |
|||
{ |
|||
error(propertyError); |
|||
} |
|||
|
|||
if (schema.FieldsByName.ContainsKey(command.Name)) |
|||
{ |
|||
error(new ValidationError($"There is already a field with name '{command.Name}'", nameof(command.Name))); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public static void CanUpdate(Schema schema, UpdateField command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
Validate.It(() => "Cannot update field.", error => |
|||
{ |
|||
if (command.Properties == null) |
|||
{ |
|||
error(new ValidationError("Properties must be defined.", nameof(command.Properties))); |
|||
} |
|||
|
|||
var propertyErrors = FieldPropertiesValidator.Validate(command.Properties); |
|||
|
|||
foreach (var propertyError in propertyErrors) |
|||
{ |
|||
error(propertyError); |
|||
} |
|||
}); |
|||
|
|||
var field = GetFieldOrThrow(schema, command.FieldId); |
|||
|
|||
if (field.IsLocked) |
|||
{ |
|||
throw new DomainException("Schema field is already locked."); |
|||
} |
|||
} |
|||
|
|||
public static void CanDelete(Schema schema, DeleteField command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
var field = GetFieldOrThrow(schema, command.FieldId); |
|||
|
|||
if (field.IsLocked) |
|||
{ |
|||
throw new DomainException("Schema field is locked."); |
|||
} |
|||
} |
|||
|
|||
public static void CanHide(Schema schema, HideField command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
var field = GetFieldOrThrow(schema, command.FieldId); |
|||
|
|||
if (field.IsHidden) |
|||
{ |
|||
throw new DomainException("Schema field is already hidden."); |
|||
} |
|||
} |
|||
|
|||
public static void CanShow(Schema schema, ShowField command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
var field = GetFieldOrThrow(schema, command.FieldId); |
|||
|
|||
if (!field.IsHidden) |
|||
{ |
|||
throw new DomainException("Schema field is already visible."); |
|||
} |
|||
} |
|||
|
|||
public static void CanDisable(Schema schema, DisableField command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
var field = GetFieldOrThrow(schema, command.FieldId); |
|||
|
|||
if (field.IsDisabled) |
|||
{ |
|||
throw new DomainException("Schema field is already disabled."); |
|||
} |
|||
} |
|||
|
|||
public static void CanEnable(Schema schema, EnableField command) |
|||
{ |
|||
var field = GetFieldOrThrow(schema, command.FieldId); |
|||
|
|||
if (!field.IsDisabled) |
|||
{ |
|||
throw new DomainException("Schema field is already enabled."); |
|||
} |
|||
} |
|||
|
|||
public static void CanLock(Schema schema, LockField command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
var field = GetFieldOrThrow(schema, command.FieldId); |
|||
|
|||
if (field.IsLocked) |
|||
{ |
|||
throw new DomainException("Schema field is already locked."); |
|||
} |
|||
} |
|||
|
|||
private static Field GetFieldOrThrow(Schema schema, long fieldId) |
|||
{ |
|||
if (!schema.FieldsById.TryGetValue(fieldId, out var field)) |
|||
{ |
|||
throw new DomainObjectNotFoundException(fieldId.ToString(), "Fields", typeof(Field)); |
|||
} |
|||
|
|||
return field; |
|||
} |
|||
} |
|||
} |
|||
@ -1,106 +0,0 @@ |
|||
// ==========================================================================
|
|||
// SchemaFieldGuard.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas.Guards |
|||
{ |
|||
public static class SchemaFieldGuard |
|||
{ |
|||
public static void GuardCanAdd(Schema schema, string name) |
|||
{ |
|||
if (schema.FieldsByName.ContainsKey(name)) |
|||
{ |
|||
var error = new ValidationError($"There is already a field with name '{name}'", "Name"); |
|||
|
|||
throw new ValidationException("Cannot add a new field.", error); |
|||
} |
|||
} |
|||
|
|||
public static void GuardCanDelete(Schema schema, long fieldId) |
|||
{ |
|||
var field = GetFieldOrThrow(schema, fieldId); |
|||
|
|||
if (field.IsLocked) |
|||
{ |
|||
throw new DomainException("Schema field is locked."); |
|||
} |
|||
} |
|||
|
|||
public static void GuardCanHide(Schema schema, long fieldId) |
|||
{ |
|||
var field = GetFieldOrThrow(schema, fieldId); |
|||
|
|||
if (field.IsHidden) |
|||
{ |
|||
throw new DomainException("Schema field is already hidden."); |
|||
} |
|||
} |
|||
|
|||
public static void GuardCanShow(Schema schema, long fieldId) |
|||
{ |
|||
var field = GetFieldOrThrow(schema, fieldId); |
|||
|
|||
if (!field.IsHidden) |
|||
{ |
|||
throw new DomainException("Schema field is already visible."); |
|||
} |
|||
} |
|||
|
|||
public static void GuardCanDisable(Schema schema, long fieldId) |
|||
{ |
|||
var field = GetFieldOrThrow(schema, fieldId); |
|||
|
|||
if (field.IsDisabled) |
|||
{ |
|||
throw new DomainException("Schema field is already disabled."); |
|||
} |
|||
} |
|||
|
|||
public static void GuardCanEnable(Schema schema, long fieldId) |
|||
{ |
|||
var field = GetFieldOrThrow(schema, fieldId); |
|||
|
|||
if (!field.IsDisabled) |
|||
{ |
|||
throw new DomainException("Schema field is already enabled."); |
|||
} |
|||
} |
|||
|
|||
public static void GuardCanLock(Schema schema, long fieldId) |
|||
{ |
|||
var field = GetFieldOrThrow(schema, fieldId); |
|||
|
|||
if (field.IsLocked) |
|||
{ |
|||
throw new DomainException("Schema field is already locked."); |
|||
} |
|||
} |
|||
|
|||
public static void GuardCanUpdate(Schema schema, long fieldId) |
|||
{ |
|||
var field = GetFieldOrThrow(schema, fieldId); |
|||
|
|||
if (field.IsLocked) |
|||
{ |
|||
throw new DomainException("Schema field is already locked."); |
|||
} |
|||
} |
|||
|
|||
private static Field GetFieldOrThrow(Schema schema, long fieldId) |
|||
{ |
|||
if (!schema.FieldsById.TryGetValue(fieldId, out var field)) |
|||
{ |
|||
throw new DomainObjectNotFoundException(fieldId.ToString(), "Fields", typeof(Field)); |
|||
} |
|||
|
|||
return field; |
|||
} |
|||
} |
|||
} |
|||
@ -1,44 +0,0 @@ |
|||
// ==========================================================================
|
|||
// SchemaGuard.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.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas.Guards |
|||
{ |
|||
public static class SchemaGuard |
|||
{ |
|||
public static void GuardCanReorder(Schema schema, List<long> fieldIds) |
|||
{ |
|||
if (fieldIds.Count != schema.Fields.Count || fieldIds.Any(x => !schema.FieldsById.ContainsKey(x))) |
|||
{ |
|||
var error = new ValidationError("Ids must cover all fields.", "FieldIds"); |
|||
|
|||
throw new ValidationException("Cannot reorder schema fields.", error); |
|||
} |
|||
} |
|||
|
|||
public static void GuardCanPublish(Schema schema) |
|||
{ |
|||
if (schema.IsPublished) |
|||
{ |
|||
throw new DomainException("Schema is already published."); |
|||
} |
|||
} |
|||
|
|||
public static void GuardCanUnpublish(Schema schema) |
|||
{ |
|||
if (!schema.IsPublished) |
|||
{ |
|||
throw new DomainException("Schema is not published."); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,63 @@ |
|||
// ==========================================================================
|
|||
// GuardWebhook.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Squidex.Domain.Apps.Read.Schemas.Services; |
|||
using Squidex.Domain.Apps.Write.Webhooks.Commands; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Webhooks.Guards |
|||
{ |
|||
public static class GuardWebhook |
|||
{ |
|||
public static Task CanCreate(CreateWebhook command, ISchemaProvider schemas) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
return Validate.It(() => "Cannot create webhook.", error => ValidateCommandAsync(command, error, schemas)); |
|||
} |
|||
|
|||
public static Task CanUpdate(UpdateWebhook command, ISchemaProvider schemas) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
return Validate.It(() => "Cannot update webhook.", error => ValidateCommandAsync(command, error, schemas)); |
|||
} |
|||
|
|||
public static void CanDelete(DeleteWebhook command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
} |
|||
|
|||
private static async Task ValidateCommandAsync(WebhookEditCommand command, Action<ValidationError> error, ISchemaProvider schemas) |
|||
{ |
|||
if (command.Url == null || !command.Url.IsAbsoluteUri) |
|||
{ |
|||
error(new ValidationError("Url must be specified and absolute.", nameof(command.Url))); |
|||
} |
|||
|
|||
if (command.Schemas == null) |
|||
{ |
|||
error(new ValidationError("Schemas cannot be null.", nameof(command.Schemas))); |
|||
} |
|||
|
|||
var schemaErrors = await Task.WhenAll( |
|||
command.Schemas.Select(async s => |
|||
await schemas.FindSchemaByIdAsync(s.SchemaId) == null |
|||
? new ValidationError($"Schema {s.SchemaId} does not exist.", nameof(command.Schemas)) |
|||
: null)); |
|||
|
|||
foreach (var schemaError in schemaErrors.Where(x => x != null)) |
|||
{ |
|||
error(schemaError); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
// ==========================================================================
|
|||
// RefTokenSerializer.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using MongoDB.Bson; |
|||
using MongoDB.Bson.Serialization; |
|||
using MongoDB.Bson.Serialization.Serializers; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Linq; |
|||
|
|||
namespace Squidex.Infrastructure.MongoDb |
|||
{ |
|||
public class JsonBsonSerializer : ClassSerializerBase<object> |
|||
{ |
|||
private readonly JsonSerializer serializer; |
|||
|
|||
public JsonBsonSerializer(JsonSerializer serializer) |
|||
{ |
|||
Guard.NotNull(serializer, nameof(serializer)); |
|||
|
|||
this.serializer = serializer; |
|||
} |
|||
|
|||
protected override object DeserializeValue(BsonDeserializationContext context, BsonDeserializationArgs args) |
|||
{ |
|||
return BsonSerializer.Deserialize<BsonDocument>(context.Reader).ToJson().ToObject(args.NominalType, serializer); |
|||
} |
|||
|
|||
protected override void SerializeValue(BsonSerializationContext context, BsonSerializationArgs args, object value) |
|||
{ |
|||
BsonSerializer.Serialize(context.Writer, JObject.FromObject(value, serializer).ToBson()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// ==========================================================================
|
|||
// TypeNameRegistry.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Squidex.Infrastructure |
|||
{ |
|||
public static class Validate |
|||
{ |
|||
public static void It(Func<string> message, Action<Action<ValidationError>> action) |
|||
{ |
|||
var errors = new List<ValidationError>(); |
|||
|
|||
action(errors.Add); |
|||
|
|||
if (errors.Any()) |
|||
{ |
|||
throw new ValidationException(message(), errors); |
|||
} |
|||
} |
|||
|
|||
public static async Task It(Func<string> message, Func<Action<ValidationError>, Task> action) |
|||
{ |
|||
var errors = new List<ValidationError>(); |
|||
|
|||
await action(errors.Add); |
|||
|
|||
if (errors.Any()) |
|||
{ |
|||
throw new ValidationException(message(), errors); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,330 +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.Apps; |
|||
using Squidex.Domain.Apps.Read.Apps.Repositories; |
|||
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.CQRS.Commands; |
|||
using Squidex.Shared.Users; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Apps |
|||
{ |
|||
public class AppCommandMiddlewareTests : HandlerTestBase<AppDomainObject> |
|||
{ |
|||
private readonly IAppRepository appRepository = A.Fake<IAppRepository>(); |
|||
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); |
|||
|
|||
sut = new AppCommandMiddleware(Handler, appRepository, appPlansProvider, appPlansBillingManager, userResolver); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Create_should_throw_exception_if_a_name_with_same_name_already_exists() |
|||
{ |
|||
var context = CreateContextForCommand(new CreateApp { Name = AppName, AppId = AppId }); |
|||
|
|||
A.CallTo(() => appRepository.FindAppAsync(AppName)) |
|||
.Returns(A.Dummy<IAppEntity>()); |
|||
|
|||
await TestCreate(app, async _ => |
|||
{ |
|||
await Assert.ThrowsAsync<ValidationException>(async () => await sut.HandleAsync(context)); |
|||
}, false); |
|||
|
|||
A.CallTo(() => appRepository.FindAppAsync(AppName)).MustHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Create_should_create_app_if_name_is_free() |
|||
{ |
|||
var context = CreateContextForCommand(new CreateApp { Name = AppName, AppId = AppId }); |
|||
|
|||
A.CallTo(() => appRepository.FindAppAsync(AppName)) |
|||
.Returns((IAppEntity)null); |
|||
|
|||
await TestCreate(app, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
|
|||
Assert.Equal(AppId, context.Result<EntityCreatedResult<Guid>>().IdOrValue); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task AssignContributor_should_throw_exception_if_user_not_found() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
var context = CreateContextForCommand(new AssignContributor { ContributorId = contributorId }); |
|||
|
|||
A.CallTo(() => userResolver.FindByIdAsync(contributorId)) |
|||
.Returns((IUser)null); |
|||
|
|||
await TestUpdate(app, async _ => |
|||
{ |
|||
await Assert.ThrowsAsync<ValidationException>(() => sut.HandleAsync(context)); |
|||
}, false); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task AssignContributor_throw_exception_if_reached_max_contributor_size() |
|||
{ |
|||
A.CallTo(() => appPlansProvider.GetPlan(null)) |
|||
.Returns(new ConfigAppLimitsPlan { MaxContributors = 2 }); |
|||
|
|||
CreateApp() |
|||
.AssignContributor(CreateCommand(new AssignContributor { ContributorId = "1" })) |
|||
.AssignContributor(CreateCommand(new AssignContributor { ContributorId = "2" })); |
|||
|
|||
var context = CreateContextForCommand(new AssignContributor { ContributorId = contributorId }); |
|||
|
|||
A.CallTo(() => userResolver.FindByIdAsync(A<string>.Ignored)) |
|||
.Returns(A.Dummy<IUser>()); |
|||
|
|||
await TestUpdate(app, async _ => |
|||
{ |
|||
await Assert.ThrowsAsync<ValidationException>(() => sut.HandleAsync(context)); |
|||
}, false); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task AssignContributor_should_throw_exception_if_null_user_not_found() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
var context = CreateContextForCommand(new AssignContributor { ContributorId = contributorId }); |
|||
|
|||
A.CallTo(() => userResolver.FindByIdAsync(contributorId)) |
|||
.Returns((IUser)null); |
|||
|
|||
await TestUpdate(app, async _ => |
|||
{ |
|||
await Assert.ThrowsAsync<ValidationException>(() => sut.HandleAsync(context)); |
|||
}, false); |
|||
} |
|||
|
|||
[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 }); |
|||
|
|||
A.CallTo(() => userResolver.FindByIdAsync(contributorId)) |
|||
.Returns(A.Dummy<IUser>()); |
|||
|
|||
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 ChangePlan_should_throw_if_plan_not_found() |
|||
{ |
|||
A.CallTo(() => appPlansProvider.IsConfiguredPlan("my-plan")) |
|||
.Returns(false); |
|||
|
|||
CreateApp() |
|||
.AttachClient(CreateCommand(new AttachClient { Id = clientName })); |
|||
|
|||
var context = CreateContextForCommand(new ChangePlan { PlanId = "my-plan" }); |
|||
|
|||
await TestUpdate(app, async _ => |
|||
{ |
|||
await Assert.ThrowsAsync<ValidationException>(() => sut.HandleAsync(context)); |
|||
}, false); |
|||
} |
|||
|
|||
[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.PlanId); |
|||
} |
|||
|
|||
[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,597 +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.CQRS; |
|||
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_throw_exception_if_command_is_not_valid() |
|||
{ |
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.Create(CreateCommand(new CreateApp())); |
|||
}); |
|||
} |
|||
|
|||
[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_throw_exception_if_command_is_not_valid() |
|||
{ |
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.ChangePlan(CreateCommand(new ChangePlan())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ChangePlan_should_throw_exception_if_plan_configured_from_other_user() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
sut.ChangePlan(CreateCommand(new ChangePlan { PlanId = "other-plan", Actor = new RefToken("User", "other") })); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.ChangePlan(CreateCommand(new ChangePlan { PlanId = planId })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ChangePlan_should_throw_exception_if_same_plan() |
|||
{ |
|||
CreateApp(); |
|||
sut.ChangePlan(CreateCommand(new ChangePlan { PlanId = planId })); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
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_throw_exception_if_command_is_not_valid() |
|||
{ |
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.AssignContributor(CreateCommand(new AssignContributor { Permission = (AppContributorPermission)123 })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void AssignContributor_should_throw_exception_if_single_owner_becomes_non_owner() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = User.Identifier, Permission = AppContributorPermission.Editor })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void AssignContributor_should_throw_exception_if_user_already_contributor() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId, Permission = AppContributorPermission.Editor })); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId, Permission = AppContributorPermission.Editor })); |
|||
}); |
|||
} |
|||
|
|||
[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_throw_exception_if_command_is_not_valid() |
|||
{ |
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.RemoveContributor(CreateCommand(new RemoveContributor())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void RemoveContributor_should_throw_exception_if_all_owners_removed() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.RemoveContributor(CreateCommand(new RemoveContributor { ContributorId = User.Identifier })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void RemoveContributor_should_throw_exception_if_contributor_not_found() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => |
|||
{ |
|||
sut.RemoveContributor(CreateCommand(new RemoveContributor { ContributorId = "not-found" })); |
|||
}); |
|||
} |
|||
|
|||
[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_throw_exception_if_command_is_not_valid() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.AttachClient(CreateCommand(new AttachClient())); |
|||
}); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.AttachClient(CreateCommand(new AttachClient { Id = string.Empty })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void AttachClient_should_throw_exception_if_id_already_exists() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
sut.AttachClient(CreateCommand(new AttachClient { Id = clientId })); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
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_throw_exception_if_command_is_not_valid() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.RevokeClient(CreateCommand(new RevokeClient())); |
|||
}); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.RevokeClient(CreateCommand(new RevokeClient { Id = string.Empty })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void RevokeClient_should_throw_exception_if_client_not_found() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => |
|||
{ |
|||
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_throw_exception_if_command_is_not_valid() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.UpdateClient(CreateCommand(new UpdateClient())); |
|||
}); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.UpdateClient(CreateCommand(new UpdateClient { Id = string.Empty })); |
|||
}); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.UpdateClient(CreateCommand(new UpdateClient { Permission = (AppClientPermission)int.MaxValue })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateClient_should_throw_exception_if_client_not_found() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => |
|||
{ |
|||
sut.UpdateClient(CreateCommand(new UpdateClient { Id = "not-found", Name = clientNewName })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateClient_should_throw_exception_if_client_has_same_reader_state() |
|||
{ |
|||
CreateApp(); |
|||
CreateClient(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.UpdateClient(CreateCommand(new UpdateClient { Id = clientId, Permission = AppClientPermission.Editor })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateClient_should_throw_exception_if_same_client_name() |
|||
{ |
|||
CreateApp(); |
|||
CreateClient(); |
|||
|
|||
sut.UpdateClient(CreateCommand(new UpdateClient { Id = clientId, Name = clientNewName })); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.UpdateClient(CreateCommand(new UpdateClient { Id = clientId, 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_throw_exception_if_command_is_not_valid() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.AddLanguage(CreateCommand(new AddLanguage())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void AddLanguage_should_throw_exception_if_language_already_exists() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.AddLanguage(CreateCommand(new AddLanguage { Language = Language.EN })); |
|||
}); |
|||
} |
|||
|
|||
[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_throw_exception_if_command_is_not_valid() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.RemoveLanguage(CreateCommand(new RemoveLanguage())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void RemoveLanguage_should_throw_exception_if_language_not_found() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => |
|||
{ |
|||
sut.RemoveLanguage(CreateCommand(new RemoveLanguage { Language = Language.DE })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void RemoveLanguage_should_throw_exception_if_master_language() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
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_throw_exception_if_command_is_not_valid() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.UpdateLanguage(CreateCommand(new UpdateLanguage())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateLanguage_should_throw_exception_if_language_not_found() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => |
|||
{ |
|||
sut.UpdateLanguage(CreateCommand(new UpdateLanguage { Language = Language.DE })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateLanguage_should_throw_exception_if_master_language() |
|||
{ |
|||
CreateApp(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.UpdateLanguage(CreateCommand(new UpdateLanguage { Language = Language.EN, IsOptional = true })); |
|||
}); |
|||
} |
|||
|
|||
[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,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.CQRS.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_asset() |
|||
{ |
|||
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,235 +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.CQRS; |
|||
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_throw_exception_if_command_is_not_valid() |
|||
{ |
|||
CreateAsset(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.Rename(CreateAssetCommand(new RenameAsset())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rename_should_throw_exception_if_new_name_is_equal_to_old_name() |
|||
{ |
|||
CreateAsset(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.Rename(CreateAssetCommand(new RenameAsset { FileName = file.FileName })); |
|||
}); |
|||
} |
|||
|
|||
[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,240 +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.Contents; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Core.Scripting; |
|||
using Squidex.Domain.Apps.Read.Apps; |
|||
using Squidex.Domain.Apps.Read.Apps.Services; |
|||
using Squidex.Domain.Apps.Read.Assets.Repositories; |
|||
using Squidex.Domain.Apps.Read.Contents.Repositories; |
|||
using Squidex.Domain.Apps.Read.Schemas; |
|||
using Squidex.Domain.Apps.Read.Schemas.Services; |
|||
using Squidex.Domain.Apps.Write.Contents.Commands; |
|||
using Squidex.Domain.Apps.Write.TestHelpers; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.CQRS.Commands; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Contents |
|||
{ |
|||
public class ContentCommandMiddlewareTests : HandlerTestBase<ContentDomainObject> |
|||
{ |
|||
private readonly ContentCommandMiddleware sut; |
|||
private readonly ContentDomainObject content; |
|||
private readonly ISchemaProvider schemas = A.Fake<ISchemaProvider>(); |
|||
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.Create(Language.DE); |
|||
private readonly Guid contentId = Guid.NewGuid(); |
|||
|
|||
private readonly NamedContentData invalidData = |
|||
new NamedContentData() |
|||
.AddField("my-field", new ContentFieldData() |
|||
.SetValue(null)); |
|||
private readonly NamedContentData data = |
|||
new NamedContentData() |
|||
.AddField("my-field", new ContentFieldData() |
|||
.SetValue(1)); |
|||
|
|||
public ContentCommandMiddlewareTests() |
|||
{ |
|||
var schemaDef = |
|||
Schema.Create("my-schema", new SchemaProperties()) |
|||
.AddField(new NumberField(1, "my-field", Partitioning.Invariant, |
|||
new NumberFieldProperties { IsRequired = true })); |
|||
|
|||
content = new ContentDomainObject(contentId, -1); |
|||
|
|||
sut = new ContentCommandMiddleware(Handler, appProvider, A.Dummy<IAssetRepository>(), schemas, scriptEngine, A.Dummy<IContentRepository>()); |
|||
|
|||
A.CallTo(() => app.LanguagesConfig).Returns(languagesConfig); |
|||
A.CallTo(() => app.PartitionResolver).Returns(languagesConfig.ToResolver()); |
|||
|
|||
A.CallTo(() => appProvider.FindAppByIdAsync(AppId)).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(() => schemas.FindSchemaByIdAsync(SchemaId, false)).Returns(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); |
|||
|
|||
var patch = new NamedContentData().AddField("my-field", new ContentFieldData().SetValue(3)); |
|||
|
|||
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,323 +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.CQRS; |
|||
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_throw_exception_if_command_is_not_valid() |
|||
{ |
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.Create(CreateContentCommand(new CreateContent())); |
|||
}); |
|||
} |
|||
|
|||
[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<ValidationException>(() => |
|||
{ |
|||
sut.Update(CreateContentCommand(new UpdateContent())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_throw_exception_if_command_is_not_valid() |
|||
{ |
|||
CreateContent(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
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<ValidationException>(() => |
|||
{ |
|||
sut.Patch(CreateContentCommand(new PatchContent())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Patch_should_throw_exception_if_command_is_not_valid() |
|||
{ |
|||
CreateContent(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
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_throw_exception_if_status_flow_not_valid() |
|||
{ |
|||
CreateContent(); |
|||
ChangeStatus(Status.Archived); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.ChangeStatus(CreateContentCommand(new ChangeContentStatus { Status = Status.Published })); |
|||
}); |
|||
} |
|||
|
|||
[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_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,139 +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.CQRS.Events; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Contents |
|||
{ |
|||
public class ContentVersionLoaderTests |
|||
{ |
|||
private readonly IEventStore eventStore = A.Fake<IEventStore>(); |
|||
private readonly IStreamNameResolver nameResolver = A.Fake<IStreamNameResolver>(); |
|||
private readonly EventDataFormatter formatter = A.Fake<EventDataFormatter>(); |
|||
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)) |
|||
.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)) |
|||
.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)) |
|||
.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)) |
|||
.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)) |
|||
.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)) |
|||
.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); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,234 @@ |
|||
// ==========================================================================
|
|||
// 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.Domain.Apps.Write.Schemas.Guards; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas |
|||
{ |
|||
public class GuardSchemaFieldTests |
|||
{ |
|||
private readonly Schema schema = new Schema("my-schema"); |
|||
|
|||
public GuardSchemaFieldTests() |
|||
{ |
|||
schema.AddField(new StringField(1, "field1", Partitioning.Invariant)); |
|||
schema.AddField(new StringField(2, "field2", Partitioning.Invariant)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanHide_should_throw_exception_if_already_hidden() |
|||
{ |
|||
var command = new HideField { FieldId = 1 }; |
|||
|
|||
schema.FieldsById[1].Hide(); |
|||
|
|||
Assert.Throws<DomainException>(() => GuardSchemaField.CanHide(schema, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanHide_should_throw_exception_if_not_found() |
|||
{ |
|||
var command = new HideField { FieldId = 3 }; |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanHide(schema, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanHide_hould_not_throw_exception_if_visible() |
|||
{ |
|||
var command = new HideField { FieldId = 1 }; |
|||
|
|||
GuardSchemaField.CanHide(schema, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanDisable_should_throw_exception_if_already_disabled() |
|||
{ |
|||
var command = new DisableField { FieldId = 1 }; |
|||
|
|||
schema.FieldsById[1].Disable(); |
|||
|
|||
Assert.Throws<DomainException>(() => GuardSchemaField.CanDisable(schema, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanDisable_should_throw_exception_if_not_found() |
|||
{ |
|||
var command = new DisableField { FieldId = 3 }; |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanDisable(schema, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanDisable_Should_not_throw_exception_if_enabled() |
|||
{ |
|||
var command = new DisableField { FieldId = 1 }; |
|||
|
|||
GuardSchemaField.CanDisable(schema, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanShow_should_throw_exception_if_already_shown() |
|||
{ |
|||
var command = new ShowField { FieldId = 1 }; |
|||
|
|||
Assert.Throws<DomainException>(() => GuardSchemaField.CanShow(schema, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanShow_should_throw_exception_if_not_found() |
|||
{ |
|||
var command = new ShowField { FieldId = 3 }; |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanShow(schema, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanShow_should_not_throw_exception_if_hidden() |
|||
{ |
|||
var command = new ShowField { FieldId = 1 }; |
|||
|
|||
schema.FieldsById[1].Hide(); |
|||
|
|||
GuardSchemaField.CanShow(schema, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanEnable_should_throw_exception_if_already_enabled() |
|||
{ |
|||
var command = new EnableField { FieldId = 1 }; |
|||
|
|||
Assert.Throws<DomainException>(() => GuardSchemaField.CanEnable(schema, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanEnable_should_throw_exception_if_not_found() |
|||
{ |
|||
var command = new EnableField { FieldId = 3 }; |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanEnable(schema, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanEnable_should_not_throw_exception_if_disabled() |
|||
{ |
|||
var command = new EnableField { FieldId = 1 }; |
|||
|
|||
schema.FieldsById[1].Disable(); |
|||
|
|||
GuardSchemaField.CanEnable(schema, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanLock_should_throw_exception_if_already_locked() |
|||
{ |
|||
var command = new LockField { FieldId = 1 }; |
|||
|
|||
schema.FieldsById[1].Lock(); |
|||
|
|||
Assert.Throws<DomainException>(() => GuardSchemaField.CanLock(schema, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void LockField_should_throw_exception_if_not_found() |
|||
{ |
|||
var command = new LockField { FieldId = 3 }; |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanLock(schema, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanLock_should_not_throw_exception_if_not_locked() |
|||
{ |
|||
var command = new LockField { FieldId = 1 }; |
|||
|
|||
GuardSchemaField.CanLock(schema, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanDelete_should_throw_exception_if_not_found() |
|||
{ |
|||
var command = new DeleteField { FieldId = 3 }; |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanDelete(schema, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanDelete_should_throw_exception_if_locked() |
|||
{ |
|||
var command = new DeleteField { FieldId = 1 }; |
|||
|
|||
schema.FieldsById[1].Lock(); |
|||
|
|||
Assert.Throws<DomainException>(() => GuardSchemaField.CanDelete(schema, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanDelete_should_not_throw_exception_if_not_locked() |
|||
{ |
|||
var command = new DeleteField { FieldId = 1 }; |
|||
|
|||
GuardSchemaField.CanDelete(schema, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUpdate_should_throw_exception_if_locked() |
|||
{ |
|||
var command = new UpdateField { FieldId = 1, Properties = new StringFieldProperties() }; |
|||
|
|||
schema.FieldsById[1].Lock(); |
|||
|
|||
Assert.Throws<DomainException>(() => GuardSchemaField.CanUpdate(schema, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUpdate_should_not_throw_exception_if_not_locked() |
|||
{ |
|||
var command = new UpdateField { FieldId = 1, Properties = new StringFieldProperties() }; |
|||
|
|||
GuardSchemaField.CanUpdate(schema, 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, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanAdd_should_throw_exception_if_name_not_valid() |
|||
{ |
|||
var command = new AddField { Name = "INVALID_NAME", Properties = new StringFieldProperties() }; |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardSchemaField.CanAdd(schema, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanAdd_should_throw_exception_if_properties_not_valid() |
|||
{ |
|||
var command = new AddField { Name = "field3", Properties = new StringFieldProperties { MinLength = 10, MaxLength = 5 } }; |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardSchemaField.CanAdd(schema, 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, command); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,197 @@ |
|||
// ==========================================================================
|
|||
// 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.Schemas; |
|||
using Squidex.Domain.Apps.Read.Schemas.Services; |
|||
using Squidex.Domain.Apps.Write.Schemas.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas.Guards |
|||
{ |
|||
public class GuardSchemaTests |
|||
{ |
|||
private readonly ISchemaProvider schemas = A.Fake<ISchemaProvider>(); |
|||
private readonly Schema schema = new Schema("my-schema"); |
|||
private readonly NamedId<Guid> appId = new NamedId<Guid>(Guid.NewGuid(), "my-app"); |
|||
|
|||
public GuardSchemaTests() |
|||
{ |
|||
schema.AddField(new StringField(1, "field1", Partitioning.Invariant)); |
|||
schema.AddField(new StringField(2, "field2", Partitioning.Invariant)); |
|||
|
|||
A.CallTo(() => schemas.FindSchemaByNameAsync(A<Guid>.Ignored, "new-schema")) |
|||
.Returns(Task.FromResult<ISchemaEntity>(null)); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task CanCreate_should_throw_exception_if_name_not_valid() |
|||
{ |
|||
var command = new CreateSchema { AppId = appId, Name = "INVALID NAME" }; |
|||
|
|||
await Assert.ThrowsAsync<ValidationException>(() => GuardSchema.CanCreate(command, schemas)); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task CanCreate_should_throw_exception_if_name_already_in_use() |
|||
{ |
|||
A.CallTo(() => schemas.FindSchemaByNameAsync(A<Guid>.Ignored, "new-schema")) |
|||
.Returns(Task.FromResult(A.Fake<ISchemaEntity>())); |
|||
|
|||
var command = new CreateSchema { AppId = appId, Name = "new-schema" }; |
|||
|
|||
await Assert.ThrowsAsync<ValidationException>(() => GuardSchema.CanCreate(command, schemas)); |
|||
} |
|||
|
|||
[Fact] |
|||
public async 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" |
|||
}; |
|||
|
|||
await Assert.ThrowsAsync<ValidationException>(() => GuardSchema.CanCreate(command, schemas)); |
|||
} |
|||
|
|||
[Fact] |
|||
public async 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" |
|||
}; |
|||
|
|||
await Assert.ThrowsAsync<ValidationException>(() => GuardSchema.CanCreate(command, schemas)); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task CanCreate_should_not_throw_exception_if_command_is_valid() |
|||
{ |
|||
var command = new CreateSchema { AppId = appId, Name = "new-schema" }; |
|||
|
|||
await GuardSchema.CanCreate(command, schemas); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanPublish_should_throw_exception_if_already_published() |
|||
{ |
|||
var command = new PublishSchema(); |
|||
|
|||
schema.Publish(); |
|||
|
|||
Assert.Throws<DomainException>(() => GuardSchema.CanPublish(schema, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanPublish_should_not_throw_exception_if_not_published() |
|||
{ |
|||
var command = new PublishSchema(); |
|||
|
|||
GuardSchema.CanPublish(schema, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUnpublish_should_throw_exception_if_already_unpublished() |
|||
{ |
|||
var command = new UnpublishSchema(); |
|||
|
|||
Assert.Throws<DomainException>(() => GuardSchema.CanUnpublish(schema, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUnpublish_should_not_throw_exception_if_already_published() |
|||
{ |
|||
var command = new UnpublishSchema(); |
|||
|
|||
schema.Publish(); |
|||
|
|||
GuardSchema.CanUnpublish(schema, 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, 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, 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, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanDelete_should_not_throw_exception() |
|||
{ |
|||
var command = new DeleteSchema(); |
|||
|
|||
GuardSchema.CanDelete(schema, command); |
|||
} |
|||
|
|||
private static StringFieldProperties ValidProperties() |
|||
{ |
|||
return new StringFieldProperties { MinLength = 10, MaxLength = 20 }; |
|||
} |
|||
|
|||
private static StringFieldProperties InvalidProperties() |
|||
{ |
|||
return new StringFieldProperties { MinLength = 20, MaxLength = 10 }; |
|||
} |
|||
} |
|||
} |
|||
@ -1,169 +0,0 @@ |
|||
// ==========================================================================
|
|||
// SchemaFieldGuardTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas.Guards |
|||
{ |
|||
public class SchemaFieldGuardTests |
|||
{ |
|||
private Schema schema = |
|||
Schema.Create("my-schema", new SchemaProperties()) |
|||
.AddField(new StringField(1, "field1", Partitioning.Invariant)) |
|||
.AddField(new StringField(2, "field2", Partitioning.Invariant)); |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_field_to_hide_already_hidden() |
|||
{ |
|||
schema = schema.HideField(1); |
|||
|
|||
Assert.Throws<DomainException>(() => SchemaFieldGuard.GuardCanHide(schema, 1)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_field_to_hide_not_found() |
|||
{ |
|||
Assert.Throws<DomainObjectNotFoundException>(() => SchemaFieldGuard.GuardCanHide(schema, 3)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_not_throw_exception_if_field_to_hide_shown() |
|||
{ |
|||
SchemaFieldGuard.GuardCanHide(schema, 1); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_field_to_disable_not_found() |
|||
{ |
|||
Assert.Throws<DomainObjectNotFoundException>(() => SchemaFieldGuard.GuardCanDisable(schema, 3)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_field_to_disable_already_disabled() |
|||
{ |
|||
schema = schema.DisableField(1); |
|||
|
|||
Assert.Throws<DomainException>(() => SchemaFieldGuard.GuardCanDisable(schema, 1)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_not_throw_exception_if_field_to_disable_shown() |
|||
{ |
|||
SchemaFieldGuard.GuardCanDisable(schema, 1); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_field_to_show_already_shown() |
|||
{ |
|||
Assert.Throws<DomainException>(() => SchemaFieldGuard.GuardCanShow(schema, 1)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_field_to_show_not_found() |
|||
{ |
|||
Assert.Throws<DomainObjectNotFoundException>(() => SchemaFieldGuard.GuardCanShow(schema, 3)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_not_throw_exception_if_field_to_show_hidden() |
|||
{ |
|||
schema = schema.HideField(1); |
|||
|
|||
SchemaFieldGuard.GuardCanShow(schema, 1); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_field_to_enable_already_enabled() |
|||
{ |
|||
Assert.Throws<DomainException>(() => SchemaFieldGuard.GuardCanEnable(schema, 1)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_field_to_enable_not_found() |
|||
{ |
|||
Assert.Throws<DomainObjectNotFoundException>(() => SchemaFieldGuard.GuardCanEnable(schema, 3)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_not_throw_exception_if_field_to_enable_disabled() |
|||
{ |
|||
schema = schema.DisableField(1); |
|||
|
|||
SchemaFieldGuard.GuardCanEnable(schema, 1); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_field_to_lock_already_locked() |
|||
{ |
|||
schema = schema.LockField(1); |
|||
|
|||
Assert.Throws<DomainException>(() => SchemaFieldGuard.GuardCanLock(schema, 1)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_field_to_lock_not_found() |
|||
{ |
|||
Assert.Throws<DomainObjectNotFoundException>(() => SchemaFieldGuard.GuardCanLock(schema, 3)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_not_throw_exception_if_field_to_lock_not_locked() |
|||
{ |
|||
SchemaFieldGuard.GuardCanLock(schema, 1); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_field_to_delete_not_found() |
|||
{ |
|||
Assert.Throws<DomainObjectNotFoundException>(() => SchemaFieldGuard.GuardCanDelete(schema, 3)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_field_to_delete_is_locked() |
|||
{ |
|||
schema = schema.LockField(1); |
|||
|
|||
Assert.Throws<DomainException>(() => SchemaFieldGuard.GuardCanDelete(schema, 1)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_field_to_update_not_locked() |
|||
{ |
|||
SchemaFieldGuard.GuardCanUpdate(schema, 1); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_field_to_update_is_locked() |
|||
{ |
|||
schema = schema.LockField(1); |
|||
|
|||
Assert.Throws<DomainException>(() => SchemaFieldGuard.GuardCanUpdate(schema, 1)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_field_to_delete_not_locked() |
|||
{ |
|||
SchemaFieldGuard.GuardCanDelete(schema, 1); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_field_to_add_already_exists() |
|||
{ |
|||
Assert.Throws<ValidationException>(() => SchemaFieldGuard.GuardCanAdd(schema, "field1")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_not_throw_exception_if_field_to_add_not_exists() |
|||
{ |
|||
SchemaFieldGuard.GuardCanAdd(schema, "field3"); |
|||
} |
|||
} |
|||
} |
|||
@ -1,65 +0,0 @@ |
|||
// ==========================================================================
|
|||
// SchemaGuardTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using Squidex.Domain.Apps.Core; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Schemas.Guards |
|||
{ |
|||
public class SchemaGuardTests |
|||
{ |
|||
private Schema schema = |
|||
Schema.Create("my-schema", new SchemaProperties()) |
|||
.AddField(new StringField(1, "field1", Partitioning.Invariant)) |
|||
.AddField(new StringField(2, "field2", Partitioning.Invariant)); |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_schema_to_publish_already_published() |
|||
{ |
|||
schema = schema.Publish(); |
|||
|
|||
Assert.Throws<DomainException>(() => SchemaGuard.GuardCanPublish(schema)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_not_throw_exception_if_schema_to_publish_not_published() |
|||
{ |
|||
SchemaGuard.GuardCanPublish(schema); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_schema_to_unpublish_already_unpublished() |
|||
{ |
|||
Assert.Throws<DomainException>(() => SchemaGuard.GuardCanUnpublish(schema)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_not_throw_exception_if_schema_to_unpublish_published() |
|||
{ |
|||
schema = schema.Publish(); |
|||
|
|||
SchemaGuard.GuardCanUnpublish(schema); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_excepotion_if_schema_fields_to_reorder_not_valid() |
|||
{ |
|||
Assert.Throws<ValidationException>(() => SchemaGuard.GuardCanReorder(schema, new List<long> { 1 })); |
|||
Assert.Throws<ValidationException>(() => SchemaGuard.GuardCanReorder(schema, new List<long> { 1, 3 })); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_not_throw_excepotion_if_schema_fields_to_reorder_are_valid() |
|||
{ |
|||
SchemaGuard.GuardCanReorder(schema, new List<long> { 1, 2 }); |
|||
} |
|||
} |
|||
} |
|||
@ -1,130 +0,0 @@ |
|||
// ==========================================================================
|
|||
// WebhookCommandMiddlewareTests.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.Webhooks; |
|||
using Squidex.Domain.Apps.Read.Schemas; |
|||
using Squidex.Domain.Apps.Read.Schemas.Services; |
|||
using Squidex.Domain.Apps.Write.TestHelpers; |
|||
using Squidex.Domain.Apps.Write.Webhooks.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.CQRS.Commands; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Webhooks |
|||
{ |
|||
public class WebhookCommandMiddlewareTests : HandlerTestBase<WebhookDomainObject> |
|||
{ |
|||
private readonly ISchemaProvider schemas = A.Fake<ISchemaProvider>(); |
|||
private readonly WebhookCommandMiddleware sut; |
|||
private readonly WebhookDomainObject webhook; |
|||
private readonly Uri url = new Uri("http://squidex.io"); |
|||
private readonly Guid schemaId = Guid.NewGuid(); |
|||
private readonly Guid webhookId = Guid.NewGuid(); |
|||
private readonly List<WebhookSchema> webhookSchemas; |
|||
|
|||
public WebhookCommandMiddlewareTests() |
|||
{ |
|||
webhook = new WebhookDomainObject(webhookId, -1); |
|||
|
|||
webhookSchemas = new List<WebhookSchema> |
|||
{ |
|||
new WebhookSchema { SchemaId = schemaId } |
|||
}; |
|||
|
|||
sut = new WebhookCommandMiddleware(Handler, schemas); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Create_should_create_webhook() |
|||
{ |
|||
var context = CreateContextForCommand(new CreateWebhook { Schemas = webhookSchemas, Url = url, WebhookId = webhookId }); |
|||
|
|||
A.CallTo(() => schemas.FindSchemaByIdAsync(schemaId, false)).Returns(A.Fake<ISchemaEntity>()); |
|||
|
|||
await TestCreate(webhook, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
|
|||
A.CallTo(() => schemas.FindSchemaByIdAsync(schemaId, false)).MustHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Create_should_throw_exception_when_schema_is_not_found() |
|||
{ |
|||
var context = CreateContextForCommand(new CreateWebhook { Schemas = webhookSchemas, Url = url, WebhookId = webhookId }); |
|||
|
|||
A.CallTo(() => schemas.FindSchemaByIdAsync(schemaId, false)).Returns((ISchemaEntity)null); |
|||
|
|||
await Assert.ThrowsAsync<ValidationException>(async () => |
|||
{ |
|||
await TestCreate(webhook, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Update_should_update_domain_object() |
|||
{ |
|||
var context = CreateContextForCommand(new UpdateWebhook { Schemas = webhookSchemas, Url = url, WebhookId = webhookId }); |
|||
|
|||
A.CallTo(() => schemas.FindSchemaByIdAsync(schemaId, false)).Returns(A.Fake<ISchemaEntity>()); |
|||
|
|||
CreateWebhook(); |
|||
|
|||
await TestUpdate(webhook, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
|
|||
A.CallTo(() => schemas.FindSchemaByIdAsync(schemaId, false)).MustHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Update_should_throw_exception_when_schema_is_not_found() |
|||
{ |
|||
var context = CreateContextForCommand(new UpdateWebhook { Schemas = webhookSchemas, Url = url, WebhookId = webhookId }); |
|||
|
|||
A.CallTo(() => schemas.FindSchemaByIdAsync(schemaId, false)).Returns((ISchemaEntity)null); |
|||
|
|||
CreateWebhook(); |
|||
|
|||
await Assert.ThrowsAsync<ValidationException>(async () => |
|||
{ |
|||
await TestCreate(webhook, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Delete_should_update_domain_object() |
|||
{ |
|||
CreateWebhook(); |
|||
|
|||
var command = CreateContextForCommand(new DeleteWebhook { WebhookId = webhookId }); |
|||
|
|||
await TestUpdate(webhook, async _ => |
|||
{ |
|||
await sut.HandleAsync(command); |
|||
}); |
|||
} |
|||
|
|||
private void CreateWebhook() |
|||
{ |
|||
webhook.Create(new CreateWebhook { Url = url }); |
|||
} |
|||
} |
|||
} |
|||
@ -1,179 +0,0 @@ |
|||
// ==========================================================================
|
|||
// WebhookDomainObjectTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Squidex.Domain.Apps.Events.Webhooks; |
|||
using Squidex.Domain.Apps.Write.TestHelpers; |
|||
using Squidex.Domain.Apps.Write.Webhooks.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.CQRS; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Webhooks |
|||
{ |
|||
public class WebhookDomainObjectTests : HandlerTestBase<WebhookDomainObject> |
|||
{ |
|||
private readonly Uri url = new Uri("http://squidex.io"); |
|||
private readonly WebhookDomainObject sut; |
|||
|
|||
public Guid WebhookId { get; } = Guid.NewGuid(); |
|||
|
|||
public WebhookDomainObjectTests() |
|||
{ |
|||
sut = new WebhookDomainObject(WebhookId, 0); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_throw_exception_if_created() |
|||
{ |
|||
sut.Create(new CreateWebhook { Url = url }); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Create(CreateWebhookCommand(new CreateWebhook { Url = url })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_throw_exception_if_command_is_not_valid() |
|||
{ |
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.Create(CreateWebhookCommand(new CreateWebhook { Url = new Uri("/invalid", UriKind.Relative) })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_create_events() |
|||
{ |
|||
var command = new CreateWebhook { Url = url }; |
|||
|
|||
sut.Create(CreateWebhookCommand(command)); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateWebhookEvent(new WebhookCreated |
|||
{ |
|||
Url = url, |
|||
Schemas = command.Schemas, |
|||
SharedSecret = command.SharedSecret, |
|||
WebhookId = command.WebhookId |
|||
}) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Update(CreateWebhookCommand(new UpdateWebhook { Url = url })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_throw_exception_if_webhook_is_deleted() |
|||
{ |
|||
CreateWebhook(); |
|||
DeleteWebhook(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Update(CreateWebhookCommand(new UpdateWebhook { Url = url })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_throw_exception_if_command_is_not_valid() |
|||
{ |
|||
CreateWebhook(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.Update(CreateWebhookCommand(new UpdateWebhook { Url = new Uri("/invalid", UriKind.Relative) })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_create_events() |
|||
{ |
|||
CreateWebhook(); |
|||
|
|||
var command = new UpdateWebhook { Url = url }; |
|||
|
|||
sut.Update(CreateWebhookCommand(command)); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateWebhookEvent(new WebhookUpdated { Url = url, Schemas = command.Schemas }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Delete_should_throw_exception_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Delete(CreateWebhookCommand(new DeleteWebhook())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Delete_should_throw_exception_if_already_deleted() |
|||
{ |
|||
CreateWebhook(); |
|||
DeleteWebhook(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Delete(CreateWebhookCommand(new DeleteWebhook())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Delete_should_update_properties_create_events() |
|||
{ |
|||
CreateWebhook(); |
|||
|
|||
sut.Delete(CreateWebhookCommand(new DeleteWebhook())); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateWebhookEvent(new WebhookDeleted()) |
|||
); |
|||
} |
|||
|
|||
private void CreateWebhook() |
|||
{ |
|||
sut.Create(CreateWebhookCommand(new CreateWebhook { Url = url })); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
|
|||
private void DeleteWebhook() |
|||
{ |
|||
sut.Delete(CreateWebhookCommand(new DeleteWebhook())); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
|
|||
protected T CreateWebhookEvent<T>(T @event) where T : WebhookEvent |
|||
{ |
|||
@event.WebhookId = WebhookId; |
|||
|
|||
return CreateEvent(@event); |
|||
} |
|||
|
|||
protected T CreateWebhookCommand<T>(T command) where T : WebhookAggregateCommand |
|||
{ |
|||
command.WebhookId = WebhookId; |
|||
|
|||
return CreateCommand(command); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue