Browse Source

Temporary project

pull/1/head
Sebastian 10 years ago
parent
commit
ba960a6fa8
  1. 7
      Squidex.sln
  2. 53
      src/Squidex.Core/Schemas/Field.cs
  3. 17
      src/Squidex.Core/Schemas/FieldProperties.cs
  4. 18
      src/Squidex.Core/Schemas/Field_Generic.cs
  5. 18
      src/Squidex.Core/Schemas/IValidator.cs
  6. 20
      src/Squidex.Core/Schemas/NamedElementProperties.cs
  7. 59
      src/Squidex.Core/Schemas/NumberField.cs
  8. 48
      src/Squidex.Core/Schemas/NumberFieldProperties.cs
  9. 6
      src/Squidex.Core/Schemas/SchemaProperties.cs
  10. 45
      src/Squidex.Core/Schemas/Validators/AllowedValuesValidator.cs
  11. 54
      src/Squidex.Core/Schemas/Validators/RangeValidator.cs
  12. 41
      src/Squidex.Core/Schemas/Validators/RequiredStringValidator.cs
  13. 27
      src/Squidex.Core/Schemas/Validators/RequiredValidator.cs
  14. 2
      src/Squidex.Infrastructure/CQRS/EventStore/DefaultNameResolver.cs
  15. 2
      src/Squidex.Infrastructure/CQRS/EventStore/EventStoreBus.cs
  16. 2
      src/Squidex.Infrastructure/CQRS/EventStore/EventStoreDomainObjectRepository.cs
  17. 12
      src/Squidex.Infrastructure/CQRS/EventStore/EventStoreFormatter.cs
  18. 48
      src/Squidex.Infrastructure/CQRS/EventStore/EventWrapper.cs
  19. 25
      src/Squidex.Infrastructure/CQRS/EventStore/IReceivedEvent.cs
  20. 11
      src/Squidex.Infrastructure/Json/LanguageConverter.cs
  21. 2
      src/Squidex/app/framework/angular/animations.ts
  22. 2
      src/Squidex/app/theme/_vendor-overrides.scss
  23. 3
      src/Squidex/app/theme/vendor.scss
  24. 2
      src/Squidex/package.json
  25. 10
      tests/RunCoverage.bat
  26. 19
      tests/Squidex.Core.Tests/Properties/AssemblyInfo.cs
  27. 107
      tests/Squidex.Core.Tests/Schemas/NumberFieldPropertiesTests.cs
  28. 52
      tests/Squidex.Core.Tests/Schemas/Validators/AllowedValuesValidatorTests.cs
  29. 76
      tests/Squidex.Core.Tests/Schemas/Validators/RangeValidatorTests.cs
  30. 67
      tests/Squidex.Core.Tests/Schemas/Validators/RequiredStringValidatorTests.cs
  31. 52
      tests/Squidex.Core.Tests/Schemas/Validators/RequiredValidatorTests.cs
  32. 22
      tests/Squidex.Core.Tests/Squidex.Core.Tests.xproj
  33. 35
      tests/Squidex.Core.Tests/project.json
  34. 18
      tests/Squidex.Infrastructure.Tests/CQRS/Commands/EnrichWithTimestampHandlerTests.cs
  35. 60
      tests/Squidex.Infrastructure.Tests/CQRS/EnvelopeHeaderTests.cs
  36. 63
      tests/Squidex.Infrastructure.Tests/CQRS/EventStore/DefaultNameResolverTests.cs
  37. 92
      tests/Squidex.Infrastructure.Tests/CQRS/EventStore/EventStoreFormatterTests.cs
  38. 2
      tests/Squidex.Infrastructure.Tests/PropertiesBagTests.cs
  39. 2
      tests/Squidex.Infrastructure.Tests/Reflection/PropertiesTypeAccessorTests.cs
  40. 53
      tests/Squidex.Infrastructure.Tests/Reflection/ReflectionExtensionTests.cs
  41. 22
      tests/Squidex.Infrastructure.Tests/Reflection/SimpleMapperTests.cs
  42. 2
      tests/Squidex.Write.Tests/project.json

7
Squidex.sln

@ -34,6 +34,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Squidex.Write.Tests", "test
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Squidex.Infrastructure.Tests", "tests\Squidex.Infrastructure.Tests\Squidex.Infrastructure.Tests.xproj", "{7FD0A92B-7862-4BB1-932B-B52A9CACB56B}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Squidex.Core.Tests", "tests\Squidex.Core.Tests\Squidex.Core.Tests.xproj", "{FD0AFD44-7A93-4F9E-B5ED-72582392E435}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -76,6 +78,10 @@ Global
{7FD0A92B-7862-4BB1-932B-B52A9CACB56B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7FD0A92B-7862-4BB1-932B-B52A9CACB56B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7FD0A92B-7862-4BB1-932B-B52A9CACB56B}.Release|Any CPU.Build.0 = Release|Any CPU
{FD0AFD44-7A93-4F9E-B5ED-72582392E435}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD0AFD44-7A93-4F9E-B5ED-72582392E435}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD0AFD44-7A93-4F9E-B5ED-72582392E435}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD0AFD44-7A93-4F9E-B5ED-72582392E435}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -90,5 +96,6 @@ Global
{28F8E9E2-FE24-41F7-A888-9FC244A9E2DD} = {4082AA58-D410-4C52-8E88-3B0A4E860B28}
{9A3DEA7E-1681-4D48-AC5C-1F0DE421A203} = {4C6B06C2-6D77-4E0E-AE32-D7050236433A}
{7FD0A92B-7862-4BB1-932B-B52A9CACB56B} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF}
{FD0AFD44-7A93-4F9E-B5ED-72582392E435} = {4C6B06C2-6D77-4E0E-AE32-D7050236433A}
EndGlobalSection
EndGlobal

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

