Browse Source

Pure immutability.

pull/169/head
Sebastian Stehle 9 years ago
parent
commit
21a41721fb
  1. 21
      Squidex.sln.DotSettings
  2. 8
      src/Squidex.Domain.Apps.Core.Model/Apps/AppClient.cs
  3. 51
      src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs
  4. 23
      src/Squidex.Domain.Apps.Core.Model/Apps/AppContributors.cs
  5. 10
      src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppClientsConverter.cs
  6. 10
      src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppContributorsConverter.cs
  7. 109
      src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs
  8. 12
      src/Squidex.Domain.Apps.Core.Model/DictionaryWrapper{TKey,TValue}.cs
  9. 2
      src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs
  10. 2
      src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs
  11. 3
      src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs
  12. 2
      src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs
  13. 2
      src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs
  14. 2
      src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs
  15. 2
      src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs
  16. 3
      src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs
  17. 46
      src/Squidex.Domain.Apps.Events/Apps/Utils/AppEventDispatcher.cs
  18. 7
      src/Squidex.Domain.Apps.Read.MongoDb/Assets/MongoAssetEntity.cs
  19. 6
      src/Squidex.Domain.Apps.Read.MongoDb/Contents/MongoContentEntity.cs
  20. 7
      src/Squidex.Domain.Apps.Read.MongoDb/History/MongoHistoryEventEntity.cs
  21. 9
      src/Squidex.Domain.Apps.Read/State/Orleans/Grains/Implementations/AppStateGrain.cs
  22. 266
      src/Squidex.Domain.Apps.Read/State/Orleans/Grains/Implementations/AppStateGrainState.cs
  23. 119
      src/Squidex.Domain.Apps.Read/State/Orleans/Grains/Implementations/AppStateGrainState_Apps.cs
  24. 60
      src/Squidex.Domain.Apps.Read/State/Orleans/Grains/Implementations/AppStateGrainState_Rules.cs
  25. 157
      src/Squidex.Domain.Apps.Read/State/Orleans/Grains/Implementations/AppStateGrainState_Schemas.cs
  26. 4
      src/Squidex.Domain.Apps.Read/State/Orleans/Grains/Implementations/JsonAppEntity.cs
  27. 27
      src/Squidex.Domain.Apps.Write/Apps/AppDomainObject.cs
  28. 6
      src/Squidex.Domain.Apps.Write/Rules/RuleDomainObject.cs
  29. 8
      src/Squidex.Domain.Apps.Write/Schemas/Guards/FieldPropertiesValidator.cs
  30. 24
      src/Squidex.Domain.Apps.Write/Schemas/SchemaDomainObject.cs
  31. 10
      src/Squidex/Controllers/Api/Rules/Models/Converters/RuleConverter.cs
  32. 3
      src/Squidex/Controllers/Api/Rules/Models/Triggers/ContentChangedTriggerDto.cs
  33. 6
      src/Squidex/Controllers/Api/Schemas/Models/Fields/NumberFieldPropertiesDto.cs
  34. 6
      src/Squidex/Controllers/Api/Schemas/Models/Fields/StringFieldPropertiesDto.cs
  35. 43
      tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientJsonTests.cs
  36. 71
      tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientsTests.cs
  37. 35
      tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppContributorsJsonTests.cs
  38. 44
      tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppContributorsTests.cs
  39. 115
      tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/LanguagesConfigTests.cs
  40. 50
      tests/Squidex.Domain.Apps.Core.Tests/Model/Rules/RuleTests.cs
  41. 7
      tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/ContentChangedTriggerTests.cs
  42. 48
      tests/Squidex.Domain.Apps.Read.Tests/Contents/GraphQLTests.cs
  43. 46
      tests/Squidex.Domain.Apps.Read.Tests/Contents/ODataQueryTests.cs
  44. 6
      tests/Squidex.Domain.Apps.Read.Tests/Rules/RuleEnqueuerTests.cs
  45. 46
      tests/Squidex.Domain.Apps.Write.Tests/Apps/Guards/GuardAppClientsTests.cs
  46. 48
      tests/Squidex.Domain.Apps.Write.Tests/Apps/Guards/GuardAppContributorsTests.cs
  47. 40
      tests/Squidex.Domain.Apps.Write.Tests/Apps/Guards/GuardAppLanguagesTests.cs
  48. 12
      tests/Squidex.Domain.Apps.Write.Tests/Contents/ContentCommandMiddlewareTests.cs
  49. 63
      tests/Squidex.Domain.Apps.Write.Tests/Rules/Guards/GuardRuleTests.cs
  50. 14
      tests/Squidex.Domain.Apps.Write.Tests/Rules/Guards/Triggers/ContentChangedTriggerTests.cs
  51. 3
      tests/Squidex.Domain.Apps.Write.Tests/Rules/RuleDomainObjectTests.cs
  52. 5
      tests/Squidex.Domain.Apps.Write.Tests/Schemas/Guards/FieldProperties/NumberFieldPropertiesTests.cs
  53. 5
      tests/Squidex.Domain.Apps.Write.Tests/Schemas/Guards/FieldProperties/StringFieldPropertiesTests.cs
  54. 74
      tests/Squidex.Domain.Apps.Write.Tests/Schemas/Guards/GuardSchemaFieldTests.cs
  55. 30
      tests/Squidex.Domain.Apps.Write.Tests/Schemas/Guards/GuardSchemaTests.cs
  56. 73
      tests/Squidex.Infrastructure.Tests/Json/Orleans/JsonExternalSerializerTests.cs

21
Squidex.sln.DotSettings

@ -3,15 +3,18 @@
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Djs/@EntryIndexRemoved">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ecshtml/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ecshtml/@EntryIndexRemoved">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ecss/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ecss/@EntryIndexRemoved">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ejs/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ejs/@EntryIndexRemoved">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Escss/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Escss/@EntryIndexRemoved">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ets/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ets/@EntryIndexRemoved">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002E_002A/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ecss/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ehtml/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ejs/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ejson/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Escss/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ets/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002E_002A/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002E_002A/@EntryIndexRemoved">True</s:Boolean>

8
src/Squidex.Domain.Apps.Core.Model/Apps/AppClient.cs

@ -42,18 +42,18 @@ namespace Squidex.Domain.Apps.Core.Apps
this.permission = permission;
}
public void Update(AppClientPermission newPermission)
public AppClient Update(AppClientPermission newPermission)
{
Guard.Enum(newPermission, nameof(newPermission));
permission = newPermission;
return new AppClient(name, secret, newPermission);
}
public void Rename(string newName)
public AppClient Rename(string newName)
{
Guard.NotNullOrEmpty(newName, nameof(newName));
name = newName;
return new AppClient(newName, secret, permission);
}
}
}

51
src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs

@ -6,32 +6,69 @@
// All rights reserved.
// ==========================================================================
using System.Collections.Immutable;
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Apps
{
public sealed class AppClients : DictionaryBase<string, AppClient>
public sealed class AppClients : DictionaryWrapper<string, AppClient>
{
public void Add(string id, AppClient client)
public static readonly AppClients Empty = new AppClients();
private AppClients()
: base(ImmutableDictionary<string, AppClient>.Empty)
{
}
public AppClients(ImmutableDictionary<string, AppClient> inner)
: base(inner)
{
}
public AppClients Add(string id, AppClient client)
{
Guard.NotNullOrEmpty(id, nameof(id));
Guard.NotNull(client, nameof(client));
Inner.Add(id, client);
return new AppClients(Inner.Add(id, client));
}
public void Add(string id, string secret)
public AppClients Add(string id, string secret)
{
Guard.NotNullOrEmpty(id, nameof(id));
Inner.Add(id, new AppClient(id, secret, AppClientPermission.Editor));
return new AppClients(Inner.Add(id, new AppClient(id, secret, AppClientPermission.Editor)));
}
public void Revoke(string id)
public AppClients Revoke(string id)
{
Guard.NotNullOrEmpty(id, nameof(id));
Inner.Remove(id);
return new AppClients(Inner.Remove(id));
}
public AppClients Rename(string id, string newName)
{
Guard.NotNullOrEmpty(id, nameof(id));
if (!TryGetValue(id, out var client))
{
return this;
}
return new AppClients(Inner.SetItem(id, client.Rename(newName)));
}
public AppClients Update(string id, AppClientPermission permission)
{
Guard.NotNullOrEmpty(id, nameof(id));
if (!TryGetValue(id, out var client))
{
return this;
}
return new AppClients(Inner.SetItem(id, client.Update(permission)));
}
}
}

23
src/Squidex.Domain.Apps.Core.Model/Apps/AppContributors.cs

@ -6,25 +6,38 @@
// All rights reserved.
// ==========================================================================
using System.Collections.Immutable;
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Apps
{
public sealed class AppContributors : DictionaryBase<string, AppContributorPermission>
public sealed class AppContributors : DictionaryWrapper<string, AppContributorPermission>
{
public void Assign(string contributorId, AppContributorPermission permission)
public static readonly AppContributors Empty = new AppContributors();
private AppContributors()
: base(ImmutableDictionary<string, AppContributorPermission>.Empty)
{
}
public AppContributors(ImmutableDictionary<string, AppContributorPermission> inner)
: base(inner)
{
}
public AppContributors Assign(string contributorId, AppContributorPermission permission)
{
Guard.NotNullOrEmpty(contributorId, nameof(contributorId));
Guard.Enum(permission, nameof(permission));
Inner[contributorId] = permission;
return new AppContributors(Inner.SetItem(contributorId, permission));
}
public void Remove(string contributorId)
public AppContributors Remove(string contributorId)
{
Guard.NotNullOrEmpty(contributorId, nameof(contributorId));
Inner.Remove(contributorId);
return new AppContributors(Inner.Remove(contributorId));
}
}
}

10
src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppClientsConverter.cs

@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Newtonsoft.Json;
using Squidex.Infrastructure.Json;
@ -31,14 +32,7 @@ namespace Squidex.Domain.Apps.Core.Apps.Json
{
var json = serializer.Deserialize<Dictionary<string, JsonAppClient>>(reader);
var clients = new AppClients();
foreach (var client in json)
{
clients.Add(client.Key, client.Value.ToClient());
}
return clients;
return new AppClients(json.ToImmutableDictionary(x => x.Key, x => x.Value.ToClient()));
}
}
}

10
src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppContributorsConverter.cs

@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Newtonsoft.Json;
using Squidex.Infrastructure.Json;
@ -31,14 +32,7 @@ namespace Squidex.Domain.Apps.Core.Apps.Json
{
var json = serializer.Deserialize<Dictionary<string, AppContributorPermission>>(reader);
var contributors = new AppContributors();
foreach (var contributor in json)
{
contributors.Assign(contributor.Key, contributor.Value);
}
return contributors;
return new AppContributors(json.ToImmutableDictionary());
}
}
}

109
src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs

