Browse Source

Datetime property and tests fixes

pull/1/head
Sebastian 9 years ago
parent
commit
ad9ebe7019
  1. 10
      build.sh
  2. 26
      src/Squidex.Core/Contents/ContentData.cs
  3. 6
      src/Squidex.Core/Schemas/BooleanFieldProperties.cs
  4. 57
      src/Squidex.Core/Schemas/DateTimeField.cs
  5. 18
      src/Squidex.Core/Schemas/DateTimeFieldEditor.cs
  6. 96
      src/Squidex.Core/Schemas/DateTimeFieldProperties.cs
  7. 14
      src/Squidex.Core/Schemas/Field.cs
  8. 3
      src/Squidex.Core/Schemas/FieldProperties.cs
  9. 3
      src/Squidex.Core/Schemas/FieldRegistry.cs
  10. 6
      src/Squidex.Core/Schemas/NumberFieldProperties.cs
  11. 51
      src/Squidex.Core/Schemas/Schema.cs
  12. 1
      src/Squidex.Core/Schemas/SchemaProperties.cs
  13. 18
      src/Squidex.Core/Schemas/StringFieldProperties.cs
  14. 4
      src/Squidex.Core/Squidex.Core.csproj
  15. 4
      src/Squidex.Events/Squidex.Events.csproj
  16. 4
      src/Squidex.Infrastructure.MongoDb/Squidex.Infrastructure.MongoDb.csproj
  17. 4
      src/Squidex.Infrastructure.Redis/RedisSubscription.cs
  18. 4
      src/Squidex.Infrastructure.Redis/Squidex.Infrastructure.Redis.csproj
  19. 1
      src/Squidex.Infrastructure/CQRS/Events/EventReceiver.cs
  20. 8
      src/Squidex.Infrastructure/CollectionExtensions.cs
  21. 4
      src/Squidex.Infrastructure/Dispatching/ActionContextDispatcher.cs
  22. 4
      src/Squidex.Infrastructure/Dispatching/ActionDispatcher.cs
  23. 4
      src/Squidex.Infrastructure/Dispatching/FuncContextDispatcher.cs
  24. 4
      src/Squidex.Infrastructure/Dispatching/FuncDispatcher.cs
  25. 4
      src/Squidex.Infrastructure/Json/NamedGuidIdConverter.cs
  26. 4
      src/Squidex.Infrastructure/Json/NamedLongIdConverter.cs
  27. 4
      src/Squidex.Infrastructure/Language.cs
  28. 4
      src/Squidex.Infrastructure/PropertiesBag.cs
  29. 12
      src/Squidex.Infrastructure/PropertyValue.cs
  30. 4
      src/Squidex.Infrastructure/Reflection/PropertiesTypeAccessor.cs
  31. 4
      src/Squidex.Infrastructure/Squidex.Infrastructure.csproj
  32. 4
      src/Squidex.Read.MongoDb/Contents/Visitors/PropertyVisitor.cs
  33. 4
      src/Squidex.Read.MongoDb/Squidex.Read.MongoDb.csproj
  34. 8
      src/Squidex.Read/Apps/Services/Implementations/CachingAppProvider.cs
  35. 8
      src/Squidex.Read/Schemas/Services/Implementations/CachingSchemaProvider.cs
  36. 4
      src/Squidex.Read/Squidex.Read.csproj
  37. 4
      src/Squidex.Write/Apps/AppContributors.cs
  38. 13
      src/Squidex.Write/Contents/ContentCommandHandler.cs
  39. 4
      src/Squidex.Write/Schemas/SchemaDomainObject.cs
  40. 4
      src/Squidex.Write/Squidex.Write.csproj
  41. 8
      src/Squidex/Config/Swagger/XmlResponseTypesProcessor.cs
  42. 1
      src/Squidex/Controllers/Api/Apps/Models/ClientDto.cs
  43. 11
      src/Squidex/Controllers/Api/Schemas/Models/Converters/SchemaConverter.cs
  44. 49
      src/Squidex/Controllers/Api/Schemas/Models/DateTimeFieldPropertiesDto.cs
  45. 1
      src/Squidex/Controllers/Api/Schemas/Models/FieldPropertiesDto.cs
  46. 8
      tests/RunCoverage.bat
  47. 16
      tests/Squidex.Core.Tests/Schemas/BooleanFieldTests.cs
  48. 141
      tests/Squidex.Core.Tests/Schemas/DateTimeFieldPropertiesTests.cs
  49. 102
      tests/Squidex.Core.Tests/Schemas/DateTimeFieldTests.cs
  50. 6
      tests/Squidex.Core.Tests/Schemas/FieldRegistryTests.cs
  51. 12
      tests/Squidex.Core.Tests/Schemas/Json/JsonSerializerTests.cs
  52. 2
      tests/Squidex.Core.Tests/Schemas/NumberFieldPropertiesTests.cs
  53. 28
      tests/Squidex.Core.Tests/Schemas/NumberFieldTests.cs
  54. 38
      tests/Squidex.Core.Tests/Schemas/SchemaTests.cs
  55. 36
      tests/Squidex.Core.Tests/Schemas/SchemaValidationTests.cs
  56. 30
      tests/Squidex.Core.Tests/Schemas/StringFieldTests.cs
  57. 4
      tests/Squidex.Read.Tests/Apps/CachingAppProviderTests.cs
  58. 4
      tests/Squidex.Read.Tests/Schemas/CachingSchemaProviderTests.cs
  59. 4
      tests/Squidex.Write.Tests/Squidex.Write.Tests.csproj

10
build.sh

@ -9,9 +9,9 @@ npm run build:copy
npm run build
cd ./../..
dotnet restore
dotnet test tests/Squidex.Core.Tests/project.json
dotnet test tests/Squidex.Infrastructure.Tests/project.json
dotnet test tests/Squidex.Read.Tests/project.json
dotnet test tests/Squidex.Write.Tests/project.json
dotnet test tests/Squidex.Core.Tests/Squidex.Core.Tests.csproj
dotnet test tests/Squidex.Infrastructure.Tests/Squidex.Infrastructure.Tests.csproj
dotnet test tests/Squidex.Read.Tests/Squidex.Read.Tests.csproj
dotnet test tests/Squidex.Write.Tests/Squidex.Write.Tests.csproj
rm -rf $(pwd)/publish/web
dotnet publish src/Squidex/project.json -c release -o $(pwd)/publish/web
dotnet publish src/Squidex/Squidex.csproj -c release -o $(pwd)/publish/web

26
src/Squidex.Core/Contents/ContentData.cs

