public async Task Can_filter_on_count()
        {
            // Arrange
            var resource = new FilterableResource
            {
                Children = new List <FilterableResource>
                {
                    new FilterableResource(),
                    new FilterableResource()
                }
            };

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                await dbContext.ClearTableAsync <FilterableResource>();
                dbContext.FilterableResources.AddRange(resource, new FilterableResource());
                await dbContext.SaveChangesAsync();
            });

            const string route = "/filterableResources?filter=equals(count(children),'2')";

            // Act
            (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync <Document>(route);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.OK);

            responseDocument.ManyData.Should().HaveCount(1);
            responseDocument.ManyData[0].Id.Should().Be(resource.StringId);
        }
        public async Task Can_filter_comparison_on_DateTime(string matchingDateTime, string nonMatchingDateTime, ComparisonOperator filterOperator,
                                                            string filterDateTime)
        {
            // Arrange
            var resource = new FilterableResource
            {
                SomeDateTime = DateTime.ParseExact(matchingDateTime, "yyyy-MM-dd", null)
            };

            var otherResource = new FilterableResource
            {
                SomeDateTime = DateTime.ParseExact(nonMatchingDateTime, "yyyy-MM-dd", null)
            };

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                await dbContext.ClearTableAsync <FilterableResource>();
                dbContext.FilterableResources.AddRange(resource, otherResource);
                await dbContext.SaveChangesAsync();
            });

            string route = $"/filterableResources?filter={filterOperator.ToString().Camelize()}(someDateTime," +
                           $"'{DateTime.ParseExact(filterDateTime, "yyyy-MM-dd", null)}')";

            // Act
            (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync <Document>(route);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.OK);

            responseDocument.ManyData.Should().HaveCount(1);
            responseDocument.ManyData[0].Attributes["someDateTime"].Should().BeCloseTo(resource.SomeDateTime);
        }
        public async Task Can_filter_in_set(string matchingText, string nonMatchingText, string filterText)
        {
            // Arrange
            var resource = new FilterableResource
            {
                SomeString = matchingText
            };

            var otherResource = new FilterableResource
            {
                SomeString = nonMatchingText
            };

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                await dbContext.ClearTableAsync <FilterableResource>();
                dbContext.FilterableResources.AddRange(resource, otherResource);
                await dbContext.SaveChangesAsync();
            });

            string route = $"/filterableResources?filter=any(someString,{filterText})";

            // Act
            (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync <Document>(route);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.OK);

            responseDocument.ManyData.Should().HaveCount(1);
            responseDocument.ManyData[0].Attributes["someString"].Should().Be(resource.SomeString);
        }
        public async Task Can_filter_comparison_on_fractional_number(double matchingValue, double nonMatchingValue, ComparisonOperator filterOperator,
                                                                     double filterValue)
        {
            // Arrange
            var resource = new FilterableResource
            {
                SomeDouble = matchingValue
            };

            var otherResource = new FilterableResource
            {
                SomeDouble = nonMatchingValue
            };

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                await dbContext.ClearTableAsync <FilterableResource>();
                dbContext.FilterableResources.AddRange(resource, otherResource);
                await dbContext.SaveChangesAsync();
            });

            string route = $"/filterableResources?filter={filterOperator.ToString().Camelize()}(someDouble,'{filterValue}')";

            // Act
            (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync <Document>(route);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.OK);

            responseDocument.ManyData.Should().HaveCount(1);
            responseDocument.ManyData[0].Attributes["someDouble"].Should().Be(resource.SomeDouble);
        }
        public async Task Can_filter_equality_on_special_characters()
        {
            // Arrange
            var resource = new FilterableResource
            {
                SomeString = "This, that & more"
            };

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                await dbContext.ClearTableAsync <FilterableResource>();
                dbContext.FilterableResources.AddRange(resource, new FilterableResource());
                await dbContext.SaveChangesAsync();
            });

            string route = $"/filterableResources?filter=equals(someString,'{HttpUtility.UrlEncode(resource.SomeString)}')";

            // Act
            (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync <Document>(route);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.OK);

            responseDocument.ManyData.Should().HaveCount(1);
            responseDocument.ManyData[0].Attributes["someString"].Should().Be(resource.SomeString);
        }
        public async Task Can_filter_equality_on_type_Guid()
        {
            // Arrange
            var resource = new FilterableResource {
                SomeGuid = Guid.NewGuid()
            };

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                await dbContext.ClearTableAsync <FilterableResource>();
                dbContext.FilterableResources.AddRange(resource, new FilterableResource());
                await dbContext.SaveChangesAsync();
            });

            var route = $"/filterableResources?filter=equals(someGuid,'{resource.SomeGuid}')";

            // Act
            var(httpResponse, responseDocument) = await _testContext.ExecuteGetAsync <Document>(route);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.OK);

            responseDocument.ManyData.Should().HaveCount(1);
            responseDocument.ManyData[0].Attributes["someGuid"].Should().Be(resource.SomeGuid.ToString());
        }
        public async Task Can_filter_equality_on_two_attributes_of_compatible_types()
        {
            // Arrange
            var resource = new FilterableResource
            {
                SomeInt32         = 5,
                SomeUnsignedInt64 = 5
            };

            var otherResource = new FilterableResource
            {
                SomeInt32         = 5,
                SomeUnsignedInt64 = 10
            };

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                await dbContext.ClearTableAsync <FilterableResource>();
                dbContext.FilterableResources.AddRange(resource, otherResource);
                await dbContext.SaveChangesAsync();
            });

            const string route = "/filterableResources?filter=equals(someInt32,someUnsignedInt64)";

            // Act
            (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync <Document>(route);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.OK);

            responseDocument.ManyData.Should().HaveCount(1);
            responseDocument.ManyData[0].Attributes["someInt32"].Should().Be(resource.SomeInt32);
            responseDocument.ManyData[0].Attributes["someUnsignedInt64"].Should().Be(resource.SomeUnsignedInt64);
        }
        public async Task Cannot_filter_equality_on_incompatible_value()
        {
            // Arrange
            var resource = new FilterableResource {
                SomeInt32 = 1
            };

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                await dbContext.ClearTableAsync <FilterableResource>();
                dbContext.FilterableResources.AddRange(resource, new FilterableResource());
                await dbContext.SaveChangesAsync();
            });

            const string route = "/filterableResources?filter=equals(someInt32,'ABC')";

            // Act
            var(httpResponse, responseDocument) = await _testContext.ExecuteGetAsync <ErrorDocument>(route);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.BadRequest);

            responseDocument.Errors.Should().HaveCount(1);

            var error = responseDocument.Errors[0];

            error.StatusCode.Should().Be(HttpStatusCode.BadRequest);
            error.Title.Should().Be("Query creation failed due to incompatible types.");
            error.Detail.Should().Be("Failed to convert 'ABC' of type 'String' to type 'Int32'.");
            error.Source.Parameter.Should().BeNull();
        }
        public async Task Can_filter_equality_on_type(string propertyName, object value)
        {
            // Arrange
            var resource = new FilterableResource();
            var property = typeof(FilterableResource).GetProperty(propertyName);

            property?.SetValue(resource, value);

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                await dbContext.ClearTableAsync <FilterableResource>();
                dbContext.FilterableResources.AddRange(resource, new FilterableResource());
                await dbContext.SaveChangesAsync();
            });

            var attributeName = propertyName.Camelize();
            var route         = $"/filterableResources?filter=equals({attributeName},'{value}')";

            // Act
            var(httpResponse, responseDocument) = await _testContext.ExecuteGetAsync <Document>(route);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.OK);

            responseDocument.ManyData.Should().HaveCount(1);
            responseDocument.ManyData[0].Attributes[attributeName].Should().Be(value is Enum ? value.ToString() : value);
        }
        public async Task Can_filter_equality_on_type_DateTimeOffset()
        {
            // Arrange
            var resource = new FilterableResource
            {
                SomeDateTimeOffset = 27.January(2003).At(11, 22, 33, 44).ToDateTimeOffset(TimeSpan.FromHours(3))
            };

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                await dbContext.ClearTableAsync <FilterableResource>();
                dbContext.FilterableResources.AddRange(resource, new FilterableResource());
                await dbContext.SaveChangesAsync();
            });

            var route = $"/filterableResources?filter=equals(someDateTimeOffset,'{WebUtility.UrlEncode(resource.SomeDateTimeOffset.ToString("O"))}')";

            // Act
            var(httpResponse, responseDocument) = await _testContext.ExecuteGetAsync <Document>(route);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.OK);

            responseDocument.ManyData.Should().HaveCount(1);
            responseDocument.ManyData[0].Attributes["someDateTimeOffset"].Should().BeCloseTo(resource.SomeDateTimeOffset);
        }