@ -10,8 +10,6 @@ using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Tasks;
// ReSharper disable InvertIf
// ReSharper disable ConvertIfStatementToReturnStatement
@ -19,6 +17,7 @@ namespace Squidex.Core.Schemas
{
public abstract class Field
{
private readonly Lazy<List<IValidator>> validators;
private readonly long id;
private string name;
private bool isDisabled;
@ -34,16 +33,6 @@ namespace Squidex.Core.Schemas
get { return name; }
}
public string Hints
{
get { return RawProperties.Hints; }
}
public string Label
{
get { return RawProperties.Label; }
}
public bool IsHidden
{
get { return isHidden; }
@ -54,46 +43,42 @@ namespace Squidex.Core.Schemas
get { return isDisabled; }
}
public bool IsRequired
{
get { return RawProperties.IsRequired; }
}
public abstract FieldProperties RawProperties { get; }
protected Field(long id, string name)
{
Guard.GreaterThan(id, 0, nameof(id));
Guard.ValidSlug(name, nameof(name));
Guard.GreaterThan(id, 0, nameof(id));
this.id = id;
this.name = name;
validators = new Lazy<List<IValidator>>(() => new List<IValidator>(CreateValidators()));
}
public abstract Field Update(FieldProperties newProperties);
public Task ValidateAsync(PropertyValue property, ICollection<string> errors)
public async Task ValidateAsync(PropertyValue property, ICollection<string> errors)
{
Guard.NotNull(property, nameof(property));
if (IsRequired && property.RawValue == null)
var value = ConvertValue(property);
var tempErrors = new List<string>();
foreach (var validator in validators.Value)
{
errors.Add("Field is required");
await validator.ValidateAsync(value, tempErrors);
}
if (property.RawValue == null)
foreach (var error in tempErrors)
{
return TaskHelper.Done;
errors.Add(error.Replace("<FIELD>", name));
}
return ValidateCoreAsync(property, errors);
}
protected virtual Task ValidateCoreAsync(PropertyValue property, ICollection<string> errors)
{
return TaskHelper.Done;
}
protected abstract IEnumerable<IValidator> CreateValidators();
protected abstract object ConvertValue(PropertyValue property);
public Field Hide()
{
@ -136,6 +121,8 @@ namespace Squidex.Core.Schemas
return clone;
}
protected abstract Field Clone();
public abstract Field Clone();
public abstract FieldProperties CloneProperties();
}
}

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

@ -13,21 +13,24 @@ namespace Squidex.Core.Schemas
{
public abstract class FieldProperties : NamedElementProperties, IValidatable
{
public bool IsRequired { get; }
public bool IsRequired { get; set; }
protected FieldProperties(string label, string hints, bool isRequired)
: base(label, hints)
public void Validate(IList<ValidationError> errors)
{
IsRequired = isRequired;
foreach (var error in ValidateCore())
{
errors.Add(error);
}
}
public void Validate(IList<ValidationError> errors)
protected virtual IEnumerable<ValidationError> ValidateCore()
{
ValidateCore(errors);
yield break;
}
protected virtual void ValidateCore(IList<ValidationError> errors)
public FieldProperties Clone()
{
return (FieldProperties) MemberwiseClone();
}
}
}

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

@ -15,12 +15,7 @@ namespace Squidex.Core.Schemas
{
private T properties;
public override FieldProperties RawProperties
{
get { return properties; }
}
public T Properties
protected T Properties
{
get { return properties; }
}
@ -36,7 +31,9 @@ namespace Squidex.Core.Schemas
public override Field Update(FieldProperties newProperties)
{
Guard.NotNull(newProperties, nameof(newProperties));
newProperties = newProperties.Clone();
var typedProperties = newProperties as T;
if (typedProperties == null)
@ -44,9 +41,14 @@ namespace Squidex.Core.Schemas
throw new ArgumentException($"Properties must be of type '{typeof(T)}", nameof(newProperties));
}
newProperties.Validate(() => $"Cannot update field with id '{Id}', becase the settings are invalid.");
newProperties.Validate(() => $"Cannot update field with id '{Id}', because the settings are invalid.");
return Update<Field<T>>(clone => clone.properties = typedProperties);
}
public override FieldProperties CloneProperties()
{
return properties.Clone();
}
}
}

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

@ -0,0 +1,18 @@
// ==========================================================================
// IValidator.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Squidex.Core.Schemas
{
public interface IValidator
{
Task ValidateAsync(object value, ICollection<string> errors);
}
}

20
src/Squidex.Core/Schemas/NamedElementProperties.cs

@ -5,27 +5,13 @@
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
namespace Squidex.Core.Schemas
{
public abstract class NamedElementProperties
{
private readonly string label;
private readonly string hints;
public string Label
{
get { return label; }
}
public string Hints
{
get { return hints; }
}
public string Label { get; set; }
protected NamedElementProperties(string label, string hints)
{
this.label = label;
this.hints = hints;
}
public string Hints { get; set; }
}
}

59
src/Squidex.Core/Schemas/NumberField.cs