@ -70,9 +70,7 @@ namespace Squidex.Core.Contents
foreach (var fieldValue in this)
{
Field field;
if (!schema.FieldsByName.TryGetValue(fieldValue.Key, out field))
if (!schema.FieldsByName.TryGetValue(fieldValue.Key, out Field field))
{
continue;
}
@ -91,11 +89,7 @@ namespace Squidex.Core.Contents
foreach (var fieldValue in this)
{
long fieldId;
Field field;
if (!long.TryParse(fieldValue.Key, out fieldId) || !schema.Fields.TryGetValue(fieldId, out field))
if (!long.TryParse(fieldValue.Key, out long fieldId) || !schema.Fields.TryGetValue(fieldId, out Field field))
{
continue;
}
@ -118,9 +112,7 @@ namespace Squidex.Core.Contents
foreach (var fieldValue in this)
{
Field field;
if (!schema.FieldsByName.TryGetValue(fieldValue.Key, out field) || (excludeHidden && field.IsHidden))
if (!schema.FieldsByName.TryGetValue(fieldValue.Key, out Field field) || (excludeHidden && field.IsHidden))
{
continue;
}
@ -134,9 +126,7 @@ namespace Squidex.Core.Contents
{
var languageCode = language.Iso2Code;
JToken value;
if (fieldValues.TryGetValue(languageCode, out value))
if (fieldValues.TryGetValue(languageCode, out JToken value))
{
fieldResult.Add(languageCode, value);
}
@ -144,9 +134,7 @@ namespace Squidex.Core.Contents
}
else
{
JToken value;
if (fieldValues.TryGetValue(invariantCode, out value))
if (fieldValues.TryGetValue(invariantCode, out JToken value))
{
fieldResult.Add(invariantCode, value);
}
@ -183,9 +171,7 @@ namespace Squidex.Core.Contents
{
var languageCode = language.Iso2Code;
JToken value;
if (fieldValues.TryGetValue(languageCode, out value) && value != null)
if (fieldValues.TryGetValue(languageCode, out JToken value) && value != null)
{
result[fieldValue.Key] = value;

6
src/Squidex.Core/Schemas/BooleanFieldProperties.cs

@ -7,6 +7,7 @@
// ==========================================================================
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure;
namespace Squidex.Core.Schemas
@ -39,6 +40,11 @@ namespace Squidex.Core.Schemas
}
}
public override JToken GetDefaultValue()
{
return DefaultValue;
}
protected override IEnumerable<ValidationError> ValidateCore()
{
if (!Editor.IsEnumValue())

57
src/Squidex.Core/Schemas/DateTimeField.cs

@ -0,0 +1,57 @@
// ==========================================================================
// DateTimeField.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Library;
using Newtonsoft.Json.Linq;
using NJsonSchema;
using Squidex.Core.Schemas.Validators;
using Squidex.Infrastructure;
namespace Squidex.Core.Schemas
{
[TypeName("DateTimeField")]
public sealed class DateTimeField : Field<DateTimeFieldProperties>
{
public DateTimeField(long id, string name, DateTimeFieldProperties properties)
: base(id, name, properties)
{
}
protected override IEnumerable<IValidator> CreateValidators()
{
if (Properties.IsRequired)
{
yield return new RequiredValidator();
}
if (Properties.MinValue.HasValue || Properties.MaxValue.HasValue)
{
yield return new RangeValidator<DateTimeOffset>(Properties.MinValue, Properties.MaxValue);
}
}
protected override object ConvertValue(JToken value)
{
return (DateTimeOffset?)value;
}
protected override void PrepareJsonSchema(JsonProperty jsonProperty)
{
jsonProperty.Type = JsonObjectType.String;
jsonProperty.Format = "date-time";
}
protected override IEdmTypeReference CreateEdmType()
{
return EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.DateTimeOffset, !Properties.IsRequired);
}
}
}

18
src/Squidex.Core/Schemas/DateTimeFieldEditor.cs

@ -0,0 +1,18 @@
// ==========================================================================
// DateTimeFieldEditor.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
namespace Squidex.Core.Schemas
{
public enum DateTimeFieldEditor
{
Date,
DateWithTimezone,
DateTime,
DateTimeWithTimezone
}
}

96
src/Squidex.Core/Schemas/DateTimeFieldProperties.cs

@ -0,0 +1,96 @@
// ==========================================================================
// DateTimeFieldProperties.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure;
namespace Squidex.Core.Schemas
{
[TypeName("DateTime")]
public sealed class DateTimeFieldProperties : FieldProperties
{
private DateTimeFieldEditor editor;
private DateTimeOffset? maxValue;
private DateTimeOffset? minValue;
private DateTimeOffset? defaultValue;
public DateTimeOffset? MaxValue
{
get { return maxValue; }
set
{
ThrowIfFrozen();
maxValue = value;
}
}
public DateTimeOffset? MinValue
{
get { return minValue; }
set
{
ThrowIfFrozen();
minValue = value;
}
}
public DateTimeOffset? DefaultValue
{
get { return defaultValue; }
set
{
ThrowIfFrozen();
defaultValue = value;
}
}
public DateTimeFieldEditor Editor
{
get { return editor; }
set
{
ThrowIfFrozen();
editor = value;
}
}
public override JToken GetDefaultValue()
{
return DefaultValue;
}
protected override IEnumerable<ValidationError> ValidateCore()
{
if (!Editor.IsEnumValue())
{
yield return new ValidationError("Editor ist not a valid value", nameof(Editor));
}
if (MaxValue.HasValue && MinValue.HasValue && MinValue.Value >= MaxValue.Value)
{
yield return new ValidationError("Max value must be greater than min value", nameof(MinValue), nameof(MaxValue));
}
if (DefaultValue.HasValue && MinValue.HasValue && DefaultValue.Value < MinValue.Value)
{
yield return new ValidationError("Default value must be greater than min value", nameof(DefaultValue));
}
if (DefaultValue.HasValue && MaxValue.HasValue && DefaultValue.Value > MaxValue.Value)
{
yield return new ValidationError("Default value must be less than max value", nameof(DefaultValue));
}
}
}
}

14
src/Squidex.Core/Schemas/Field.cs

@ -13,6 +13,7 @@ using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Library;
using Newtonsoft.Json.Linq;
using NJsonSchema;
using Squidex.Core.Contents;
using Squidex.Infrastructure;
// ReSharper disable InvertIf
@ -65,6 +66,19 @@ namespace Squidex.Core.Schemas
public abstract Field Update(FieldProperties newProperties);
public void Enrich(ContentFieldData fieldData, Language language)
{
Guard.NotNull(fieldData, nameof(fieldData));
Guard.NotNull(language, nameof(language));
var defaultValue = RawProperties.GetDefaultValue();
if (!RawProperties.IsRequired && defaultValue != null && fieldData.GetOrDefault(language.Iso2Code) == null)
{
fieldData.AddValue(language.Iso2Code, defaultValue);
}
}
public async Task ValidateAsync(JToken value, ICollection<string> errors, Language language = null)
{
Guard.NotNull(value, nameof(value));

3
src/Squidex.Core/Schemas/FieldProperties.cs

@ -7,6 +7,7 @@
// ==========================================================================
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure;
namespace Squidex.Core.Schemas
@ -62,6 +63,8 @@ namespace Squidex.Core.Schemas
}
}
public abstract JToken GetDefaultValue();
public void Validate(IList<ValidationError> errors)
{
foreach (var error in ValidateCore())

3
src/Squidex.Core/Schemas/FieldRegistry.cs

@ -64,6 +64,9 @@ namespace Squidex.Core.Schemas
Add<StringFieldProperties>(
(id, name, p) => new StringField(id, name, (StringFieldProperties)p));
Add<DateTimeFieldProperties>(
(id, name, p) => new DateTimeField(id, name, (DateTimeFieldProperties)p));
}
public void Add<TFieldProperties>(FactoryFunction fieldFactory)

6
src/Squidex.Core/Schemas/NumberFieldProperties.cs

@ -8,6 +8,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure;
namespace Squidex.Core.Schemas
@ -76,6 +77,11 @@ namespace Squidex.Core.Schemas
}
}
public override JToken GetDefaultValue()
{
return DefaultValue;
}
protected override IEnumerable<ValidationError> ValidateCore()
{
if (!Editor.IsEnumValue())

51
src/Squidex.Core/Schemas/Schema.cs

@ -162,9 +162,7 @@ namespace Squidex.Core.Schemas
{
Guard.NotNull(updater, nameof(updater));
Field field;
if (!fieldsById.TryGetValue(fieldId, out field))
if (!fieldsById.TryGetValue(fieldId, out Field field))
{
throw new DomainObjectNotFoundException(fieldId.ToString(), "Fields", typeof(Field));
}
@ -211,9 +209,7 @@ namespace Squidex.Core.Schemas
foreach (var fieldData in data)
{
Field field;
if (!fieldsByName.TryGetValue(fieldData.Key, out field))
if (!fieldsByName.TryGetValue(fieldData.Key, out Field field))
{
errors.Add(new ValidationError($"{fieldData.Key} is not a known field", fieldData.Key));
}
@ -225,9 +221,7 @@ namespace Squidex.Core.Schemas
{
foreach (var languageValue in fieldData.Value)
{
Language language;
if (!Language.TryGetLanguage(languageValue.Key, out language))
if (!Language.TryGetLanguage(languageValue.Key, out Language language))
{
fieldErrors.Add($"{field.Name} has an invalid language '{languageValue.Key}'");
}
@ -248,9 +242,7 @@ namespace Squidex.Core.Schemas
fieldErrors.Add($"{field.Name} can only contain a single entry for invariant language ({Language.Invariant.Iso2Code})");
}
JToken value;
if (fieldData.Value.TryGetValue(Language.Invariant.Iso2Code, out value))
if (fieldData.Value.TryGetValue(Language.Invariant.Iso2Code, out JToken value))
{
await field.ValidateAsync(value, fieldErrors);
}
@ -281,16 +273,13 @@ namespace Squidex.Core.Schemas
foreach (var field in fieldsByName.Values)
{
var fieldErrors = new List<string>();
var fieldData = data.GetOrDefault(field.Name) ?? new ContentFieldData();
var fieldData = data.GetOrCreate(field.Name, k => new ContentFieldData());
if (field.RawProperties.IsLocalizable)
{
foreach (var valueLanguage in fieldData.Keys)
{
Language language;
if (!Language.TryGetLanguage(valueLanguage, out language))
if (!Language.TryGetLanguage(valueLanguage, out Language language))
{
fieldErrors.Add($"{field.Name} has an invalid language '{valueLanguage}'");
}
@ -325,5 +314,33 @@ namespace Squidex.Core.Schemas
}
}
}
public void Enrich(ContentData data, HashSet<Language> languages)
{
Guard.NotNull(data, nameof(data));
Guard.NotEmpty(languages, nameof(languages));
foreach (var field in fieldsByName.Values)
{
var fieldData = data.GetOrCreate(field.Name, k => new ContentFieldData());
if (field.RawProperties.IsLocalizable)
{
foreach (var language in languages)
{
field.Enrich(fieldData, language);
}
}
else
{
field.Enrich(fieldData, Language.Invariant);
}
if (fieldData.Count > 0)
{
data.AddField(field.Name, fieldData);
}
}
}
}
}

1
src/Squidex.Core/Schemas/SchemaProperties.cs

@ -5,6 +5,7 @@
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
namespace Squidex.Core.Schemas
{
public sealed class SchemaProperties : NamedElementProperties

18
src/Squidex.Core/Schemas/StringFieldProperties.cs

@ -9,6 +9,7 @@
using System.Collections.Generic;
using Squidex.Infrastructure;
using System.Collections.Immutable;
using Newtonsoft.Json.Linq;
// ReSharper disable ObjectCreationAsStatement
@ -21,6 +22,7 @@ namespace Squidex.Core.Schemas
private int? maxLength;
private string pattern;
private string patternMessage;
private string defaultValue;
private ImmutableList<string> allowedValues;
private StringFieldEditor editor;
@ -46,6 +48,17 @@ namespace Squidex.Core.Schemas
}
}
public string DefaultValue
{
get { return defaultValue; }
set
{
ThrowIfFrozen();
defaultValue = value;
}
}
public string Pattern
{
get { return pattern; }
@ -90,6 +103,11 @@ namespace Squidex.Core.Schemas
}
}
public override JToken GetDefaultValue()
{
return DefaultValue;
}
protected override IEnumerable<ValidationError> ValidateCore()
{
if (!Editor.IsEnumValue())

4
src/Squidex.Core/Squidex.Core.csproj

@ -3,6 +3,10 @@
<TargetFramework>netstandard1.6</TargetFramework>
<PackageTargetFallback>$(PackageTargetFallback);dnxcore50</PackageTargetFallback>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Squidex.Infrastructure\Squidex.Infrastructure.csproj" />
</ItemGroup>

4
src/Squidex.Events/Squidex.Events.csproj

@ -3,6 +3,10 @@
<TargetFramework>netstandard1.6</TargetFramework>
<PackageTargetFallback>$(PackageTargetFallback);dnxcore50</PackageTargetFallback>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Squidex.Core\Squidex.Core.csproj" />
<ProjectReference Include="..\Squidex.Infrastructure\Squidex.Infrastructure.csproj" />

4
src/Squidex.Infrastructure.MongoDb/Squidex.Infrastructure.MongoDb.csproj

@ -2,6 +2,10 @@
<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Squidex.Infrastructure\Squidex.Infrastructure.csproj" />
</ItemGroup>

4
src/Squidex.Infrastructure.Redis/RedisSubscription.cs

@ -64,9 +64,7 @@ namespace Squidex.Infrastructure.Redis
return;
}
Guid sender;
if (!Guid.TryParse(parts[0], out sender))
if (!Guid.TryParse(parts[0], out Guid sender))
{
return;
}

4
src/Squidex.Infrastructure.Redis/Squidex.Infrastructure.Redis.csproj

@ -2,6 +2,10 @@
<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Squidex.Infrastructure\Squidex.Infrastructure.csproj" />
</ItemGroup>

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

@ -136,7 +136,6 @@ namespace Squidex.Infrastructure.CQRS.Events
{
try
{
logger.LogDebug("[{0}]: Reset started", eventConsumer);
await eventConsumer.ClearAsync();

8
src/Squidex.Infrastructure/CollectionExtensions.cs

@ -109,9 +109,7 @@ namespace Squidex.Infrastructure
public static TValue GetOrCreate<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> creator)
{
TValue result;
if (!dictionary.TryGetValue(key, out result))
if (!dictionary.TryGetValue(key, out TValue result))
{
result = creator(key);
}
@ -121,9 +119,7 @@ namespace Squidex.Infrastructure
public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> creator)
{
TValue result;
if (!dictionary.TryGetValue(key, out result))
if (!dictionary.TryGetValue(key, out TValue result))
{
result = creator(key);

4
src/Squidex.Infrastructure/Dispatching/ActionContextDispatcher.cs

@ -30,9 +30,7 @@ namespace Squidex.Infrastructure.Dispatching
public static bool Dispatch(TTarget target, TIn input, TContext context)
{
Action<TTarget, object, TContext> handler;
if (!Handlers.TryGetValue(input.GetType(), out handler))
if (!Handlers.TryGetValue(input.GetType(), out Action<TTarget, object, TContext> handler))
{
return false;
}

4
src/Squidex.Infrastructure/Dispatching/ActionDispatcher.cs

@ -30,9 +30,7 @@ namespace Squidex.Infrastructure.Dispatching
public static bool Dispatch(TTarget target, TIn item)
{
Action<TTarget, object> handler;
if (!Handlers.TryGetValue(item.GetType(), out handler))
if (!Handlers.TryGetValue(item.GetType(), out Action<TTarget, object> handler))
{
return false;
}

4
src/Squidex.Infrastructure/Dispatching/FuncContextDispatcher.cs

@ -31,9 +31,7 @@ namespace Squidex.Infrastructure.Dispatching
public static TOut Dispatch(TTarget target, TIn item, TContext context)
{
Func<TTarget, object, TContext, TOut > handler;
return Handlers.TryGetValue(item.GetType(), out handler) ? handler(target, item, context) : default(TOut);
return Handlers.TryGetValue(item.GetType(), out Func<TTarget, object, TContext, TOut> handler) ? handler(target, item, context) : default(TOut);
}
}
}

4
src/Squidex.Infrastructure/Dispatching/FuncDispatcher.cs

@ -31,9 +31,7 @@ namespace Squidex.Infrastructure.Dispatching
public static TOut Dispatch(TTarget target, TIn item)
{
Func<TTarget, object, TOut> handler;
return Handlers.TryGetValue(item.GetType(), out handler) ? handler(target, item) : default(TOut);
return Handlers.TryGetValue(item.GetType(), out Func<TTarget, object, TOut> handler) ? handler(target, item) : default(TOut);
}
}
}

4
src/Squidex.Infrastructure/Json/NamedGuidIdConverter.cs

@ -35,9 +35,7 @@ namespace Squidex.Infrastructure.Json
throw new JsonException("Named id must have more than 2 parts divided by commata");
}
Guid id;
if (!Guid.TryParse(parts[0], out id))
if (!Guid.TryParse(parts[0], out Guid id))
{
throw new JsonException("Named id must be a valid guid");
}

4
src/Squidex.Infrastructure/Json/NamedLongIdConverter.cs

@ -35,9 +35,7 @@ namespace Squidex.Infrastructure.Json
throw new JsonException("Named id must have more than 2 parts divided by commata");
}
long id;
if (!long.TryParse(parts[0], out id))
if (!long.TryParse(parts[0], out long id))
{
throw new JsonException("Named id must be a valid long");
}

