Browse Source

1) Tests improved.

2) Asset field.
pull/65/head
Sebastian Stehle 9 years ago
parent
commit
d2b75c4357
  1. 51
      src/Squidex.Core/Schemas/AssetsField.cs
  2. 28
      src/Squidex.Core/Schemas/AssetsFieldProperties.cs
  3. 25
      src/Squidex.Core/Schemas/AssetsValue.cs
  4. 6
      src/Squidex.Core/Schemas/FieldRegistry.cs
  5. 2
      src/Squidex.Core/Schemas/GeolocationField.cs
  6. 18
      src/Squidex.Core/Schemas/IAssetTester.cs
  7. 57
      src/Squidex.Core/Schemas/Validators/AssetsValidator.cs
  8. 3
      src/Squidex.Core/Squidex.Core.csproj
  9. 1
      src/Squidex.Events/Assets/AssetCreated.cs
  10. 1
      src/Squidex.Events/Assets/AssetUpdated.cs
  11. 5
      src/Squidex.Infrastructure.GoogleCloud/GoogleCloudAssetStore.cs
  12. 12
      src/Squidex.Infrastructure/Assets/ImageSharp/ImageSharpAssetThumbnailGenerator.cs
  13. 4
      src/Squidex.Infrastructure/Language.cs
  14. 2
      src/Squidex.Infrastructure/Squidex.Infrastructure.csproj
  15. 8
      src/Squidex.Read.MongoDb/Assets/MongoAssetRepository.cs
  16. 2
      src/Squidex.Read/Assets/IAssetEntity.cs
  17. 6
      src/Squidex.Write/Assets/AssetDomainObject.cs
  18. 2
      src/Squidex/Config/Domain/StoreMongoDbModule.cs
  19. 23
      src/Squidex/Controllers/Api/Schemas/Models/AssetsFieldPropertiesDto.cs
  20. 11
      src/Squidex/Controllers/Api/Schemas/Models/Converters/SchemaConverter.cs
  21. 1
      src/Squidex/Controllers/Api/Schemas/Models/FieldPropertiesDto.cs
  22. 8
      src/Squidex/Squidex.csproj
  23. 5
      tests/Squidex.Core.Tests/ContentEnrichmentTests.cs
  24. 60
      tests/Squidex.Core.Tests/Schemas/AssetsFieldPropertiesTests.cs
  25. 118
      tests/Squidex.Core.Tests/Schemas/AssetsFieldTests.cs
  26. 3
      tests/Squidex.Core.Tests/Schemas/FieldRegistryTests.cs
  27. 5
      tests/Squidex.Core.Tests/Schemas/Json/JsonSerializerTests.cs
  28. 5
      tests/Squidex.Core.Tests/Schemas/SchemaTests.cs
  29. 65
      tests/Squidex.Infrastructure.Tests/Assets/ImageSharpAssetThumbnailGeneratorTests.cs
  30. 6
      tests/Squidex.Infrastructure.Tests/Caching/InvalidatingMemoryCacheTest.cs
  31. 13
      tests/Squidex.Infrastructure.Tests/LanguageTests.cs
  32. 161
      tests/Squidex.Infrastructure.Tests/Log/SemanticLogAdapterTests.cs
  33. 2
      tests/Squidex.Write.Tests/Schemas/SchemaCommandHandlerTests.cs
  34. 3
      tests/Squidex.Write.Tests/Schemas/SchemaDomainObjectTests.cs

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

@ -0,0 +1,51 @@
// ==========================================================================
// AssetsField.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using Microsoft.OData.Edm;
using Newtonsoft.Json.Linq;
using NJsonSchema;
using Squidex.Core.Schemas.Validators;
namespace Squidex.Core.Schemas
{
public sealed class AssetsField : Field<AssetsFieldProperties>
{
private readonly IAssetTester assetTester;
public AssetsField(long id, string name, AssetsFieldProperties properties, IAssetTester assetTester)
: base(id, name, properties)
{
this.assetTester = assetTester;
}
protected override IEnumerable<IValidator> CreateValidators()
{
yield return new AssetsValidator(assetTester, Properties.IsRequired);
}
public override object ConvertValue(JToken value)
{
return new AssetsValue(value.ToObject<Guid[]>());
}
protected override void PrepareJsonSchema(JsonProperty jsonProperty, Func<string, JsonSchema4, JsonSchema4> schemaResolver)
{
var itemSchema = schemaResolver("AssetItem", new JsonSchema4 { Type = JsonObjectType.String });
jsonProperty.Type = JsonObjectType.Array;
jsonProperty.Item = itemSchema;
}
protected override IEdmTypeReference CreateEdmType()
{
return null;
}
}
}