@ -6,70 +6,47 @@
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Core.Schemas.Validators;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Tasks;
using System.Linq;
namespace Squidex.Core.Schemas
{
public sealed class NumberField : Field<NumberFieldProperties>
{
public double? MaxValue
{
get { return Properties.MaxValue; }
}
public double? MinValue
{
get { return Properties.MinValue; }
}
public double[] AllowedValues
{
get { return Properties.AllowedValues; }
}
public NumberField(long id, string name, NumberFieldProperties properties)
: base(id, name, properties)
{
}
protected override Task ValidateCoreAsync(PropertyValue property, ICollection<string> errors)
protected override IEnumerable<IValidator> CreateValidators()
{
try
if (Properties.IsRequired)
{
var value = property.ToDouble(CultureInfo.InvariantCulture);
if (MinValue.HasValue && value < MinValue.Value)
{
errors.Add($"Must be greater than {MinValue}");
}
if (MaxValue.HasValue && value > MaxValue.Value)
{
errors.Add($"Must be less than {MaxValue}");
}
yield return new RequiredValidator();
}
if (AllowedValues != null && !AllowedValues.Contains(value))
{
errors.Add($"Can only be one of the following value: {string.Join(", ", AllowedValues)}");
}
if (Properties.MinValue.HasValue || Properties.MaxValue.HasValue)
{
yield return new RangeValidator<double>(Properties.MinValue, Properties.MaxValue);
}
catch (InvalidCastException)
if (Properties.AllowedValues != null)
{
errors.Add("Value is not a valid number");
yield return new AllowedValuesValidator<double>(Properties.AllowedValues.ToArray());
}
}
return TaskHelper.Done;
protected override object ConvertValue(PropertyValue property)
{
return property.ToNullableDouble(CultureInfo.InvariantCulture);
}
protected override Field Clone()
public override Field Clone()
{
return (Field)MemberwiseClone();
return new NumberField(Id, Name, Properties);
}
}
}

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

@ -7,6 +7,7 @@
// ==========================================================================
using System.Collections.Generic;
using System.Collections.Immutable;
using Squidex.Infrastructure;
namespace Squidex.Core.Schemas
@ -16,55 +17,42 @@ namespace Squidex.Core.Schemas
{
public string Placeholder { get; set; }
public double? DefaultValue { get; }
public double? MaxValue { get; set; }
public double? MaxValue { get; }
public double? MinValue { get; set; }
public double? MinValue { get; }
public double? DefaultValue { get; set; }
public double[] AllowedValues { get; }
public ImmutableList<double> AllowedValues { get; set; }
public NumberFieldProperties(
string label,
string hints,
string placeholder,
double? minValue,
double? maxValue,
double? defaultValue,
double[] allowedValues,
bool isRequired)
: base(label, hints, isRequired)
{
Placeholder = placeholder;
MinValue = minValue;
MaxValue = maxValue;
AllowedValues = allowedValues;
DefaultValue = defaultValue;
}
protected override void ValidateCore(IList<ValidationError> errors)
protected override IEnumerable<ValidationError> ValidateCore()
{
if (MaxValue.HasValue && MinValue.HasValue && MinValue.Value >= MaxValue.Value)
{
errors.Add(new ValidationError("MinValue cannot be larger than max value", "MinValue", "MaxValue"));
yield return new ValidationError("Max value must be greater than min value.", nameof(MinValue), nameof(MaxValue));
}
if (AllowedValues != null && (MinValue.HasValue || MaxValue.HasValue))
{
yield return new ValidationError("Either or allowed values or range can be defined.",
nameof(AllowedValues),
nameof(MinValue),
nameof(MaxValue));
}
if (!DefaultValue.HasValue)
{
return;
yield break;
}
if (MinValue.HasValue && DefaultValue.Value < MinValue.Value)
{
errors.Add(new ValidationError("DefaultValue must be larger than the min value.", "DefaultValue"));
yield return new ValidationError("Default value must be greater than min value.", nameof(DefaultValue));
}
if (MaxValue.HasValue && DefaultValue.Value > MaxValue.Value)
{
errors.Add(new ValidationError("DefaultValue must be smaller than the max value.", "DefaultValue"));
yield return new ValidationError("Default value must be less than max value.", nameof(DefaultValue));
}
}
}

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

@ -9,11 +9,5 @@ namespace Squidex.Core.Schemas
{
public sealed class SchemaProperties : NamedElementProperties
{
public SchemaProperties(
string label,
string hints)
: base(label, hints)
{
}
}
}

45
src/Squidex.Core/Schemas/Validators/AllowedValuesValidator.cs

@ -0,0 +1,45 @@
// ==========================================================================
// AllowedValuesValidator.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Tasks;
namespace Squidex.Core.Schemas.Validators
{
public sealed class AllowedValuesValidator<T> : IValidator
{
private readonly T[] allowedValues;
public AllowedValuesValidator(params T[] allowedValues)
{
Guard.NotNull(allowedValues, nameof(allowedValues));
this.allowedValues = allowedValues;
}
public Task ValidateAsync(object value, ICollection<string> errors)
{
if (value == null)
{
return TaskHelper.Done;
}
var typedValue = (T)value;
if (!allowedValues.Contains(typedValue))
{
errors.Add("<FIELD> is not an allowed value");
}
return TaskHelper.Done;
}
}
}

54
src/Squidex.Core/Schemas/Validators/RangeValidator.cs