@ -13,80 +13,101 @@ using System.Collections.Immutable;
using System.Linq;
using Squidex.Infrastructure;
#pragma warning disable IDE0016 // Use 'throw' expression
namespace Squidex.Domain.Apps.Core.Apps
{
public sealed class LanguagesConfig : IFieldPartitioning
{
private State state;
public static readonly LanguagesConfig Empty = new LanguagesConfig(ImmutableDictionary<Language, LanguageConfig>.Empty, null, false);
public static readonly LanguagesConfig English = LanguagesConfig.Build(Language.EN);
private readonly ImmutableDictionary<Language, LanguageConfig> languages;
private readonly LanguageConfig master;
public LanguageConfig Master
{
get { return state.Master; }
get { return master; }
}
IFieldPartitionItem IFieldPartitioning.Master
{
get { return state.Master; }
get { return master; }
}
IEnumerator IEnumerable.GetEnumerator()
{
return state.Languages.Values.GetEnumerator();
return languages.Values.GetEnumerator();
}
IEnumerator<IFieldPartitionItem> IEnumerable<IFieldPartitionItem>.GetEnumerator()
{
return state.Languages.Values.GetEnumerator();
return languages.Values.GetEnumerator();
}
public int Count
{
get { return state.Languages.Count; }
get { return languages.Count; }
}
private LanguagesConfig(ICollection<LanguageConfig> configs)
private LanguagesConfig(ImmutableDictionary<Language, LanguageConfig> languages, LanguageConfig master, bool checkMaster = true)
{
Guard.NotNull(configs, nameof(configs));
if (checkMaster)
{
this.master = master ?? throw new InvalidOperationException("Config has no master language.");
}
foreach (var languageConfig in languages.Values)
{
foreach (var fallback in languageConfig.LanguageFallbacks)
{
if (!languages.ContainsKey(fallback))
{
var message = $"Config for language '{languageConfig.Language.Iso2Code}' contains unsupported fallback language '{fallback.Iso2Code}'";
state = new State(configs.ToImmutableDictionary(x => x.Language), configs.FirstOrDefault());
throw new InvalidOperationException(message);
}
}
}
this.languages = languages;
}
public static LanguagesConfig Build(params LanguageConfig[] configs)
public static LanguagesConfig Build(ICollection<LanguageConfig> configs)
{
Guard.NotNull(configs, nameof(configs));
return new LanguagesConfig(configs);
return new LanguagesConfig(configs.ToImmutableDictionary(x => x.Language), configs.FirstOrDefault());
}
public static LanguagesConfig Build(params Language[] languages)
public static LanguagesConfig Build(params LanguageConfig[] configs)
{
Guard.NotNull(languages, nameof(languages));
return Build(configs?.ToList());
}
return new LanguagesConfig(languages.Select(x => new LanguageConfig(x, false)).ToList());
public static LanguagesConfig Build(params Language[] languages)
{
return Build(languages?.Select(x => new LanguageConfig(x, false))?.ToList());
}
public void MakeMaster(Language language)
public LanguagesConfig MakeMaster(Language language)
{
Guard.NotNull(language, nameof(language));
state = new State(state.Languages, state.Languages[language]);
return new LanguagesConfig(languages, languages[language]);
}
public void Set(LanguageConfig config)
public LanguagesConfig Set(LanguageConfig config)
{
Guard.NotNull(config, nameof(config));
state = new State(state.Languages.SetItem(config.Language, config), state.Master?.Language == config.Language ? config : state.Master);
return new LanguagesConfig(languages.SetItem(config.Language, config), Master?.Language == config.Language ? config : Master);
}
public void Remove(Language language)
public LanguagesConfig Remove(Language language)
{
Guard.NotNull(language, nameof(language));
var newLanguages =
state.Languages.Values.Where(x => x.Language != language)
languages.Values.Where(x => x.Language != language)
.Select(config =>
{
return new LanguageConfig(
@ -97,26 +118,26 @@ namespace Squidex.Domain.Apps.Core.Apps
.ToImmutableDictionary(x => x.Language);
var newMaster =
state.Master.Language != language ?
state.Master :
Master.Language != language ?
Master :
newLanguages.Values.FirstOrDefault();
state = new State(newLanguages, newMaster);
return new LanguagesConfig(newLanguages, newMaster);
}
public bool Contains(Language language)
{
return language != null && state.Languages.ContainsKey(language);
return language != null && languages.ContainsKey(language);
}
public bool TryGetConfig(Language language, out LanguageConfig config)
{
return state.Languages.TryGetValue(language, out config);
return languages.TryGetValue(language, out config);
}
public bool TryGetItem(string key, out IFieldPartitionItem item)
{
if (Language.IsValidLanguage(key) && state.Languages.TryGetValue(key, out var value))
if (Language.IsValidLanguage(key) && languages.TryGetValue(key, out var value))
{
item = value;
@ -130,38 +151,6 @@ namespace Squidex.Domain.Apps.Core.Apps
}
}
private sealed class State
{
public ImmutableDictionary<Language, LanguageConfig> Languages { get; }
public LanguageConfig Master { get; }
public State(ImmutableDictionary<Language, LanguageConfig> languages, LanguageConfig master)
{
foreach (var languageConfig in languages.Values)
{
foreach (var fallback in languageConfig.LanguageFallbacks)
{
if (!languages.ContainsKey(fallback))
{
var message = $"Config for language '{languageConfig.Language.Iso2Code}' contains unsupported fallback language '{fallback.Iso2Code}'";
throw new InvalidOperationException(message);
}
}
}
Languages = languages;
if (master == null)
{
throw new InvalidOperationException("Config has no master language.");
}
this.Master = master;
}
}
public PartitionResolver ToResolver()
{
return partitioning =>

12
src/Squidex.Domain.Apps.Core.Model/DictionaryBase.cs → src/Squidex.Domain.Apps.Core.Model/DictionaryWrapper{TKey,TValue}.cs

@ -8,12 +8,13 @@
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
namespace Squidex.Domain.Apps.Core
{
public abstract class DictionaryBase<TKey, TValue> : IReadOnlyDictionary<TKey, TValue>
public abstract class DictionaryWrapper<TKey, TValue> : IReadOnlyDictionary<TKey, TValue>
{
private readonly Dictionary<TKey, TValue> inner = new Dictionary<TKey, TValue>();
private readonly ImmutableDictionary<TKey, TValue> inner;
public TValue this[TKey key]
{
@ -35,11 +36,16 @@ namespace Squidex.Domain.Apps.Core
get { return inner.Count; }
}
protected Dictionary<TKey, TValue> Inner
protected ImmutableDictionary<TKey, TValue> Inner
{
get { return inner; }
}
protected DictionaryWrapper(ImmutableDictionary<TKey, TValue> inner)
{
this.inner = inner;
}
public bool ContainsKey(TKey key)
{
return inner.ContainsKey(key);

2
src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs

@ -6,8 +6,6 @@
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Schemas

2
src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs

@ -6,8 +6,6 @@
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Schemas

3
src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs

@ -6,9 +6,6 @@
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using NodaTime;
using Squidex.Infrastructure;

2
src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs

@ -6,8 +6,6 @@
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Schemas

2
src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs

@ -6,8 +6,6 @@
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Schemas

2
src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs

@ -6,9 +6,7 @@
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using System.Collections.Immutable;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Schemas

2
src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs

@ -7,8 +7,6 @@
// ==========================================================================
using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Schemas

3
src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs

@ -6,11 +6,8 @@
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using System.Collections.Immutable;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json;
namespace Squidex.Domain.Apps.Core.Schemas
{

46
src/Squidex.Domain.Apps.Events/Apps/Utils/AppEventDispatcher.cs

@ -13,53 +13,47 @@ namespace Squidex.Domain.Apps.Events.Apps.Utils
{
public static class AppEventDispatcher
{
public static void Apply(this AppContributors contributors, AppContributorRemoved @event)
public static AppContributors Apply(this AppContributors contributors, AppContributorRemoved @event)
{
contributors.Remove(@event.ContributorId);
return contributors.Remove(@event.ContributorId);
}
public static void Apply(this AppContributors contributors, AppContributorAssigned @event)
public static AppContributors Apply(this AppContributors contributors, AppContributorAssigned @event)
{
contributors.Assign(@event.ContributorId, @event.Permission);
return contributors.Assign(@event.ContributorId, @event.Permission);
}
public static void Apply(this LanguagesConfig languagesConfig, AppLanguageAdded @event)
public static LanguagesConfig Apply(this LanguagesConfig languagesConfig, AppLanguageAdded @event)
{
languagesConfig.Set(new LanguageConfig(@event.Language));
return languagesConfig.Set(new LanguageConfig(@event.Language));
}
public static void Apply(this LanguagesConfig languagesConfig, AppLanguageRemoved @event)
public static LanguagesConfig Apply(this LanguagesConfig languagesConfig, AppLanguageRemoved @event)
{
languagesConfig.Remove(@event.Language);
return languagesConfig.Remove(@event.Language);
}
public static void Apply(this AppClients clients, AppClientAttached @event)
public static AppClients Apply(this AppClients clients, AppClientAttached @event)
{
clients.Add(@event.Id, @event.Secret);
return clients.Add(@event.Id, @event.Secret);
}
public static void Apply(this AppClients clients, AppClientRevoked @event)
public static AppClients Apply(this AppClients clients, AppClientRevoked @event)
{
clients.Revoke(@event.Id);
return clients.Revoke(@event.Id);
}
public static void Apply(this AppClients clients, AppClientRenamed @event)
public static AppClients Apply(this AppClients clients, AppClientRenamed @event)
{
if (clients.TryGetValue(@event.Id, out var client))
{
client.Rename(@event.Name);
}
return clients.Rename(@event.Id, @event.Name);
}
public static void Apply(this AppClients clients, AppClientUpdated @event)
public static AppClients Apply(this AppClients clients, AppClientUpdated @event)
{
if (clients.TryGetValue(@event.Id, out var client))
{
client.Update(@event.Permission);
}
return clients.Update(@event.Id, @event.Permission);
}
public static void Apply(this LanguagesConfig languagesConfig, AppLanguageUpdated @event)
public static LanguagesConfig Apply(this LanguagesConfig languagesConfig, AppLanguageUpdated @event)
{
var fallback = @event.Fallback;
@ -70,12 +64,14 @@ namespace Squidex.Domain.Apps.Events.Apps.Utils
fallback = fallback.Intersect(existingLangauges).ToList();
}
languagesConfig.Set(new LanguageConfig(@event.Language, @event.IsOptional, fallback));
languagesConfig = languagesConfig.Set(new LanguageConfig(@event.Language, @event.IsOptional, fallback));
if (@event.IsMaster)
{
languagesConfig.MakeMaster(@event.Language);
languagesConfig = languagesConfig.MakeMaster(@event.Language);
}
return languagesConfig;
}
}
}

7
src/Squidex.Domain.Apps.Read.MongoDb/Assets/MongoAssetEntity.cs

@ -14,7 +14,12 @@ using Squidex.Infrastructure.MongoDb;
namespace Squidex.Domain.Apps.Read.MongoDb.Assets
{
public sealed class MongoAssetEntity : MongoEntity, IAssetEntity
public sealed class MongoAssetEntity :
MongoEntity,
IAssetEntity,
IUpdateableEntityWithVersion,
IUpdateableEntityWithCreatedBy,
IUpdateableEntityWithLastModifiedBy
{
[BsonRequired]
[BsonElement]

6
src/Squidex.Domain.Apps.Read.MongoDb/Contents/MongoContentEntity.cs

@ -19,7 +19,11 @@ using Squidex.Infrastructure.MongoDb;
namespace Squidex.Domain.Apps.Read.MongoDb.Contents
{
public sealed class MongoContentEntity : IContentEntity
public sealed class MongoContentEntity :
IContentEntity,
IUpdateableEntityWithVersion,
IUpdateableEntityWithCreatedBy,
IUpdateableEntityWithLastModifiedBy
{
private NamedContentData data;

7
src/Squidex.Domain.Apps.Read.MongoDb/History/MongoHistoryEventEntity.cs

@ -14,7 +14,10 @@ using Squidex.Infrastructure.MongoDb;
namespace Squidex.Domain.Apps.Read.MongoDb.History
{
public sealed class MongoHistoryEventEntity : MongoEntity, IAppRefEntity, IEntityWithCreatedBy
public sealed class MongoHistoryEventEntity : MongoEntity,
IEntityWithAppRef,
IUpdateableEntityWithVersion,
IUpdateableEntityWithCreatedBy
{
[BsonRequired]
[BsonElement]
@ -40,7 +43,7 @@ namespace Squidex.Domain.Apps.Read.MongoDb.History
[BsonElement]
public Dictionary<string, string> Parameters { get; set; }
RefToken IEntityWithCreatedBy.CreatedBy
RefToken IUpdateableEntityWithCreatedBy.CreatedBy
{
get
{

9
src/Squidex.Domain.Apps.Read/State/Orleans/Grains/Implementations/AppStateGrain.cs

@ -31,6 +31,13 @@ namespace Squidex.Domain.Apps.Read.State.Orleans.Grains.Implementations
this.fieldRegistry = fieldRegistry;
}
public override Task OnActivateAsync()
{
State.SetRegistry(fieldRegistry);
return base.OnActivateAsync();
}
public Task<Immutable<(IAppEntity, ISchemaEntity)>> GetAppWithSchemaAsync(Guid id)
{
var schema = State.FindSchema(x => x.Id == id && !x.IsDeleted);
@ -75,7 +82,7 @@ namespace Squidex.Domain.Apps.Read.State.Orleans.Grains.Implementations
public Task HandleAsync(Immutable<Envelope<IEvent>> message)
{
State.Apply(message.Value, fieldRegistry);
State.Apply(message.Value);
return WriteStateAsync();
}

266
src/Squidex.Domain.Apps.Read/State/Orleans/Grains/Implementations/AppStateGrainState.cs

@ -10,29 +10,19 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Events;
using Squidex.Domain.Apps.Events.Apps;
using Squidex.Domain.Apps.Events.Apps.Utils;
using Squidex.Domain.Apps.Events.Rules;
using Squidex.Domain.Apps.Events.Rules.Utils;
using Squidex.Domain.Apps.Events.Schemas;
using Squidex.Domain.Apps.Events.Schemas.Old;
using Squidex.Domain.Apps.Events.Schemas.Utils;
using Squidex.Domain.Apps.Read.Apps;
using Squidex.Domain.Apps.Read.Rules;
using Squidex.Domain.Apps.Read.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Reflection;
#pragma warning disable CS0612 // Type or member is obsolete
using Squidex.Infrastructure.Dispatching;
namespace Squidex.Domain.Apps.Read.State.Orleans.Grains.Implementations
{
public sealed class AppStateGrainState
public sealed partial class AppStateGrainState
{
private FieldRegistry registry;
[JsonProperty]
public JsonAppEntity App { get; set; }
@ -42,6 +32,11 @@ namespace Squidex.Domain.Apps.Read.State.Orleans.Grains.Implementations
[JsonProperty]
public Dictionary<Guid, JsonSchemaEntity> Schemas { get; set; }
public void SetRegistry(FieldRegistry registry)
{
this.registry = registry;
}
public IAppEntity GetApp()
{
return App;
@ -69,253 +64,14 @@ namespace Squidex.Domain.Apps.Read.State.Orleans.Grains.Implementations
Schemas = new Dictionary<Guid, JsonSchemaEntity>();
}
public void Apply(Envelope<IEvent> envelope, FieldRegistry registry)
public void Apply(Envelope<IEvent> envelope)
{
switch (envelope.Payload)
{
case AppCreated @event:
{
Reset();
App = EntityMapper.Create<JsonAppEntity>(@event, envelope.Headers, a =>
{
SimpleMapper.Map(@event, a);
a.Clients = new AppClients();
a.Contributors = new AppContributors();
a.LanguagesConfig = LanguagesConfig.Build(Language.EN);
});
break;
}
case AppPlanChanged @event:
UpdateApp(envelope, a =>
{
SimpleMapper.Map(@event, a);
});
break;
case AppClientAttached @event:
UpdateApp(envelope, a =>
{
a.Clients.Apply(@event);
});
break;
case AppClientRevoked @event:
UpdateApp(envelope, a =>
{
a.Clients.Apply(@event);
});
break;
case AppClientRenamed @event:
UpdateApp(envelope, a =>
{
a.Clients.Apply(@event);
});
break;
case AppClientUpdated @event:
UpdateApp(envelope, a =>
{
a.Clients.Apply(@event);
});
break;
case AppContributorRemoved @event:
UpdateApp(envelope, a =>
{
a.Contributors.Apply(@event);
});
break;
case AppContributorAssigned @event:
UpdateApp(envelope, a =>
{
a.Contributors.Apply(@event);
});
break;
case AppLanguageAdded @event:
UpdateApp(envelope, a =>
{
a.LanguagesConfig.Apply(@event);
});
break;
case AppLanguageRemoved @event:
UpdateApp(envelope, a =>
{
a.LanguagesConfig.Apply(@event);
});
break;
case AppLanguageUpdated @event:
UpdateApp(envelope, a =>
{
a.LanguagesConfig.Apply(@event);
});
break;
case RuleCreated @event:
Rules[@event.RuleId] = EntityMapper.Create<JsonRuleEntity>(@event, envelope.Headers, r =>
{
r.RuleDef = RuleEventDispatcher.Create(@event);
});
break;
case RuleUpdated @event:
UpdateRule(envelope, r =>
{
r.RuleDef = r.RuleDef.Apply(@event);
});
break;
case RuleEnabled @event:
UpdateRule(envelope, r =>
{
r.RuleDef = r.RuleDef.Apply(@event);
});
break;
case RuleDisabled @event:
Rules.Remove(@event.RuleId);
break;
case SchemaCreated @event:
Schemas[@event.SchemaId.Id] = EntityMapper.Create<JsonSchemaEntity>(@event, envelope.Headers, s =>
{
s.SchemaDef = SchemaEventDispatcher.Create(@event, registry);
SimpleMapper.Map(@event, s);
});
break;
case FieldAdded @event:
UpdateSchema(envelope, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event, registry);
});
break;
case FieldDeleted @event:
UpdateSchema(envelope, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
break;
case FieldLocked @event:
UpdateSchema(envelope, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
break;
case FieldHidden @event:
UpdateSchema(envelope, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
break;
case FieldShown @event:
UpdateSchema(envelope, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
break;
case FieldDisabled @event:
UpdateSchema(envelope, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
break;
case FieldEnabled @event:
UpdateSchema(envelope, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
break;
case FieldUpdated @event:
UpdateSchema(envelope, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
break;
case SchemaFieldsReordered @event:
UpdateSchema(envelope, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
break;
case SchemaUpdated @event:
UpdateSchema(envelope, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
break;
case SchemaPublished @event:
UpdateSchema(envelope, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
break;
case ScriptsConfigured @event:
UpdateSchema(envelope, s =>
{
SimpleMapper.Map(s, @event);
});
break;
case SchemaDeleted @event:
Schemas.Remove(@event.SchemaId.Id);
break;
case WebhookAdded @event:
UpdateSchema(envelope);
break;
case WebhookDeleted @event:
UpdateSchema(envelope);
break;
}
this.DispatchAction(envelope.Payload, envelope.Headers);
if (App != null)
{
App.Etag = Guid.NewGuid().ToString();
}
}
private void UpdateApp(Envelope<IEvent> envelope, Action<JsonAppEntity> updater = null)
{
var e = envelope.To<AppEvent>();
App.Update(e.Payload, e.Headers, updater);
}
private void UpdateRule(Envelope<IEvent> envelope, Action<JsonRuleEntity> updater = null)
{
var e = envelope.To<RuleEvent>();
Rules[e.Payload.RuleId].Clone().Update(e.Payload, e.Headers, updater);
}
private void UpdateSchema(Envelope<IEvent> envelope, Action<JsonSchemaEntity> updater = null)
{
var e = envelope.To<SchemaEvent>();
Schemas[e.Payload.SchemaId.Id].Clone().Update(e.Payload, e.Headers, updater);
}
}
}

119
src/Squidex.Domain.Apps.Read/State/Orleans/Grains/Implementations/AppStateGrainState_Apps.cs

@ -0,0 +1,119 @@
// ==========================================================================
// AppStateGrainState_Apps.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.Utils;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Domain.Apps.Read.State.Orleans.Grains.Implementations
{
public sealed partial class AppStateGrainState
{
public void On(AppCreated @event, EnvelopeHeaders headers)
{
Reset();
App = EntityMapper.Create<JsonAppEntity>(@event, headers, a =>
{
SimpleMapper.Map(@event, a);
a.LanguagesConfig = LanguagesConfig.Build(Language.EN);
});
}
public void On(AppLanguageAdded @event, EnvelopeHeaders headers)
{
UpdateApp(@event, headers, a =>
{
a.LanguagesConfig = a.LanguagesConfig.Apply(@event);
});
}
public void On(AppLanguageRemoved @event, EnvelopeHeaders headers)
{
UpdateApp(@event, headers, a =>
{
a.LanguagesConfig = a.LanguagesConfig.Apply(@event);
});
}
public void On(AppLanguageUpdated @event, EnvelopeHeaders headers)
{
UpdateApp(@event, headers, a =>
{
a.LanguagesConfig = a.LanguagesConfig.Apply(@event);
});
}
public void On(AppContributorAssigned @event, EnvelopeHeaders headers)
{
UpdateApp(@event, headers, a =>
{
a.Contributors = a.Contributors.Apply(@event);
});
}
public void On(AppContributorRemoved @event, EnvelopeHeaders headers)
{
UpdateApp(@event, headers, a =>
{
a.Contributors = a.Contributors.Apply(@event);
});
}
public void On(AppClientAttached @event, EnvelopeHeaders headers)
{
UpdateApp(@event, headers, a =>
{
a.Clients = a.Clients.Apply(@event);
});
}
public void On(AppClientUpdated @event, EnvelopeHeaders headers)
{
UpdateApp(@event, headers, a =>
{
a.Clients = a.Clients.Apply(@event);
});
}
public void On(AppClientRenamed @event, EnvelopeHeaders headers)
{
UpdateApp(@event, headers, a =>
{
a.Clients = a.Clients.Apply(@event);
});
}
public void On(AppClientRevoked @event, EnvelopeHeaders headers)
{
UpdateApp(@event, headers, a =>
{
a.Clients = a.Clients.Apply(@event);
});
}
public void On(AppPlanChanged @event, EnvelopeHeaders headers)
{
UpdateApp(@event, headers, a =>
{
SimpleMapper.Map(@event, a);
});
}
private void UpdateApp(AppEvent @event, EnvelopeHeaders headers, Action<JsonAppEntity> updater = null)
{
App = App.Clone().Update(@event, headers, updater);
}
}
}

60
src/Squidex.Domain.Apps.Read/State/Orleans/Grains/Implementations/AppStateGrainState_Rules.cs

@ -0,0 +1,60 @@
// ==========================================================================
// AppStateGrainState_Rules.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using Squidex.Domain.Apps.Events.Rules;
using Squidex.Domain.Apps.Events.Rules.Utils;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Domain.Apps.Read.State.Orleans.Grains.Implementations
{
public sealed partial class AppStateGrainState
{
public void On(RuleCreated @event, EnvelopeHeaders headers)
{
Rules[@event.RuleId] = EntityMapper.Create<JsonRuleEntity>(@event, headers, r =>
{
r.RuleDef = RuleEventDispatcher.Create(@event);
});
}
public void On(RuleUpdated @event, EnvelopeHeaders headers)
{
UpdateRule(@event, headers, r =>
{
r.RuleDef = r.RuleDef.Apply(@event);
});
}
public void On(RuleEnabled @event, EnvelopeHeaders headers)
{
UpdateRule(@event, headers, r =>
{
r.RuleDef = r.RuleDef.Apply(@event);
});
}
public void On(RuleDisabled @event, EnvelopeHeaders headers)
{
UpdateRule(@event, headers, r =>
{
r.RuleDef = r.RuleDef.Apply(@event);
});
}
public void On(RuleDeleted @event, EnvelopeHeaders headers)
{
Rules.Remove(@event.RuleId);
}
private void UpdateRule(RuleEvent @event, EnvelopeHeaders headers, Action<JsonRuleEntity> updater = null)
{
Rules[@event.RuleId].Clone().Update(@event, headers, updater);
}
}
}

157
src/Squidex.Domain.Apps.Read/State/Orleans/Grains/Implementations/AppStateGrainState_Schemas.cs

@ -0,0 +1,157 @@
// ==========================================================================
// AppStateGrainState_Schemas.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using Squidex.Domain.Apps.Events;
using Squidex.Domain.Apps.Events.Schemas;
using Squidex.Domain.Apps.Events.Schemas.Old;
using Squidex.Domain.Apps.Events.Schemas.Utils;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Reflection;
#pragma warning disable CS0612 // Type or member is obsolete
namespace Squidex.Domain.Apps.Read.State.Orleans.Grains.Implementations
{
public sealed partial class AppStateGrainState
{
public void On(SchemaCreated @event, EnvelopeHeaders headers)
{
Schemas[@event.SchemaId.Id] = EntityMapper.Create<JsonSchemaEntity>(@event, headers, s =>
{
s.SchemaDef = SchemaEventDispatcher.Create(@event, registry);
SimpleMapper.Map(@event, s);
});
}
public void On(SchemaPublished @event, EnvelopeHeaders headers)
{
UpdateSchema(@event, headers, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
}
public void On(SchemaUnpublished @event, EnvelopeHeaders headers)
{
UpdateSchema(@event, headers, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
}
public void On(ScriptsConfigured @event, EnvelopeHeaders headers)
{
UpdateSchema(@event, headers, s =>
{
SimpleMapper.Map(s, @event);
});
}
public void On(SchemaUpdated @event, EnvelopeHeaders headers)
{
UpdateSchema(@event, headers, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
}
public void On(SchemaFieldsReordered @event, EnvelopeHeaders headers)
{
UpdateSchema(@event, headers, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
}
public void On(SchemaDeleted @event)
{
Schemas.Remove(@event.SchemaId.Id);
}
public void On(FieldAdded @event, EnvelopeHeaders headers)
{
UpdateSchema(@event, headers, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event, registry);
});
}
public void On(FieldUpdated @event, EnvelopeHeaders headers)
{
UpdateSchema(@event, headers, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
}
public void On(FieldLocked @event, EnvelopeHeaders headers)
{
UpdateSchema(@event, headers, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
}
public void On(FieldDisabled @event, EnvelopeHeaders headers)
{
UpdateSchema(@event, headers, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
}
public void On(FieldEnabled @event, EnvelopeHeaders headers)
{
UpdateSchema(@event, headers, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
}
public void On(FieldHidden @event, EnvelopeHeaders headers)
{
UpdateSchema(@event, headers, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
}
public void On(FieldShown @event, EnvelopeHeaders headers)
{
UpdateSchema(@event, headers, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
}
public void On(FieldDeleted @event, EnvelopeHeaders headers)
{
UpdateSchema(@event, headers, s =>
{
s.SchemaDef = s.SchemaDef.Apply(@event);
});
}
public void On(WebhookAdded @event, EnvelopeHeaders headers)
{
UpdateSchema(@event, headers);
}
public void On(WebhookDeleted @event, EnvelopeHeaders headers)
{
UpdateSchema(@event, headers);
}
private void UpdateSchema(SchemaEvent @event, EnvelopeHeaders headers, Action<JsonSchemaEntity> updater = null)
{
Schemas[@event.SchemaId.Id].Clone().Update(@event, headers, updater);
}
}
}

4
src/Squidex.Domain.Apps.Read/State/Orleans/Grains/Implementations/JsonAppEntity.cs

@ -29,10 +29,10 @@ namespace Squidex.Domain.Apps.Read.State.Orleans.Grains.Implementations
public string PlanOwner { get; set; }
[JsonProperty]
public AppClients Clients { get; set; }
public AppClients Clients { get; set; } = AppClients.Empty;
[JsonProperty]
public AppContributors Contributors { get; set; }
public AppContributors Contributors { get; set; } = AppContributors.Empty;
[JsonProperty]
public LanguagesConfig LanguagesConfig { get; set; }

27
src/Squidex.Domain.Apps.Write/Apps/AppDomainObject.cs

@ -22,10 +22,9 @@ namespace Squidex.Domain.Apps.Write.Apps
{
public class AppDomainObject : DomainObjectBase
{
private static readonly Language DefaultLanguage = Language.EN;
private readonly AppContributors contributors = new AppContributors();
private readonly AppClients clients = new AppClients();
private readonly LanguagesConfig languagesConfig = LanguagesConfig.Build(DefaultLanguage);
private AppContributors contributors = AppContributors.Empty;
private AppClients clients = AppClients.Empty;
private LanguagesConfig languagesConfig = LanguagesConfig.English;
private AppPlan plan;
private string name;
@ -66,47 +65,47 @@ namespace Squidex.Domain.Apps.Write.Apps
protected void On(AppContributorAssigned @event)
{
contributors.Apply(@event);
contributors = contributors.Apply(@event);
}
protected void On(AppContributorRemoved @event)
{
contributors.Apply(@event);
contributors = contributors.Apply(@event);
}
protected void On(AppClientAttached @event)
{
clients.Apply(@event);
clients = clients.Apply(@event);
}
protected void On(AppClientUpdated @event)
{
clients.Apply(@event);
clients = clients.Apply(@event);
}
protected void On(AppClientRenamed @event)
{
clients.Apply(@event);
clients = clients.Apply(@event);
}
protected void On(AppClientRevoked @event)
{
clients.Apply(@event);
clients = clients.Apply(@event);
}
protected void On(AppLanguageAdded @event)
{
languagesConfig.Apply(@event);
languagesConfig = languagesConfig.Apply(@event);
}
protected void On(AppLanguageRemoved @event)
{
languagesConfig.Apply(@event);
languagesConfig = languagesConfig.Apply(@event);
}
protected void On(AppLanguageUpdated @event)
{
languagesConfig.Apply(@event);
languagesConfig = languagesConfig.Apply(@event);
}
protected void On(AppPlanChanged @event)
@ -234,7 +233,7 @@ namespace Squidex.Domain.Apps.Write.Apps
private static AppLanguageAdded CreateInitialLanguage(NamedId<Guid> id)
{
return new AppLanguageAdded { AppId = id, Language = DefaultLanguage };
return new AppLanguageAdded { AppId = id, Language = Language.EN };
}
private static AppContributorAssigned CreateInitialOwner(NamedId<Guid> id, SquidexCommand command)

6
src/Squidex.Domain.Apps.Write/Rules/RuleDomainObject.cs

@ -41,17 +41,17 @@ namespace Squidex.Domain.Apps.Write.Rules
protected void On(RuleUpdated @event)
{
rule.Apply(@event);
rule = rule.Apply(@event);
}
protected void On(RuleEnabled @event)
{
rule.Apply(@event);
rule = rule.Apply(@event);
}
protected void On(RuleDisabled @event)
{
rule.Apply(@event);
rule = rule.Apply(@event);
}
protected void On(RuleDeleted @event)

8
src/Squidex.Domain.Apps.Write/Schemas/Guards/FieldPropertiesValidator.cs

@ -111,7 +111,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
nameof(properties.Editor));
}
if ((properties.Editor == NumberFieldEditor.Radio || properties.Editor == NumberFieldEditor.Dropdown) && (properties.AllowedValues == null || properties.AllowedValues.Length == 0))
if ((properties.Editor == NumberFieldEditor.Radio || properties.Editor == NumberFieldEditor.Dropdown) && (properties.AllowedValues == null || properties.AllowedValues.Count == 0))
{
yield return new ValidationError("Radio buttons or dropdown list need allowed values.",
nameof(properties.AllowedValues));
@ -136,7 +136,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
nameof(properties.MaxValue));
}
if (properties.AllowedValues != null && properties.AllowedValues.Length > 0 && (properties.MinValue.HasValue || properties.MaxValue.HasValue))
if (properties.AllowedValues != null && properties.AllowedValues.Count > 0 && (properties.MinValue.HasValue || properties.MaxValue.HasValue))
{
yield return new ValidationError("Either allowed values or min and max value can be defined.",
nameof(properties.AllowedValues),
@ -163,7 +163,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
nameof(properties.Editor));
}
if ((properties.Editor == StringFieldEditor.Radio || properties.Editor == StringFieldEditor.Dropdown) && (properties.AllowedValues == null || properties.AllowedValues.Length == 0))
if ((properties.Editor == StringFieldEditor.Radio || properties.Editor == StringFieldEditor.Dropdown) && (properties.AllowedValues == null || properties.AllowedValues.Count == 0))
{
yield return new ValidationError("Radio buttons or dropdown list need allowed values.",
nameof(properties.AllowedValues));
@ -182,7 +182,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
nameof(properties.MaxLength));
}
if (properties.AllowedValues != null && properties.AllowedValues.Length > 0 && (properties.MinLength.HasValue || properties.MaxLength.HasValue))
if (properties.AllowedValues != null && properties.AllowedValues.Count > 0 && (properties.MinLength.HasValue || properties.MaxLength.HasValue))
{
yield return new ValidationError("Either allowed values or min and max length can be defined.",
nameof(properties.AllowedValues),

24
src/Squidex.Domain.Apps.Write/Schemas/SchemaDomainObject.cs

@ -56,62 +56,62 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
totalFields++;
schema.Apply(@event, registry);
schema = schema.Apply(@event, registry);
}
protected void On(FieldUpdated @event)
{
schema.Apply(@event);
schema = schema.Apply(@event);
}
protected void On(FieldLocked @event)
{
schema.Apply(@event);
schema = schema.Apply(@event);
}
protected void On(FieldHidden @event)
{
schema.Apply(@event);
schema = schema.Apply(@event);
}
protected void On(FieldShown @event)
{
schema.Apply(@event);
schema = schema.Apply(@event);
}
protected void On(FieldDisabled @event)
{
schema.Apply(@event);
schema = schema.Apply(@event);
}
protected void On(FieldEnabled @event)
{
schema.Apply(@event);
schema = schema.Apply(@event);
}
protected void On(SchemaUpdated @event)
{
schema.Apply(@event);
schema = schema.Apply(@event);
}
protected void On(FieldDeleted @event)
{
schema.Apply(@event);
schema = schema.Apply(@event);
}
protected void On(SchemaFieldsReordered @event)
{
schema.Apply(@event);
schema = schema.Apply(@event);
}
protected void On(SchemaPublished @event)
{
schema.Apply(@event);
schema = schema.Apply(@event);
}
protected void On(SchemaUnpublished @event)
{
schema.Apply(@event);
schema = schema.Apply(@event);
}
protected void On(SchemaDeleted @event)

10
src/Squidex/Controllers/Api/Rules/Models/Converters/RuleConverter.cs

@ -20,16 +20,16 @@ namespace Squidex.Controllers.Api.Rules.Models.Converters
var dto = new RuleDto();
SimpleMapper.Map(entity, dto);
SimpleMapper.Map(entity.Rule, dto);
SimpleMapper.Map(entity.RuleDef, dto);
if (entity.Rule.Trigger != null)
if (entity.RuleDef.Trigger != null)
{
dto.Trigger = RuleTriggerDtoFactory.Create(entity.Rule.Trigger);
dto.Trigger = RuleTriggerDtoFactory.Create(entity.RuleDef.Trigger);
}
if (entity.Rule.Action != null)
if (entity.RuleDef.Action != null)
{
dto.Action = RuleActionDtoFactory.Create(entity.Rule.Action);
dto.Action = RuleActionDtoFactory.Create(entity.RuleDef.Action);
}
return dto;

3
src/Squidex/Controllers/Api/Rules/Models/Triggers/ContentChangedTriggerDto.cs

@ -7,6 +7,7 @@
// ==========================================================================
using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using NJsonSchema.Annotations;
@ -29,7 +30,7 @@ namespace Squidex.Controllers.Api.Rules.Models.Triggers
{
return new ContentChangedTrigger
{
Schemas = Schemas.Select(x => SimpleMapper.Map(x, new ContentChangedTriggerSchema())).ToList()
Schemas = Schemas.Select(x => SimpleMapper.Map(x, new ContentChangedTriggerSchema())).ToImmutableList()
};
}
}

6
src/Squidex/Controllers/Api/Schemas/Models/Fields/NumberFieldPropertiesDto.cs

@ -6,6 +6,7 @@
// All rights reserved.
// ==========================================================================
using System.Collections.Immutable;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using NJsonSchema.Annotations;
@ -47,6 +48,11 @@ namespace Squidex.Controllers.Api.Schemas.Models.Fields
{
var result = SimpleMapper.Map(this, new NumberFieldProperties());
if (AllowedValues != null)
{
result.AllowedValues = ImmutableList.Create(AllowedValues);
}
return result;
}
}

6
src/Squidex/Controllers/Api/Schemas/Models/Fields/StringFieldPropertiesDto.cs

@ -6,6 +6,7 @@
// All rights reserved.
// ==========================================================================
using System.Collections.Immutable;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using NJsonSchema.Annotations;
@ -57,6 +58,11 @@ namespace Squidex.Controllers.Api.Schemas.Models.Fields
{
var result = SimpleMapper.Map(this, new StringFieldProperties());
if (AllowedValues != null)
{
result.AllowedValues = ImmutableList.Create(AllowedValues);
}
return result;
}
}

43
tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientJsonTests.cs

@ -0,0 +1,43 @@
// ==========================================================================
// AppClientJsonTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using FluentAssertions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Squidex.Domain.Apps.Core.Apps;
using Xunit;
namespace Squidex.Domain.Apps.Core.Model.Apps
{
public class AppClientJsonTests
{
private readonly JsonSerializer serializer = TestData.DefaultSerializer();
[Fact]
public void Should_serialize_and_deserialize()
{
var clients = AppClients.Empty;
clients = clients.Add("1", "my-secret");
clients = clients.Add("2", "my-secret");
clients = clients.Add("3", "my-secret");
clients = clients.Add("4", "my-secret");
clients = clients.Update("3", AppClientPermission.Editor);
clients = clients.Rename("3", "My Client 3");
clients = clients.Rename("2", "My Client 2");
clients = clients.Revoke("4");
var appClients = JToken.FromObject(clients, serializer).ToObject<AppClients>(serializer);
appClients.ShouldBeEquivalentTo(clients);
}
}
}

71
tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientsTests.cs

@ -8,96 +8,87 @@
using System;
using FluentAssertions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Squidex.Domain.Apps.Core.Apps;
using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Core.Model.Apps
{
public class AppClientsTests
{
private readonly JsonSerializer serializer = TestData.DefaultSerializer();
private readonly AppClients sut = new AppClients();
public AppClientsTests()
{
sut.Add("1", "my-secret");
}
private readonly AppClients clients_0 = AppClients.Empty.Add("1", "my-secret");
[Fact]
public void Should_assign_client()
{
sut.Add("2", "my-secret");
var clients_1 = clients_0.Add("2", "my-secret");
sut["2"].ShouldBeEquivalentTo(new AppClient("2", "my-secret", AppClientPermission.Editor));
clients_1["2"].ShouldBeEquivalentTo(new AppClient("2", "my-secret", AppClientPermission.Editor));
}
[Fact]
public void Should_assign_client_with_permission()
public void Should_assign_clients_with_permission()
{
sut.Add("2", new AppClient("my-name", "my-secret", AppClientPermission.Reader));
var clients_1 = clients_0.Add("2", new AppClient("my-name", "my-secret", AppClientPermission.Reader));
sut["2"].ShouldBeEquivalentTo(new AppClient("my-name", "my-secret", AppClientPermission.Reader));
clients_1["2"].ShouldBeEquivalentTo(new AppClient("my-name", "my-secret", AppClientPermission.Reader));
}
[Fact]
public void Should_throw_exception_if_assigning_client_with_same_id()
public void Should_throw_exception_if_assigning_clients_with_same_id()
{
sut.Add("2", "my-secret");
var clients_1 = clients_0.Add("2", "my-secret");
Assert.Throws<ArgumentException>(() => sut.Add("2", "my-secret"));
Assert.Throws<ArgumentException>(() => clients_1.Add("2", "my-secret"));
}
[Fact]
public void Should_rename_client()
{
sut["1"].Rename("my-name");
var clients_1 = clients_0.Rename("1", "new-name");
sut["1"].ShouldBeEquivalentTo(new AppClient("my-name", "my-secret", AppClientPermission.Editor));
clients_1["1"].ShouldBeEquivalentTo(new AppClient("new-name", "my-secret", AppClientPermission.Editor));
}
[Fact]
public void Should_update_client()
public void Should_return_same_clients_if_client_to_rename_not_found()
{
sut["1"].Update(AppClientPermission.Reader);
var clients_1 = clients_0.Rename("2", "new-name");
sut["1"].ShouldBeEquivalentTo(new AppClient("1", "my-secret", AppClientPermission.Reader));
Assert.Same(clients_0, clients_1);
}
[Fact]
public void Should_revoke_client()
public void Should_update_client()
{
sut.Revoke("1");
var client_1 = clients_0.Update("1", AppClientPermission.Reader);
Assert.Empty(sut);
client_1["1"].ShouldBeEquivalentTo(new AppClient("1", "my-secret", AppClientPermission.Reader));
}
[Fact]
public void Should_do_nothing_if_client_to_revoke_not_found()
public void Should_return_same_clients_if_client_to_update_not_found()
{
sut.Revoke("2");
var clients_1 = clients_0.Update("2", AppClientPermission.Reader);
Assert.Single(sut);
Assert.Same(clients_0, clients_1);
}
[Fact]
public void Should_serialize_and_deserialize()
public void Should_revoke_client()
{
sut.Add("2", "my-secret");
sut.Add("3", "my-secret");
sut.Add("4", "my-secret");
sut["3"].Update(AppClientPermission.Editor);
var clients_1 = clients_0.Revoke("1");
sut["3"].Rename("My Client 3");
sut["2"].Rename("My Client 2");
sut.Revoke("4");
Assert.Empty(clients_1);
}
var appClients = JToken.FromObject(sut, serializer).ToObject<AppClients>(serializer);
[Fact]
public void Should_do_nothing_if_client_to_revoke_not_found()
{
var clients_1 = clients_0.Revoke("2");
appClients.ShouldBeEquivalentTo(sut);
Assert.NotSame(clients_0, clients_1);
}
}
}

35
tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppContributorsJsonTests.cs

@ -0,0 +1,35 @@
// ==========================================================================
// AppContributorsJsonTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using FluentAssertions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Squidex.Domain.Apps.Core.Apps;
using Xunit;
namespace Squidex.Domain.Apps.Core.Model.Apps
{
public class AppContributorsJsonTests
{
private readonly JsonSerializer serializer = TestData.DefaultSerializer();
[Fact]
public void Should_serialize_and_deserialize()
{
var contributors = AppContributors.Empty;
contributors = contributors.Assign("1", AppContributorPermission.Developer);
contributors = contributors.Assign("2", AppContributorPermission.Editor);
contributors = contributors.Assign("3", AppContributorPermission.Owner);
var serialized = JToken.FromObject(contributors, serializer).ToObject<AppContributors>(serializer);
serialized.ShouldBeEquivalentTo(contributors);
}
}
}

44
tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppContributorsTests.cs

@ -6,65 +6,51 @@
// All rights reserved.
// ==========================================================================
using FluentAssertions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Squidex.Domain.Apps.Core.Apps;
using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Core.Model.Apps
{
public class AppContributorsTests
{
private readonly JsonSerializer serializer = TestData.DefaultSerializer();
private readonly AppContributors sut = new AppContributors();
private readonly AppContributors contributors_0 = AppContributors.Empty;
[Fact]
public void Should_assign_new_contributor()
{
sut.Assign("1", AppContributorPermission.Developer);
sut.Assign("2", AppContributorPermission.Editor);
var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Developer);
var contributors_2 = contributors_1.Assign("2", AppContributorPermission.Editor);
Assert.Equal(AppContributorPermission.Developer, sut["1"]);
Assert.Equal(AppContributorPermission.Editor, sut["2"]);
Assert.Equal(AppContributorPermission.Developer, contributors_2["1"]);
Assert.Equal(AppContributorPermission.Editor, contributors_2["2"]);
}
[Fact]
public void Should_replace_contributor_if_already_exists()
{
sut.Assign("1", AppContributorPermission.Developer);
sut.Assign("1", AppContributorPermission.Owner);
var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Developer);
var contributors_2 = contributors_1.Assign("1", AppContributorPermission.Owner);
Assert.Equal(AppContributorPermission.Owner, sut["1"]);
Assert.Equal(AppContributorPermission.Owner, contributors_2["1"]);
}
[Fact]
public void Should_remove_contributor()
{
sut.Assign("1", AppContributorPermission.Developer);
sut.Remove("1");
var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Developer);
var contributors_2 = contributors_1.Remove("1");
Assert.Empty(sut);
Assert.Empty(contributors_2);
}
[Fact]
public void Should_do_nothing_if_contributor_to_remove_not_found()
{
sut.Remove("2");
Assert.Empty(sut);
}
[Fact]
public void Should_serialize_and_deserialize()
{
sut.Assign("1", AppContributorPermission.Developer);
sut.Assign("2", AppContributorPermission.Editor);
sut.Assign("3", AppContributorPermission.Owner);
var serialized = JToken.FromObject(sut, serializer).ToObject<AppContributors>(serializer);
var contributors_1 = contributors_0.Remove("2");
serialized.ShouldBeEquivalentTo(sut);
Assert.Empty(contributors_1);
}
}
}

115
tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/LanguagesConfigTests.cs

@ -20,27 +20,27 @@ namespace Squidex.Domain.Apps.Core.Model.Apps
public class LanguagesConfigTests
{
[Fact]
public void Should_create_initial_config()
public void Should_create_initial_config_0()
{
var config = LanguagesConfig.Build(Language.DE);
var config_0 = LanguagesConfig.Build(Language.DE);
config.OfType<LanguageConfig>().ToList().ShouldBeEquivalentTo(
config_0.OfType<LanguageConfig>().ToList().ShouldBeEquivalentTo(
new List<LanguageConfig>
{
new LanguageConfig(Language.DE)
});
Assert.Equal(Language.DE, config.Master.Language);
Assert.Equal(Language.DE, config_0.Master.Language);
Assert.Equal("de", ((IFieldPartitioning)config).Master.Key);
Assert.Equal("de", ((IFieldPartitioning)config_0).Master.Key);
}
[Fact]
public void Should_create_initial_config_with_multiple_languages()
public void Should_create_initial_config_0_with_multiple_languages()
{
var config = LanguagesConfig.Build(Language.DE, Language.EN, Language.IT);
var config_0 = LanguagesConfig.Build(Language.DE, Language.EN, Language.IT);
config.OfType<LanguageConfig>().ToList().ShouldBeEquivalentTo(
config_0.OfType<LanguageConfig>().ToList().ShouldBeEquivalentTo(
new List<LanguageConfig>
{
new LanguageConfig(Language.DE),
@ -48,12 +48,16 @@ namespace Squidex.Domain.Apps.Core.Model.Apps
new LanguageConfig(Language.IT)
});
Assert.Equal(Language.DE, config.Master.Language);
Assert.Equal(3, config.Count);
config_0.TryGetConfig(Language.DE, out var master);
Assert.Equal(Language.DE, config_0.Master.Language);
Assert.Equal(3, config_0.Count);
Assert.Same(master, config_0.Master);
}
[Fact]
public void Should_create_initial_config_with_configs()
public void Should_create_initial_config_0_with_config_0s()
{
var configs = new[]
{
@ -61,83 +65,82 @@ namespace Squidex.Domain.Apps.Core.Model.Apps
new LanguageConfig(Language.EN),
new LanguageConfig(Language.IT)
};
var config = LanguagesConfig.Build(configs);
var config_0 = LanguagesConfig.Build(configs);
config.OfType<LanguageConfig>().ToList().ShouldBeEquivalentTo(configs);
config_0.OfType<LanguageConfig>().ToList().ShouldBeEquivalentTo(configs);
Assert.Equal(configs[0], config.Master);
Assert.Equal(configs[0], config_0.Master);
Assert.Same(configs[0], config_0.Master);
}
[Fact]
public void Should_add_language()
{
var config = LanguagesConfig.Build(Language.DE);
config.Set(new LanguageConfig(Language.IT));
var config_0 = LanguagesConfig.Build(Language.DE);
var config_1 = config_0.Set(new LanguageConfig(Language.IT));
config.OfType<LanguageConfig>().ToList().ShouldBeEquivalentTo(
config_1.OfType<LanguageConfig>().ToList().ShouldBeEquivalentTo(
new List<LanguageConfig>
{
new LanguageConfig(Language.DE),
new LanguageConfig(Language.IT)
});
Assert.True(config.TryGetConfig(Language.IT, out var _));
Assert.True(config.Contains(Language.IT));
Assert.True(config_1.TryGetConfig(Language.IT, out var _));
Assert.True(config_1.Contains(Language.IT));
}
[Fact]
public void Should_make_first_language_to_master()
{
var config = LanguagesConfig.Build(Language.IT);
var config_0 = LanguagesConfig.Build(Language.IT);
Assert.Equal(Language.IT, config.Master.Language);
Assert.Equal(Language.IT, config_0.Master.Language);
}
[Fact]
public void Should_not_throw_exception_if_language_to_add_already_exists()
{
var config = LanguagesConfig.Build(Language.DE);
var config_0 = LanguagesConfig.Build(Language.DE);
config.Set(new LanguageConfig(Language.DE));
config_0.Set(new LanguageConfig(Language.DE));
}
[Fact]
public void Should_make_master_language()
{
var config = LanguagesConfig.Build(Language.DE);
var config_0 = LanguagesConfig.Build(Language.DE);
config.Set(new LanguageConfig(Language.UK));
config.Set(new LanguageConfig(Language.IT));
config.MakeMaster(Language.IT);
var config_1 = config_0.Set(new LanguageConfig(Language.UK));
var config_2 = config_1.Set(new LanguageConfig(Language.IT));
var config_3 = config_2.MakeMaster(Language.IT);
Assert.Equal(Language.IT, config.Master.Language);
Assert.Equal(Language.IT, config_3.Master.Language);
}
[Fact]
public void Should_throw_exception_if_language_to_make_master_is_not_found()
{
var config = LanguagesConfig.Build(Language.DE);
var config_0 = LanguagesConfig.Build(Language.DE);
Assert.Throws<KeyNotFoundException>(() => config.MakeMaster(Language.EN));
Assert.Throws<KeyNotFoundException>(() => config_0.MakeMaster(Language.EN));
}
[Fact]
public void Should_not_throw_exception_if_language_is_already_master_language()
{
var config = LanguagesConfig.Build(Language.DE);
var config_0 = LanguagesConfig.Build(Language.DE);
config.MakeMaster(Language.DE);
config_0.MakeMaster(Language.DE);
}
[Fact]
public void Should_remove_language()
{
var config = LanguagesConfig.Build(Language.DE, Language.IT, Language.RU);
var config_0 = LanguagesConfig.Build(Language.DE, Language.IT, Language.RU);
var config_1 = config_0.Remove(Language.IT);
config.Remove(Language.IT);
config.ToList().ShouldBeEquivalentTo(
config_1.ToList().ShouldBeEquivalentTo(
new List<LanguageConfig>
{
new LanguageConfig(Language.DE),
@ -148,15 +151,14 @@ namespace Squidex.Domain.Apps.Core.Model.Apps
[Fact]
public void Should_remove_fallbacks_when_removing_language()
{
var config =
var config_0 =
LanguagesConfig.Build(
new LanguageConfig(Language.DE),
new LanguageConfig(Language.IT, false, Language.RU, Language.IT),
new LanguageConfig(Language.RU, false, Language.DE, Language.IT));
var config_1 = config_0.Remove(Language.IT);
config.Remove(Language.IT);
config.OfType<LanguageConfig>().ToList().ShouldBeEquivalentTo(
config_1.OfType<LanguageConfig>().ToList().ShouldBeEquivalentTo(
new List<LanguageConfig>
{
new LanguageConfig(Language.DE),
@ -167,28 +169,27 @@ namespace Squidex.Domain.Apps.Core.Model.Apps
[Fact]
public void Should_not_throw_exception_if_language_to_remove_is_not_found()
{
var config = LanguagesConfig.Build(Language.DE);
var config_0 = LanguagesConfig.Build(Language.DE);
config.Remove(Language.EN);
config_0.Remove(Language.EN);
}
[Fact]
public void Should_hrow_exception_if_language_to_remove_is_master()
public void Should_throw_exception_if_language_to_remove_is_master()
{
var config = LanguagesConfig.Build(Language.DE);
var config_0 = LanguagesConfig.Build(Language.DE);
Assert.Throws<InvalidOperationException>(() => config.Remove(Language.DE));
Assert.Throws<InvalidOperationException>(() => config_0.Remove(Language.DE));
}
[Fact]
public void Should_update_language()
{
var config = LanguagesConfig.Build(Language.DE);
config.Set(new LanguageConfig(Language.IT));
config.Set(new LanguageConfig(Language.IT, true, Language.DE));
var config_0 = LanguagesConfig.Build(Language.DE);
var config_1 = config_0.Set(new LanguageConfig(Language.IT));
var config_2 = config_1.Set(new LanguageConfig(Language.IT, true, Language.DE));
config.OfType<LanguageConfig>().ToList().ShouldBeEquivalentTo(
config_2.OfType<LanguageConfig>().ToList().ShouldBeEquivalentTo(
new List<LanguageConfig>
{
new LanguageConfig(Language.DE),
@ -199,20 +200,20 @@ namespace Squidex.Domain.Apps.Core.Model.Apps
[Fact]
public void Should_throw_exception_if_fallback_language_is_invalid()
{
var config = LanguagesConfig.Build(Language.DE);
var config_0 = LanguagesConfig.Build(Language.DE);
Assert.Throws<InvalidOperationException>(() => config.Set(new LanguageConfig(Language.DE, false, Language.EN)));
Assert.Throws<InvalidOperationException>(() => config_0.Set(new LanguageConfig(Language.DE, false, Language.EN)));
}
[Fact]
public void Should_provide_enumerators()
{
var config = LanguagesConfig.Build(Language.DE);
var config_0 = LanguagesConfig.Build(Language.DE);
Assert.NotEmpty(config);
Assert.NotEmpty(config_0);
Assert.NotNull(((IEnumerable)config).GetEnumerator());
Assert.NotNull(((IEnumerable<IFieldPartitionItem>)config).GetEnumerator());
Assert.NotNull(((IEnumerable)config_0).GetEnumerator());
Assert.NotNull(((IEnumerable<IFieldPartitionItem>)config_0).GetEnumerator());
}
}
}

50
tests/Squidex.Domain.Apps.Core.Tests/Model/Rules/RuleTests.cs

@ -15,12 +15,14 @@ using Squidex.Domain.Apps.Core.Rules.Actions;
using Squidex.Domain.Apps.Core.Rules.Triggers;
using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Core.Model.Rules
{
public class RuleTests
{
private readonly JsonSerializer serializer = TestData.DefaultSerializer();
private readonly Rule sut = new Rule(new ContentChangedTrigger(), new WebhookAction());
private readonly Rule rule_0 = new Rule(new ContentChangedTrigger(), new WebhookAction());
public sealed class OtherTrigger : RuleTrigger
{
@ -54,18 +56,22 @@ namespace Squidex.Domain.Apps.Core.Model.Rules
[Fact]
public void Should_set_enabled_to_true_when_enabling()
{
sut.Enable();
var rule_1 = rule_0.Disable();
var rule_2 = rule_1.Enable();
var rule_3 = rule_2.Enable();
Assert.True(sut.IsEnabled);
Assert.False(rule_1.IsEnabled);
Assert.True(rule_3.IsEnabled);
}
[Fact]
public void Should_set_enabled_to_false_when_disabling()
{
sut.Enable();
sut.Disable();
var rule_1 = rule_0.Disable();
var rule_2 = rule_1.Disable();
Assert.False(sut.IsEnabled);
Assert.True(rule_0.IsEnabled);
Assert.False(rule_2.IsEnabled);
}
[Fact]
@ -73,15 +79,16 @@ namespace Squidex.Domain.Apps.Core.Model.Rules
{
var newTrigger = new ContentChangedTrigger();
sut.Update(newTrigger);
var rule_1 = rule_0.Update(newTrigger);
Assert.Same(newTrigger, sut.Trigger);
Assert.NotSame(newTrigger, rule_0.Trigger);
Assert.Same(newTrigger, rule_1.Trigger);
}
[Fact]
public void Should_throw_exception_when_new_trigger_has_other_type()
{
Assert.Throws<ArgumentException>(() => sut.Update(new OtherTrigger()));
Assert.Throws<ArgumentException>(() => rule_0.Update(new OtherTrigger()));
}
[Fact]
@ -89,25 +96,38 @@ namespace Squidex.Domain.Apps.Core.Model.Rules
{
var newAction = new WebhookAction();
sut.Update(newAction);
var rule_1 = rule_0.Update(newAction);
Assert.Same(newAction, sut.Action);
Assert.NotSame(newAction, rule_0.Action);
Assert.Same(newAction, rule_1.Action);
}
[Fact]
public void Should_throw_exception_when_new_action_has_other_type()
{
Assert.Throws<ArgumentException>(() => sut.Update(new OtherAction()));
Assert.Throws<ArgumentException>(() => rule_0.Update(new OtherAction()));
}
[Fact]
public void Should_serialize_and_deserialize()
{
sut.Disable();
var rule_1 = rule_0.Disable();
var appClients = JToken.FromObject(rule_1, serializer).ToObject<Rule>(serializer);
var appClients = JToken.FromObject(sut, serializer).ToObject<Rule>(serializer);
appClients.ShouldBeEquivalentTo(rule_0);
}
appClients.ShouldBeEquivalentTo(sut);
[Fact]
public void Should_freeze_webhook_action()
{
TestData.TestFreeze(new WebhookAction());
}
[Fact]
public void Should_freeze_contentchanged_trigger()
{
TestData.TestFreeze(new ContentChangedTrigger());
}
}
}

7
tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/ContentChangedTriggerTests.cs

@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.HandleRules;
using Squidex.Domain.Apps.Core.HandleRules.Triggers;
@ -67,8 +68,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules.Triggers
{
var trigger = new ContentChangedTrigger
{
Schemas = new List<ContentChangedTriggerSchema>
{
Schemas = ImmutableList.Create<ContentChangedTriggerSchema>(
new ContentChangedTriggerSchema
{
SendCreate = sendCreate == 1,
@ -76,8 +76,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules.Triggers
SendDelete = sendDelete == 1,
SendPublish = sendPublish == 1,
SchemaId = SchemaMatch.Id
}
}
})
};
var result = sut.Triggers(new Envelope<AppEvent>(@event), trigger);

48
tests/Squidex.Domain.Apps.Read.Tests/Contents/GraphQLTests.cs

@ -38,7 +38,7 @@ namespace Squidex.Domain.Apps.Read.Contents
private static readonly Guid schemaId = Guid.NewGuid();
private static readonly Guid appId = Guid.NewGuid();
private static readonly string appName = "my-app";
private readonly Schema schemaDef = new Schema("my-schema");
private readonly Schema schemaDef;
private readonly IContentQueryService contentQuery = A.Fake<IContentQueryService>();
private readonly IAssetRepository assetRepository = A.Fake<IAssetRepository>();
private readonly ISchemaEntity schema = A.Fake<ISchemaEntity>();
@ -50,32 +50,26 @@ namespace Squidex.Domain.Apps.Read.Contents
public GraphQLTests()
{
schemaDef.AddField(new JsonField(1, "my-json", Partitioning.Invariant,
new JsonFieldProperties()));
schemaDef.AddField(new StringField(2, "my-string", Partitioning.Language,
new StringFieldProperties()));
schemaDef.AddField(new NumberField(3, "my-number", Partitioning.Invariant,
new NumberFieldProperties()));
schemaDef.AddField(new AssetsField(4, "my-assets", Partitioning.Invariant,
new AssetsFieldProperties()));
schemaDef.AddField(new BooleanField(5, "my-boolean", Partitioning.Invariant,
new BooleanFieldProperties()));
schemaDef.AddField(new DateTimeField(6, "my-datetime", Partitioning.Invariant,
new DateTimeFieldProperties()));
schemaDef.AddField(new ReferencesField(7, "my-references", Partitioning.Invariant,
new ReferencesFieldProperties { SchemaId = schemaId }));
schemaDef.AddField(new ReferencesField(9, "my-invalid", Partitioning.Invariant,
new ReferencesFieldProperties { SchemaId = Guid.NewGuid() }));
schemaDef.AddField(new GeolocationField(10, "my-geolocation", Partitioning.Invariant,
new GeolocationFieldProperties()));
schemaDef =
new Schema("my-schema")
.AddField(new JsonField(1, "my-json", Partitioning.Invariant,
new JsonFieldProperties()))
.AddField(new StringField(2, "my-string", Partitioning.Language,
new StringFieldProperties()))
.AddField(new NumberField(3, "my-number", Partitioning.Invariant,
new NumberFieldProperties()))
.AddField(new AssetsField(4, "my-assets", Partitioning.Invariant,
new AssetsFieldProperties()))
.AddField(new BooleanField(5, "my-boolean", Partitioning.Invariant,
new BooleanFieldProperties()))
.AddField(new DateTimeField(6, "my-datetime", Partitioning.Invariant,
new DateTimeFieldProperties()))
.AddField(new ReferencesField(7, "my-references", Partitioning.Invariant,
new ReferencesFieldProperties { SchemaId = schemaId }))
.AddField(new ReferencesField(9, "my-invalid", Partitioning.Invariant,
new ReferencesFieldProperties { SchemaId = Guid.NewGuid() }))
.AddField(new GeolocationField(10, "my-geolocation", Partitioning.Invariant,
new GeolocationFieldProperties()));
A.CallTo(() => app.Id).Returns(appId);
A.CallTo(() => app.Name).Returns(appName);

46
tests/Squidex.Domain.Apps.Read.Tests/Contents/ODataQueryTests.cs

@ -7,6 +7,7 @@
// ==========================================================================
using System;
using System.Collections.Immutable;
using FakeItEasy;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
@ -29,7 +30,7 @@ namespace Squidex.Domain.Apps.Read.Contents
{
public class ODataQueryTests
{
private readonly Schema schemaDef = new Schema("user");
private readonly Schema schemaDef;
private readonly IBsonSerializerRegistry registry = BsonSerializer.SerializerRegistry;
private readonly IBsonSerializer<MongoContentEntity> serializer = BsonSerializer.SerializerRegistry.GetSerializer<MongoContentEntity>();
private readonly IEdmModel edmModel;
@ -42,30 +43,25 @@ namespace Squidex.Domain.Apps.Read.Contents
public ODataQueryTests()
{
schemaDef.Update(new SchemaProperties { Hints = "The User" });
schemaDef.AddField(new StringField(1, "firstName", Partitioning.Language,
new StringFieldProperties { Label = "FirstName", IsRequired = true, AllowedValues = new[] { "1", "2" } }));
schemaDef.AddField(new StringField(2, "lastName", Partitioning.Language,
new StringFieldProperties { Hints = "Last Name", Editor = StringFieldEditor.Input }));
schemaDef.AddField(new BooleanField(3, "isAdmin", Partitioning.Invariant,
new BooleanFieldProperties()));
schemaDef.AddField(new NumberField(4, "age", Partitioning.Invariant,
new NumberFieldProperties { MinValue = 1, MaxValue = 10 }));
schemaDef.AddField(new DateTimeField(5, "birthday", Partitioning.Invariant,
new DateTimeFieldProperties()));
schemaDef.AddField(new AssetsField(6, "pictures", Partitioning.Invariant,
new AssetsFieldProperties()));
schemaDef.AddField(new ReferencesField(7, "friends", Partitioning.Invariant,
new ReferencesFieldProperties()));
schemaDef.AddField(new StringField(8, "dashed-field", Partitioning.Invariant,
new StringFieldProperties()));
schemaDef =
new Schema("user")
.AddField(new StringField(1, "firstName", Partitioning.Language,
new StringFieldProperties { Label = "FirstName", IsRequired = true, AllowedValues = ImmutableList.Create("1", "2") }))
.AddField(new StringField(2, "lastName", Partitioning.Language,
new StringFieldProperties { Hints = "Last Name", Editor = StringFieldEditor.Input }))
.AddField(new BooleanField(3, "isAdmin", Partitioning.Invariant,
new BooleanFieldProperties()))
.AddField(new NumberField(4, "age", Partitioning.Invariant,
new NumberFieldProperties { MinValue = 1, MaxValue = 10 }))
.AddField(new DateTimeField(5, "birthday", Partitioning.Invariant,
new DateTimeFieldProperties()))
.AddField(new AssetsField(6, "pictures", Partitioning.Invariant,
new AssetsFieldProperties()))
.AddField(new ReferencesField(7, "friends", Partitioning.Invariant,
new ReferencesFieldProperties()))
.AddField(new StringField(8, "dashed-field", Partitioning.Invariant,
new StringFieldProperties()))
.Update(new SchemaProperties { Hints = "The User" });
var builder = new EdmModelBuilder(new MemoryCache(Options.Create(new MemoryCacheOptions())));

6
tests/Squidex.Domain.Apps.Read.Tests/Rules/RuleEnqueuerTests.cs

@ -74,9 +74,9 @@ namespace Squidex.Domain.Apps.Read.Rules
var ruleEntity2 = A.Fake<IRuleEntity>();
var ruleEntity3 = A.Fake<IRuleEntity>();
A.CallTo(() => ruleEntity1.Rule).Returns(rule1);
A.CallTo(() => ruleEntity2.Rule).Returns(rule2);
A.CallTo(() => ruleEntity3.Rule).Returns(rule3);
A.CallTo(() => ruleEntity1.RuleDef).Returns(rule1);
A.CallTo(() => ruleEntity2.RuleDef).Returns(rule2);
A.CallTo(() => ruleEntity3.RuleDef).Returns(rule3);
A.CallTo(() => appProvider.GetRulesAsync(appId.Name))
.Returns(new List<IRuleEntity> { ruleEntity1, ruleEntity2, ruleEntity3 });

46
tests/Squidex.Domain.Apps.Write.Tests/Apps/Guards/GuardAppClientsTests.cs

@ -11,18 +11,20 @@ using Squidex.Domain.Apps.Write.Apps.Commands;
using Squidex.Infrastructure;
using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Write.Apps.Guards
{
public class GuardAppClientsTests
{
private readonly AppClients clients = new AppClients();
private readonly AppClients clients_0 = AppClients.Empty;
[Fact]
public void CanAttach_should_throw_execption_if_client_id_is_null()
{
var command = new AttachClient();
Assert.Throws<ValidationException>(() => GuardAppClients.CanAttach(clients, command));
Assert.Throws<ValidationException>(() => GuardAppClients.CanAttach(clients_0, command));
}
[Fact]
@ -30,9 +32,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new AttachClient { Id = "android" };
clients.Add("android", "secret");
var clients_1 = clients_0.Add("android", "secret");
Assert.Throws<ValidationException>(() => GuardAppClients.CanAttach(clients, command));
Assert.Throws<ValidationException>(() => GuardAppClients.CanAttach(clients_1, command));
}
[Fact]
@ -40,9 +42,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new AttachClient { Id = "ios" };
clients.Add("android", "secret");
var clients_1 = clients_0.Add("android", "secret");
GuardAppClients.CanAttach(clients, command);
GuardAppClients.CanAttach(clients_1, command);
}
[Fact]
@ -50,7 +52,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RevokeClient();
Assert.Throws<ValidationException>(() => GuardAppClients.CanRevoke(clients, command));
Assert.Throws<ValidationException>(() => GuardAppClients.CanRevoke(clients_0, command));
}
[Fact]
@ -58,7 +60,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RevokeClient { Id = "ios" };
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppClients.CanRevoke(clients, command));
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppClients.CanRevoke(clients_0, command));
}
[Fact]
@ -66,9 +68,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RevokeClient { Id = "ios" };
clients.Add("ios", "secret");
var clients_1 = clients_0.Add("ios", "secret");
GuardAppClients.CanRevoke(clients, command);
GuardAppClients.CanRevoke(clients_1, command);
}
[Fact]
@ -76,7 +78,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new UpdateClient();
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients, command));
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients_0, command));
}
[Fact]
@ -84,7 +86,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new UpdateClient { Id = "ios", Name = "iOS" };
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppClients.CanUpdate(clients, command));
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppClients.CanUpdate(clients_0, command));
}
[Fact]
@ -92,9 +94,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new UpdateClient { Id = "ios" };
clients.Add("ios", "secret");
var clients_1 = clients_0.Add("ios", "secret");
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients, command));
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients_1, command));
}
[Fact]
@ -102,9 +104,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new UpdateClient { Id = "ios", Permission = (AppClientPermission)10 };
clients.Add("ios", "secret");
var clients_1 = clients_0.Add("ios", "secret");
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients, command));
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients_1, command));
}
[Fact]
@ -112,9 +114,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new UpdateClient { Id = "ios", Name = "ios" };
clients.Add("ios", "secret");
var clients_1 = clients_0.Add("ios", "secret");
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients, command));
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients_1, command));
}
[Fact]
@ -122,9 +124,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new UpdateClient { Id = "ios", Permission = AppClientPermission.Editor };
clients.Add("ios", "secret");
var clients_1 = clients_0.Add("ios", "secret");
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients, command));
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients_1, command));
}
[Fact]
@ -132,9 +134,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new UpdateClient { Id = "ios", Name = "iOS", Permission = AppClientPermission.Reader };
clients.Add("ios", "secret");
var clients_1 = clients_0.Add("ios", "secret");
GuardAppClients.CanUpdate(clients, command);
GuardAppClients.CanUpdate(clients_1, command);
}
}
}

48
tests/Squidex.Domain.Apps.Write.Tests/Apps/Guards/GuardAppContributorsTests.cs

@ -15,13 +15,15 @@ using Squidex.Infrastructure;
using Squidex.Shared.Users;
using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Write.Apps.Guards
{
public class GuardAppContributorsTests
{
private readonly IUserResolver users = A.Fake<IUserResolver>();
private readonly IAppLimitsPlan appPlan = A.Fake<IAppLimitsPlan>();
private readonly AppContributors contributors = new AppContributors();
private readonly AppContributors contributors_0 = AppContributors.Empty;
public GuardAppContributorsTests()
{
@ -37,7 +39,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new AssignContributor();
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors, command, users, appPlan));
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan));
}
[Fact]
@ -45,7 +47,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new AssignContributor { ContributorId = "1", Permission = (AppContributorPermission)10 };
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors, command, users, appPlan));
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan));
}
[Fact]
@ -53,9 +55,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new AssignContributor { ContributorId = "1" };
contributors.Assign("1", AppContributorPermission.Owner);
var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Owner);
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors, command, users, appPlan));
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors_1, command, users, appPlan));
}
[Fact]
@ -66,7 +68,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
var command = new AssignContributor { ContributorId = "1", Permission = (AppContributorPermission)10 };
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors, command, users, appPlan));
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan));
}
[Fact]
@ -77,10 +79,10 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
var command = new AssignContributor { ContributorId = "3" };
contributors.Assign("1", AppContributorPermission.Owner);
contributors.Assign("2", AppContributorPermission.Editor);
var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Owner);
var contributors_2 = contributors_1.Assign("2", AppContributorPermission.Editor);
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors, command, users, appPlan));
return Assert.ThrowsAsync<ValidationException>(() => GuardAppContributors.CanAssign(contributors_2, command, users, appPlan));
}
[Fact]
@ -88,7 +90,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new AssignContributor { ContributorId = "1" };
return GuardAppContributors.CanAssign(contributors, command, users, appPlan);
return GuardAppContributors.CanAssign(contributors_0, command, users, appPlan);
}
[Fact]
@ -96,9 +98,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new AssignContributor { ContributorId = "1" };
contributors.Assign("1", AppContributorPermission.Editor);
var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Editor);
return GuardAppContributors.CanAssign(contributors, command, users, appPlan);
return GuardAppContributors.CanAssign(contributors_1, command, users, appPlan);
}
[Fact]
@ -109,10 +111,10 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
var command = new AssignContributor { ContributorId = "1" };
contributors.Assign("1", AppContributorPermission.Editor);
contributors.Assign("2", AppContributorPermission.Editor);
var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Editor);
var contributors_2 = contributors_1.Assign("2", AppContributorPermission.Editor);
return GuardAppContributors.CanAssign(contributors, command, users, appPlan);
return GuardAppContributors.CanAssign(contributors_2, command, users, appPlan);
}
[Fact]
@ -120,7 +122,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RemoveContributor();
Assert.Throws<ValidationException>(() => GuardAppContributors.CanRemove(contributors, command));
Assert.Throws<ValidationException>(() => GuardAppContributors.CanRemove(contributors_0, command));
}
[Fact]
@ -128,7 +130,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RemoveContributor { ContributorId = "1" };
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppContributors.CanRemove(contributors, command));
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppContributors.CanRemove(contributors_0, command));
}
[Fact]
@ -136,10 +138,10 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RemoveContributor { ContributorId = "1" };
contributors.Assign("1", AppContributorPermission.Owner);
contributors.Assign("2", AppContributorPermission.Editor);
var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Owner);
var contributors_2 = contributors_1.Assign("2", AppContributorPermission.Editor);
Assert.Throws<ValidationException>(() => GuardAppContributors.CanRemove(contributors, command));
Assert.Throws<ValidationException>(() => GuardAppContributors.CanRemove(contributors_2, command));
}
[Fact]
@ -147,10 +149,10 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RemoveContributor { ContributorId = "1" };
contributors.Assign("1", AppContributorPermission.Owner);
contributors.Assign("2", AppContributorPermission.Owner);
var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Owner);
var contributors_2 = contributors_1.Assign("2", AppContributorPermission.Owner);
GuardAppContributors.CanRemove(contributors, command);
GuardAppContributors.CanRemove(contributors_2, command);
}
}
}