28
src/Squidex.Core/Schemas/AssetsFieldProperties.cs

@ -0,0 +1,28 @@
// ==========================================================================
// AssetsFieldProperties.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure;
namespace Squidex.Core.Schemas
{
[TypeName("AssetsField")]
public sealed class AssetsFieldProperties : FieldProperties
{
public override JToken GetDefaultValue()
{
return new JArray();
}
protected override IEnumerable<ValidationError> ValidateCore()
{
yield break;
}
}
}

25
src/Squidex.Core/Schemas/AssetsValue.cs

@ -0,0 +1,25 @@
// ==========================================================================
// AssetsValue.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
namespace Squidex.Core.Schemas
{
public sealed class AssetsValue
{
private readonly List<Guid> EmptyAssetIds = new List<Guid>();
public IReadOnlyList<Guid> AssetIds { get; }
public AssetsValue(IReadOnlyList<Guid> assetIds)
{
AssetIds = assetIds ?? EmptyAssetIds;
}
}
}

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

@ -50,9 +50,10 @@ namespace Squidex.Core.Schemas
}
}
public FieldRegistry(TypeNameRegistry typeNameRegistry)
public FieldRegistry(TypeNameRegistry typeNameRegistry, IAssetTester assetTester)
{
Guard.NotNull(typeNameRegistry, nameof(typeNameRegistry));
Guard.NotNull(assetTester, nameof(assetTester));
this.typeNameRegistry = typeNameRegistry;
@ -71,6 +72,9 @@ namespace Squidex.Core.Schemas
Add<JsonFieldProperties>(
(id, name, p) => new JsonField(id, name, (JsonFieldProperties)p));
Add<AssetsFieldProperties>(
(id, name, p) => new AssetsField(id, name, (AssetsFieldProperties)p, assetTester));
Add<GeolocationFieldProperties>(
(id, name, p) => new GeolocationField(id, name, (GeolocationFieldProperties)p));
}

2
src/Squidex.Core/Schemas/GeolocationField.cs

@ -47,7 +47,7 @@ namespace Squidex.Core.Schemas
var lat = (double)geolocation["latitude"];
var lon = (double)geolocation["longitude"];
Guard.Between(lat, -90, 90, "latitude");
Guard.Between(lat, -90, 90, "latitude");
Guard.Between(lon, -180, 180, "longitude");
return value;

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

@ -0,0 +1,18 @@
// ==========================================================================
// IAssetTester.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Threading.Tasks;
namespace Squidex.Core.Schemas
{
public interface IAssetTester
{
Task<bool> IsValidAsync(Guid assetId);
}
}

57
src/Squidex.Core/Schemas/Validators/AssetsValidator.cs

@ -0,0 +1,57 @@
// ==========================================================================
// AssetsValidator.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Linq;
using System.Threading.Tasks;
namespace Squidex.Core.Schemas.Validators
{
public sealed class AssetsValidator : IValidator
{
private readonly IAssetTester assetTester;
private readonly bool isRequired;
public AssetsValidator(IAssetTester assetTester, bool isRequired)
{
this.assetTester = assetTester;
this.isRequired = isRequired;
}
public async Task ValidateAsync(object value, Action<string> addError)
{
var assets = value as AssetsValue;
if (assets == null || assets.AssetIds.Count == 0)
{
if (isRequired)
{
addError("<FIELD> is required");
}
return;
}
var assetTasks = assets.AssetIds.Select(CheckAsset).ToArray();
await Task.WhenAll(assetTasks);
foreach (var notFoundId in assetTasks.Where(x => !x.Result.IsFound).Select(x => x.Result.AssetId))
{
addError($"<FIELD> contains invalid asset '{notFoundId}'");
}
}
private async Task<(Guid AssetId, bool IsFound)> CheckAsset(Guid id)
{
var isFound = await assetTester.IsValidAsync(id);
return (id, isFound);
}
}
}