@ -0,0 +1,54 @@
// ==========================================================================
// RangeValidator.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Squidex.Infrastructure.Tasks;
namespace Squidex.Core.Schemas.Validators
{
public sealed class RangeValidator<T> : IValidator where T : struct, IComparable<T>
{
private readonly T? min;
private readonly T? max;
public RangeValidator(T? min, T? max)
{
if (min.HasValue && max.HasValue && min.Value.CompareTo(max.Value) >= 0)
{
throw new ArgumentException("MinValue must larger than max value");
}
this.min = min;
this.max = max;
}
public Task ValidateAsync(object value, ICollection<string> errors)
{
if (value == null)
{
return TaskHelper.Done;
}
var typedValue = (T)value;
if (min.HasValue && typedValue.CompareTo(min.Value) < 0)
{
errors.Add($"<FIELD> must be greater than {min}");
}
if (max.HasValue && typedValue.CompareTo(max.Value) > 0)
{
errors.Add($"<FIELD> must be greater than {min}");
}
return TaskHelper.Done;
}
}
}

41
src/Squidex.Core/Schemas/Validators/RequiredStringValidator.cs

@ -0,0 +1,41 @@
// ==========================================================================
// RequiredStringValidator.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using System.Threading.Tasks;
using Squidex.Infrastructure.Tasks;
namespace Squidex.Core.Schemas.Validators
{
public class RequiredStringValidator : IValidator
{
private readonly bool validateEmptyStrings;
public RequiredStringValidator(bool validateEmptyStrings = false)
{
this.validateEmptyStrings = validateEmptyStrings;
}
public Task ValidateAsync(object value, ICollection<string> errors)
{
if (value != null && !(value is string))
{
return TaskHelper.Done;
}
var valueAsString = (string) value;
if (valueAsString == null || (validateEmptyStrings && string.IsNullOrWhiteSpace(valueAsString)))
{
errors.Add("<FIELD> is required");
}
return TaskHelper.Done;
}
}
}

27
src/Squidex.Core/Schemas/Validators/RequiredValidator.cs

@ -0,0 +1,27 @@
// ==========================================================================
// RequiredValidator.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using System.Threading.Tasks;
using Squidex.Infrastructure.Tasks;
namespace Squidex.Core.Schemas.Validators
{
public class RequiredValidator : IValidator
{
public Task ValidateAsync(object value, ICollection<string> errors)
{
if (value == null)
{
errors.Add("<FIELD> is required");
}
return TaskHelper.Done;
}
}
}

2
src/Squidex.Infrastructure/CQRS/EventStore/DefaultNameResolver.cs

@ -20,7 +20,7 @@ namespace Squidex.Infrastructure.CQRS.EventStore
{
Guard.NotNullOrEmpty(prefix, nameof(prefix));
this.prefix = prefix;
this.prefix = prefix.ToLowerInvariant();
}
public string GetStreamName(Type aggregateType, Guid id)

2
src/Squidex.Infrastructure/CQRS/EventStore/EventStoreBus.cs

@ -95,7 +95,7 @@ namespace Squidex.Infrastructure.CQRS.EventStore
return;
}
var @event = formatter.Parse(resolvedEvent);
var @event = formatter.Parse(new EventWrapper(resolvedEvent));
logger.LogInformation("Received event {0} ({1})", @event.Payload.GetType().Name, @event.Headers.AggregateId());

2
src/Squidex.Infrastructure/CQRS/EventStore/EventStoreDomainObjectRepository.cs

@ -83,7 +83,7 @@ namespace Squidex.Infrastructure.CQRS.EventStore
foreach (var resolved in currentSlice.Events)
{
var envelope = formatter.Parse(resolved);
var envelope = formatter.Parse(new EventWrapper(resolved));
domainObject.ApplyEvent(envelope);
}

12
src/Squidex.Infrastructure/CQRS/EventStore/EventStoreFormatter.cs

@ -26,17 +26,17 @@ namespace Squidex.Infrastructure.CQRS.EventStore
this.serializerSettings = serializerSettings ?? new JsonSerializerSettings();
}
public Envelope<IEvent> Parse(ResolvedEvent @event)
public Envelope<IEvent> Parse(IReceivedEvent @event)
{
var headers = ReadJson<PropertiesBag>(@event.Event.Metadata);
var headers = ReadJson<PropertiesBag>(@event.Metadata);
var eventType = TypeNameRegistry.GetType(@event.Event.EventType);
var eventData = ReadJson<IEvent>(@event.Event.Data, eventType);
var eventType = TypeNameRegistry.GetType(@event.EventType);
var eventData = ReadJson<IEvent>(@event.Payload, eventType);
var envelope = new Envelope<IEvent>(eventData, headers);
envelope.Headers.Set(CommonHeaders.Timestamp, Instant.FromDateTimeUtc(DateTime.SpecifyKind(@event.Event.Created, DateTimeKind.Utc)));
envelope.Headers.Set(CommonHeaders.EventNumber, @event.OriginalEventNumber);
envelope.Headers.Set(CommonHeaders.Timestamp, Instant.FromDateTimeUtc(DateTime.SpecifyKind(@event.Created, DateTimeKind.Utc)));
envelope.Headers.Set(CommonHeaders.EventNumber, @event.EventNumber);
return envelope;
}

48
src/Squidex.Infrastructure/CQRS/EventStore/EventWrapper.cs

@ -0,0 +1,48 @@
// ==========================================================================
// EventWrapper.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using EventStore.ClientAPI;
namespace Squidex.Infrastructure.CQRS.EventStore
{
internal sealed class EventWrapper : IReceivedEvent
{
private readonly ResolvedEvent @event;
public int EventNumber
{
get { return @event.OriginalEventNumber; }
}
public string EventType
{
get { return @event.Event.EventType; }
}
public byte[] Metadata
{
get { return @event.Event.Metadata; }
}
public byte[] Payload
{
get { return @event.Event.Data; }
}
public DateTime Created
{
get { return @event.Event.Created; }
}
public EventWrapper(ResolvedEvent @event)
{
this.@event = @event;
}
}
}

