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_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/@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_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/@EntryIndexedValue">True</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_002Ehtml/@EntryIndexedValue">True</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_002Ejs/@EntryIndexedValue">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_002Ejson/@EntryIndexedValue">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_002Escss/@EntryIndexedValue">True</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_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; this.permission = permission;
} }
public void Update(AppClientPermission newPermission) public AppClient Update(AppClientPermission newPermission)
{ {
Guard.Enum(newPermission, nameof(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)); 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. // All rights reserved.
// ========================================================================== // ==========================================================================
using System.Collections.Immutable;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Apps 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.NotNullOrEmpty(id, nameof(id));
Guard.NotNull(client, nameof(client)); 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)); 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)); 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. // All rights reserved.
// ========================================================================== // ==========================================================================
using System.Collections.Immutable;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Apps 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.NotNullOrEmpty(contributorId, nameof(contributorId));
Guard.Enum(permission, nameof(permission)); 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)); 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using Newtonsoft.Json; using Newtonsoft.Json;
using Squidex.Infrastructure.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 json = serializer.Deserialize<Dictionary<string, JsonAppClient>>(reader);
var clients = new AppClients(); return new AppClients(json.ToImmutableDictionary(x => x.Key, x => x.Value.ToClient()));
foreach (var client in json)
{
clients.Add(client.Key, client.Value.ToClient());
}
return clients;
} }
} }
} }

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

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

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