40
tests/Squidex.Domain.Apps.Write.Tests/Apps/Guards/GuardAppLanguagesTests.cs

@ -12,18 +12,20 @@ using Squidex.Domain.Apps.Write.Apps.Commands;
using Squidex.Infrastructure;
using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Write.Apps.Guards
{
public class GuardAppLanguagesTests
{
private readonly LanguagesConfig languages = LanguagesConfig.Build(Language.DE);
private readonly LanguagesConfig languages_0 = LanguagesConfig.Build(Language.DE);
[Fact]
public void CanAddLanguage_should_throw_exception_if_language_is_null()
{
var command = new AddLanguage();
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanAdd(languages, command));
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanAdd(languages_0, command));
}
[Fact]
@ -31,7 +33,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new AddLanguage { Language = Language.DE };
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanAdd(languages, command));
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanAdd(languages_0, command));
}
[Fact]
@ -39,7 +41,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new AddLanguage { Language = Language.EN };
GuardAppLanguages.CanAdd(languages, command);
GuardAppLanguages.CanAdd(languages_0, command);
}
[Fact]
@ -47,7 +49,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RemoveLanguage();
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanRemove(languages, command));
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanRemove(languages_0, command));
}
[Fact]
@ -55,7 +57,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RemoveLanguage { Language = Language.EN };
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppLanguages.CanRemove(languages, command));
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppLanguages.CanRemove(languages_0, command));
}
[Fact]
@ -63,7 +65,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RemoveLanguage { Language = Language.DE };
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanRemove(languages, command));
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanRemove(languages_0, command));
}
[Fact]
@ -71,9 +73,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RemoveLanguage { Language = Language.EN };
languages.Set(new LanguageConfig(Language.EN));
var languages_1 = languages_0.Set(new LanguageConfig(Language.EN));
GuardAppLanguages.CanRemove(languages, command);
GuardAppLanguages.CanRemove(languages_1, command);
}
[Fact]
@ -81,9 +83,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new UpdateLanguage();
languages.Set(new LanguageConfig(Language.EN));
var languages_1 = languages_0.Set(new LanguageConfig(Language.EN));
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanUpdate(languages, command));
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanUpdate(languages_1, command));
}
[Fact]
@ -91,9 +93,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new UpdateLanguage { Language = Language.DE, IsOptional = true };
languages.Set(new LanguageConfig(Language.EN));
var languages_1 = languages_0.Set(new LanguageConfig(Language.EN));
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanUpdate(languages, command));
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanUpdate(languages_1, command));
}
[Fact]
@ -101,9 +103,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new UpdateLanguage { Language = Language.DE, Fallback = new List<Language> { Language.IT } };
languages.Set(new LanguageConfig(Language.EN));
var languages_1 = languages_0.Set(new LanguageConfig(Language.EN));
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanUpdate(languages, command));
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanUpdate(languages_1, command));
}
[Fact]
@ -111,9 +113,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new UpdateLanguage { Language = Language.IT };
languages.Set(new LanguageConfig(Language.EN));
var languages_1 = languages_0.Set(new LanguageConfig(Language.EN));
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppLanguages.CanUpdate(languages, command));
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppLanguages.CanUpdate(languages_1, command));
}
[Fact]
@ -121,9 +123,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new UpdateLanguage { Language = Language.DE, Fallback = new List<Language> { Language.EN } };
languages.Set(new LanguageConfig(Language.EN));
var languages_1 = languages_0.Set(new LanguageConfig(Language.EN));
GuardAppLanguages.CanUpdate(languages, command);
GuardAppLanguages.CanUpdate(languages_1, command);
}
}
}