25
src/Squidex.Infrastructure/CQRS/EventStore/IReceivedEvent.cs

@ -0,0 +1,25 @@
// ==========================================================================
// IReceivedEvent.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
namespace Squidex.Infrastructure.CQRS.EventStore
{
public interface IReceivedEvent
{
int EventNumber { get; }
string EventType { get; }
byte[] Metadata { get; }
byte[] Payload { get; }
DateTime Created { get; }
}
}

11
src/Squidex.Infrastructure/Json/LanguageConverter.cs

@ -15,16 +15,7 @@ namespace Squidex.Infrastructure.Json
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var language = value as Language;
if (language != null)
{
writer.WriteValue(language.Iso2Code);
}
else
{
writer.WriteNull();
}
writer.WriteValue(((Language)value).Iso2Code);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)

2
src/Squidex/app/framework/angular/animations.ts

@ -53,5 +53,5 @@ function buildHeightAnimation(name = 'height', timing = '200ms'): Ng2.AnimationE
);
};
export const fadeAnimation = buildfadeAnimation;
export const fadeAnimation = buildFadeAnimation();

2
src/Squidex/app/theme/_vendor-overrides.scss

@ -1,8 +1,6 @@
@import '_mixins.scss';
@import '_vars.scss';
$fa-font-path: '~font-awesome/fonts';
$brand-primary: $color-theme-blue;
$brand-success: $color-theme-green;

3
src/Squidex/app/theme/vendor.scss

@ -1,8 +1,5 @@
@import '_vendor-overrides.scss';
// Font Awesome
@import './../../node_modules/font-awesome/scss/font-awesome.scss';
// Bootstrap
@import './../../node_modules/bootstrap/scss/bootstrap-flex.scss';

2
src/Squidex/package.json

@ -25,7 +25,6 @@
"babel-polyfill": "^6.16.0",
"bootstrap": "^4.0.0-alpha.2",
"core-js": "^2.4.1",
"font-awesome": "^4.7.0",
"immutable": "^3.8.1",
"moment": "^2.17.0",
"mousetrap": "^1.6.0",
@ -49,7 +48,6 @@
"exports-loader": "^0.6.3",
"extract-text-webpack-plugin": "^2.0.0-beta.4",
"file-loader": "^0.9.0",
"font-awesome-sass-loader": "^1.0.2",
"html-loader": "^0.4.4",
"html-webpack-plugin": "^2.24.1",
"image-webpack-loader": "^3.0.0",

10
tests/RunCoverage.bat

@ -25,6 +25,16 @@ exit /b %errorlevel%
-output:"%~dp0\GeneratedReports\Infrastructure.xml" ^
-oldStyle
"%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" ^
-filter:"+[Squidex*]*" ^
-skipautoprops ^
-output:"%~dp0\GeneratedReports\Core.xml" ^
-oldStyle
exit /b %errorlevel%
"%UserProfile%\.nuget\packages\OpenCover\4.6.519\tools\OpenCover.Console.exe" ^
-register:user ^
-target:"C:\Program Files\dotnet\dotnet.exe" ^

19
tests/Squidex.Core.Tests/Properties/AssemblyInfo.cs