示例#11
0
        public async Task Can_filter_equality_on_type_Decimal()
        {
            // Arrange
            var resource = new FilterableResource
            {
                SomeDecimal = 0.5m
            };

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                await dbContext.ClearTableAsync <FilterableResource>();
                dbContext.FilterableResources.AddRange(resource, new FilterableResource());
                await dbContext.SaveChangesAsync();
            });

            string route = $"/filterableResources?filter=equals(someDecimal,'{resource.SomeDecimal}')";

            // Act
            (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync <Document>(route);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.OK);

            responseDocument.ManyData.Should().HaveCount(1);
            responseDocument.ManyData[0].Attributes["someDecimal"].Should().Be(resource.SomeDecimal);
        }
        public async Task Can_filter_equality_on_two_attributes_of_same_nullable_type()
        {
            // Arrange
            var resource = new FilterableResource
            {
                SomeNullableInt32  = 5,
                OtherNullableInt32 = 5
            };

            var otherResource = new FilterableResource
            {
                SomeNullableInt32  = 5,
                OtherNullableInt32 = 10
            };

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                await dbContext.ClearTableAsync <FilterableResource>();
                dbContext.FilterableResources.AddRange(resource, otherResource);
                await dbContext.SaveChangesAsync();
            });

            var route = "/filterableResources?filter=equals(someNullableInt32,otherNullableInt32)";

            // Act
            var(httpResponse, responseDocument) = await _testContext.ExecuteGetAsync <Document>(route);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.OK);

            responseDocument.ManyData.Should().HaveCount(1);
            responseDocument.ManyData[0].Attributes["someNullableInt32"].Should().Be(resource.SomeNullableInt32);
            responseDocument.ManyData[0].Attributes["otherNullableInt32"].Should().Be(resource.OtherNullableInt32);
        }
        public async Task Can_filter_on_logical_functions(string filterExpression)
        {
            // Arrange
            var resource1 = new FilterableResource
            {
                SomeString = "ABC",
                SomeInt32  = 11,
                SomeEnum   = DayOfWeek.Tuesday
            };

            var resource2 = new FilterableResource
            {
                SomeString = "XYZ",
                SomeInt32  = 99,
                SomeEnum   = DayOfWeek.Saturday
            };

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                await dbContext.ClearTableAsync <FilterableResource>();
                dbContext.FilterableResources.AddRange(resource1, resource2);
                await dbContext.SaveChangesAsync();
            });

            var route = $"/filterableResources?filter={filterExpression}";

            // Act
            var(httpResponse, responseDocument) = await _testContext.ExecuteGetAsync <Document>(route);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.OK);

            responseDocument.ManyData.Should().HaveCount(1);
            responseDocument.ManyData[0].Id.Should().Be(resource1.StringId);
        }
        public async Task Can_filter_text_match(string matchingText, string nonMatchingText, TextMatchKind matchKind, string filterText)
        {
            // Arrange
            var resource = new FilterableResource
            {
                SomeString = matchingText
            };

            var otherResource = new FilterableResource
            {
                SomeString = nonMatchingText
            };

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                await dbContext.ClearTableAsync <FilterableResource>();
                dbContext.FilterableResources.AddRange(resource, otherResource);
                await dbContext.SaveChangesAsync();
            });

            var route = $"/filterableResources?filter={matchKind.ToString().Camelize()}(someString,'{filterText}')";

            // Act
            var(httpResponse, responseDocument) = await _testContext.ExecuteGetAsync <Document>(route);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.OK);

            responseDocument.ManyData.Should().HaveCount(1);
            responseDocument.ManyData[0].Attributes["someString"].Should().Be(resource.SomeString);
        }
        public async Task Can_filter_is_null_on_type(string propertyName)
        {
            // Arrange
            var resource = new FilterableResource();
            var property = typeof(FilterableResource).GetProperty(propertyName);

            property?.SetValue(resource, null);

            var otherResource = new FilterableResource
            {
                SomeString                 = "X",
                SomeNullableBoolean        = true,
                SomeNullableInt32          = 1,
                SomeNullableUnsignedInt64  = 1,
                SomeNullableDecimal        = 1,
                SomeNullableDouble         = 1,
                SomeNullableGuid           = Guid.NewGuid(),
                SomeNullableDateTime       = 1.January(2001),
                SomeNullableDateTimeOffset = 1.January(2001).ToDateTimeOffset(TimeSpan.FromHours(-1)),
                SomeNullableTimeSpan       = TimeSpan.FromHours(1),
                SomeNullableEnum           = DayOfWeek.Friday
            };

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                await dbContext.ClearTableAsync <FilterableResource>();
                dbContext.FilterableResources.AddRange(resource, otherResource);
                await dbContext.SaveChangesAsync();
            });

            var attributeName = propertyName.Camelize();
            var route         = $"/filterableResources?filter=equals({attributeName},null)";

            // Act
            var(httpResponse, responseDocument) = await _testContext.ExecuteGetAsync <Document>(route);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.OK);

            responseDocument.ManyData.Should().HaveCount(1);
            responseDocument.ManyData[0].Attributes[attributeName].Should().Be(null);
        }