12
tests/Squidex.Domain.Apps.Write.Tests/Contents/ContentCommandMiddlewareTests.cs

@ -59,12 +59,12 @@ namespace Squidex.Domain.Apps.Write.Contents
public ContentCommandMiddlewareTests()
{
var schemaDef = new Schema("my-schema");
schemaDef.AddField(new NumberField(1, "my-field1", Partitioning.Invariant,
new NumberFieldProperties { IsRequired = true }));
schemaDef.AddField(new NumberField(2, "my-field2", Partitioning.Invariant,
new NumberFieldProperties { IsRequired = false }));
var schemaDef =
new Schema("my-schema")
.AddField(new NumberField(1, "my-field1", Partitioning.Invariant,
new NumberFieldProperties { IsRequired = true }))
.AddField(new NumberField(2, "my-field2", Partitioning.Invariant,
new NumberFieldProperties { IsRequired = false }));
content = new ContentDomainObject(contentId, -1);

63
tests/Squidex.Domain.Apps.Write.Tests/Rules/Guards/GuardRuleTests.cs

@ -7,7 +7,7 @@
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
using FakeItEasy;
using Squidex.Domain.Apps.Core.Rules;
@ -19,12 +19,14 @@ using Squidex.Domain.Apps.Write.Rules.Commands;
using Squidex.Infrastructure;
using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Write.Rules.Guards
{
public class GuardRuleTests
{
private readonly Uri validUrl = new Uri("https://squidex.io");
private readonly Rule rule = new Rule(new ContentChangedTrigger(), new WebhookAction());
private readonly Rule rule_0 = new Rule(new ContentChangedTrigger(), new WebhookAction());
private readonly NamedId<Guid> appId = new NamedId<Guid>(Guid.NewGuid(), "my-app");
private readonly IAppProvider appProvider = A.Fake<IAppProvider>();
@ -37,15 +39,14 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards
[Fact]
public async Task CanCreate_should_throw_exception_if_trigger_null()
{
var command = new CreateRule
var command = CreateCommand(new CreateRule
{
Trigger = null,
Action = new WebhookAction
{
Url = validUrl
},
AppId = appId
};
}
});
await Assert.ThrowsAsync<ValidationException>(() => GuardRule.CanCreate(command, appProvider));
}
@ -53,15 +54,14 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards
[Fact]
public async Task CanCreate_should_throw_exception_if_action_null()
{
var command = new CreateRule
var command = CreateCommand(new CreateRule
{
Trigger = new ContentChangedTrigger
{
Schemas = new List<ContentChangedTriggerSchema>()
Schemas = ImmutableList<ContentChangedTriggerSchema>.Empty
},
Action = null,
AppId = appId
};
Action = null
});
await Assert.ThrowsAsync<ValidationException>(() => GuardRule.CanCreate(command, appProvider));
}
@ -69,18 +69,17 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards
[Fact]
public async Task CanCreate_should_not_throw_exception_if_trigger_and_action_valid()
{
var command = new CreateRule
var command = CreateCommand(new CreateRule
{
Trigger = new ContentChangedTrigger
{
Schemas = new List<ContentChangedTriggerSchema>()
Schemas = ImmutableList<ContentChangedTriggerSchema>.Empty
},
Action = new WebhookAction
{
Url = validUrl
},
AppId = appId
};
}
});
await GuardRule.CanCreate(command, appProvider);
}
@ -96,18 +95,17 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards
[Fact]
public async Task CanUpdate_should_not_throw_exception_if_trigger_and_action_valid()
{
var command = new UpdateRule
var command = CreateCommand(new UpdateRule
{
Trigger = new ContentChangedTrigger
{
Schemas = new List<ContentChangedTriggerSchema>()
Schemas = ImmutableList<ContentChangedTriggerSchema>.Empty
},
Action = new WebhookAction
{
Url = validUrl
},
AppId = appId
};
}
});
await GuardRule.CanUpdate(command, appProvider);
}
@ -117,9 +115,9 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards
{
var command = new EnableRule();
rule.Enable();
var rule_1 = rule_0.Enable();
Assert.Throws<ValidationException>(() => GuardRule.CanEnable(command, rule));
Assert.Throws<ValidationException>(() => GuardRule.CanEnable(command, rule_1));
}
[Fact]
@ -127,9 +125,9 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards
{
var command = new EnableRule();
rule.Disable();
var rule_1 = rule_0.Disable();
GuardRule.CanEnable(command, rule);
GuardRule.CanEnable(command, rule_1);
}
[Fact]
@ -137,9 +135,9 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards
{
var command = new DisableRule();
rule.Disable();
var rule_1 = rule_0.Disable();
Assert.Throws<ValidationException>(() => GuardRule.CanDisable(command, rule));
Assert.Throws<ValidationException>(() => GuardRule.CanDisable(command, rule_1));
}
[Fact]
@ -147,9 +145,9 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards
{
var command = new DisableRule();
rule.Enable();
var rule_1 = rule_0.Enable();
GuardRule.CanDisable(command, rule);
GuardRule.CanDisable(command, rule_1);
}
[Fact]
@ -159,5 +157,12 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards
GuardRule.CanDelete(command);
}
private T CreateCommand<T>(T command) where T : AppCommand
{
command.AppId = appId;
return command;
}
}
}