@ -0,0 +1,19 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Squidex.Core.Tests")]
[assembly: AssemblyTrademark("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("fd0afd44-7a93-4f9e-b5ed-72582392e435")]

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

@ -0,0 +1,107 @@
// ==========================================================================
// NumberFieldPropertiesTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using System.Collections.Immutable;
using Squidex.Core.Schemas;
using Squidex.Infrastructure;
using Xunit;
using FluentAssertions;
namespace Squidex.Core.Tests.Schemas
{
public class NumberFieldPropertiesTests
{
private readonly List<ValidationError> errors = new List<ValidationError>();
[Fact]
public void Should_not_add_error_if_properties_are_valid()
{
var properties = new NumberFieldProperties
{
MinValue = 0,
MaxValue = 100,
DefaultValue = 5
};
properties.Validate(errors);
Assert.Equal(0, errors.Count);
}
[Fact]
public void Should_add_error_if_default_value_is_less_than_min()
{
var properties = new NumberFieldProperties { MinValue = 10, DefaultValue = 5 };
properties.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 properties = new NumberFieldProperties { MaxValue = 0, DefaultValue = 5 };
properties.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 properties = new NumberFieldProperties { MinValue = 10, MaxValue = 5 };
properties.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_allowed_values_and_max_is_specified()
{
var properties = new NumberFieldProperties { MaxValue = 10, AllowedValues = ImmutableList.Create<double>(4) };
properties.Validate(errors);
errors.ShouldBeEquivalentTo(
new List<ValidationError>
{
new ValidationError("Either or allowed values or range can be defined.", "AllowedValues", "MinValue", "MaxValue")
});
}
[Fact]
public void Should_add_error_if_allowed_values_and_min_is_specified()
{
var properties = new NumberFieldProperties { MinValue = 10, AllowedValues = ImmutableList.Create<double>(4) };
properties.Validate(errors);
errors.ShouldBeEquivalentTo(
new List<ValidationError>
{
new ValidationError("Either or allowed values or range can be defined.", "AllowedValues", "MinValue", "MaxValue")
});
}
}
}

52
tests/Squidex.Core.Tests/Schemas/Validators/AllowedValuesValidatorTests.cs

@ -0,0 +1,52 @@
// ==========================================================================
// AllowedValuesValidatorTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using System.Threading.Tasks;
using Squidex.Core.Schemas.Validators;
using Xunit;
using FluentAssertions;
namespace Squidex.Core.Tests.Schemas.Validators
{
public class AllowedValuesValidatorTests
{
private readonly List<string> errors = new List<string>();
[Fact]
public async Task Should_not_error_if_value_null()
{
var sut = new AllowedValuesValidator<int>(100, 200);
await sut.ValidateAsync(null, errors);
Assert.Equal(0, errors.Count);
}
[Fact]
public async Task Should_not_error_if_value_is_allowed()
{
var sut = new AllowedValuesValidator<int>(100, 200);
await sut.ValidateAsync(100, errors);
Assert.Equal(0, errors.Count);
}
[Fact]
public async Task Should_add_error_if_value_is_not_allowed()
{
var sut = new AllowedValuesValidator<int>(100, 200);
await sut.ValidateAsync(50, errors);
errors.ShouldBeEquivalentTo(
new[] { "<FIELD> is not an allowed value" });
}
}
}

76
tests/Squidex.Core.Tests/Schemas/Validators/RangeValidatorTests.cs

@ -0,0 +1,76 @@
// ==========================================================================
// MinMaxValidatorTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using FluentAssertions;
using Squidex.Core.Schemas.Validators;
using Xunit;
namespace Squidex.Core.Tests.Schemas.Validators
{
public class RangeValidatorTests
{
private readonly List<string> errors = new List<string>();
[Theory]
[InlineData(20, 10)]
[InlineData(10, 10)]
public void Should_throw_error_if_min_greater_than_max(int? min, int? max)
{
Assert.Throws<ArgumentException>(() => new RangeValidator<int>(min, max));
}
[Theory]
[InlineData(null, null)]
[InlineData(1000, null)]
[InlineData(1000, 2000)]
[InlineData(null, 2000)]
public async Task Should_not_error_if_value_is_within_range(int? min, int? max)
{
var sut = new RangeValidator<int>(min, max);
await sut.ValidateAsync(1500, errors);
Assert.Equal(0, errors.Count);
}
[Fact]
public async Task Should_not_error_if_value_null()
{
var sut = new RangeValidator<int>(100, 200);
await sut.ValidateAsync(null, errors);
Assert.Equal(0, errors.Count);
}
[Theory]
public async Task Should_add_error_if_value_is_smaller_than_min()
{
var sut = new RangeValidator<int>(2000, null);
await sut.ValidateAsync(1500, errors);
errors.ShouldBeEquivalentTo(
new[] { "<FIELD> must be greater than '1500'" });
}
[Theory]
public async Task Should_add_error_if_value_is_greater_than_max()
{
var sut = new RangeValidator<int>(null, 1000);
await sut.ValidateAsync(1500, errors);
errors.ShouldBeEquivalentTo(
new[] { "<FIELD> must be less than '1000'" });
}
}
}

67
tests/Squidex.Core.Tests/Schemas/Validators/RequiredStringValidatorTests.cs

@ -0,0 +1,67 @@
// ==========================================================================
// RequiredValidatorTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using System.Threading.Tasks;
using Squidex.Core.Schemas.Validators;
using Xunit;
using FluentAssertions;
namespace Squidex.Core.Tests.Schemas.Validators
{
public sealed class RequiredStringValidatorTests
{
private readonly List<string> errors = new List<string>();
[Theory]
[InlineData("MyString")]
[InlineData("")]
[InlineData(" ")]
[InlineData(" ")]
public async Task Should_not_add_error_if_object_is_valid(string value)
{
var sut = new RequiredStringValidator();
await sut.ValidateAsync(value, errors);
Assert.Equal(0, errors.Count);
}
[Fact]
public async Task Should_not_add_error_if_object_is_another_type()
{
var sut = new RequiredStringValidator();
await sut.ValidateAsync(true, errors);
Assert.Equal(0, errors.Count);
}
[Fact]
public async Task Should_add_error_if_empty_strings_are_not_allowed()
{
var sut = new RequiredStringValidator(true);
await sut.ValidateAsync(string.Empty, errors);
errors.ShouldBeEquivalentTo(
new[] { "<FIELD> is required" });
}
[Fact]
public async Task Should_add_error_if_object_is_null()
{
var sut = new RequiredStringValidator();
await sut.ValidateAsync(null, errors);
errors.ShouldBeEquivalentTo(
new[] { "<FIELD> is required" });
}
}
}

52
tests/Squidex.Core.Tests/Schemas/Validators/RequiredValidatorTests.cs

@ -0,0 +1,52 @@
// ==========================================================================
// RequiredValidatorTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using System.Threading.Tasks;
using Squidex.Core.Schemas.Validators;
using Xunit;
using FluentAssertions;
namespace Squidex.Core.Tests.Schemas.Validators
{
public sealed class RequiredValidatorTests
{
private readonly List<string> errors = new List<string>();
[Fact]
public async Task Should_not_add_error_if_object_is_valid()
{
var sut = new RequiredValidator();
await sut.ValidateAsync(true, errors);
Assert.Equal(0, errors.Count);
}
[Fact]
public async Task Should_not_add_error_for_empty_string()
{
var sut = new RequiredValidator();
await sut.ValidateAsync(string.Empty, errors);
Assert.Equal(0, errors.Count);
}
[Fact]
public async Task Should_add_error_if_object_is_null()
{
var sut = new RequiredValidator();
await sut.ValidateAsync(null, errors);
errors.ShouldBeEquivalentTo(
new[] { "<FIELD> is required" });
}
}
}

22
tests/Squidex.Core.Tests/Squidex.Core.Tests.xproj

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>fd0afd44-7a93-4f9e-b5ed-72582392e435</ProjectGuid>
<RootNamespace>Squidex.Core.Tests</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

35
tests/Squidex.Core.Tests/project.json

@ -0,0 +1,35 @@
{
"buildOptions": {
"copyToOutput": {
"include": [
"xunit.runner.json"
]
}
},
"dependencies": {
"FluentAssertions": "4.15.0",
"dotnet-test-xunit": "2.2.0-preview2-build1029",
"Moq": "4.6.38-alpha",
"Squidex.Core": "1.0.0-*",
"Squidex.Infrastructure": "1.0.0-*",
"xunit": "2.2.0-beta3-build3402"
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
}
}
},
"testRunner": "xunit",
"tooling": {
"defaultNamespace": "Squidex.Core.Tests"
},
"tools": {
"Microsoft.DotNet.Watcher.Tools": "1.0.0-preview2-final"
},
"version": "1.0.0-*"
}

18
tests/Squidex.Infrastructure.Tests/CQRS/Commands/EnrichWithTimestampHandlerTests.cs

@ -22,9 +22,9 @@ namespace Squidex.Infrastructure.CQRS.Commands
{
public DateTime Timestamp { get; set; }
}
[Fact]
public async Task Should_set_timestamp_when_is_timestamp_command()
public async Task Should_set_timestamp_for_timestamp_command()
{
var utc = DateTime.Today;
var sut = new EnrichWithTimestampHandler(() => utc);
@ -37,6 +37,20 @@ namespace Squidex.Infrastructure.CQRS.Commands
Assert.Equal(utc, command.Timestamp);
}
[Fact]
public async Task Should_set_with_now_datetime_for_timestamp_command()
{
var now = DateTime.UtcNow;
var sut = new EnrichWithTimestampHandler();
var command = new TimestampCommand();
var result = await sut.HandleAsync(new CommandContext(command));
Assert.False(result);
Assert.True(command.Timestamp >= now && command.Timestamp <= DateTime.UtcNow);
}
[Fact]
public async Task Should_do_nothing_for_normal_command()
{

60
tests/Squidex.Infrastructure.Tests/CQRS/EnvelopeHeaderTests.cs

@ -0,0 +1,60 @@
// ==========================================================================
// EnvelopeHeaderTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Linq;
using Xunit;
namespace Squidex.Infrastructure.CQRS
{
public class EnvelopeHeaderTests
{
[Fact]
public void Should_create_headers()
{
var headers = new EnvelopeHeaders();
Assert.Equal(0, headers.Count);
}
[Fact]
public void Should_create_headers_with_null_properties()
{
var headers = new EnvelopeHeaders(null);
Assert.Equal(0, headers.Count);
}
[Fact]
public void Should_create_headers_as_copy()
{
var source = new PropertiesBag().Set("Key1", 123);
var headers = new EnvelopeHeaders(source);
CompareHeaders(headers, source);
}
[Fact]
public void Should_clone_headers()
{
var source = new PropertiesBag().Set("Key1", 123);
var headers = new EnvelopeHeaders(source);
var clone = headers.Clone();
CompareHeaders(headers, clone);
}
private static void CompareHeaders(PropertiesBag lhs, PropertiesBag rhs)
{
foreach (var key in lhs.PropertyNames.Concat(rhs.PropertyNames).Distinct())
{
Assert.Equal(lhs[key].ToString(), rhs[key].ToString());
}
}
}
}

63
tests/Squidex.Infrastructure.Tests/CQRS/EventStore/DefaultNameResolverTests.cs

@ -0,0 +1,63 @@
// ==========================================================================
// DefaultNameResolverTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using Squidex.Infrastructure.CQRS.Events;
using Xunit;
namespace Squidex.Infrastructure.CQRS.EventStore
{
public class DefaultNameResolverTests
{
private sealed class User : DomainObject
{
public User(Guid id, int version)
: base(id, version)
{
}
protected override void DispatchEvent(Envelope<IEvent> @event)
{
}
}
private sealed class UserDomainObject : DomainObject
{
public UserDomainObject(Guid id, int version)
: base(id, version)
{
}
protected override void DispatchEvent(Envelope<IEvent> @event)
{
}
}
[Fact]
public void Should_calculate_name()
{
var sut = new DefaultNameResolver("Squidex");
var user = new User(Guid.NewGuid(), 1);
var name = sut.GetStreamName(typeof(User), user.Id);
Assert.Equal($"squidex-user-{user.Id}", name);
}
[Fact]
public void Should_calculate_name_and_remove_suffix()
{
var sut = new DefaultNameResolver("Squidex");
var user = new UserDomainObject(Guid.NewGuid(), 1);
var name = sut.GetStreamName(typeof(User), user.Id);
Assert.Equal($"squidex-user-{user.Id}", name);
}
}
}

92
tests/Squidex.Infrastructure.Tests/CQRS/EventStore/EventStoreFormatterTests.cs

@ -0,0 +1,92 @@
// ==========================================================================
// EventStoreFormatterTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Linq;
using Newtonsoft.Json;
using NodaTime;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Json;
using Xunit;
namespace Squidex.Infrastructure.CQRS.EventStore
{
public class EventStoreFormatterTests
{
public sealed class Event : IEvent
{
public string MyProperty { get; set; }
}
public sealed class ReceivedEvent : IReceivedEvent
{
public int EventNumber { get; set; }
public string EventType { get; set; }
public byte[] Metadata { get; set; }
public byte[] Payload { get; set; }
public DateTime Created { get; set; }
}
private static readonly JsonSerializerSettings serializerSettings = new JsonSerializerSettings();
static EventStoreFormatterTests()
{
serializerSettings.Converters.Add(new PropertiesBagConverter());
}
public EventStoreFormatterTests()
{
TypeNameRegistry.Map(typeof(Event), "Event");
}
[Fact]
public void Should_serialize_and_deserialize_envelope()
{
var commitId = Guid.NewGuid();
var inputEvent = new Envelope<Event>(new Event { MyProperty = "My-Property" });
inputEvent.SetAggregateId(Guid.NewGuid());
inputEvent.SetAppId(Guid.NewGuid());
inputEvent.SetCommitId(commitId);
inputEvent.SetEventId(Guid.NewGuid());
inputEvent.SetEventNumber(1);
inputEvent.SetTimestamp(SystemClock.Instance.GetCurrentInstant());
var sut = new EventStoreFormatter(serializerSettings);
var eventData = sut.ToEventData(inputEvent.To<IEvent>(), commitId);
var receivedEvent = new ReceivedEvent
{
Payload = eventData.Data,
Created = inputEvent.Headers.Timestamp().ToDateTimeUtc(),
EventNumber = 1,
EventType = "event",
Metadata = eventData.Metadata
};
var outputEvent = sut.Parse(receivedEvent).To<Event>();
CompareHeaders(outputEvent.Headers, inputEvent.Headers);
Assert.Equal(inputEvent.Payload.MyProperty, outputEvent.Payload.MyProperty);
}
private static void CompareHeaders(PropertiesBag lhs, PropertiesBag rhs)
{
foreach (var key in lhs.PropertyNames.Concat(rhs.PropertyNames).Distinct())
{
Assert.Equal(lhs[key].ToString(), rhs[key].ToString());
}
}
}
}

2
tests/Squidex.Infrastructure.Tests/PropertiesBagTests.cs

@ -32,7 +32,7 @@ namespace Squidex.Infrastructure
}
[Fact]
public void Should_serialize_and_deserialize_empty()
public void Should_serialize_and_deserialize_empty_bag()
{
var serializerSettings = new JsonSerializerSettings();

2
tests/Squidex.Infrastructure.Tests/Reflection/PropertiesTypeAccessorTest.cs → tests/Squidex.Infrastructure.Tests/Reflection/PropertiesTypeAccessorTests.cs

@ -12,7 +12,7 @@ using Xunit;
namespace Squidex.Infrastructure.Reflection
{
public class PropertiesTypeAccessorTest
public class PropertiesTypeAccessorTests
{
public class TestClass
{

53
tests/Squidex.Infrastructure.Tests/Reflection/ReflectionExtensionTests.cs

@ -0,0 +1,53 @@
// ==========================================================================
// ReflectionExtensionTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Linq;
using Xunit;
// ReSharper disable UnusedMember.Local
namespace Squidex.Infrastructure.Reflection
{
public class ReflectionExtensionTests
{
private interface IMain : ISub1
{
string MainProp { get; set; }
}
private interface ISub1 : ISub2
{
string Sub1Prop { get; set; }
}
private interface ISub2
{
string Sub2Prop { get; set; }
}
private class Main
{
public string MainProp { get; set; }
}
[Fact]
public void Should_find_all_public_properties_of_interfaces()
{
var properties = typeof(IMain).GetPublicProperties().Select(x => x.Name).OrderBy(x => x).ToArray();
Assert.Equal(new [] { "MainProp", "Sub1Prop", "Sub2Prop" }, properties);
}
[Fact]
public void Should_find_all_public_properties_of_classes()
{
var properties = typeof(Main).GetPublicProperties().Select(x => x.Name).OrderBy(x => x).ToArray();
Assert.Equal(new[] { "MainProp" }, properties);
}
}
}

22
tests/Squidex.Infrastructure.Tests/Reflection/SimpleMapperTests.cs

@ -8,6 +8,7 @@
using System;
using Xunit;
// ReSharper disable UnusedParameter.Local
namespace Squidex.Infrastructure.Reflection
{
@ -68,6 +69,22 @@ namespace Squidex.Infrastructure.Reflection
Assert.Throws<ArgumentNullException>(() => SimpleMapper.Map(new Class1(), (Class2)null));
}
[Fact]
public void Should_to_type()
{
var class1 = new Class1
{
UnmappedString = Guid.NewGuid().ToString(),
MappedString = Guid.NewGuid().ToString(),
MappedNumber = 123,
MappedGuid = Guid.NewGuid()
};
var class2 = SimpleMapper.Map<Class1, Class2>(class1);
AssertObjectEquality(class1, class2);
}
[Fact]
public void Should_map_between_types()
{
@ -82,6 +99,11 @@ namespace Squidex.Infrastructure.Reflection
SimpleMapper.Map(class1, class2);
AssertObjectEquality(class1, class2);
}
private static void AssertObjectEquality(Class1 class1, Class2 class2)
{
Assert.Equal(class1.MappedString, class2.MappedString);
Assert.Equal(class1.MappedNumber, class2.MappedNumber);
Assert.Equal(class1.MappedGuid.ToString(), class2.MappedGuid);

2
tests/Squidex.Write.Tests/project.json

@ -27,7 +27,7 @@
},
"testRunner": "xunit",
"tooling": {
"defaultNamespace": "Squidex.Core.Tests"
"defaultNamespace": "Squidex.Write.Tests"
},
"tools": {
"Microsoft.DotNet.Watcher.Tools": "1.0.0-preview2-final"

Loading…
Cancel
Save