3
src/Squidex.Core/Squidex.Core.csproj

@ -14,7 +14,8 @@
<PackageReference Include="protobuf-net" Version="2.1.0" />
<PackageReference Include="System.Collections.Immutable" Version="1.3.1" />
<PackageReference Include="NodaTime" Version="2.0.0" />
<PackageReference Include="NJsonSchema" Version="8.30.6304.31883" />
<PackageReference Include="NJsonSchema" Version="8.32.6319.16936" />
<PackageReference Include="System.ValueTuple" Version="4.3.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.6' ">
<PackageReference Include="Microsoft.OData.Core" Version="6.15.0" />

1
src/Squidex.Events/Assets/AssetCreated.cs

@ -6,7 +6,6 @@
// All rights reserved.
// ==========================================================================
using System;
using Squidex.Infrastructure;
namespace Squidex.Events.Assets

1
src/Squidex.Events/Assets/AssetUpdated.cs

@ -6,7 +6,6 @@
// All rights reserved.
// ==========================================================================
using System;
using Squidex.Infrastructure;
namespace Squidex.Events.Assets

5
src/Squidex.Infrastructure.GoogleCloud/GoogleCloudAssetStore.cs

@ -56,10 +56,7 @@ namespace Squidex.Infrastructure.GoogleCloud
{
throw new AssetNotFoundException($"Asset {id}, {version} not found.", ex);
}
else
{
throw;
}
throw;
}
}

12
src/Squidex.Infrastructure/Assets/ImageSharp/ImageSharpAssetThumbnailGenerator.cs

@ -30,6 +30,8 @@ namespace Squidex.Infrastructure.Assets.ImageSharp
if (width == null && height == null)
{
source.CopyTo(destination);
return;
}
if (!Enum.TryParse<ResizeMode>(mode, true, out var resizeMode))
@ -64,22 +66,16 @@ namespace Squidex.Infrastructure.Assets.ImageSharp
{
return Task.Run(() =>
{
ImageInfo imageInfo = null;
try
{
var image = Image.Load(source);
if (image.Width > 0 && image.Height > 0)
{
imageInfo = new ImageInfo(image.Width, image.Height);
}
return new ImageInfo(image.Width, image.Height);
}
catch
{
imageInfo = null;
return null;
}
return imageInfo;
});
}
}

4
src/Squidex.Infrastructure/Language.cs