14
tests/Squidex.Domain.Apps.Write.Tests/Rules/Guards/Triggers/ContentChangedTriggerTests.cs

@ -7,7 +7,7 @@
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
using FakeItEasy;
using Squidex.Domain.Apps.Core.Rules.Triggers;
@ -30,10 +30,9 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards.Triggers
var trigger = new ContentChangedTrigger
{
Schemas = new List<ContentChangedTriggerSchema>
{
Schemas = ImmutableList.Create(
new ContentChangedTriggerSchema()
}
)
};
var errors = await RuleTriggerValidator.ValidateAsync(appName, trigger, appProvider);
@ -56,7 +55,7 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards.Triggers
{
var trigger = new ContentChangedTrigger
{
Schemas = new List<ContentChangedTriggerSchema>()
Schemas = ImmutableList<ContentChangedTriggerSchema>.Empty
};
var errors = await RuleTriggerValidator.ValidateAsync(appName, trigger, appProvider);
@ -72,10 +71,9 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards.Triggers
var trigger = new ContentChangedTrigger
{
Schemas = new List<ContentChangedTriggerSchema>
{
Schemas = ImmutableList.Create(
new ContentChangedTriggerSchema()
}
)
};
var errors = await RuleTriggerValidator.ValidateAsync(appName, trigger, appProvider);

3
tests/Squidex.Domain.Apps.Write.Tests/Rules/RuleDomainObjectTests.cs

@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Squidex.Domain.Apps.Core.Rules;
using Squidex.Domain.Apps.Core.Rules.Actions;
using Squidex.Domain.Apps.Core.Rules.Triggers;
@ -83,7 +84,7 @@ namespace Squidex.Domain.Apps.Write.Rules
{
var newTrigger = new ContentChangedTrigger
{
Schemas = new List<ContentChangedTriggerSchema>()
Schemas = ImmutableList<ContentChangedTriggerSchema>.Empty
};
var newAction = new WebhookAction

5
tests/Squidex.Domain.Apps.Write.Tests/Schemas/Guards/FieldProperties/NumberFieldPropertiesTests.cs

@ -7,6 +7,7 @@
// ==========================================================================
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using FluentAssertions;
using Squidex.Domain.Apps.Core.Schemas;
@ -77,7 +78,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards.FieldProperties
[Fact]
public void Should_add_error_if_allowed_values_and_max_value_is_specified()
{
var sut = new NumberFieldProperties { MaxValue = 10, AllowedValues = new[] { 4d } };
var sut = new NumberFieldProperties { MaxValue = 10, AllowedValues = ImmutableList.Create(4d) };
var errors = FieldPropertiesValidator.Validate(sut).ToList();
@ -91,7 +92,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards.FieldProperties
[Fact]
public void Should_add_error_if_allowed_values_and_min_value_is_specified()
{
var sut = new NumberFieldProperties { MinValue = 10, AllowedValues = new[] { 4d } };
var sut = new NumberFieldProperties { MinValue = 10, AllowedValues = ImmutableList.Create(4d) };
var errors = FieldPropertiesValidator.Validate(sut).ToList();

5
tests/Squidex.Domain.Apps.Write.Tests/Schemas/Guards/FieldProperties/StringFieldPropertiesTests.cs

@ -7,6 +7,7 @@
// ==========================================================================
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using FluentAssertions;
using Squidex.Domain.Apps.Core.Schemas;
@ -34,7 +35,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards.FieldProperties
[Fact]
public void Should_add_error_if_allowed_values_and_max_value_is_specified()
{
var sut = new StringFieldProperties { MinLength = 10, AllowedValues = new[] { "4" } };
var sut = new StringFieldProperties { MinLength = 10, AllowedValues = ImmutableList.Create("4") };
var errors = FieldPropertiesValidator.Validate(sut).ToList();
@ -48,7 +49,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards.FieldProperties
[Fact]
public void Should_add_error_if_allowed_values_and_min_value_is_specified()
{
var sut = new StringFieldProperties { MaxLength = 10, AllowedValues = new string[] { "4" } };
var sut = new StringFieldProperties { MaxLength = 10, AllowedValues = ImmutableList.Create("4") };
var errors = FieldPropertiesValidator.Validate(sut).ToList();

74
tests/Squidex.Domain.Apps.Write.Tests/Schemas/Guards/GuardSchemaFieldTests.cs

@ -13,18 +13,22 @@ using Squidex.Domain.Apps.Write.Schemas.Guards;
using Squidex.Infrastructure;
using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Write.Schemas
{
public class GuardSchemaFieldTests
{
private readonly Schema schema = new Schema("my-schema");
private readonly Schema schema_0;
private readonly StringFieldProperties validProperties = new StringFieldProperties();
private readonly StringFieldProperties invalidProperties = new StringFieldProperties { MinLength = 10, MaxLength = 5 };
public GuardSchemaFieldTests()
{
schema.AddField(new StringField(1, "field1", Partitioning.Invariant));
schema.AddField(new StringField(2, "field2", Partitioning.Invariant));
schema_0 =
new Schema("my-schema")
.AddField(new StringField(1, "field1", Partitioning.Invariant))
.AddField(new StringField(2, "field2", Partitioning.Invariant));
}
[Fact]
@ -32,9 +36,9 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new HideField { FieldId = 1 };
schema.FieldsById[1].Hide();
var schema_1 = schema_0.HideField(1);
Assert.Throws<DomainException>(() => GuardSchemaField.CanHide(schema, command));
Assert.Throws<DomainException>(() => GuardSchemaField.CanHide(schema_1, command));
}
[Fact]
@ -42,7 +46,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new HideField { FieldId = 3 };
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanHide(schema, command));
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanHide(schema_0, command));
}
[Fact]
@ -50,7 +54,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new HideField { FieldId = 1 };
GuardSchemaField.CanHide(schema, command);
GuardSchemaField.CanHide(schema_0, command);
}
[Fact]
@ -58,9 +62,9 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new DisableField { FieldId = 1 };
schema.FieldsById[1].Disable();
var schema_1 = schema_0.DisableField(1);
Assert.Throws<DomainException>(() => GuardSchemaField.CanDisable(schema, command));
Assert.Throws<DomainException>(() => GuardSchemaField.CanDisable(schema_1, command));
}
[Fact]
@ -68,7 +72,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new DisableField { FieldId = 3 };
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanDisable(schema, command));
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanDisable(schema_0, command));
}
[Fact]
@ -76,7 +80,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new DisableField { FieldId = 1 };
GuardSchemaField.CanDisable(schema, command);
GuardSchemaField.CanDisable(schema_0, command);
}
[Fact]
@ -84,7 +88,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new ShowField { FieldId = 1 };
Assert.Throws<DomainException>(() => GuardSchemaField.CanShow(schema, command));
Assert.Throws<DomainException>(() => GuardSchemaField.CanShow(schema_0, command));
}
[Fact]
@ -92,7 +96,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new ShowField { FieldId = 3 };
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanShow(schema, command));
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanShow(schema_0, command));
}
[Fact]
@ -100,9 +104,9 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new ShowField { FieldId = 1 };
schema.FieldsById[1].Hide();
var schema_1 = schema_0.HideField(1);
GuardSchemaField.CanShow(schema, command);
GuardSchemaField.CanShow(schema_1, command);
}
[Fact]
@ -110,7 +114,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new EnableField { FieldId = 1 };
Assert.Throws<DomainException>(() => GuardSchemaField.CanEnable(schema, command));
Assert.Throws<DomainException>(() => GuardSchemaField.CanEnable(schema_0, command));
}
[Fact]
@ -118,7 +122,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new EnableField { FieldId = 3 };
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanEnable(schema, command));
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanEnable(schema_0, command));
}
[Fact]
@ -126,9 +130,9 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new EnableField { FieldId = 1 };
schema.FieldsById[1].Disable();
var schema_1 = schema_0.DisableField(1);
GuardSchemaField.CanEnable(schema, command);
GuardSchemaField.CanEnable(schema_1, command);
}
[Fact]
@ -136,9 +140,9 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new LockField { FieldId = 1 };
schema.FieldsById[1].Lock();
var schema_1 = schema_0.LockField(1);
Assert.Throws<DomainException>(() => GuardSchemaField.CanLock(schema, command));
Assert.Throws<DomainException>(() => GuardSchemaField.CanLock(schema_1, command));
}
[Fact]
@ -146,7 +150,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new LockField { FieldId = 3 };
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanLock(schema, command));
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanLock(schema_0, command));
}
[Fact]
@ -154,7 +158,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new LockField { FieldId = 1 };
GuardSchemaField.CanLock(schema, command);
GuardSchemaField.CanLock(schema_0, command);
}
[Fact]
@ -162,7 +166,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new DeleteField { FieldId = 3 };
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanDelete(schema, command));
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanDelete(schema_0, command));
}
[Fact]
@ -170,9 +174,9 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new DeleteField { FieldId = 1 };
schema.FieldsById[1].Lock();
var schema_1 = schema_0.LockField(1);
Assert.Throws<DomainException>(() => GuardSchemaField.CanDelete(schema, command));
Assert.Throws<DomainException>(() => GuardSchemaField.CanDelete(schema_1, command));
}
[Fact]
@ -180,7 +184,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new DeleteField { FieldId = 1 };
GuardSchemaField.CanDelete(schema, command);
GuardSchemaField.CanDelete(schema_0, command);
}
[Fact]
@ -188,9 +192,9 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new UpdateField { FieldId = 1, Properties = new StringFieldProperties() };
schema.FieldsById[1].Lock();
var schema_1 = schema_0.LockField(1);
Assert.Throws<DomainException>(() => GuardSchemaField.CanUpdate(schema, command));
Assert.Throws<DomainException>(() => GuardSchemaField.CanUpdate(schema_1, command));
}
[Fact]
@ -198,7 +202,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new UpdateField { FieldId = 1, Properties = new StringFieldProperties() };
GuardSchemaField.CanUpdate(schema, command);
GuardSchemaField.CanUpdate(schema_0, command);
}
[Fact]
@ -206,7 +210,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new AddField { Name = "field1", Properties = new StringFieldProperties() };
Assert.Throws<ValidationException>(() => GuardSchemaField.CanAdd(schema, command));
Assert.Throws<ValidationException>(() => GuardSchemaField.CanAdd(schema_0, command));
}
[Fact]
@ -214,7 +218,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new AddField { Name = "INVALID_NAME", Properties = validProperties };
Assert.Throws<ValidationException>(() => GuardSchemaField.CanAdd(schema, command));
Assert.Throws<ValidationException>(() => GuardSchemaField.CanAdd(schema_0, command));
}
[Fact]
@ -222,7 +226,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new AddField { Name = "field3", Properties = invalidProperties };
Assert.Throws<ValidationException>(() => GuardSchemaField.CanAdd(schema, command));
Assert.Throws<ValidationException>(() => GuardSchemaField.CanAdd(schema_0, command));
}
[Fact]
@ -230,7 +234,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new AddField { Name = "field3", Partitioning = "INVALID_PARTITIONING", Properties = validProperties };
Assert.Throws<ValidationException>(() => GuardSchemaField.CanAdd(schema, command));
Assert.Throws<ValidationException>(() => GuardSchemaField.CanAdd(schema_0, command));
}
[Fact]
@ -238,7 +242,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{
var command = new AddField { Name = "field3", Properties = new StringFieldProperties() };
GuardSchemaField.CanAdd(schema, command);
GuardSchemaField.CanAdd(schema_0, command);
}
}
}

