From 973219d164ca90e6e18ca4b4dbe9838034cd688e Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sun, 26 Feb 2017 18:49:07 +0100 Subject: [PATCH] Tests --- src/Squidex.Core/Schemas/DateTimeField.cs | 11 +---- .../InstantSerializer.cs | 7 ++- .../Contents/Visitors/ConstantVisitor.cs | 34 +++++++++++++ .../Contents/Visitors/FilterVisitor.cs | 21 ++++++-- .../Contents/Visitors/SchemaExtensions.cs | 4 +- .../MongoDb/Contents/ODataQueryTests.cs | 49 ++++++++++++++++--- 6 files changed, 105 insertions(+), 21 deletions(-) diff --git a/src/Squidex.Core/Schemas/DateTimeField.cs b/src/Squidex.Core/Schemas/DateTimeField.cs index aaeb51cd5..7670cfd66 100644 --- a/src/Squidex.Core/Schemas/DateTimeField.cs +++ b/src/Squidex.Core/Schemas/DateTimeField.cs @@ -69,19 +69,12 @@ namespace Squidex.Core.Schemas { jsonProperty.Type = JsonObjectType.String; - if (Properties.Editor == DateTimeFieldEditor.Date) - { - jsonProperty.Format = JsonFormatStrings.Date; - } - else - { - jsonProperty.Format = JsonFormatStrings.DateTime; - } + jsonProperty.Format = JsonFormatStrings.DateTime; } protected override IEdmTypeReference CreateEdmType() { - return EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Date, !Properties.IsRequired); + return EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.DateTimeOffset, !Properties.IsRequired); } } } diff --git a/src/Squidex.Infrastructure.MongoDb/InstantSerializer.cs b/src/Squidex.Infrastructure.MongoDb/InstantSerializer.cs index a018e4d77..bc9046d87 100644 --- a/src/Squidex.Infrastructure.MongoDb/InstantSerializer.cs +++ b/src/Squidex.Infrastructure.MongoDb/InstantSerializer.cs @@ -14,7 +14,7 @@ using NodaTime; namespace Squidex.Infrastructure.MongoDb { - public sealed class InstantSerializer : SerializerBase + public sealed class InstantSerializer : SerializerBase, IBsonPolymorphicSerializer { private static bool isRegistered; private static readonly object LockObject = new object(); @@ -38,6 +38,11 @@ namespace Squidex.Infrastructure.MongoDb return false; } + public bool IsDiscriminatorCompatibleWithObjectSerializer + { + get { return true; } + } + public override Instant Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { var value = context.Reader.ReadDateTime(); diff --git a/src/Squidex.Read.MongoDb/Contents/Visitors/ConstantVisitor.cs b/src/Squidex.Read.MongoDb/Contents/Visitors/ConstantVisitor.cs index 82e2e4f2b..21c5c7405 100644 --- a/src/Squidex.Read.MongoDb/Contents/Visitors/ConstantVisitor.cs +++ b/src/Squidex.Read.MongoDb/Contents/Visitors/ConstantVisitor.cs @@ -6,8 +6,16 @@ // All rights reserved. // ========================================================================== +using System; using Microsoft.OData.Core.UriParser.Semantic; using Microsoft.OData.Core.UriParser.Visitors; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Library; +using NodaTime; +using NodaTime.Text; + +// ReSharper disable ConvertIfStatementToReturnStatement +// ReSharper disable InvertIf namespace Squidex.Read.MongoDb.Contents.Visitors { @@ -24,6 +32,32 @@ namespace Squidex.Read.MongoDb.Contents.Visitors return node.Accept(Instance); } + public override object Visit(ConvertNode nodeIn) + { + var booleanType = EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.Boolean); + + if (nodeIn.TypeReference.Definition == booleanType) + { + return bool.Parse(Visit(nodeIn.Source).ToString()); + } + + var dateTimeType = EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.DateTimeOffset); + + if (nodeIn.TypeReference.Definition == dateTimeType) + { + var value = Visit(nodeIn.Source); + + if (value is DateTimeOffset) + { + return Instant.FromDateTimeOffset((DateTimeOffset)value); + } + + return InstantPattern.General.Parse(Visit(nodeIn.Source).ToString()).Value; + } + + return base.Visit(nodeIn); + } + public override object Visit(ConstantNode nodeIn) { return nodeIn.Value; diff --git a/src/Squidex.Read.MongoDb/Contents/Visitors/FilterVisitor.cs b/src/Squidex.Read.MongoDb/Contents/Visitors/FilterVisitor.cs index d44c21712..4f72f14fa 100644 --- a/src/Squidex.Read.MongoDb/Contents/Visitors/FilterVisitor.cs +++ b/src/Squidex.Read.MongoDb/Contents/Visitors/FilterVisitor.cs @@ -15,6 +15,7 @@ using MongoDB.Bson; using MongoDB.Driver; using Squidex.Core.Schemas; +// ReSharper disable InvertIf // ReSharper disable SwitchStatementMissingSomeCases // ReSharper disable ConvertIfStatementToSwitchStatement @@ -49,17 +50,26 @@ namespace Squidex.Read.MongoDb.Contents.Visitors public override FilterDefinition Visit(SingleValueFunctionCallNode nodeIn) { + var fieldNode = nodeIn.Parameters.ElementAt(0); + var valueNode = nodeIn.Parameters.ElementAt(1); + if (nodeIn.Name == "endswith") { - return Filter.Regex(BuildFieldDefinition(nodeIn.Parameters.ElementAt(0)), new BsonRegularExpression(BuildValue(nodeIn.Parameters.ElementAt(1)) + "$", "i")); + var value = BuildRegex(valueNode, v => v + "$"); + + return Filter.Regex(BuildFieldDefinition(fieldNode), value); } if (nodeIn.Name == "startswith") { - return Filter.Regex(BuildFieldDefinition(nodeIn.Parameters.ElementAt(0)), new BsonRegularExpression("^" + BuildValue(nodeIn.Parameters.ElementAt(1)), "i")); + var value = BuildRegex(valueNode, v => "^" + v); + + return Filter.Regex(BuildFieldDefinition(fieldNode), value); } if (nodeIn.Name == "contains") { - return Filter.Regex(BuildFieldDefinition(nodeIn.Parameters.ElementAt(0)), new BsonRegularExpression(BuildValue(nodeIn.Parameters.ElementAt(1)).ToString(), "i")); + var value = BuildRegex(valueNode, v => v); + + return Filter.Regex(BuildFieldDefinition(fieldNode), value); } throw new NotSupportedException(); @@ -103,6 +113,11 @@ namespace Squidex.Read.MongoDb.Contents.Visitors throw new NotSupportedException(); } + private static BsonRegularExpression BuildRegex(QueryNode node, Func formatter) + { + return new BsonRegularExpression(formatter(BuildValue(node).ToString()), "i"); + } + private FieldDefinition BuildFieldDefinition(QueryNode nodeIn) { return PropertyVisitor.Visit(nodeIn, schema); diff --git a/src/Squidex.Read.MongoDb/Contents/Visitors/SchemaExtensions.cs b/src/Squidex.Read.MongoDb/Contents/Visitors/SchemaExtensions.cs index 0376e60c2..7a9cf44ca 100644 --- a/src/Squidex.Read.MongoDb/Contents/Visitors/SchemaExtensions.cs +++ b/src/Squidex.Read.MongoDb/Contents/Visitors/SchemaExtensions.cs @@ -32,9 +32,9 @@ namespace Squidex.Read.MongoDb.Contents.Visitors var entityType = new EdmEntityType("Squidex", schema.Name); entityType.AddStructuralProperty("data", new EdmComplexTypeReference(schemaType, false)); - entityType.AddStructuralProperty("created", EdmPrimitiveTypeKind.Date); + entityType.AddStructuralProperty("created", EdmPrimitiveTypeKind.DateTimeOffset); entityType.AddStructuralProperty("createdBy", EdmPrimitiveTypeKind.String); - entityType.AddStructuralProperty("lastModified", EdmPrimitiveTypeKind.Date); + entityType.AddStructuralProperty("lastModified", EdmPrimitiveTypeKind.DateTimeOffset); entityType.AddStructuralProperty("lastModifiedBy", EdmPrimitiveTypeKind.String); model.AddElement(container); diff --git a/tests/Squidex.Read.Tests/MongoDb/Contents/ODataQueryTests.cs b/tests/Squidex.Read.Tests/MongoDb/Contents/ODataQueryTests.cs index e13b80df6..882ea67b9 100644 --- a/tests/Squidex.Read.Tests/MongoDb/Contents/ODataQueryTests.cs +++ b/tests/Squidex.Read.Tests/MongoDb/Contents/ODataQueryTests.cs @@ -14,6 +14,7 @@ using MongoDB.Driver; using Moq; using Squidex.Core.Schemas; using Squidex.Infrastructure; +using Squidex.Infrastructure.MongoDb; using Squidex.Read.MongoDb.Contents.Visitors; using Xunit; @@ -28,11 +29,13 @@ namespace Squidex.Read.MongoDb.Contents .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 StringFieldProperties { Hints = "Last Name", Editor = StringFieldEditor.Input })) + .AddOrUpdateField(new BooleanField(3, "isAdmin", new BooleanFieldProperties())) .AddOrUpdateField(new NumberField(4, "age", - new NumberFieldProperties { MinValue = 1, MaxValue = 10 })); + new NumberFieldProperties { MinValue = 1, MaxValue = 10 })) + .AddOrUpdateField(new DateTimeField(5, "birthday", + new DateTimeFieldProperties())); private readonly IBsonSerializerRegistry registry = BsonSerializer.SerializerRegistry; private readonly IBsonSerializer serializer = BsonSerializer.SerializerRegistry.GetSerializer(); @@ -42,10 +45,15 @@ namespace Squidex.Read.MongoDb.Contents Language.DE }; + static ODataQueryTests() + { + InstantSerializer.Register(); + } + [Fact] public void Should_parse_query() { - var parser = schema.ParseQuery(languages, "$filter=data/FirstName/de eq 'Sebastian'"); + var parser = schema.ParseQuery(languages, "$filter=data/firstName/de eq 'Sebastian'"); Assert.NotNull(parser); } @@ -95,6 +103,24 @@ namespace Squidex.Read.MongoDb.Contents Assert.Equal(o, i); } + [Fact] + public void Should_create_datetime_equals_query() + { + var i = F("$filter=data/birthday/iv eq 1988-01-19T12:00:00Z"); + var o = C("{ 'Data.5.iv' : ISODate(\"1988-01-19T12:00:00Z\") }"); + + Assert.Equal(o, i); + } + + [Fact] + public void Should_create_boolean_equals_query() + { + var i = F("$filter=data/isAdmin/iv eq true"); + var o = C("{ 'Data.3.iv' : true }"); + + Assert.Equal(o, i); + } + [Fact] public void Should_create_string_not_equals_query() { @@ -206,14 +232,25 @@ namespace Squidex.Read.MongoDb.Contents } [Fact] - public void Should_not_set_top() + public void Should_set_max_top_if_larger() + { + var parser = schema.ParseQuery(languages, "$top=300"); + var cursor = new Mock>(); + + cursor.Object.Take(parser); + + cursor.Verify(x => x.Limit(200)); + } + + [Fact] + public void Should_set_default_top() { var parser = schema.ParseQuery(languages, ""); var cursor = new Mock>(); cursor.Object.Take(parser); - cursor.Verify(x => x.Limit(It.IsAny()), Times.Never); + cursor.Verify(x => x.Limit(20)); } [Fact]