@ -16,10 +16,10 @@ namespace Squidex.Infrastructure
{
public sealed partial class Language
{
private static readonly Regex CultureRegex = new Regex("([a-z]{2})(\\-[a-z]{2})?");
private static readonly Regex CultureRegex = new Regex("^([a-z]{2})(\\-[a-z]{2})?$");
private readonly string iso2Code;
private readonly string englishName;
private static readonly Dictionary<string, Language> AllLanguagesField = new Dictionary<string, Language>();
private static readonly Dictionary<string, Language> AllLanguagesField = new Dictionary<string, Language>(StringComparer.OrdinalIgnoreCase);
public static readonly Language Invariant = AddLanguage("iv", "Invariant");

2
src/Squidex.Infrastructure/Squidex.Infrastructure.csproj

@ -8,7 +8,7 @@
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ImageSharp" Version="1.0.0-alpha6-00060" />
<PackageReference Include="ImageSharp" Version="1.0.0-alpha7-00006" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />

8
src/Squidex.Read.MongoDb/Assets/MongoAssetRepository.cs

@ -12,6 +12,7 @@ using System.Linq;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver;
using Squidex.Core.Schemas;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.MongoDb;
using Squidex.Read.Assets;
@ -19,7 +20,7 @@ using Squidex.Read.Assets.Repositories;
namespace Squidex.Read.MongoDb.Assets
{
public partial class MongoAssetRepository : MongoRepositoryBase<MongoAssetEntity>, IAssetRepository, IEventConsumer
public partial class MongoAssetRepository : MongoRepositoryBase<MongoAssetEntity>, IAssetRepository, IAssetTester, IEventConsumer
{
public MongoAssetRepository(IMongoDatabase database)
: base(database)
@ -36,6 +37,11 @@ namespace Squidex.Read.MongoDb.Assets
return collection.Indexes.CreateOneAsync(IndexKeys.Descending(x => x.LastModified).Ascending(x => x.AppId).Ascending(x => x.FileName).Ascending(x => x.MimeType));
}
public async Task<bool> IsValidAsync(Guid assetId)
{
return await Collection.Find(x => x.Id == assetId).CountAsync() == 1;
}
public async Task<IReadOnlyList<IAssetEntity>> QueryAsync(Guid appId, HashSet<string> mimeTypes = null, string query = null, int take = 10, int skip = 0)
{
var filter = CreateFilter(appId, mimeTypes, query);

2
src/Squidex.Read/Assets/IAssetEntity.cs

@ -6,8 +6,6 @@
// All rights reserved.
// ==========================================================================
using System;
namespace Squidex.Read.Assets
{
public interface IAssetEntity : IAppRefEntity, IEntityWithCreatedBy, IEntityWithLastModifiedBy, IEntityWithVersion

6
src/Squidex.Write/Assets/AssetDomainObject.cs

@ -24,7 +24,6 @@ namespace Squidex.Write.Assets
private bool isDeleted;
private long fileVersion;
private string fileName;
private Guid fileId;
public bool IsDeleted
{
@ -36,11 +35,6 @@ namespace Squidex.Write.Assets
get { return fileName; }
}
public Guid FileId
{
get { return fileId; }
}
public AssetDomainObject(Guid id, int version)
: base(id, version)
{

2
src/Squidex/Config/Domain/StoreMongoDbModule.cs

@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.MongoDB;
using Microsoft.Extensions.Configuration;
using MongoDB.Driver;
using Squidex.Core.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.MongoDb;
@ -136,6 +137,7 @@ namespace Squidex.Config.Domain
builder.RegisterType<MongoAssetRepository>()
.WithParameter(ResolvedParameter.ForNamed<IMongoDatabase>(MongoDatabaseRegistration))
.As<IAssetRepository>()
.As<IAssetTester>()
.As<IEventConsumer>()
.As<IExternalSystem>()
.AsSelf()

23
src/Squidex/Controllers/Api/Schemas/Models/AssetsFieldPropertiesDto.cs

@ -0,0 +1,23 @@
// ==========================================================================
// AssetsFieldPropertiesDto.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using NJsonSchema.Annotations;
using Squidex.Core.Schemas;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Controllers.Api.Schemas.Models
{
[JsonSchema("Assets")]
public sealed class AssetsFieldPropertiesDto : FieldPropertiesDto
{
public override FieldProperties ToProperties()
{
return SimpleMapper.Map(this, new AssetsFieldProperties());
}
}
}

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

@ -42,6 +42,10 @@ namespace Squidex.Controllers.Api.Schemas.Models.Converters
{
typeof(GeolocationFieldProperties),
p => Convert((GeolocationFieldProperties)p)
},
{
typeof(AssetsFieldProperties),
p => Convert((AssetsFieldProperties)p)
}
};
@ -94,6 +98,13 @@ namespace Squidex.Controllers.Api.Schemas.Models.Converters
return result;
}
private static FieldPropertiesDto Convert(AssetsFieldProperties source)
{
var result = SimpleMapper.Map(source, new AssetsFieldPropertiesDto());
return result;
}
private static FieldPropertiesDto Convert(StringFieldProperties source)
{
var result = SimpleMapper.Map(source, new StringFieldPropertiesDto());

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

@ -15,6 +15,7 @@ using Squidex.Core.Schemas;
namespace Squidex.Controllers.Api.Schemas.Models
{
[JsonConverter(typeof(JsonInheritanceConverter), "fieldType")]
[KnownType(typeof(AssetsFieldPropertiesDto))]
[KnownType(typeof(BooleanFieldPropertiesDto))]
[KnownType(typeof(DateTimeFieldPropertiesDto))]
[KnownType(typeof(GeolocationFieldPropertiesDto))]

8
src/Squidex/Squidex.csproj

@ -39,9 +39,9 @@
<ItemGroup>
<PackageReference Include="Autofac" Version="4.5.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.0.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.1.0" />
<PackageReference Include="IdentityServer4" Version="1.5.0" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="1.1.0" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="1.2.0" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="1.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" Version="1.1.1" />
@ -62,9 +62,9 @@
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.1" />
<PackageReference Include="MongoDB.Driver" Version="2.4.3" />
<PackageReference Include="NJsonSchema" Version="8.30.6304.31883" />
<PackageReference Include="NJsonSchema" Version="8.32.6319.16936" />
<PackageReference Include="NodaTime.Serialization.JsonNet" Version="2.0.0" />
<PackageReference Include="NSwag.AspNetCore" Version="10.1.0" />
<PackageReference Include="NSwag.AspNetCore" Version="10.5.0" />
<PackageReference Include="OpenCover" Version="4.6.519" />
<PackageReference Include="ReportGenerator" Version="2.5.6" />
<PackageReference Include="StackExchange.Redis.StrongName" Version="1.2.1" />

5
tests/Squidex.Core.Tests/ContentEnrichmentTests.cs

@ -7,6 +7,7 @@
// ==========================================================================
using System.Collections.Generic;
using Moq;
using NodaTime;
using NodaTime.Text;
using Squidex.Core.Contents;
@ -38,7 +39,9 @@ namespace Squidex.Core
.AddOrUpdateField(new DateTimeField(5, "my-datetime",
new DateTimeFieldProperties { DefaultValue = now }))
.AddOrUpdateField(new GeolocationField(6, "my-geolocation",
new GeolocationFieldProperties()));
new GeolocationFieldProperties()))
.AddOrUpdateField(new AssetsField(7, "my-assets",
new AssetsFieldProperties(), new Mock<IAssetTester>().Object));
var data =
new ContentData()

60
tests/Squidex.Core.Tests/Schemas/AssetsFieldPropertiesTests.cs

@ -0,0 +1,60 @@
// ==========================================================================
// AssetFieldPropertiesTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Linq;
using System.Reflection;
using Xunit;
namespace Squidex.Core.Schemas
{
public class AssetsFieldPropertiesTests
{
[Fact]
public void Should_set_or_freeze_sut()
{
var sut = new AssetsFieldProperties();
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;
}
});
}
}
}
}