30
tests/Squidex.Domain.Apps.Write.Tests/Schemas/Guards/GuardSchemaTests.cs

@ -18,18 +18,22 @@ using Squidex.Domain.Apps.Write.Schemas.Commands;
using Squidex.Infrastructure;
using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Write.Schemas.Guards
{
public class GuardSchemaTests
{
private readonly IAppProvider appProvider = A.Fake<IAppProvider>();
private readonly Schema schema = new Schema("my-schema");
private readonly Schema schema_0;
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));
schema_0 =
new Schema("my-schema")
.AddField(new StringField(1, "field1", Partitioning.Invariant))
.AddField(new StringField(2, "field2", Partitioning.Invariant));
A.CallTo(() => appProvider.GetSchemaAsync(A<string>.Ignored, "new-schema", false))
.Returns(Task.FromResult<ISchemaEntity>(null));
@ -121,9 +125,9 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
{
var command = new PublishSchema();
schema.Publish();
var schema_1 = schema_0.Publish();
Assert.Throws<DomainException>(() => GuardSchema.CanPublish(schema, command));
Assert.Throws<DomainException>(() => GuardSchema.CanPublish(schema_1, command));
}
[Fact]
@ -131,7 +135,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
{
var command = new PublishSchema();
GuardSchema.CanPublish(schema, command);
GuardSchema.CanPublish(schema_0, command);
}
[Fact]
@ -139,7 +143,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
{
var command = new UnpublishSchema();
Assert.Throws<DomainException>(() => GuardSchema.CanUnpublish(schema, command));
Assert.Throws<DomainException>(() => GuardSchema.CanUnpublish(schema_0, command));
}
[Fact]
@ -147,9 +151,9 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
{
var command = new UnpublishSchema();
schema.Publish();
var schema_1 = schema_0.Publish();
GuardSchema.CanUnpublish(schema, command);
GuardSchema.CanUnpublish(schema_1, command);
}
[Fact]
@ -157,7 +161,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
{
var command = new ReorderFields { FieldIds = new List<long> { 1, 3 } };
Assert.Throws<ValidationException>(() => GuardSchema.CanReorder(schema, command));
Assert.Throws<ValidationException>(() => GuardSchema.CanReorder(schema_0, command));
}
[Fact]
@ -165,7 +169,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
{
var command = new ReorderFields { FieldIds = new List<long> { 1 } };
Assert.Throws<ValidationException>(() => GuardSchema.CanReorder(schema, command));
Assert.Throws<ValidationException>(() => GuardSchema.CanReorder(schema_0, command));
}
[Fact]
@ -173,7 +177,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
{
var command = new ReorderFields { FieldIds = new List<long> { 1, 2 } };
GuardSchema.CanReorder(schema, command);
GuardSchema.CanReorder(schema_0, command);
}
[Fact]
@ -181,7 +185,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
{
var command = new DeleteSchema();
GuardSchema.CanDelete(schema, command);
GuardSchema.CanDelete(schema_0, command);
}
private static StringFieldProperties ValidProperties()