4
src/Squidex.Infrastructure/Language.cs

@ -103,9 +103,7 @@ namespace Squidex.Infrastructure
input = match.Groups[0].Value;
}
Language result;
if (TryGetLanguage(input.ToLowerInvariant(), out result))
if (TryGetLanguage(input.ToLowerInvariant(), out Language result))
{
return result;
}

4
src/Squidex.Infrastructure/PropertiesBag.cs

@ -99,9 +99,7 @@ namespace Squidex.Infrastructure
throw new ArgumentException($"The property names '{newPropertyName}' are equal.", newPropertyName);
}
PropertyValue property;
if (!internalDictionary.TryGetValue(oldPropertyName, out property))
if (!internalDictionary.TryGetValue(oldPropertyName, out PropertyValue property))
{
return false;
}

12
src/Squidex.Infrastructure/PropertyValue.cs

@ -58,9 +58,7 @@ namespace Squidex.Infrastructure
{
result = null;
Func<PropertyValue, CultureInfo, object> parser;
if (!Parsers.TryGetValue(binder.Type, out parser))
if (!Parsers.TryGetValue(binder.Type, out Func<PropertyValue, CultureInfo, object> parser))
{
return false;
}
@ -147,16 +145,12 @@ namespace Squidex.Infrastructure
private T? ToNullableOrParseValue<T>(IFormatProvider culture, Func<string, T> parser) where T : struct
{
T result;
return TryParse(culture, parser, out result) ? result : (T?)null;
return TryParse(culture, parser, out T result) ? result : (T?)null;
}
private T ToOrParseValue<T>(IFormatProvider culture, Func<string, T> parser)
{
T result;
return TryParse(culture, parser, out result) ? result : default(T);
return TryParse(culture, parser, out T result) ? result : default(T);
}
private bool TryParse<T>(IFormatProvider culture, Func<string, T> parser, out T result)

4
src/Squidex.Infrastructure/Reflection/PropertiesTypeAccessor.cs

@ -68,9 +68,7 @@ namespace Squidex.Infrastructure.Reflection
{
Guard.NotNullOrEmpty(propertyName, nameof(propertyName));
IPropertyAccessor accessor;
if (!accessors.TryGetValue(propertyName, out accessor))
if (!accessors.TryGetValue(propertyName, out IPropertyAccessor accessor))
{
throw new ArgumentException("Property does not exist.", nameof(propertyName));
}

4
src/Squidex.Infrastructure/Squidex.Infrastructure.csproj

@ -2,6 +2,10 @@
<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.0" />

4
src/Squidex.Read.MongoDb/Contents/Visitors/PropertyVisitor.cs

@ -29,9 +29,7 @@ namespace Squidex.Read.MongoDb.Contents.Visitors
if (propertyNames.Length == 3)
{
Field field;
if (!schema.FieldsByName.TryGetValue(propertyNames[1], out field))
if (!schema.FieldsByName.TryGetValue(propertyNames[1], out Field field))
{
throw new NotSupportedException();
}

4
src/Squidex.Read.MongoDb/Squidex.Read.MongoDb.csproj

@ -3,6 +3,10 @@
<TargetFramework>netstandard1.6</TargetFramework>
<PackageTargetFallback>$(PackageTargetFallback);dnxcore50</PackageTargetFallback>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Squidex.Core\Squidex.Core.csproj" />
<ProjectReference Include="..\Squidex.Events\Squidex.Events.csproj" />

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

@ -35,9 +35,7 @@ namespace Squidex.Read.Apps.Services.Implementations
{
var cacheKey = BuildIdCacheKey(appId);
IAppEntity result;
if (!Cache.TryGetValue(cacheKey, out result))
if (!Cache.TryGetValue(cacheKey, out IAppEntity result))
{
result = await repository.FindAppAsync(appId);
@ -58,9 +56,7 @@ namespace Squidex.Read.Apps.Services.Implementations
var cacheKey = BuildNameCacheKey(name);
IAppEntity result;
if (!Cache.TryGetValue(cacheKey, out result))
if (!Cache.TryGetValue(cacheKey, out IAppEntity result))
{
result = await repository.FindAppAsync(name);

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

@ -36,9 +36,7 @@ namespace Squidex.Read.Schemas.Services.Implementations
{
var cacheKey = BuildIdCacheKey(id);
ISchemaEntityWithSchema result;
if (!Cache.TryGetValue(cacheKey, out result))
if (!Cache.TryGetValue(cacheKey, out ISchemaEntityWithSchema result))
{
result = await repository.FindSchemaAsync(id);
@ -59,9 +57,7 @@ namespace Squidex.Read.Schemas.Services.Implementations
var cacheKey = BuildNameCacheKey(appId, name);
ISchemaEntityWithSchema result;
if (!Cache.TryGetValue(cacheKey, out result))
if (!Cache.TryGetValue(cacheKey, out ISchemaEntityWithSchema result))
{
result = await repository.FindSchemaAsync(appId, name);

4
src/Squidex.Read/Squidex.Read.csproj

@ -3,6 +3,10 @@
<TargetFramework>netstandard1.6</TargetFramework>
<PackageTargetFallback>$(PackageTargetFallback);dnxcore50</PackageTargetFallback>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Squidex.Core\Squidex.Core.csproj" />
<ProjectReference Include="..\Squidex.Events\Squidex.Events.csproj" />

4
src/Squidex.Write/Apps/AppContributors.cs

@ -50,9 +50,7 @@ namespace Squidex.Write.Apps
private void ThrowIfFound(string contributorId, PermissionLevel permission, Func<string> message)
{
PermissionLevel currentPermission;
if (contributors.TryGetValue(contributorId, out currentPermission) && currentPermission == permission)
if (contributors.TryGetValue(contributorId, out PermissionLevel currentPermission) && currentPermission == permission)
{
var error = new ValidationError("Contributor is already part of the app with same permissions", "ContributorId");

13
src/Squidex.Write/Contents/ContentCommandHandler.cs

@ -96,13 +96,18 @@ namespace Squidex.Write.Contents
await Task.WhenAll(taskForApp, taskForSchema);
var errors = new List<ValidationError>();
var languages = new HashSet<Language>(taskForApp.Result.Languages);
await taskForSchema.Result.Schema.ValidateAsync(command.Data, errors, new HashSet<Language>(taskForApp.Result.Languages));
var schemaObject = taskForSchema.Result.Schema;
var schemaErrors = new List<ValidationError>();
if (errors.Count > 0)
await schemaObject.ValidateAsync(command.Data, schemaErrors, languages);
schemaObject.Enrich(command.Data, languages);
if (schemaErrors.Count > 0)
{
throw new ValidationException(message(), errors);
throw new ValidationException(message(), schemaErrors);
}
}
}

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

@ -240,9 +240,7 @@ namespace Squidex.Write.Schemas
{
SimpleMapper.Map(fieldCommand, @event);
Field field;
if (schema.Fields.TryGetValue(fieldCommand.FieldId, out field))
if (schema.Fields.TryGetValue(fieldCommand.FieldId, out Field field))
{
@event.FieldId = new NamedId<long>(field.Id, field.Name);
}

4
src/Squidex.Write/Squidex.Write.csproj

@ -3,6 +3,10 @@
<TargetFramework>netstandard1.6</TargetFramework>
<PackageTargetFallback>$(PackageTargetFallback);dnxcore50</PackageTargetFallback>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Squidex.Core\Squidex.Core.csproj" />
<ProjectReference Include="..\Squidex.Events\Squidex.Events.csproj" />

8
src/Squidex/Config/Swagger/XmlResponseTypesProcessor.cs

@ -37,9 +37,7 @@ namespace Squidex.Config.Swagger
{
var statusCode = match.Groups["Code"].Value;
SwaggerResponse response;
if (!operation.Responses.TryGetValue(statusCode, out response))
if (!operation.Responses.TryGetValue(statusCode, out SwaggerResponse response))
{
response = new SwaggerResponse();
@ -83,9 +81,7 @@ namespace Squidex.Config.Swagger
private static void RemoveOkResponse(SwaggerOperation operation)
{
SwaggerResponse response;
if (operation.Responses.TryGetValue("200", out response) &&
if (operation.Responses.TryGetValue("200", out SwaggerResponse response) &&
response.Description != null &&
response.Description.Contains("=>"))
{

1
src/Squidex/Controllers/Api/Apps/Models/ClientDto.cs

@ -6,7 +6,6 @@
// All rights reserved.
// ==========================================================================
using System;
using System.ComponentModel.DataAnnotations;
namespace Squidex.Controllers.Api.Apps.Models

11
src/Squidex/Controllers/Api/Schemas/Models/Converters/SchemaConverter.cs

@ -23,6 +23,10 @@ namespace Squidex.Controllers.Api.Schemas.Models.Converters
typeof(NumberFieldProperties),
p => Convert((NumberFieldProperties)p)
},
{
typeof(DateTimeFieldProperties),
p => Convert((DateTimeFieldProperties)p)
},
{
typeof(StringFieldProperties),
p => Convert((StringFieldProperties)p)
@ -63,6 +67,13 @@ namespace Squidex.Controllers.Api.Schemas.Models.Converters
return result;
}
private static FieldPropertiesDto Convert(DateTimeFieldProperties source)
{
var result = SimpleMapper.Map(source, new DateTimeFieldPropertiesDto());
return result;
}
private static FieldPropertiesDto Convert(StringFieldProperties source)
{
var result = SimpleMapper.Map(source, new StringFieldPropertiesDto());

49
src/Squidex/Controllers/Api/Schemas/Models/DateTimeFieldPropertiesDto.cs

@ -0,0 +1,49 @@
// ==========================================================================
// DateTimeFieldPropertiesDto.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Collections.Immutable;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using NJsonSchema.Annotations;
using Squidex.Core.Schemas;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Controllers.Api.Schemas.Models
{
[JsonSchema("dateTime")]
public sealed class DateTimeFieldPropertiesDto : FieldPropertiesDto
{
/// <summary>
/// The default value for the field value.
/// </summary>
public string DefaultValue { get; set; }
/// <summary>
/// The maximum allowed value for the field value.
/// </summary>
public string MaxValue { get; set; }
/// <summary>
/// The minimum allowed value for the field value.
/// </summary>
public string MinValue { get; set; }
/// <summary>
/// The editor that is used to manage this field.
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public DateTimeFieldEditor Editor { get; set; }
public override FieldProperties ToProperties()
{
var result = SimpleMapper.Map(this, new DateTimeFieldProperties());
return result;
}
}
}

1
src/Squidex/Controllers/Api/Schemas/Models/FieldPropertiesDto.cs

@ -16,6 +16,7 @@ namespace Squidex.Controllers.Api.Schemas.Models
{
[JsonConverter(typeof(JsonInheritanceConverter), "fieldType")]
[KnownType(typeof(BooleanFieldPropertiesDto))]
[KnownType(typeof(DateTimeFieldPropertiesDto))]
[KnownType(typeof(NumberFieldPropertiesDto))]
[KnownType(typeof(StringFieldPropertiesDto))]
public abstract class FieldPropertiesDto

8
tests/RunCoverage.bat

@ -19,7 +19,7 @@ exit /b %errorlevel%
"%UserProfile%\.nuget\packages\OpenCover\4.6.519\tools\OpenCover.Console.exe" ^
-register:user ^
-target:"C:\Program Files\dotnet\dotnet.exe" ^
-targetargs:"test %~dp0\Squidex.Infrastructure.Tests" ^
-targetargs:"test %~dp0\Squidex.Infrastructure.Tests\Squidex.Infrastructure.Tests.csproj" ^
-filter:"+[Squidex*]*" ^
-skipautoprops ^
-output:"%~dp0\GeneratedReports\Infrastructure.xml" ^
@ -28,7 +28,7 @@ exit /b %errorlevel%
"%UserProfile%\.nuget\packages\OpenCover\4.6.519\tools\OpenCover.Console.exe" ^
-register:user ^
-target:"C:\Program Files\dotnet\dotnet.exe" ^
-targetargs:"test %~dp0\Squidex.Core.Tests" ^
-targetargs:"test %~dp0\Squidex.Core.Tests\Squidex.Core.Tests.csproj" ^
-filter:"+[Squidex*]*" ^
-skipautoprops ^
-output:"%~dp0\GeneratedReports\Core.xml" ^
@ -37,7 +37,7 @@ exit /b %errorlevel%
"%UserProfile%\.nuget\packages\OpenCover\4.6.519\tools\OpenCover.Console.exe" ^
-register:user ^
-target:"C:\Program Files\dotnet\dotnet.exe" ^
-targetargs:"test %~dp0\Squidex.Write.Tests" ^
-targetargs:"test %~dp0\Squidex.Write.Tests\Squidex.Write.Tests.csproj" ^
-filter:"+[Squidex*]*" ^
-skipautoprops ^
-output:"%~dp0\GeneratedReports\Write.xml" ^
@ -46,7 +46,7 @@ exit /b %errorlevel%
"%UserProfile%\.nuget\packages\OpenCover\4.6.519\tools\OpenCover.Console.exe" ^
-register:user ^
-target:"C:\Program Files\dotnet\dotnet.exe" ^
-targetargs:"test %~dp0\Squidex.Read.Tests" ^
-targetargs:"test %~dp0\Squidex.Read.Tests\Squidex.Read.Tests.csproj" ^
-filter:"+[Squidex*]*" ^
-skipautoprops ^
-output:"%~dp0\GeneratedReports\Read.xml" ^

16
tests/Squidex.Core.Tests/Schemas/BooleanFieldTests.cs

@ -21,9 +21,9 @@ namespace Squidex.Core.Schemas
[Fact]
public void Should_instantiate_field()
{
var sut = new BooleanField(1, "name", new BooleanFieldProperties());
var sut = new BooleanField(1, "my-bolean", new BooleanFieldProperties());
Assert.Equal("name", sut.Name);
Assert.Equal("my-bolean", sut.Name);
}
[Fact]
@ -37,7 +37,7 @@ namespace Squidex.Core.Schemas
[Fact]
public async Task Should_not_add_error_if_valid_null()
{
var sut = new BooleanField(1, "name", new BooleanFieldProperties { Label = "Name" });
var sut = new BooleanField(1, "my-bolean", new BooleanFieldProperties { Label = "My-Boolean" });
await sut.ValidateAsync(CreateValue(null), errors);
@ -47,7 +47,7 @@ namespace Squidex.Core.Schemas
[Fact]
public async Task Should_not_add_error_if_valid()
{
var sut = new BooleanField(1, "name", new BooleanFieldProperties { Label = "Name" });
var sut = new BooleanField(1, "my-bolean", new BooleanFieldProperties { Label = "My-Boolean" });
await sut.ValidateAsync(CreateValue(true), errors);
@ -57,23 +57,23 @@ namespace Squidex.Core.Schemas
[Fact]
public async Task Should_add_errors_if_boolean_is_required()
{
var sut = new BooleanField(1, "name", new BooleanFieldProperties { Label = "Name", IsRequired = true });
var sut = new BooleanField(1, "my-bolean", new BooleanFieldProperties { Label = "My-Boolean", IsRequired = true });
await sut.ValidateAsync(CreateValue(null), errors);
errors.ShouldBeEquivalentTo(
new[] { "Name is required" });
new[] { "My-Boolean is required" });
}
[Fact]
public async Task Should_add_errors_if_value_is_not_valid()
{
var sut = new BooleanField(1, "name", new BooleanFieldProperties { Label = "Name" });
var sut = new BooleanField(1, "my-bolean", new BooleanFieldProperties { Label = "My-Boolean" });
await sut.ValidateAsync(CreateValue("Invalid"), errors);
errors.ShouldBeEquivalentTo(
new[] { "Name is not a valid value" });
new[] { "My-Boolean is not a valid value" });
}
private static JValue CreateValue(object v)

141
tests/Squidex.Core.Tests/Schemas/DateTimeFieldPropertiesTests.cs

@ -0,0 +1,141 @@
// ==========================================================================
// DateTimeFieldPropertiesTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using FluentAssertions;
using Squidex.Infrastructure;
using Xunit;
namespace Squidex.Core.Schemas
{
public class DateTimeFieldPropertiesTests
{
private readonly List<ValidationError> errors = new List<ValidationError>();
[Fact]
public void Should_not_add_error_if_sut_is_valid()
{
var sut = new DateTimeFieldProperties
{
MinValue = FutureDays(10),
MaxValue = FutureDays(20),
DefaultValue = FutureDays(15)
};
sut.Validate(errors);
Assert.Equal(0, errors.Count);
}
[Fact]
public void Should_add_error_if_default_value_is_less_than_min()
{
var sut = new DateTimeFieldProperties { MinValue = FutureDays(10), DefaultValue = FutureDays(5) };
sut.Validate(errors);
errors.ShouldBeEquivalentTo(
new List<ValidationError>
{
new ValidationError("Default value must be greater than min value", "DefaultValue")
});
}
[Fact]
public void Should_add_error_if_default_value_is_greater_than_min()
{
var sut = new DateTimeFieldProperties { MaxValue = FutureDays(10), DefaultValue = FutureDays(15) };
sut.Validate(errors);
errors.ShouldBeEquivalentTo(
new List<ValidationError>
{
new ValidationError("Default value must be less than max value", "DefaultValue")
});
}
[Fact]
public void Should_add_error_if_min_greater_than_max()
{
var sut = new DateTimeFieldProperties { MinValue = FutureDays(10), MaxValue = FutureDays(5) };
sut.Validate(errors);
errors.ShouldBeEquivalentTo(
new List<ValidationError>
{
new ValidationError("Max value must be greater than min value", "MinValue", "MaxValue")
});
}
[Fact]
public void Should_add_error_if_editor_is_not_valid()
{
var sut = new DateTimeFieldProperties { Editor = (DateTimeFieldEditor)123 };
sut.Validate(errors);
errors.ShouldBeEquivalentTo(
new List<ValidationError>
{
new ValidationError("Editor ist not a valid value", "Editor")
});
}
[Fact]
public void Should_set_or_freeze_sut()
{
var sut = new DateTimeFieldProperties();
foreach (var property in sut.GetType().GetRuntimeProperties().Where(x => x.Name != "IsFrozen"))
{
var value =
property.PropertyType.GetTypeInfo().IsValueType ?
Activator.CreateInstance(property.PropertyType) :
null;
property.SetValue(sut, value);
var result = property.GetValue(sut);
Assert.Equal(value, result);
}
sut.Freeze();
foreach (var property in sut.GetType().GetRuntimeProperties().Where(x => x.Name != "IsFrozen"))
{
var value =
property.PropertyType.GetTypeInfo().IsValueType ?
Activator.CreateInstance(property.PropertyType) :
null;
Assert.Throws<InvalidOperationException>(() =>
{
try
{
property.SetValue(sut, value);
}
catch (Exception ex)
{
throw ex.InnerException;
}
});
}
}
private static DateTimeOffset FutureDays(int days)
{
return DateTimeOffset.UtcNow.AddDays(days);
}
}
}

102
tests/Squidex.Core.Tests/Schemas/DateTimeFieldTests.cs

@ -0,0 +1,102 @@
// ==========================================================================
// DateTimeFieldTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using FluentAssertions;
using Newtonsoft.Json.Linq;
using Xunit;
namespace Squidex.Core.Schemas
{
public class DateTimeFieldTests
{
private readonly List<string> errors = new List<string>();
[Fact]
public void Should_instantiate_field()
{
var sut = new DateTimeField(1, "my-datetime", new DateTimeFieldProperties());
Assert.Equal("my-datetime", sut.Name);
}
[Fact]
public void Should_clone_object()
{
var sut = new DateTimeField(1, "my-datetime", new DateTimeFieldProperties());
Assert.NotEqual(sut, sut.Enable());
}
[Fact]
public async Task Should_not_add_error_if_valid()
{
var sut = new DateTimeField(1, "my-datetime", new DateTimeFieldProperties { Label = "My-DateTime" });
await sut.ValidateAsync(CreateValue(null), errors);
Assert.Empty(errors);
}
[Fact]
public async Task Should_add_errors_if_datetime_is_required()
{
var sut = new DateTimeField(1, "my-datetime", new DateTimeFieldProperties { Label = "My-DateTime", IsRequired = true });
await sut.ValidateAsync(CreateValue(null), errors);
errors.ShouldBeEquivalentTo(
new[] { "My-DateTime is required" });
}
[Fact]
public async Task Should_add_errors_if_datetime_is_less_than_min()
{
var sut = new DateTimeField(1, "my-datetime", new DateTimeFieldProperties { Label = "My-DateTime", MinValue = FutureDays(10) });
await sut.ValidateAsync(CreateValue(FutureDays(0)), errors);
errors.ShouldBeEquivalentTo(
new[] { $"My-DateTime must be greater than '{DateTimeOffset.UtcNow.AddDays(10)}'" });
}
[Fact]
public async Task Should_add_errors_if_datetime_is_greater_than_max()
{
var sut = new DateTimeField(1, "my-datetime", new DateTimeFieldProperties { Label = "My-DateTime", MaxValue = FutureDays(10) });
await sut.ValidateAsync(CreateValue(FutureDays(20)), errors);
errors.ShouldBeEquivalentTo(
new[] { $"My-DateTime must be less than '{FutureDays(10)}'" });
}
[Fact]
public async Task Should_add_errors_if_value_is_not_valid()
{
var sut = new DateTimeField(1, "my-datetime", new DateTimeFieldProperties { Label = "My-DateTime" });
await sut.ValidateAsync(CreateValue("Invalid"), errors);
errors.ShouldBeEquivalentTo(
new[] { "My-DateTime is not a valid value" });
}
private static DateTimeOffset FutureDays(int days)
{
return DateTimeOffset.UtcNow.AddDays(days);
}
private static JValue CreateValue(object v)
{
return new JValue(v);
}
}
}

6
tests/Squidex.Core.Tests/Schemas/FieldRegistryTests.cs

@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure;
using Xunit;
@ -19,6 +20,11 @@ namespace Squidex.Core.Schemas
private sealed class InvalidProperties : FieldProperties
{
public override JToken GetDefaultValue()
{
return null;
}
protected override IEnumerable<ValidationError> ValidateCore()
{
yield break;

12
tests/Squidex.Core.Tests/Schemas/Json/JsonSerializerTests.cs

@ -33,12 +33,14 @@ namespace Squidex.Core.Schemas.Json
{
var schema =
Schema.Create("my-schema", new SchemaProperties())
.AddOrUpdateField(new StringField(1, "field1",
new StringFieldProperties { Label = "Field1", Pattern = "[0-9]{3}" })).DisableField(1)
.AddOrUpdateField(new NumberField(2, "field2",
new NumberFieldProperties { Hints = "Hints" }))
.AddOrUpdateField(new BooleanField(3, "field3",
.AddOrUpdateField(new StringField(1, "my-string",
new StringFieldProperties { Label = "My-String", Pattern = "[0-9]{3}" })).DisableField(1)
.AddOrUpdateField(new NumberField(2, "my-number",
new NumberFieldProperties { Hints = "My-Number" }))
.AddOrUpdateField(new BooleanField(3, "my-boolean",
new BooleanFieldProperties())).HideField(2)
.AddOrUpdateField(new DateTimeField(4, "my-datetime",
new DateTimeFieldProperties())).HideField(2)
.Publish();
var deserialized = sut.Deserialize(sut.Serialize(schema));

2
tests/Squidex.Core.Tests/Schemas/NumberFieldPropertiesTests.cs

@ -22,7 +22,7 @@ namespace Squidex.Core.Schemas
private readonly List<ValidationError> errors = new List<ValidationError>();
[Fact]
public void Should_not_add_error_if_sut_are_valid()
public void Should_not_add_error_if_sut_is_valid()
{
var sut = new NumberFieldProperties
{

28
tests/Squidex.Core.Tests/Schemas/NumberFieldTests.cs

@ -22,15 +22,15 @@ namespace Squidex.Core.Schemas
[Fact]
public void Should_instantiate_field()
{
var sut = new NumberField(1, "name", new NumberFieldProperties());
var sut = new NumberField(1, "my-number", new NumberFieldProperties());
Assert.Equal("name", sut.Name);
Assert.Equal("my-number", sut.Name);
}
[Fact]
public void Should_clone_object()
{
var sut = new NumberField(1, "name", new NumberFieldProperties());
var sut = new NumberField(1, "my-number", new NumberFieldProperties());
Assert.NotEqual(sut, sut.Enable());
}
@ -38,7 +38,7 @@ namespace Squidex.Core.Schemas
[Fact]
public async Task Should_not_add_error_if_valid()
{
var sut = new NumberField(1, "name", new NumberFieldProperties { Label = "Name" });
var sut = new NumberField(1, "my-number", new NumberFieldProperties { Label = "My-Number" });
await sut.ValidateAsync(CreateValue(null), errors);
@ -48,56 +48,56 @@ namespace Squidex.Core.Schemas
[Fact]
public async Task Should_add_errors_if_number_is_required()
{
var sut = new NumberField(1, "name", new NumberFieldProperties { Label = "Name", IsRequired = true });
var sut = new NumberField(1, "my-number", new NumberFieldProperties { Label = "My-Number", IsRequired = true });
await sut.ValidateAsync(CreateValue(null), errors);
errors.ShouldBeEquivalentTo(
new [] { "Name is required" });
new [] { "My-Number is required" });
}
[Fact]
public async Task Should_add_errors_if_number_is_less_than_min()
{
var sut = new NumberField(1, "name", new NumberFieldProperties { Label = "Name", MinValue = 10 });
var sut = new NumberField(1, "my-number", new NumberFieldProperties { Label = "My-Number", MinValue = 10 });
await sut.ValidateAsync(CreateValue(5), errors);
errors.ShouldBeEquivalentTo(
new[] { "Name must be greater than '10'" });
new[] { "My-Number must be greater than '10'" });
}
[Fact]
public async Task Should_add_errors_if_number_is_greater_than_max()
{
var sut = new NumberField(1, "name", new NumberFieldProperties { Label = "Name", MaxValue = 10 });
var sut = new NumberField(1, "my-number", new NumberFieldProperties { Label = "My-Number", MaxValue = 10 });
await sut.ValidateAsync(CreateValue(20), errors);
errors.ShouldBeEquivalentTo(
new[] { "Name must be less than '10'" });
new[] { "My-Number must be less than '10'" });
}
[Fact]
public async Task Should_add_errors_if_number_is_not_allowed()
{
var sut = new NumberField(1, "name", new NumberFieldProperties { Label = "Name", AllowedValues = ImmutableList.Create(10d) });
var sut = new NumberField(1, "my-number", new NumberFieldProperties { Label = "My-Number", AllowedValues = ImmutableList.Create(10d) });
await sut.ValidateAsync(CreateValue(20), errors);
errors.ShouldBeEquivalentTo(
new[] { "Name is not an allowed value" });
new[] { "My-Number is not an allowed value" });
}
[Fact]
public async Task Should_add_errors_if_value_is_not_valid()
{
var sut = new NumberField(1, "name", new NumberFieldProperties { Label = "Name" });
var sut = new NumberField(1, "my-number", new NumberFieldProperties { Label = "My-Number" });
await sut.ValidateAsync(CreateValue("Invalid"), errors);
errors.ShouldBeEquivalentTo(
new[] { "Name is not a valid value" });
new[] { "My-Number is not a valid value" });
}
private static JValue CreateValue(object v)

38
tests/Squidex.Core.Tests/Schemas/SchemaTests.cs

@ -9,6 +9,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure;
using Xunit;
@ -20,6 +21,11 @@ namespace Squidex.Core.Schemas
private sealed class InvalidProperties : FieldProperties
{
public override JToken GetDefaultValue()
{
return null;
}
protected override IEnumerable<ValidationError> ValidateCore()
{
yield break;
@ -247,26 +253,24 @@ namespace Squidex.Core.Schemas
[Fact]
public void Should_build_schema()
{
var schema =
Schema.Create("user", new SchemaProperties { Hints = "The User" })
.AddOrUpdateField(new StringField(1, "firstName",
new StringFieldProperties { Label = "FirstName", IsLocalizable = true, IsRequired = true, AllowedValues = new [] { "1", "2" }.ToImmutableList() }))
.AddOrUpdateField(new StringField(2, "lastName",
new StringFieldProperties { Hints = "Last Name" }))
.AddOrUpdateField(new BooleanField(3, "admin",
new BooleanFieldProperties()))
.AddOrUpdateField(new NumberField(4, "age",
new NumberFieldProperties { MinValue = 1, MaxValue = 10 }));
var languages = new HashSet<Language>(new[] { Language.DE, Language.EN });
var json = schema.BuildSchema(languages, (n, s) => s).ToJson();
var json = BuildMixedSchema().BuildSchema(languages, (n, s) => s).ToJson();
Assert.NotNull(json);
}
[Fact]
public void Should_build_edm_model()
{
var languages = new HashSet<Language>(new[] { Language.DE, Language.EN });
var edmModel = BuildMixedSchema().BuildEdmType(languages, x => x);
Assert.NotNull(edmModel);
}
private Schema BuildMixedSchema()
{
var schema =
Schema.Create("user", new SchemaProperties { Hints = "The User" })
@ -276,14 +280,12 @@ namespace Squidex.Core.Schemas
new StringFieldProperties { Hints = "Last Name" }))
.AddOrUpdateField(new BooleanField(3, "admin",
new BooleanFieldProperties()))
.AddOrUpdateField(new NumberField(4, "age",
.AddOrUpdateField(new DateTimeField(4, "birtday",
new DateTimeFieldProperties()))
.AddOrUpdateField(new NumberField(5, "age",
new NumberFieldProperties { MinValue = 1, MaxValue = 10 }));
var languages = new HashSet<Language>(new[] { Language.DE, Language.EN });
var edmModel = schema.BuildEdmType(languages, x => x);
Assert.NotNull(edmModel);
return schema;
}
private NumberField AddField()

36
tests/Squidex.Core.Tests/Schemas/SchemaValidationTests.cs

@ -6,6 +6,7 @@
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using FluentAssertions;
@ -283,5 +284,40 @@ namespace Squidex.Core.Schemas
new ValidationError("my-field has an unsupported language 'it'", "my-field")
});
}
[Fact]
private void Should_enrich_with_default_values()
{
var schema =
Schema.Create("my-schema", new SchemaProperties())
.AddOrUpdateField(
new StringField(1, "my-string", new StringFieldProperties { DefaultValue = "EN-String", IsLocalizable = true }))
.AddOrUpdateField(
new BooleanField(2, "my-boolean", new BooleanFieldProperties { DefaultValue = true }))
.AddOrUpdateField(
new NumberField(3, "my-number", new NumberFieldProperties { DefaultValue = 123 }))
.AddOrUpdateField(
new DateTimeField(4, "my-datetime", new DateTimeFieldProperties { DefaultValue = DateTime.Today }));
var data =
new ContentData()
.AddField("my-string",
new ContentFieldData()
.AddValue("de", "DE-String"))
.AddField("my-number",
new ContentFieldData()
.AddValue("iv", 456));
schema.Enrich(data, languages);
Assert.Equal(456, (int)data["my-number"]["iv"]);
Assert.Equal("DE-String", (string)data["my-string"]["de"]);
Assert.Equal("EN-String", (string)data["my-string"]["en"]);
Assert.Equal(DateTime.Today, (DateTime)data["my-datetime"]["iv"]);
Assert.Equal(true, (bool)data["my-boolean"]["iv"]);
}
}
}

30
tests/Squidex.Core.Tests/Schemas/StringFieldTests.cs

@ -22,15 +22,15 @@ namespace Squidex.Core.Schemas
[Fact]
public void Should_instantiate_field()
{
var sut = new StringField(1, "name", new StringFieldProperties());
var sut = new StringField(1, "my-string", new StringFieldProperties());
Assert.Equal("name", sut.Name);
Assert.Equal("my-string", sut.Name);
}
[Fact]
public void Should_clone_object()
{
var sut = new StringField(1, "name", new StringFieldProperties());
var sut = new StringField(1, "my-string", new StringFieldProperties());
Assert.NotEqual(sut, sut.Enable());
}
@ -38,7 +38,7 @@ namespace Squidex.Core.Schemas
[Fact]
public async Task Should_not_add_error_if_valid()
{
var sut = new StringField(1, "name", new StringFieldProperties { Label = "Name" });
var sut = new StringField(1, "my-string", new StringFieldProperties { Label = "My-String" });
await sut.ValidateAsync(CreateValue(null), errors);
@ -48,62 +48,62 @@ namespace Squidex.Core.Schemas
[Fact]
public async Task Should_add_errors_if_string_is_required()
{
var sut = new StringField(1, "name", new StringFieldProperties { Label = "Name", IsRequired = true });
var sut = new StringField(1, "my-string", new StringFieldProperties { Label = "My-String", IsRequired = true });
await sut.ValidateAsync(CreateValue(null), errors);
errors.ShouldBeEquivalentTo(
new[] { "Name is required" });
new[] { "My-String is required" });
}
[Fact]
public async Task Should_add_errors_if_string_is_shorter_than_min_length()
{
var sut = new StringField(1, "name", new StringFieldProperties { Label = "Name", MinLength = 10 });
var sut = new StringField(1, "my-string", new StringFieldProperties { Label = "My-String", MinLength = 10 });
await sut.ValidateAsync(CreateValue("123"), errors);
errors.ShouldBeEquivalentTo(
new[] { "Name must have more than '10' characters" });
new[] { "My-String must have more than '10' characters" });
}
[Fact]
public async Task Should_add_errors_if_string_is_longer_than_max_length()
{
var sut = new StringField(1, "name", new StringFieldProperties { Label = "Name", MaxLength = 5 });
var sut = new StringField(1, "my-string", new StringFieldProperties { Label = "My-String", MaxLength = 5 });
await sut.ValidateAsync(CreateValue("12345678"), errors);
errors.ShouldBeEquivalentTo(
new[] { "Name must have less than '5' characters" });
new[] { "My-String must have less than '5' characters" });
}
[Fact]
public async Task Should_add_errors_if_string_not_allowed()
{
var sut = new StringField(1, "name", new StringFieldProperties { Label = "Name", AllowedValues = ImmutableList.Create("Foo") });
var sut = new StringField(1, "my-string", new StringFieldProperties { Label = "My-String", AllowedValues = ImmutableList.Create("Foo") });
await sut.ValidateAsync(CreateValue("Bar"), errors);
errors.ShouldBeEquivalentTo(
new[] { "Name is not an allowed value" });
new[] { "My-String is not an allowed value" });
}
[Fact]
public async Task Should_add_errors_if_number_is_not_valid_pattern()
{
var sut = new StringField(1, "name", new StringFieldProperties { Label = "Name", Pattern = "[0-9]{3}" });
var sut = new StringField(1, "my-string", new StringFieldProperties { Label = "My-String", Pattern = "[0-9]{3}" });
await sut.ValidateAsync(CreateValue("abc"), errors);
errors.ShouldBeEquivalentTo(
new[] { "Name is not valid" });
new[] { "My-String is not valid" });
}
[Fact]
public async Task Should_add_errors_if_number_is_not_valid_pattern_with_message()
{
var sut = new StringField(1, "name", new StringFieldProperties { Label = "Name", Pattern = "[0-9]{3}", PatternMessage = "Custom Error Message" });
var sut = new StringField(1, "my-string", new StringFieldProperties { Label = "My-String", Pattern = "[0-9]{3}", PatternMessage = "Custom Error Message" });
await sut.ValidateAsync(CreateValue("abc"), errors);

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

@ -63,7 +63,7 @@ namespace Squidex.Read.Apps
repository.Verify(x => x.FindAppAsync(appId.Id), Times.Never());
}
[Theory]
[Fact]
public async Task Should_clear_cache_for_id_after_update_event()
{
var apps = ProviderResults(appV1, appV2);
@ -79,7 +79,7 @@ namespace Squidex.Read.Apps
repository.Verify(x => x.FindAppAsync(appId.Id), Times.Exactly(2));
}
[Theory]
[Fact]
public async Task Should_clear_cache_for_name_after_update_event()
{
var apps = ProviderResults(appV1, appV2);

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

@ -64,7 +64,7 @@ namespace Squidex.Read.Schemas
repository.Verify(x => x.FindSchemaAsync(schemaId.Id), Times.Never());
}
[Theory]
[Fact]
public async Task Should_clear_cache_for_id_after_update_event()
{
var schemas = ProviderResults(schemaV1, schemaV2);
@ -80,7 +80,7 @@ namespace Squidex.Read.Schemas
repository.Verify(x => x.FindSchemaAsync(schemaId.Id), Times.Exactly(2));
}
[Theory]
[Fact]
public async Task Should_clear_cache_for_name_after_update_event()
{
var schemas = ProviderResults(schemaV1, schemaV2);

4
tests/Squidex.Write.Tests/Squidex.Write.Tests.csproj

@ -5,6 +5,10 @@
<PackageTargetFallback>$(PackageTargetFallback);dnxcore50</PackageTargetFallback>
<RootNamespace>Squidex.Write</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Squidex.Core\Squidex.Core.csproj" />
<ProjectReference Include="..\..\src\Squidex.Infrastructure\Squidex.Infrastructure.csproj" />

Loading…
Cancel
Save