118
tests/Squidex.Core.Tests/Schemas/AssetsFieldTests.cs

@ -0,0 +1,118 @@
// ==========================================================================
// AssetFieldTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using FluentAssertions;
using Moq;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure.Tasks;
using Xunit;
namespace Squidex.Core.Schemas
{
public class AssetsFieldTests
{
private readonly Mock<IAssetTester> assetTester = new Mock<IAssetTester>();
private readonly List<string> errors = new List<string>();
[Fact]
public void Should_instantiate_field()
{
var sut = new AssetsField(1, "my-asset", new AssetsFieldProperties(), assetTester.Object);
Assert.Equal("my-asset", sut.Name);
}
[Fact]
public void Should_clone_object()
{
var sut = new AssetsField(1, "my-asset", new AssetsFieldProperties(), assetTester.Object);
Assert.NotEqual(sut, sut.Enable());
}
[Fact]
public async Task Should_not_add_error_if_assets_are_valid()
{
var assetId = Guid.NewGuid();
assetTester.Setup(x => x.IsValidAsync(assetId)).Returns(TaskHelper.True);
var sut = new AssetsField(1, "my-asset", new AssetsFieldProperties(), assetTester.Object);
await sut.ValidateAsync(CreateValue(assetId), errors);
Assert.Empty(errors);
}
[Fact]
public async Task Should_not_add_error_if_assets_are_null_and_valid()
{
var sut = new AssetsField(1, "my-asset", new AssetsFieldProperties(), assetTester.Object);
await sut.ValidateAsync(CreateValue(null), errors);
Assert.Empty(errors);
}
[Fact]
public async Task Should_add_errors_if_assets_are_required_and_null()
{
var sut = new AssetsField(1, "my-asset", new AssetsFieldProperties { IsRequired = true }, assetTester.Object);
await sut.ValidateAsync(CreateValue(null), errors);
errors.ShouldBeEquivalentTo(
new[] { "<FIELD> is required" });
}
[Fact]
public async Task Should_add_errors_if_assets_are_required_and_empty()
{
var sut = new AssetsField(1, "my-asset", new AssetsFieldProperties { IsRequired = true }, assetTester.Object);
await sut.ValidateAsync(CreateValue(), errors);
errors.ShouldBeEquivalentTo(
new[] { "<FIELD> is required" });
}
[Fact]
public async Task Should_add_errors_if_value_is_not_valid()
{
var sut = new AssetsField(1, "my-asset", new AssetsFieldProperties(), assetTester.Object);
await sut.ValidateAsync("invalid", errors);
errors.ShouldBeEquivalentTo(
new[] { "<FIELD> is not a valid value" });
}
[Fact]
public async Task Should_add_errors_if_asset_are_not_valid()
{
var assetId = Guid.NewGuid();
assetTester.Setup(x => x.IsValidAsync(assetId)).Returns(TaskHelper.False);
var sut = new AssetsField(1, "my-asset", new AssetsFieldProperties(), assetTester.Object);
await sut.ValidateAsync(CreateValue(assetId), errors);
errors.ShouldBeEquivalentTo(
new[] { $"<FIELD> contains invalid asset '{assetId}'" });
}
private static JToken CreateValue(params Guid[] ids)
{
return ids == null ? JValue.CreateNull() : (JToken)new JArray(ids);
}
}
}

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