@ -13,80 +13,101 @@ using System.Collections.Immutable;
using System.Linq; using System.Linq;
using Squidex.Infrastructure; using Squidex.Infrastructure;
#pragma warning disable IDE0016 // Use 'throw' expression
namespace Squidex.Domain.Apps.Core.Apps namespace Squidex.Domain.Apps.Core.Apps
{ {
public sealed class LanguagesConfig : IFieldPartitioning 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 public LanguageConfig Master
{ {
get { return state.Master; } get { return master; }
} }
IFieldPartitionItem IFieldPartitioning.Master IFieldPartitionItem IFieldPartitioning.Master
{ {
get { return state.Master; } get { return master; }
} }
IEnumerator IEnumerable.GetEnumerator() IEnumerator IEnumerable.GetEnumerator()
{ {
return state.Languages.Values.GetEnumerator(); return languages.Values.GetEnumerator();
} }
IEnumerator<IFieldPartitionItem> IEnumerable<IFieldPartitionItem>.GetEnumerator() IEnumerator<IFieldPartitionItem> IEnumerable<IFieldPartitionItem>.GetEnumerator()
{ {
return state.Languages.Values.GetEnumerator(); return languages.Values.GetEnumerator();
} }
public int Count 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)); 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)); 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)); 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)); Guard.NotNull(language, nameof(language));
var newLanguages = var newLanguages =
state.Languages.Values.Where(x => x.Language != language) languages.Values.Where(x => x.Language != language)
.Select(config => .Select(config =>
{ {
return new LanguageConfig( return new LanguageConfig(
@ -97,26 +118,26 @@ namespace Squidex.Domain.Apps.Core.Apps
.ToImmutableDictionary(x => x.Language); .ToImmutableDictionary(x => x.Language);
var newMaster = var newMaster =
state.Master.Language != language ? Master.Language != language ?
state.Master : Master :
newLanguages.Values.FirstOrDefault(); newLanguages.Values.FirstOrDefault();
state = new State(newLanguages, newMaster); return new LanguagesConfig(newLanguages, newMaster);
} }
public bool Contains(Language language) 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) 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) 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; 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() public PartitionResolver ToResolver()
{ {
return partitioning => 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
namespace Squidex.Domain.Apps.Core 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] public TValue this[TKey key]
{ {
@ -35,11 +36,16 @@ namespace Squidex.Domain.Apps.Core
get { return inner.Count; } get { return inner.Count; }
} }
protected Dictionary<TKey, TValue> Inner protected ImmutableDictionary<TKey, TValue> Inner
{ {
get { return inner; } get { return inner; }
} }
protected DictionaryWrapper(ImmutableDictionary<TKey, TValue> inner)
{
this.inner = inner;
}
public bool ContainsKey(TKey key) public bool ContainsKey(TKey key)
{ {
return inner.ContainsKey(key); return inner.ContainsKey(key);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -6,11 +6,8 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.Json;
namespace Squidex.Domain.Apps.Core.Schemas 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 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)) return clients.Rename(@event.Id, @event.Name);
{
client.Rename(@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)) return clients.Update(@event.Id, @event.Permission);
{
client.Update(@event.Permission);
}
} }
public static void Apply(this LanguagesConfig languagesConfig, AppLanguageUpdated @event) public static LanguagesConfig Apply(this LanguagesConfig languagesConfig, AppLanguageUpdated @event)
{ {
var fallback = @event.Fallback; var fallback = @event.Fallback;
@ -70,12 +64,14 @@ namespace Squidex.Domain.Apps.Events.Apps.Utils
fallback = fallback.Intersect(existingLangauges).ToList(); 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) 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 namespace Squidex.Domain.Apps.Read.MongoDb.Assets
{ {
public sealed class MongoAssetEntity : MongoEntity, IAssetEntity public sealed class MongoAssetEntity :
MongoEntity,
IAssetEntity,
IUpdateableEntityWithVersion,
IUpdateableEntityWithCreatedBy,
IUpdateableEntityWithLastModifiedBy
{ {
[BsonRequired] [BsonRequired]
[BsonElement] [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 namespace Squidex.Domain.Apps.Read.MongoDb.Contents
{ {
public sealed class MongoContentEntity : IContentEntity public sealed class MongoContentEntity :
IContentEntity,
IUpdateableEntityWithVersion,
IUpdateableEntityWithCreatedBy,
IUpdateableEntityWithLastModifiedBy
{ {
private NamedContentData data; 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 namespace Squidex.Domain.Apps.Read.MongoDb.History
{ {
public sealed class MongoHistoryEventEntity : MongoEntity, IAppRefEntity, IEntityWithCreatedBy public sealed class MongoHistoryEventEntity : MongoEntity,
IEntityWithAppRef,
IUpdateableEntityWithVersion,
IUpdateableEntityWithCreatedBy
{ {
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement]
@ -40,7 +43,7 @@ namespace Squidex.Domain.Apps.Read.MongoDb.History
[BsonElement] [BsonElement]
public Dictionary<string, string> Parameters { get; set; } public Dictionary<string, string> Parameters { get; set; }
RefToken IEntityWithCreatedBy.CreatedBy RefToken IUpdateableEntityWithCreatedBy.CreatedBy
{ {
get 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; this.fieldRegistry = fieldRegistry;
} }
public override Task OnActivateAsync()
{
State.SetRegistry(fieldRegistry);
return base.OnActivateAsync();
}
public Task<Immutable<(IAppEntity, ISchemaEntity)>> GetAppWithSchemaAsync(Guid id) public Task<Immutable<(IAppEntity, ISchemaEntity)>> GetAppWithSchemaAsync(Guid id)
{ {
var schema = State.FindSchema(x => x.Id == id && !x.IsDeleted); 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) public Task HandleAsync(Immutable<Envelope<IEvent>> message)
{ {
State.Apply(message.Value, fieldRegistry); State.Apply(message.Value);
return WriteStateAsync(); 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.Collections.Generic;
using System.Linq; using System.Linq;
using Newtonsoft.Json; using Newtonsoft.Json;
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Core.Schemas; 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.Apps;
using Squidex.Domain.Apps.Read.Rules; using Squidex.Domain.Apps.Read.Rules;
using Squidex.Domain.Apps.Read.Schemas; using Squidex.Domain.Apps.Read.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events; using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Dispatching;
#pragma warning disable CS0612 // Type or member is obsolete
namespace Squidex.Domain.Apps.Read.State.Orleans.Grains.Implementations namespace Squidex.Domain.Apps.Read.State.Orleans.Grains.Implementations
{ {
public sealed class AppStateGrainState public sealed partial class AppStateGrainState
{ {
private FieldRegistry registry;
[JsonProperty] [JsonProperty]
public JsonAppEntity App { get; set; } public JsonAppEntity App { get; set; }
@ -42,6 +32,11 @@ namespace Squidex.Domain.Apps.Read.State.Orleans.Grains.Implementations
[JsonProperty] [JsonProperty]
public Dictionary<Guid, JsonSchemaEntity> Schemas { get; set; } public Dictionary<Guid, JsonSchemaEntity> Schemas { get; set; }
public void SetRegistry(FieldRegistry registry)
{
this.registry = registry;
}
public IAppEntity GetApp() public IAppEntity GetApp()
{ {
return App; return App;
@ -69,253 +64,14 @@ namespace Squidex.Domain.Apps.Read.State.Orleans.Grains.Implementations
Schemas = new Dictionary<Guid, JsonSchemaEntity>(); Schemas = new Dictionary<Guid, JsonSchemaEntity>();
} }
public void Apply(Envelope<IEvent> envelope, FieldRegistry registry) public void Apply(Envelope<IEvent> envelope)
{ {
switch (envelope.Payload) this.DispatchAction(envelope.Payload, envelope.Headers);
{
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;
}
if (App != null) if (App != null)
{ {
App.Etag = Guid.NewGuid().ToString(); 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; } public string PlanOwner { get; set; }
[JsonProperty] [JsonProperty]
public AppClients Clients { get; set; } public AppClients Clients { get; set; } = AppClients.Empty;
[JsonProperty] [JsonProperty]
public AppContributors Contributors { get; set; } public AppContributors Contributors { get; set; } = AppContributors.Empty;
[JsonProperty] [JsonProperty]
public LanguagesConfig LanguagesConfig { get; set; } 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 public class AppDomainObject : DomainObjectBase
{ {
private static readonly Language DefaultLanguage = Language.EN; private AppContributors contributors = AppContributors.Empty;
private readonly AppContributors contributors = new AppContributors(); private AppClients clients = AppClients.Empty;
private readonly AppClients clients = new AppClients(); private LanguagesConfig languagesConfig = LanguagesConfig.English;
private readonly LanguagesConfig languagesConfig = LanguagesConfig.Build(DefaultLanguage);
private AppPlan plan; private AppPlan plan;
private string name; private string name;
@ -66,47 +65,47 @@ namespace Squidex.Domain.Apps.Write.Apps
protected void On(AppContributorAssigned @event) protected void On(AppContributorAssigned @event)
{ {
contributors.Apply(@event); contributors = contributors.Apply(@event);
} }
protected void On(AppContributorRemoved @event) protected void On(AppContributorRemoved @event)
{ {
contributors.Apply(@event); contributors = contributors.Apply(@event);
} }
protected void On(AppClientAttached @event) protected void On(AppClientAttached @event)
{ {
clients.Apply(@event); clients = clients.Apply(@event);
} }
protected void On(AppClientUpdated @event) protected void On(AppClientUpdated @event)
{ {
clients.Apply(@event); clients = clients.Apply(@event);
} }
protected void On(AppClientRenamed @event) protected void On(AppClientRenamed @event)
{ {
clients.Apply(@event); clients = clients.Apply(@event);
} }
protected void On(AppClientRevoked @event) protected void On(AppClientRevoked @event)
{ {
clients.Apply(@event); clients = clients.Apply(@event);
} }
protected void On(AppLanguageAdded @event) protected void On(AppLanguageAdded @event)
{ {
languagesConfig.Apply(@event); languagesConfig = languagesConfig.Apply(@event);
} }
protected void On(AppLanguageRemoved @event) protected void On(AppLanguageRemoved @event)
{ {
languagesConfig.Apply(@event); languagesConfig = languagesConfig.Apply(@event);
} }
protected void On(AppLanguageUpdated @event) protected void On(AppLanguageUpdated @event)
{ {
languagesConfig.Apply(@event); languagesConfig = languagesConfig.Apply(@event);
} }
protected void On(AppPlanChanged @event) protected void On(AppPlanChanged @event)
@ -234,7 +233,7 @@ namespace Squidex.Domain.Apps.Write.Apps
private static AppLanguageAdded CreateInitialLanguage(NamedId<Guid> id) 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) 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) protected void On(RuleUpdated @event)
{ {
rule.Apply(@event); rule = rule.Apply(@event);
} }
protected void On(RuleEnabled @event) protected void On(RuleEnabled @event)
{ {
rule.Apply(@event); rule = rule.Apply(@event);
} }
protected void On(RuleDisabled @event) protected void On(RuleDisabled @event)
{ {
rule.Apply(@event); rule = rule.Apply(@event);
} }
protected void On(RuleDeleted @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)); 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.", yield return new ValidationError("Radio buttons or dropdown list need allowed values.",
nameof(properties.AllowedValues)); nameof(properties.AllowedValues));
@ -136,7 +136,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
nameof(properties.MaxValue)); 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.", yield return new ValidationError("Either allowed values or min and max value can be defined.",
nameof(properties.AllowedValues), nameof(properties.AllowedValues),
@ -163,7 +163,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
nameof(properties.Editor)); 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.", yield return new ValidationError("Radio buttons or dropdown list need allowed values.",
nameof(properties.AllowedValues)); nameof(properties.AllowedValues));
@ -182,7 +182,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
nameof(properties.MaxLength)); 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.", yield return new ValidationError("Either allowed values or min and max length can be defined.",
nameof(properties.AllowedValues), nameof(properties.AllowedValues),

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

@ -56,62 +56,62 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
totalFields++; totalFields++;
schema.Apply(@event, registry); schema = schema.Apply(@event, registry);
} }
protected void On(FieldUpdated @event) protected void On(FieldUpdated @event)
{ {
schema.Apply(@event); schema = schema.Apply(@event);
} }
protected void On(FieldLocked @event) protected void On(FieldLocked @event)
{ {
schema.Apply(@event); schema = schema.Apply(@event);
} }
protected void On(FieldHidden @event) protected void On(FieldHidden @event)
{ {
schema.Apply(@event); schema = schema.Apply(@event);
} }
protected void On(FieldShown @event) protected void On(FieldShown @event)
{ {
schema.Apply(@event); schema = schema.Apply(@event);
} }
protected void On(FieldDisabled @event) protected void On(FieldDisabled @event)
{ {
schema.Apply(@event); schema = schema.Apply(@event);
} }
protected void On(FieldEnabled @event) protected void On(FieldEnabled @event)
{ {
schema.Apply(@event); schema = schema.Apply(@event);
} }
protected void On(SchemaUpdated @event) protected void On(SchemaUpdated @event)
{ {
schema.Apply(@event); schema = schema.Apply(@event);
} }
protected void On(FieldDeleted @event) protected void On(FieldDeleted @event)
{ {
schema.Apply(@event); schema = schema.Apply(@event);
} }
protected void On(SchemaFieldsReordered @event) protected void On(SchemaFieldsReordered @event)
{ {
schema.Apply(@event); schema = schema.Apply(@event);
} }
protected void On(SchemaPublished @event) protected void On(SchemaPublished @event)
{ {
schema.Apply(@event); schema = schema.Apply(@event);
} }
protected void On(SchemaUnpublished @event) protected void On(SchemaUnpublished @event)
{ {
schema.Apply(@event); schema = schema.Apply(@event);
} }
protected void On(SchemaDeleted @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(); var dto = new RuleDto();
SimpleMapper.Map(entity, dto); 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; return dto;

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

@ -7,6 +7,7 @@
// ========================================================================== // ==========================================================================
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using NJsonSchema.Annotations; using NJsonSchema.Annotations;
@ -29,7 +30,7 @@ namespace Squidex.Controllers.Api.Rules.Models.Triggers
{ {
return new ContentChangedTrigger 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. // All rights reserved.
// ========================================================================== // ==========================================================================
using System.Collections.Immutable;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters; using Newtonsoft.Json.Converters;
using NJsonSchema.Annotations; using NJsonSchema.Annotations;
@ -47,6 +48,11 @@ namespace Squidex.Controllers.Api.Schemas.Models.Fields
{ {
var result = SimpleMapper.Map(this, new NumberFieldProperties()); var result = SimpleMapper.Map(this, new NumberFieldProperties());
if (AllowedValues != null)
{
result.AllowedValues = ImmutableList.Create(AllowedValues);
}
return result; return result;
} }
} }

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

@ -6,6 +6,7 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System.Collections.Immutable;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters; using Newtonsoft.Json.Converters;
using NJsonSchema.Annotations; using NJsonSchema.Annotations;
@ -57,6 +58,11 @@ namespace Squidex.Controllers.Api.Schemas.Models.Fields
{ {
var result = SimpleMapper.Map(this, new StringFieldProperties()); var result = SimpleMapper.Map(this, new StringFieldProperties());
if (AllowedValues != null)
{
result.AllowedValues = ImmutableList.Create(AllowedValues);
}
return result; 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 System;
using FluentAssertions; using FluentAssertions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Apps;
using Xunit; using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Core.Model.Apps namespace Squidex.Domain.Apps.Core.Model.Apps
{ {
public class AppClientsTests public class AppClientsTests
{ {
private readonly JsonSerializer serializer = TestData.DefaultSerializer(); private readonly AppClients clients_0 = AppClients.Empty.Add("1", "my-secret");
private readonly AppClients sut = new AppClients();
public AppClientsTests()
{
sut.Add("1", "my-secret");
}
[Fact] [Fact]
public void Should_assign_client() 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] [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] [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] [Fact]
public void Should_rename_client() 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] [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] [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] [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] [Fact]
public void Should_serialize_and_deserialize() public void Should_revoke_client()
{ {
sut.Add("2", "my-secret"); var clients_1 = clients_0.Revoke("1");
sut.Add("3", "my-secret");
sut.Add("4", "my-secret");
sut["3"].Update(AppClientPermission.Editor);
sut["3"].Rename("My Client 3"); Assert.Empty(clients_1);
sut["2"].Rename("My Client 2"); }
sut.Revoke("4");
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. // All rights reserved.
// ========================================================================== // ==========================================================================
using FluentAssertions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Apps;
using Xunit; using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Core.Model.Apps namespace Squidex.Domain.Apps.Core.Model.Apps
{ {
public class AppContributorsTests public class AppContributorsTests
{ {
private readonly JsonSerializer serializer = TestData.DefaultSerializer(); private readonly AppContributors contributors_0 = AppContributors.Empty;
private readonly AppContributors sut = new AppContributors();
[Fact] [Fact]
public void Should_assign_new_contributor() public void Should_assign_new_contributor()
{ {
sut.Assign("1", AppContributorPermission.Developer); var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Developer);
sut.Assign("2", AppContributorPermission.Editor); var contributors_2 = contributors_1.Assign("2", AppContributorPermission.Editor);
Assert.Equal(AppContributorPermission.Developer, sut["1"]); Assert.Equal(AppContributorPermission.Developer, contributors_2["1"]);
Assert.Equal(AppContributorPermission.Editor, sut["2"]); Assert.Equal(AppContributorPermission.Editor, contributors_2["2"]);
} }
[Fact] [Fact]
public void Should_replace_contributor_if_already_exists() public void Should_replace_contributor_if_already_exists()
{ {
sut.Assign("1", AppContributorPermission.Developer); var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Developer);
sut.Assign("1", AppContributorPermission.Owner); var contributors_2 = contributors_1.Assign("1", AppContributorPermission.Owner);
Assert.Equal(AppContributorPermission.Owner, sut["1"]); Assert.Equal(AppContributorPermission.Owner, contributors_2["1"]);
} }
[Fact] [Fact]
public void Should_remove_contributor() public void Should_remove_contributor()
{ {
sut.Assign("1", AppContributorPermission.Developer); var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Developer);
sut.Remove("1"); var contributors_2 = contributors_1.Remove("1");
Assert.Empty(sut); Assert.Empty(contributors_2);
} }
[Fact] [Fact]
public void Should_do_nothing_if_contributor_to_remove_not_found() public void Should_do_nothing_if_contributor_to_remove_not_found()
{ {
sut.Remove("2"); var contributors_1 = contributors_0.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);
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 public class LanguagesConfigTests
{ {
[Fact] [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 List<LanguageConfig>
{ {
new LanguageConfig(Language.DE) 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] [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 List<LanguageConfig>
{ {
new LanguageConfig(Language.DE), new LanguageConfig(Language.DE),
@ -48,12 +48,16 @@ namespace Squidex.Domain.Apps.Core.Model.Apps
new LanguageConfig(Language.IT) new LanguageConfig(Language.IT)
}); });
Assert.Equal(Language.DE, config.Master.Language); config_0.TryGetConfig(Language.DE, out var master);
Assert.Equal(3, config.Count);
Assert.Equal(Language.DE, config_0.Master.Language);
Assert.Equal(3, config_0.Count);
Assert.Same(master, config_0.Master);
} }
[Fact] [Fact]
public void Should_create_initial_config_with_configs() public void Should_create_initial_config_0_with_config_0s()
{ {
var configs = new[] var configs = new[]
{ {
@ -61,83 +65,82 @@ namespace Squidex.Domain.Apps.Core.Model.Apps
new LanguageConfig(Language.EN), new LanguageConfig(Language.EN),
new LanguageConfig(Language.IT) 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] [Fact]
public void Should_add_language() public void Should_add_language()
{ {
var config = LanguagesConfig.Build(Language.DE); var config_0 = LanguagesConfig.Build(Language.DE);
var config_1 = config_0.Set(new LanguageConfig(Language.IT));
config.Set(new LanguageConfig(Language.IT));
config.OfType<LanguageConfig>().ToList().ShouldBeEquivalentTo( config_1.OfType<LanguageConfig>().ToList().ShouldBeEquivalentTo(
new List<LanguageConfig> new List<LanguageConfig>
{ {
new LanguageConfig(Language.DE), new LanguageConfig(Language.DE),
new LanguageConfig(Language.IT) new LanguageConfig(Language.IT)
}); });
Assert.True(config.TryGetConfig(Language.IT, out var _)); Assert.True(config_1.TryGetConfig(Language.IT, out var _));
Assert.True(config.Contains(Language.IT)); Assert.True(config_1.Contains(Language.IT));
} }
[Fact] [Fact]
public void Should_make_first_language_to_master() 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] [Fact]
public void Should_not_throw_exception_if_language_to_add_already_exists() 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] [Fact]
public void Should_make_master_language() 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)); var config_1 = config_0.Set(new LanguageConfig(Language.UK));
config.Set(new LanguageConfig(Language.IT)); var config_2 = config_1.Set(new LanguageConfig(Language.IT));
config.MakeMaster(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] [Fact]
public void Should_throw_exception_if_language_to_make_master_is_not_found() 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] [Fact]
public void Should_not_throw_exception_if_language_is_already_master_language() 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] [Fact]
public void Should_remove_language() 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_1.ToList().ShouldBeEquivalentTo(
config.ToList().ShouldBeEquivalentTo(
new List<LanguageConfig> new List<LanguageConfig>
{ {
new LanguageConfig(Language.DE), new LanguageConfig(Language.DE),
@ -148,15 +151,14 @@ namespace Squidex.Domain.Apps.Core.Model.Apps
[Fact] [Fact]
public void Should_remove_fallbacks_when_removing_language() public void Should_remove_fallbacks_when_removing_language()
{ {
var config = var config_0 =
LanguagesConfig.Build( LanguagesConfig.Build(
new LanguageConfig(Language.DE), new LanguageConfig(Language.DE),
new LanguageConfig(Language.IT, false, Language.RU, Language.IT), new LanguageConfig(Language.IT, false, Language.RU, Language.IT),
new LanguageConfig(Language.RU, false, Language.DE, Language.IT)); new LanguageConfig(Language.RU, false, Language.DE, Language.IT));
var config_1 = config_0.Remove(Language.IT);
config.Remove(Language.IT); config_1.OfType<LanguageConfig>().ToList().ShouldBeEquivalentTo(
config.OfType<LanguageConfig>().ToList().ShouldBeEquivalentTo(
new List<LanguageConfig> new List<LanguageConfig>
{ {
new LanguageConfig(Language.DE), new LanguageConfig(Language.DE),
@ -167,28 +169,27 @@ namespace Squidex.Domain.Apps.Core.Model.Apps
[Fact] [Fact]
public void Should_not_throw_exception_if_language_to_remove_is_not_found() 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] [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] [Fact]
public void Should_update_language() public void Should_update_language()
{ {
var config = LanguagesConfig.Build(Language.DE); var config_0 = LanguagesConfig.Build(Language.DE);
var config_1 = config_0.Set(new LanguageConfig(Language.IT));
config.Set(new LanguageConfig(Language.IT)); var config_2 = config_1.Set(new LanguageConfig(Language.IT, true, Language.DE));
config.Set(new LanguageConfig(Language.IT, true, Language.DE));
config.OfType<LanguageConfig>().ToList().ShouldBeEquivalentTo( config_2.OfType<LanguageConfig>().ToList().ShouldBeEquivalentTo(
new List<LanguageConfig> new List<LanguageConfig>
{ {
new LanguageConfig(Language.DE), new LanguageConfig(Language.DE),
@ -199,20 +200,20 @@ namespace Squidex.Domain.Apps.Core.Model.Apps
[Fact] [Fact]
public void Should_throw_exception_if_fallback_language_is_invalid() 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] [Fact]
public void Should_provide_enumerators() 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)config_0).GetEnumerator());
Assert.NotNull(((IEnumerable<IFieldPartitionItem>)config).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 Squidex.Domain.Apps.Core.Rules.Triggers;
using Xunit; using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Core.Model.Rules namespace Squidex.Domain.Apps.Core.Model.Rules
{ {
public class RuleTests public class RuleTests
{ {
private readonly JsonSerializer serializer = TestData.DefaultSerializer(); 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 public sealed class OtherTrigger : RuleTrigger
{ {
@ -54,18 +56,22 @@ namespace Squidex.Domain.Apps.Core.Model.Rules
[Fact] [Fact]
public void Should_set_enabled_to_true_when_enabling() 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] [Fact]
public void Should_set_enabled_to_false_when_disabling() public void Should_set_enabled_to_false_when_disabling()
{ {
sut.Enable(); var rule_1 = rule_0.Disable();
sut.Disable(); var rule_2 = rule_1.Disable();
Assert.False(sut.IsEnabled); Assert.True(rule_0.IsEnabled);
Assert.False(rule_2.IsEnabled);
} }
[Fact] [Fact]
@ -73,15 +79,16 @@ namespace Squidex.Domain.Apps.Core.Model.Rules
{ {
var newTrigger = new ContentChangedTrigger(); 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] [Fact]
public void Should_throw_exception_when_new_trigger_has_other_type() 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] [Fact]
@ -89,25 +96,38 @@ namespace Squidex.Domain.Apps.Core.Model.Rules
{ {
var newAction = new WebhookAction(); 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] [Fact]
public void Should_throw_exception_when_new_action_has_other_type() 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] [Fact]
public void Should_serialize_and_deserialize() 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules;
using Squidex.Domain.Apps.Core.HandleRules.Triggers; using Squidex.Domain.Apps.Core.HandleRules.Triggers;
@ -67,8 +68,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules.Triggers
{ {
var trigger = new ContentChangedTrigger var trigger = new ContentChangedTrigger
{ {
Schemas = new List<ContentChangedTriggerSchema> Schemas = ImmutableList.Create<ContentChangedTriggerSchema>(
{
new ContentChangedTriggerSchema new ContentChangedTriggerSchema
{ {
SendCreate = sendCreate == 1, SendCreate = sendCreate == 1,
@ -76,8 +76,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules.Triggers
SendDelete = sendDelete == 1, SendDelete = sendDelete == 1,
SendPublish = sendPublish == 1, SendPublish = sendPublish == 1,
SchemaId = SchemaMatch.Id SchemaId = SchemaMatch.Id
} })
}
}; };
var result = sut.Triggers(new Envelope<AppEvent>(@event), trigger); 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 schemaId = Guid.NewGuid();
private static readonly Guid appId = Guid.NewGuid(); private static readonly Guid appId = Guid.NewGuid();
private static readonly string appName = "my-app"; 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 IContentQueryService contentQuery = A.Fake<IContentQueryService>();
private readonly IAssetRepository assetRepository = A.Fake<IAssetRepository>(); private readonly IAssetRepository assetRepository = A.Fake<IAssetRepository>();
private readonly ISchemaEntity schema = A.Fake<ISchemaEntity>(); private readonly ISchemaEntity schema = A.Fake<ISchemaEntity>();
@ -50,32 +50,26 @@ namespace Squidex.Domain.Apps.Read.Contents
public GraphQLTests() public GraphQLTests()
{ {
schemaDef.AddField(new JsonField(1, "my-json", Partitioning.Invariant, schemaDef =
new JsonFieldProperties())); new Schema("my-schema")
.AddField(new JsonField(1, "my-json", Partitioning.Invariant,
schemaDef.AddField(new StringField(2, "my-string", Partitioning.Language, new JsonFieldProperties()))
new StringFieldProperties())); .AddField(new StringField(2, "my-string", Partitioning.Language,
new StringFieldProperties()))
schemaDef.AddField(new NumberField(3, "my-number", Partitioning.Invariant, .AddField(new NumberField(3, "my-number", Partitioning.Invariant,
new NumberFieldProperties())); new NumberFieldProperties()))
.AddField(new AssetsField(4, "my-assets", Partitioning.Invariant,
schemaDef.AddField(new AssetsField(4, "my-assets", Partitioning.Invariant, new AssetsFieldProperties()))
new AssetsFieldProperties())); .AddField(new BooleanField(5, "my-boolean", Partitioning.Invariant,
new BooleanFieldProperties()))
schemaDef.AddField(new BooleanField(5, "my-boolean", Partitioning.Invariant, .AddField(new DateTimeField(6, "my-datetime", Partitioning.Invariant,
new BooleanFieldProperties())); new DateTimeFieldProperties()))
.AddField(new ReferencesField(7, "my-references", Partitioning.Invariant,
schemaDef.AddField(new DateTimeField(6, "my-datetime", Partitioning.Invariant, new ReferencesFieldProperties { SchemaId = schemaId }))
new DateTimeFieldProperties())); .AddField(new ReferencesField(9, "my-invalid", Partitioning.Invariant,
new ReferencesFieldProperties { SchemaId = Guid.NewGuid() }))
schemaDef.AddField(new ReferencesField(7, "my-references", Partitioning.Invariant, .AddField(new GeolocationField(10, "my-geolocation", Partitioning.Invariant,
new ReferencesFieldProperties { SchemaId = schemaId })); new GeolocationFieldProperties()));
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()));
A.CallTo(() => app.Id).Returns(appId); A.CallTo(() => app.Id).Returns(appId);
A.CallTo(() => app.Name).Returns(appName); A.CallTo(() => app.Name).Returns(appName);

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

@ -7,6 +7,7 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.Collections.Immutable;
using FakeItEasy; using FakeItEasy;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -29,7 +30,7 @@ namespace Squidex.Domain.Apps.Read.Contents
{ {
public class ODataQueryTests public class ODataQueryTests
{ {
private readonly Schema schemaDef = new Schema("user"); private readonly Schema schemaDef;
private readonly IBsonSerializerRegistry registry = BsonSerializer.SerializerRegistry; private readonly IBsonSerializerRegistry registry = BsonSerializer.SerializerRegistry;
private readonly IBsonSerializer<MongoContentEntity> serializer = BsonSerializer.SerializerRegistry.GetSerializer<MongoContentEntity>(); private readonly IBsonSerializer<MongoContentEntity> serializer = BsonSerializer.SerializerRegistry.GetSerializer<MongoContentEntity>();
private readonly IEdmModel edmModel; private readonly IEdmModel edmModel;
@ -42,30 +43,25 @@ namespace Squidex.Domain.Apps.Read.Contents
public ODataQueryTests() public ODataQueryTests()
{ {
schemaDef.Update(new SchemaProperties { Hints = "The User" }); schemaDef =
new Schema("user")
schemaDef.AddField(new StringField(1, "firstName", Partitioning.Language, .AddField(new StringField(1, "firstName", Partitioning.Language,
new StringFieldProperties { Label = "FirstName", IsRequired = true, AllowedValues = new[] { "1", "2" } })); new StringFieldProperties { Label = "FirstName", IsRequired = true, AllowedValues = ImmutableList.Create("1", "2") }))
schemaDef.AddField(new StringField(2, "lastName", Partitioning.Language, .AddField(new StringField(2, "lastName", Partitioning.Language,
new StringFieldProperties { Hints = "Last Name", Editor = StringFieldEditor.Input })); new StringFieldProperties { Hints = "Last Name", Editor = StringFieldEditor.Input }))
.AddField(new BooleanField(3, "isAdmin", Partitioning.Invariant,
schemaDef.AddField(new BooleanField(3, "isAdmin", Partitioning.Invariant, new BooleanFieldProperties()))
new BooleanFieldProperties())); .AddField(new NumberField(4, "age", Partitioning.Invariant,
new NumberFieldProperties { MinValue = 1, MaxValue = 10 }))
schemaDef.AddField(new NumberField(4, "age", Partitioning.Invariant, .AddField(new DateTimeField(5, "birthday", Partitioning.Invariant,
new NumberFieldProperties { MinValue = 1, MaxValue = 10 })); new DateTimeFieldProperties()))
.AddField(new AssetsField(6, "pictures", Partitioning.Invariant,
schemaDef.AddField(new DateTimeField(5, "birthday", Partitioning.Invariant, new AssetsFieldProperties()))
new DateTimeFieldProperties())); .AddField(new ReferencesField(7, "friends", Partitioning.Invariant,
new ReferencesFieldProperties()))
schemaDef.AddField(new AssetsField(6, "pictures", Partitioning.Invariant, .AddField(new StringField(8, "dashed-field", Partitioning.Invariant,
new AssetsFieldProperties())); new StringFieldProperties()))
.Update(new SchemaProperties { Hints = "The User" });
schemaDef.AddField(new ReferencesField(7, "friends", Partitioning.Invariant,
new ReferencesFieldProperties()));
schemaDef.AddField(new StringField(8, "dashed-field", Partitioning.Invariant,
new StringFieldProperties()));
var builder = new EdmModelBuilder(new MemoryCache(Options.Create(new MemoryCacheOptions()))); 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 ruleEntity2 = A.Fake<IRuleEntity>();
var ruleEntity3 = A.Fake<IRuleEntity>(); var ruleEntity3 = A.Fake<IRuleEntity>();
A.CallTo(() => ruleEntity1.Rule).Returns(rule1); A.CallTo(() => ruleEntity1.RuleDef).Returns(rule1);
A.CallTo(() => ruleEntity2.Rule).Returns(rule2); A.CallTo(() => ruleEntity2.RuleDef).Returns(rule2);
A.CallTo(() => ruleEntity3.Rule).Returns(rule3); A.CallTo(() => ruleEntity3.RuleDef).Returns(rule3);
A.CallTo(() => appProvider.GetRulesAsync(appId.Name)) A.CallTo(() => appProvider.GetRulesAsync(appId.Name))
.Returns(new List<IRuleEntity> { ruleEntity1, ruleEntity2, ruleEntity3 }); .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 Squidex.Infrastructure;
using Xunit; using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Write.Apps.Guards namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
public class GuardAppClientsTests public class GuardAppClientsTests
{ {
private readonly AppClients clients = new AppClients(); private readonly AppClients clients_0 = AppClients.Empty;
[Fact] [Fact]
public void CanAttach_should_throw_execption_if_client_id_is_null() public void CanAttach_should_throw_execption_if_client_id_is_null()
{ {
var command = new AttachClient(); var command = new AttachClient();
Assert.Throws<ValidationException>(() => GuardAppClients.CanAttach(clients, command)); Assert.Throws<ValidationException>(() => GuardAppClients.CanAttach(clients_0, command));
} }
[Fact] [Fact]
@ -30,9 +32,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new AttachClient { Id = "android" }; 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] [Fact]
@ -40,9 +42,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new AttachClient { Id = "ios" }; 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] [Fact]
@ -50,7 +52,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new RevokeClient(); var command = new RevokeClient();
Assert.Throws<ValidationException>(() => GuardAppClients.CanRevoke(clients, command)); Assert.Throws<ValidationException>(() => GuardAppClients.CanRevoke(clients_0, command));
} }
[Fact] [Fact]
@ -58,7 +60,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new RevokeClient { Id = "ios" }; var command = new RevokeClient { Id = "ios" };
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppClients.CanRevoke(clients, command)); Assert.Throws<DomainObjectNotFoundException>(() => GuardAppClients.CanRevoke(clients_0, command));
} }
[Fact] [Fact]
@ -66,9 +68,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new RevokeClient { Id = "ios" }; 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] [Fact]
@ -76,7 +78,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new UpdateClient(); var command = new UpdateClient();
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients, command)); Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients_0, command));
} }
[Fact] [Fact]
@ -84,7 +86,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new UpdateClient { Id = "ios", Name = "iOS" }; var command = new UpdateClient { Id = "ios", Name = "iOS" };
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppClients.CanUpdate(clients, command)); Assert.Throws<DomainObjectNotFoundException>(() => GuardAppClients.CanUpdate(clients_0, command));
} }
[Fact] [Fact]
@ -92,9 +94,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new UpdateClient { Id = "ios" }; 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] [Fact]
@ -102,9 +104,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new UpdateClient { Id = "ios", Permission = (AppClientPermission)10 }; 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] [Fact]
@ -112,9 +114,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new UpdateClient { Id = "ios", Name = "ios" }; 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] [Fact]
@ -122,9 +124,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new UpdateClient { Id = "ios", Permission = AppClientPermission.Editor }; 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] [Fact]
@ -132,9 +134,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new UpdateClient { Id = "ios", Name = "iOS", Permission = AppClientPermission.Reader }; 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 Squidex.Shared.Users;
using Xunit; using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Write.Apps.Guards namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
public class GuardAppContributorsTests public class GuardAppContributorsTests
{ {
private readonly IUserResolver users = A.Fake<IUserResolver>(); private readonly IUserResolver users = A.Fake<IUserResolver>();
private readonly IAppLimitsPlan appPlan = A.Fake<IAppLimitsPlan>(); private readonly IAppLimitsPlan appPlan = A.Fake<IAppLimitsPlan>();
private readonly AppContributors contributors = new AppContributors(); private readonly AppContributors contributors_0 = AppContributors.Empty;
public GuardAppContributorsTests() public GuardAppContributorsTests()
{ {
@ -37,7 +39,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new AssignContributor(); 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] [Fact]
@ -45,7 +47,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new AssignContributor { ContributorId = "1", Permission = (AppContributorPermission)10 }; 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] [Fact]
@ -53,9 +55,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new AssignContributor { ContributorId = "1" }; 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] [Fact]
@ -66,7 +68,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
var command = new AssignContributor { ContributorId = "1", Permission = (AppContributorPermission)10 }; 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] [Fact]
@ -77,10 +79,10 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
var command = new AssignContributor { ContributorId = "3" }; var command = new AssignContributor { ContributorId = "3" };
contributors.Assign("1", AppContributorPermission.Owner); var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Owner);
contributors.Assign("2", AppContributorPermission.Editor); 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] [Fact]
@ -88,7 +90,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new AssignContributor { ContributorId = "1" }; var command = new AssignContributor { ContributorId = "1" };
return GuardAppContributors.CanAssign(contributors, command, users, appPlan); return GuardAppContributors.CanAssign(contributors_0, command, users, appPlan);
} }
[Fact] [Fact]
@ -96,9 +98,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new AssignContributor { ContributorId = "1" }; 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] [Fact]
@ -109,10 +111,10 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
var command = new AssignContributor { ContributorId = "1" }; var command = new AssignContributor { ContributorId = "1" };
contributors.Assign("1", AppContributorPermission.Editor); var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Editor);
contributors.Assign("2", 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] [Fact]
@ -120,7 +122,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new RemoveContributor(); var command = new RemoveContributor();
Assert.Throws<ValidationException>(() => GuardAppContributors.CanRemove(contributors, command)); Assert.Throws<ValidationException>(() => GuardAppContributors.CanRemove(contributors_0, command));
} }
[Fact] [Fact]
@ -128,7 +130,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new RemoveContributor { ContributorId = "1" }; var command = new RemoveContributor { ContributorId = "1" };
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppContributors.CanRemove(contributors, command)); Assert.Throws<DomainObjectNotFoundException>(() => GuardAppContributors.CanRemove(contributors_0, command));
} }
[Fact] [Fact]
@ -136,10 +138,10 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new RemoveContributor { ContributorId = "1" }; var command = new RemoveContributor { ContributorId = "1" };
contributors.Assign("1", AppContributorPermission.Owner); var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Owner);
contributors.Assign("2", AppContributorPermission.Editor); 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] [Fact]
@ -147,10 +149,10 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new RemoveContributor { ContributorId = "1" }; var command = new RemoveContributor { ContributorId = "1" };
contributors.Assign("1", AppContributorPermission.Owner); var contributors_1 = contributors_0.Assign("1", AppContributorPermission.Owner);
contributors.Assign("2", 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 Squidex.Infrastructure;
using Xunit; using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Write.Apps.Guards namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
public class GuardAppLanguagesTests public class GuardAppLanguagesTests
{ {
private readonly LanguagesConfig languages = LanguagesConfig.Build(Language.DE); private readonly LanguagesConfig languages_0 = LanguagesConfig.Build(Language.DE);
[Fact] [Fact]
public void CanAddLanguage_should_throw_exception_if_language_is_null() public void CanAddLanguage_should_throw_exception_if_language_is_null()
{ {
var command = new AddLanguage(); var command = new AddLanguage();
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanAdd(languages, command)); Assert.Throws<ValidationException>(() => GuardAppLanguages.CanAdd(languages_0, command));
} }
[Fact] [Fact]
@ -31,7 +33,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new AddLanguage { Language = Language.DE }; var command = new AddLanguage { Language = Language.DE };
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanAdd(languages, command)); Assert.Throws<ValidationException>(() => GuardAppLanguages.CanAdd(languages_0, command));
} }
[Fact] [Fact]
@ -39,7 +41,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new AddLanguage { Language = Language.EN }; var command = new AddLanguage { Language = Language.EN };
GuardAppLanguages.CanAdd(languages, command); GuardAppLanguages.CanAdd(languages_0, command);
} }
[Fact] [Fact]
@ -47,7 +49,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new RemoveLanguage(); var command = new RemoveLanguage();
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanRemove(languages, command)); Assert.Throws<ValidationException>(() => GuardAppLanguages.CanRemove(languages_0, command));
} }
[Fact] [Fact]
@ -55,7 +57,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new RemoveLanguage { Language = Language.EN }; var command = new RemoveLanguage { Language = Language.EN };
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppLanguages.CanRemove(languages, command)); Assert.Throws<DomainObjectNotFoundException>(() => GuardAppLanguages.CanRemove(languages_0, command));
} }
[Fact] [Fact]
@ -63,7 +65,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new RemoveLanguage { Language = Language.DE }; var command = new RemoveLanguage { Language = Language.DE };
Assert.Throws<ValidationException>(() => GuardAppLanguages.CanRemove(languages, command)); Assert.Throws<ValidationException>(() => GuardAppLanguages.CanRemove(languages_0, command));
} }
[Fact] [Fact]
@ -71,9 +73,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new RemoveLanguage { Language = Language.EN }; 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] [Fact]
@ -81,9 +83,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new UpdateLanguage(); 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] [Fact]
@ -91,9 +93,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new UpdateLanguage { Language = Language.DE, IsOptional = true }; 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] [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 } }; 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] [Fact]
@ -111,9 +113,9 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{ {
var command = new UpdateLanguage { Language = Language.IT }; 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] [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 } }; 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() public ContentCommandMiddlewareTests()
{ {
var schemaDef = new Schema("my-schema"); var schemaDef =
new Schema("my-schema")
schemaDef.AddField(new NumberField(1, "my-field1", Partitioning.Invariant, .AddField(new NumberField(1, "my-field1", Partitioning.Invariant,
new NumberFieldProperties { IsRequired = true })); new NumberFieldProperties { IsRequired = true }))
schemaDef.AddField(new NumberField(2, "my-field2", Partitioning.Invariant, .AddField(new NumberField(2, "my-field2", Partitioning.Invariant,
new NumberFieldProperties { IsRequired = false })); new NumberFieldProperties { IsRequired = false }));
content = new ContentDomainObject(contentId, -1); content = new ContentDomainObject(contentId, -1);

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

@ -7,7 +7,7 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.Collections.Generic; using System.Collections.Immutable;
using System.Threading.Tasks; using System.Threading.Tasks;
using FakeItEasy; using FakeItEasy;
using Squidex.Domain.Apps.Core.Rules; using Squidex.Domain.Apps.Core.Rules;
@ -19,12 +19,14 @@ using Squidex.Domain.Apps.Write.Rules.Commands;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Xunit; using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Write.Rules.Guards namespace Squidex.Domain.Apps.Write.Rules.Guards
{ {
public class GuardRuleTests public class GuardRuleTests
{ {
private readonly Uri validUrl = new Uri("https://squidex.io"); 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 NamedId<Guid> appId = new NamedId<Guid>(Guid.NewGuid(), "my-app");
private readonly IAppProvider appProvider = A.Fake<IAppProvider>(); private readonly IAppProvider appProvider = A.Fake<IAppProvider>();
@ -37,15 +39,14 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards
[Fact] [Fact]
public async Task CanCreate_should_throw_exception_if_trigger_null() public async Task CanCreate_should_throw_exception_if_trigger_null()
{ {
var command = new CreateRule var command = CreateCommand(new CreateRule
{ {
Trigger = null, Trigger = null,
Action = new WebhookAction Action = new WebhookAction
{ {
Url = validUrl Url = validUrl
}, }
AppId = appId });
};
await Assert.ThrowsAsync<ValidationException>(() => GuardRule.CanCreate(command, appProvider)); await Assert.ThrowsAsync<ValidationException>(() => GuardRule.CanCreate(command, appProvider));
} }
@ -53,15 +54,14 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards
[Fact] [Fact]
public async Task CanCreate_should_throw_exception_if_action_null() public async Task CanCreate_should_throw_exception_if_action_null()
{ {
var command = new CreateRule var command = CreateCommand(new CreateRule
{ {
Trigger = new ContentChangedTrigger Trigger = new ContentChangedTrigger
{ {
Schemas = new List<ContentChangedTriggerSchema>() Schemas = ImmutableList<ContentChangedTriggerSchema>.Empty
}, },
Action = null, Action = null
AppId = appId });
};
await Assert.ThrowsAsync<ValidationException>(() => GuardRule.CanCreate(command, appProvider)); await Assert.ThrowsAsync<ValidationException>(() => GuardRule.CanCreate(command, appProvider));
} }
@ -69,18 +69,17 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards
[Fact] [Fact]
public async Task CanCreate_should_not_throw_exception_if_trigger_and_action_valid() 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 Trigger = new ContentChangedTrigger
{ {
Schemas = new List<ContentChangedTriggerSchema>() Schemas = ImmutableList<ContentChangedTriggerSchema>.Empty
}, },
Action = new WebhookAction Action = new WebhookAction
{ {
Url = validUrl Url = validUrl
}, }
AppId = appId });
};
await GuardRule.CanCreate(command, appProvider); await GuardRule.CanCreate(command, appProvider);
} }
@ -96,18 +95,17 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards
[Fact] [Fact]
public async Task CanUpdate_should_not_throw_exception_if_trigger_and_action_valid() 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 Trigger = new ContentChangedTrigger
{ {
Schemas = new List<ContentChangedTriggerSchema>() Schemas = ImmutableList<ContentChangedTriggerSchema>.Empty
}, },
Action = new WebhookAction Action = new WebhookAction
{ {
Url = validUrl Url = validUrl
}, }
AppId = appId });
};
await GuardRule.CanUpdate(command, appProvider); await GuardRule.CanUpdate(command, appProvider);
} }
@ -117,9 +115,9 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards
{ {
var command = new EnableRule(); 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] [Fact]
@ -127,9 +125,9 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards
{ {
var command = new EnableRule(); var command = new EnableRule();
rule.Disable(); var rule_1 = rule_0.Disable();
GuardRule.CanEnable(command, rule); GuardRule.CanEnable(command, rule_1);
} }
[Fact] [Fact]
@ -137,9 +135,9 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards
{ {
var command = new DisableRule(); 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] [Fact]
@ -147,9 +145,9 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards
{ {
var command = new DisableRule(); var command = new DisableRule();
rule.Enable(); var rule_1 = rule_0.Enable();
GuardRule.CanDisable(command, rule); GuardRule.CanDisable(command, rule_1);
} }
[Fact] [Fact]
@ -159,5 +157,12 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards
GuardRule.CanDelete(command); 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;
using System.Collections.Generic; using System.Collections.Immutable;
using System.Threading.Tasks; using System.Threading.Tasks;
using FakeItEasy; using FakeItEasy;
using Squidex.Domain.Apps.Core.Rules.Triggers; using Squidex.Domain.Apps.Core.Rules.Triggers;
@ -30,10 +30,9 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards.Triggers
var trigger = new ContentChangedTrigger var trigger = new ContentChangedTrigger
{ {
Schemas = new List<ContentChangedTriggerSchema> Schemas = ImmutableList.Create(
{
new ContentChangedTriggerSchema() new ContentChangedTriggerSchema()
} )
}; };
var errors = await RuleTriggerValidator.ValidateAsync(appName, trigger, appProvider); var errors = await RuleTriggerValidator.ValidateAsync(appName, trigger, appProvider);
@ -56,7 +55,7 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards.Triggers
{ {
var trigger = new ContentChangedTrigger var trigger = new ContentChangedTrigger
{ {
Schemas = new List<ContentChangedTriggerSchema>() Schemas = ImmutableList<ContentChangedTriggerSchema>.Empty
}; };
var errors = await RuleTriggerValidator.ValidateAsync(appName, trigger, appProvider); var errors = await RuleTriggerValidator.ValidateAsync(appName, trigger, appProvider);
@ -72,10 +71,9 @@ namespace Squidex.Domain.Apps.Write.Rules.Guards.Triggers
var trigger = new ContentChangedTrigger var trigger = new ContentChangedTrigger
{ {
Schemas = new List<ContentChangedTriggerSchema> Schemas = ImmutableList.Create(
{
new ContentChangedTriggerSchema() new ContentChangedTriggerSchema()
} )
}; };
var errors = await RuleTriggerValidator.ValidateAsync(appName, trigger, appProvider); 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using Squidex.Domain.Apps.Core.Rules; using Squidex.Domain.Apps.Core.Rules;
using Squidex.Domain.Apps.Core.Rules.Actions; using Squidex.Domain.Apps.Core.Rules.Actions;
using Squidex.Domain.Apps.Core.Rules.Triggers; using Squidex.Domain.Apps.Core.Rules.Triggers;
@ -83,7 +84,7 @@ namespace Squidex.Domain.Apps.Write.Rules
{ {
var newTrigger = new ContentChangedTrigger var newTrigger = new ContentChangedTrigger
{ {
Schemas = new List<ContentChangedTriggerSchema>() Schemas = ImmutableList<ContentChangedTriggerSchema>.Empty
}; };
var newAction = new WebhookAction 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.Generic;
using System.Collections.Immutable;
using System.Linq; using System.Linq;
using FluentAssertions; using FluentAssertions;
using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas;
@ -77,7 +78,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards.FieldProperties
[Fact] [Fact]
public void Should_add_error_if_allowed_values_and_max_value_is_specified() 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(); var errors = FieldPropertiesValidator.Validate(sut).ToList();
@ -91,7 +92,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards.FieldProperties
[Fact] [Fact]
public void Should_add_error_if_allowed_values_and_min_value_is_specified() 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(); 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.Generic;
using System.Collections.Immutable;
using System.Linq; using System.Linq;
using FluentAssertions; using FluentAssertions;
using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas;
@ -34,7 +35,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards.FieldProperties
[Fact] [Fact]
public void Should_add_error_if_allowed_values_and_max_value_is_specified() 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(); var errors = FieldPropertiesValidator.Validate(sut).ToList();
@ -48,7 +49,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards.FieldProperties
[Fact] [Fact]
public void Should_add_error_if_allowed_values_and_min_value_is_specified() 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(); 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 Squidex.Infrastructure;
using Xunit; using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Write.Schemas namespace Squidex.Domain.Apps.Write.Schemas
{ {
public class GuardSchemaFieldTests 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 validProperties = new StringFieldProperties();
private readonly StringFieldProperties invalidProperties = new StringFieldProperties { MinLength = 10, MaxLength = 5 }; private readonly StringFieldProperties invalidProperties = new StringFieldProperties { MinLength = 10, MaxLength = 5 };
public GuardSchemaFieldTests() public GuardSchemaFieldTests()
{ {
schema.AddField(new StringField(1, "field1", Partitioning.Invariant)); schema_0 =
schema.AddField(new StringField(2, "field2", Partitioning.Invariant)); new Schema("my-schema")
.AddField(new StringField(1, "field1", Partitioning.Invariant))
.AddField(new StringField(2, "field2", Partitioning.Invariant));
} }
[Fact] [Fact]
@ -32,9 +36,9 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new HideField { FieldId = 1 }; 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] [Fact]
@ -42,7 +46,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new HideField { FieldId = 3 }; var command = new HideField { FieldId = 3 };
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanHide(schema, command)); Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanHide(schema_0, command));
} }
[Fact] [Fact]
@ -50,7 +54,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new HideField { FieldId = 1 }; var command = new HideField { FieldId = 1 };
GuardSchemaField.CanHide(schema, command); GuardSchemaField.CanHide(schema_0, command);
} }
[Fact] [Fact]
@ -58,9 +62,9 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new DisableField { FieldId = 1 }; 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] [Fact]
@ -68,7 +72,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new DisableField { FieldId = 3 }; var command = new DisableField { FieldId = 3 };
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanDisable(schema, command)); Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanDisable(schema_0, command));
} }
[Fact] [Fact]
@ -76,7 +80,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new DisableField { FieldId = 1 }; var command = new DisableField { FieldId = 1 };
GuardSchemaField.CanDisable(schema, command); GuardSchemaField.CanDisable(schema_0, command);
} }
[Fact] [Fact]
@ -84,7 +88,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new ShowField { FieldId = 1 }; var command = new ShowField { FieldId = 1 };
Assert.Throws<DomainException>(() => GuardSchemaField.CanShow(schema, command)); Assert.Throws<DomainException>(() => GuardSchemaField.CanShow(schema_0, command));
} }
[Fact] [Fact]
@ -92,7 +96,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new ShowField { FieldId = 3 }; var command = new ShowField { FieldId = 3 };
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanShow(schema, command)); Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanShow(schema_0, command));
} }
[Fact] [Fact]
@ -100,9 +104,9 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new ShowField { FieldId = 1 }; 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] [Fact]
@ -110,7 +114,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new EnableField { FieldId = 1 }; var command = new EnableField { FieldId = 1 };
Assert.Throws<DomainException>(() => GuardSchemaField.CanEnable(schema, command)); Assert.Throws<DomainException>(() => GuardSchemaField.CanEnable(schema_0, command));
} }
[Fact] [Fact]
@ -118,7 +122,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new EnableField { FieldId = 3 }; var command = new EnableField { FieldId = 3 };
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanEnable(schema, command)); Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanEnable(schema_0, command));
} }
[Fact] [Fact]
@ -126,9 +130,9 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new EnableField { FieldId = 1 }; 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] [Fact]
@ -136,9 +140,9 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new LockField { FieldId = 1 }; 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] [Fact]
@ -146,7 +150,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new LockField { FieldId = 3 }; var command = new LockField { FieldId = 3 };
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanLock(schema, command)); Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanLock(schema_0, command));
} }
[Fact] [Fact]
@ -154,7 +158,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new LockField { FieldId = 1 }; var command = new LockField { FieldId = 1 };
GuardSchemaField.CanLock(schema, command); GuardSchemaField.CanLock(schema_0, command);
} }
[Fact] [Fact]
@ -162,7 +166,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new DeleteField { FieldId = 3 }; var command = new DeleteField { FieldId = 3 };
Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanDelete(schema, command)); Assert.Throws<DomainObjectNotFoundException>(() => GuardSchemaField.CanDelete(schema_0, command));
} }
[Fact] [Fact]
@ -170,9 +174,9 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new DeleteField { FieldId = 1 }; 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] [Fact]
@ -180,7 +184,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new DeleteField { FieldId = 1 }; var command = new DeleteField { FieldId = 1 };
GuardSchemaField.CanDelete(schema, command); GuardSchemaField.CanDelete(schema_0, command);
} }
[Fact] [Fact]
@ -188,9 +192,9 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new UpdateField { FieldId = 1, Properties = new StringFieldProperties() }; 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] [Fact]
@ -198,7 +202,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new UpdateField { FieldId = 1, Properties = new StringFieldProperties() }; var command = new UpdateField { FieldId = 1, Properties = new StringFieldProperties() };
GuardSchemaField.CanUpdate(schema, command); GuardSchemaField.CanUpdate(schema_0, command);
} }
[Fact] [Fact]
@ -206,7 +210,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new AddField { Name = "field1", Properties = new StringFieldProperties() }; 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] [Fact]
@ -214,7 +218,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new AddField { Name = "INVALID_NAME", Properties = validProperties }; 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] [Fact]
@ -222,7 +226,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new AddField { Name = "field3", Properties = invalidProperties }; var command = new AddField { Name = "field3", Properties = invalidProperties };
Assert.Throws<ValidationException>(() => GuardSchemaField.CanAdd(schema, command)); Assert.Throws<ValidationException>(() => GuardSchemaField.CanAdd(schema_0, command));
} }
[Fact] [Fact]
@ -230,7 +234,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new AddField { Name = "field3", Partitioning = "INVALID_PARTITIONING", Properties = validProperties }; 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] [Fact]
@ -238,7 +242,7 @@ namespace Squidex.Domain.Apps.Write.Schemas
{ {
var command = new AddField { Name = "field3", Properties = new StringFieldProperties() }; 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 Squidex.Infrastructure;
using Xunit; using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Write.Schemas.Guards namespace Squidex.Domain.Apps.Write.Schemas.Guards
{ {
public class GuardSchemaTests public class GuardSchemaTests
{ {
private readonly IAppProvider appProvider = A.Fake<IAppProvider>(); 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"); private readonly NamedId<Guid> appId = new NamedId<Guid>(Guid.NewGuid(), "my-app");
public GuardSchemaTests() public GuardSchemaTests()
{ {
schema.AddField(new StringField(1, "field1", Partitioning.Invariant)); schema_0 =
schema.AddField(new StringField(2, "field2", Partitioning.Invariant)); 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)) A.CallTo(() => appProvider.GetSchemaAsync(A<string>.Ignored, "new-schema", false))
.Returns(Task.FromResult<ISchemaEntity>(null)); .Returns(Task.FromResult<ISchemaEntity>(null));
@ -121,9 +125,9 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
{ {
var command = new PublishSchema(); 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] [Fact]
@ -131,7 +135,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
{ {
var command = new PublishSchema(); var command = new PublishSchema();
GuardSchema.CanPublish(schema, command); GuardSchema.CanPublish(schema_0, command);
} }
[Fact] [Fact]
@ -139,7 +143,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
{ {
var command = new UnpublishSchema(); var command = new UnpublishSchema();
Assert.Throws<DomainException>(() => GuardSchema.CanUnpublish(schema, command)); Assert.Throws<DomainException>(() => GuardSchema.CanUnpublish(schema_0, command));
} }
[Fact] [Fact]
@ -147,9 +151,9 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
{ {
var command = new UnpublishSchema(); var command = new UnpublishSchema();
schema.Publish(); var schema_1 = schema_0.Publish();
GuardSchema.CanUnpublish(schema, command); GuardSchema.CanUnpublish(schema_1, command);
} }
[Fact] [Fact]
@ -157,7 +161,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
{ {
var command = new ReorderFields { FieldIds = new List<long> { 1, 3 } }; 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] [Fact]
@ -165,7 +169,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
{ {
var command = new ReorderFields { FieldIds = new List<long> { 1 } }; 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] [Fact]
@ -173,7 +177,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
{ {
var command = new ReorderFields { FieldIds = new List<long> { 1, 2 } }; var command = new ReorderFields { FieldIds = new List<long> { 1, 2 } };
GuardSchema.CanReorder(schema, command); GuardSchema.CanReorder(schema_0, command);
} }
[Fact] [Fact]
@ -181,7 +185,7 @@ namespace Squidex.Domain.Apps.Write.Schemas.Guards
{ {
var command = new DeleteSchema(); var command = new DeleteSchema();
GuardSchema.CanDelete(schema, command); GuardSchema.CanDelete(schema_0, command);
} }
private static StringFieldProperties ValidProperties() 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 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()); private readonly JsonExternalSerializer sut = new JsonExternalSerializer(JsonSerializer.CreateDefault());
public JsonExternalSerializerTests()
{
}
[Fact] [Fact]
public void Should_serialize_js_only() public void Should_serialize_js_only()
{ {
Assert.True(sut.IsSupportedType(typeof(J<int>))); var serializer = new JsonExternalSerializer(JsonSerializer.CreateDefault(), typeof(int), typeof(bool));
Assert.True(sut.IsSupportedType(typeof(J<List<int>>)));
Assert.False(sut.IsSupportedType(typeof(int))); Assert.True(sut.IsSupportedType(typeof(int)));
Assert.False(sut.IsSupportedType(typeof(List<int>))); Assert.True(sut.IsSupportedType(typeof(bool)));
Assert.False(sut.IsSupportedType(typeof(float)));
Assert.False(sut.IsSupportedType(typeof(double)));
} }
[Fact] [Fact]
@ -67,38 +40,20 @@ namespace Squidex.Infrastructure.Json.Orleans
Assert.Null(copy); 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] [Fact]
public void Should_copy_non_immutable_values() public void Should_copy_non_immutable_values()
{ {
var value = new J<List<int>>(new List<int> { 1, 2, 3 }); var value = new List<int> { 1, 2, 3 };
var copy = (J<List<int>>)sut.DeepCopy(value, null); var copy = (List<int>)sut.DeepCopy(value, null);
Assert.Equal(value.Value, copy.Value); Assert.Equal(value, copy);
Assert.NotSame(value.Value, copy.Value); Assert.NotSame(value, copy);
} }
[Fact] [Fact]
public void Should_serialize_and_deserialize_value() 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 writtenLength = 0;
var writtenBuffer = (byte[])null; var writtenBuffer = (byte[])null;
@ -123,10 +78,10 @@ namespace Squidex.Infrastructure.Json.Orleans
A.CallTo(() => reader.ReadBytes(writtenLength)) A.CallTo(() => reader.ReadBytes(writtenLength))
.Returns(writtenBuffer); .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.Equal(value, copy);
Assert.NotSame(value.Value, copy.Value); Assert.NotSame(value, copy);
} }
} }
} }

Loading…
Cancel
Save