73
tests/Squidex.Infrastructure.Tests/Json/Orleans/JsonExternalSerializerTests.cs

@ -17,45 +17,18 @@ namespace Squidex.Infrastructure.Json.Orleans
{
public class JsonExternalSerializerTests
{
/*
class Context : ISerializationContext
{
public IBinaryTokenStreamWriter StreamWriter => throw new NotImplementedException();
public int CurrentOffset => throw new NotImplementedException();
public IServiceProvider ServiceProvider => throw new NotImplementedException();
public object AdditionalContext => throw new NotImplementedException();
public int CheckObjectWhileSerializing(object raw)
{
return 0;
}
public void RecordObject(object original, int offset)
{
}
public void SerializeInner(object obj, Type expected)
{
}
}*/
private readonly JsonExternalSerializer sut = new JsonExternalSerializer(JsonSerializer.CreateDefault());
public JsonExternalSerializerTests()
{
}
[Fact]
public void Should_serialize_js_only()
{
Assert.True(sut.IsSupportedType(typeof(J<int>)));
Assert.True(sut.IsSupportedType(typeof(J<List<int>>)));
var serializer = new JsonExternalSerializer(JsonSerializer.CreateDefault(), typeof(int), typeof(bool));
Assert.False(sut.IsSupportedType(typeof(int)));
Assert.False(sut.IsSupportedType(typeof(List<int>)));
Assert.True(sut.IsSupportedType(typeof(int)));
Assert.True(sut.IsSupportedType(typeof(bool)));
Assert.False(sut.IsSupportedType(typeof(float)));
Assert.False(sut.IsSupportedType(typeof(double)));
}
[Fact]
@ -67,38 +40,20 @@ namespace Squidex.Infrastructure.Json.Orleans
Assert.Null(copy);
}
[Fact]
public void Should_copy_null_json()
{
var value = new J<List<int>>(null);
var copy = (J<List<int>>)sut.DeepCopy(value, null);
Assert.Null(copy.Value);
}
[Fact]
public void Should_not_copy_immutable_values()
{
var value = new J<List<int>>(new List<int> { 1, 2, 3 }, true);
var copy = (J<List<int>>)sut.DeepCopy(value, null);
Assert.Same(value.Value, copy.Value);
}
[Fact]
public void Should_copy_non_immutable_values()
{
var value = new J<List<int>>(new List<int> { 1, 2, 3 });
var copy = (J<List<int>>)sut.DeepCopy(value, null);
var value = new List<int> { 1, 2, 3 };
var copy = (List<int>)sut.DeepCopy(value, null);
Assert.Equal(value.Value, copy.Value);
Assert.NotSame(value.Value, copy.Value);
Assert.Equal(value, copy);
Assert.NotSame(value, copy);
}
[Fact]
public void Should_serialize_and_deserialize_value()
{
var value = new J<List<int>>(new List<int> { 1, 2, 3 });
var value = new List<int>(new List<int> { 1, 2, 3 });
var writtenLength = 0;
var writtenBuffer = (byte[])null;
@ -123,10 +78,10 @@ namespace Squidex.Infrastructure.Json.Orleans
A.CallTo(() => reader.ReadBytes(writtenLength))
.Returns(writtenBuffer);
var copy = (J<List<int>>)sut.Deserialize(value.GetType(), readerContext);
var copy = (List<int>)sut.Deserialize(value.GetType(), readerContext);
Assert.Equal(value.Value, copy.Value);
Assert.NotSame(value.Value, copy.Value);
Assert.Equal(value, copy);
Assert.NotSame(value, copy);
}
}
}

Loading…
Cancel
Save