@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using Moq;
using Newtonsoft.Json.Linq;
using Squidex.Infrastructure;
using Xunit;
@ -16,7 +17,7 @@ namespace Squidex.Core.Schemas
{
public class FieldRegistryTests
{
private readonly FieldRegistry sut = new FieldRegistry(new TypeNameRegistry());
private readonly FieldRegistry sut = new FieldRegistry(new TypeNameRegistry(), new Mock<IAssetTester>().Object);
private sealed class InvalidProperties : FieldProperties
{

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

@ -7,6 +7,7 @@
// ==========================================================================
using FluentAssertions;
using Moq;
using Newtonsoft.Json;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json;
@ -25,7 +26,7 @@ namespace Squidex.Core.Schemas.Json
serializerSettings.TypeNameHandling = TypeNameHandling.Auto;
serializerSettings.SerializationBinder = new TypeNameSerializationBinder(typeNameRegistry);
sut = new SchemaJsonSerializer(new FieldRegistry(typeNameRegistry), serializerSettings);
sut = new SchemaJsonSerializer(new FieldRegistry(typeNameRegistry, new Mock<IAssetTester>().Object), serializerSettings);
}
[Fact]
@ -45,6 +46,8 @@ namespace Squidex.Core.Schemas.Json
new DateTimeFieldProperties()))
.AddOrUpdateField(new GeolocationField(6, "my-geolocation",
new GeolocationFieldProperties()))
.AddOrUpdateField(new AssetsField(7, "my-asset",
new AssetsFieldProperties(), new Mock<IAssetTester>().Object))
.Publish();
var deserialized = sut.Deserialize(sut.Serialize(schema));

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

@ -10,6 +10,7 @@ using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Moq;
using Newtonsoft.Json.Linq;
using NJsonSchema;
using Squidex.Infrastructure;
@ -332,7 +333,9 @@ namespace Squidex.Core.Schemas
.AddOrUpdateField(new DateTimeField(7, "my-date",
new DateTimeFieldProperties { Editor = DateTimeFieldEditor.Date }))
.AddOrUpdateField(new GeolocationField(8, "my-geolocation",
new GeolocationFieldProperties()));
new GeolocationFieldProperties()))
.AddOrUpdateField(new AssetsField(9, "my-assets",
new AssetsFieldProperties(), new Mock<IAssetTester>().Object));
return schema;
}

65
tests/Squidex.Infrastructure.Tests/Assets/ImageSharpAssetThumbnailGeneratorTests.cs

@ -0,0 +1,65 @@
// ==========================================================================
// ImageSharpAssetThumbnailGeneratorTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.IO;
using System.Threading.Tasks;
using Squidex.Infrastructure.Assets.ImageSharp;
using Xunit;
namespace Squidex.Infrastructure.Assets
{
public class ImageSharpAssetThumbnailGeneratorTests
{
private const string Image = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMTM0A1t6AAAADElEQVQYV2P4//8/AAX+Av6nNYGEAAAAAElFTkSuQmCC";
private readonly ImageSharpAssetThumbnailGenerator sut = new ImageSharpAssetThumbnailGenerator();
[Fact]
public async Task Should_return_same_image_if_no_size_is_passed_for_thumbnail()
{
var source = new MemoryStream(Convert.FromBase64String(Image));
var target = new MemoryStream();
await sut.CreateThumbnailAsync(source, target, null, null, "resize");
Assert.Equal(target.Length, source.Length);
}
[Fact]
public async Task Should_resize_image_to_target()
{
var source = new MemoryStream(Convert.FromBase64String(Image));
var target = new MemoryStream();
await sut.CreateThumbnailAsync(source, target, 100, 100, "resize");
Assert.True(target.Length > source.Length);
}
[Fact]
public async Task Should_return_image_information_if_image_is_valid()
{
var source = new MemoryStream(Convert.FromBase64String(Image));
var imageInfo = await sut.GetImageInfoAsync(source);
Assert.Equal(1, imageInfo.PixelHeight);
Assert.Equal(1, imageInfo.PixelWidth);
}
[Fact]
public async Task Should_return_null_if_stream_is_not_an_image()
{
var source = new MemoryStream(Convert.FromBase64String("YXNkc2Fk"));
var imageInfo = await sut.GetImageInfoAsync(source);
Assert.Null(imageInfo);
}
}
}

6
tests/Squidex.Infrastructure.Tests/Caching/InvalidatingMemoryCacheTest.cs

@ -63,7 +63,7 @@ namespace Squidex.Infrastructure.Caching
{
sut.Invalidate(123);
pubsub.Verify(x => x.Publish("CacheInvalidations", It.IsAny<string>(), false), Times.Never());
pubsub.Verify(x => x.Publish("CacheInvalidations", It.IsAny<string>(), true), Times.Never());
}
[Fact]
@ -71,7 +71,7 @@ namespace Squidex.Infrastructure.Caching
{
sut.Invalidate("a-key");
pubsub.Verify(x => x.Publish("CacheInvalidations", "a-key", false), Times.Once());
pubsub.Verify(x => x.Publish("CacheInvalidations", "a-key", true), Times.Once());
}
[Fact]
@ -79,7 +79,7 @@ namespace Squidex.Infrastructure.Caching
{
((IMemoryCache)sut).Invalidate("a-key");
pubsub.Verify(x => x.Publish("CacheInvalidations", "a-key", false), Times.Once());
pubsub.Verify(x => x.Publish("CacheInvalidations", "a-key", true), Times.Once());
}
[Fact]

13
tests/Squidex.Infrastructure.Tests/LanguageTests.cs

@ -54,6 +54,18 @@ namespace Squidex.Infrastructure
Language.DE.SerializeAndDeserialize(new LanguageConverter());
}
[Fact]
public void Should_return_true_for_valid_language()
{
Assert.True(Language.IsValidLanguage("de"));
}
[Fact]
public void Should_return_false_for_invalid_language()
{
Assert.False(Language.IsValidLanguage("xx"));
}
[Theory]
[InlineData("de", "German")]
[InlineData("en", "English")]
@ -65,6 +77,7 @@ namespace Squidex.Infrastructure
Assert.Equal(key, language.Iso2Code);
Assert.Equal(englishName, language.EnglishName);
Assert.Equal(englishName, language.ToString());
}
[Theory]

161
tests/Squidex.Infrastructure.Tests/Log/SemanticLogAdapterTests.cs

@ -0,0 +1,161 @@
// ==========================================================================
// SemanticLogAdapterTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using Moq;
using Squidex.Infrastructure.Log.Adapter;
using Xunit;
namespace Squidex.Infrastructure.Log
{
public class SemanticLogAdapterTests
{
private readonly List<ILogChannel> channels = new List<ILogChannel>();
private readonly Lazy<SemanticLog> log;
private readonly Mock<ILogChannel> channel = new Mock<ILogChannel>();
private readonly SemanticLogLoggerProvider sut;
private string output;
public SemanticLog Log
{
get { return log.Value; }
}
public SemanticLogAdapterTests()
{
channels.Add(channel.Object);
channel.Setup(x => x.Log(It.IsAny<SemanticLogLevel>(), It.IsAny<string>())).Callback(
new Action<SemanticLogLevel, string>((level, message) =>
{
output = message;
}));
log = new Lazy<SemanticLog>(() => new SemanticLog(channels, new List<ILogAppender>(), () => new JsonLogWriter()));
sut = new SemanticLogLoggerProvider(log.Value);
}
[Fact]
public void Should_do_nothing_when_disposing()
{
sut.Dispose();
}
[Fact]
public void Should_provide_a_scope()
{
var logger = sut.CreateLogger("test-category");
Assert.NotNull(logger.BeginScope(1));
}
[Fact]
public void Should_log_always()
{
var logger = sut.CreateLogger("test-category");
Assert.True(logger.IsEnabled(LogLevel.Critical));
Assert.True(logger.IsEnabled((LogLevel)123));
}
[Fact]
public void Should_log_message_with_event_id()
{
var eventId = new EventId(1000);
var logger = sut.CreateLogger("my-category");
logger.Log(LogLevel.Debug, eventId, 1, null, (x, e) => "my-message");
var expected =
MakeTestCall(w => w
.WriteProperty("logLevel", "Debug")
.WriteProperty("message", "my-message")
.WriteObject("eventId", e => e
.WriteProperty("id", 1000))
.WriteProperty("category", "my-category"));
Assert.Equal(expected, output);
}
[Fact]
public void Should_log_message_with_event_id_and_name()
{
var eventId = new EventId(1000, "my-event");
var logger = sut.CreateLogger("my-category");
logger.Log(LogLevel.Debug, eventId, 1, null, (x, e) => "my-message");
var expected =
MakeTestCall(w => w
.WriteProperty("logLevel", "Debug")
.WriteProperty("message", "my-message")
.WriteObject("eventId", e => e
.WriteProperty("id", 1000)
.WriteProperty("name", "my-event"))
.WriteProperty("category", "my-category"));
Assert.Equal(expected, output);
}
[Fact]
public void Should_log_message_with_exception()
{
var exception = new InvalidOperationException();
var logger = sut.CreateLogger("my-category");
logger.Log(LogLevel.Debug, new EventId(0), 1, exception, (x, e) => "my-message");
var expected =
MakeTestCall(w => w
.WriteProperty("logLevel", "Debug")
.WriteProperty("message", "my-message")
.WriteException(exception)
.WriteProperty("category", "my-category"));
Assert.Equal(expected, output);
}
[Theory]
[InlineData(LogLevel.None, "Debug")]
[InlineData(LogLevel.Debug, "Debug")]
[InlineData(LogLevel.Error, "Error")]
[InlineData(LogLevel.Trace, "Trace")]
[InlineData(LogLevel.Warning, "Warning")]
[InlineData(LogLevel.Critical, "Fatal")]
[InlineData(LogLevel.Information, "Information")]
public void Should_log_message(LogLevel level, string semanticLogLevel)
{
var logger = sut.CreateLogger("my-category");
logger.Log(level, new EventId(0), 1, null, (x, e) => "my-message");
var expected =
MakeTestCall(w => w
.WriteProperty("logLevel", semanticLogLevel)
.WriteProperty("message", "my-message")
.WriteProperty("category", "my-category"));
Assert.Equal(expected, output);
}
private static string MakeTestCall(Action<IObjectWriter> writer)
{
IObjectWriter sut = new JsonLogWriter();
writer(sut);
return sut.ToString();
}
}
}

2
tests/Squidex.Write.Tests/Schemas/SchemaCommandHandlerTests.cs

@ -28,7 +28,7 @@ namespace Squidex.Write.Schemas
private readonly Mock<ISchemaProvider> schemaProvider = new Mock<ISchemaProvider>();
private readonly SchemaCommandHandler sut;
private readonly SchemaDomainObject schema;
private readonly FieldRegistry registry = new FieldRegistry(new TypeNameRegistry());
private readonly FieldRegistry registry = new FieldRegistry(new TypeNameRegistry(), new Mock<IAssetTester>().Object);
private readonly string fieldName = "age";
public SchemaCommandHandlerTests()

3
tests/Squidex.Write.Tests/Schemas/SchemaDomainObjectTests.cs

@ -8,6 +8,7 @@
using System.Collections.Generic;
using System.Linq;
using Moq;
using Squidex.Core.Schemas;
using Squidex.Events.Schemas;
using Squidex.Infrastructure;
@ -30,7 +31,7 @@ namespace Squidex.Write.Schemas
{
fieldId = new NamedId<long>(1, fieldName);
var fieldRegistry = new FieldRegistry(new TypeNameRegistry());
var fieldRegistry = new FieldRegistry(new TypeNameRegistry(), new Mock<IAssetTester>().Object);
sut = new SchemaDomainObject(SchemaId, 0, fieldRegistry);
}

Loading…
Cancel
Save