@@ -35,6 +35,18 @@ public sealed class FilterOperatorTests : IClassFixture<IntegrationTestContext<T
3535 private const string TimeSpanInTheRange = "2:15:51:42.397" ;
3636 private const string TimeSpanUpperBound = "2:16:22:41.736" ;
3737
38+ private const string IsoDateOnlyLowerBound = "2000-10-22" ;
39+ private const string IsoDateOnlyInTheRange = "2000-11-22" ;
40+ private const string IsoDateOnlyUpperBound = "2000-12-22" ;
41+
42+ private const string InvariantDateOnlyLowerBound = "10/22/2000" ;
43+ private const string InvariantDateOnlyInTheRange = "11/22/2000" ;
44+ private const string InvariantDateOnlyUpperBound = "12/22/2000" ;
45+
46+ private const string TimeOnlyLowerBound = "15:28:54.997" ;
47+ private const string TimeOnlyInTheRange = "15:51:42.397" ;
48+ private const string TimeOnlyUpperBound = "16:22:41.736" ;
49+
3850 private readonly IntegrationTestContext < TestableStartup < FilterDbContext > , FilterDbContext > _testContext ;
3951
4052 public FilterOperatorTests ( IntegrationTestContext < TestableStartup < FilterDbContext > , FilterDbContext > testContext )
@@ -556,6 +568,96 @@ await _testContext.RunOnDatabaseAsync(async dbContext =>
556568 responseDocument . Data . ManyValue [ 0 ] . Attributes . ShouldContainKey ( "someTimeSpan" ) . With ( value => value . Should ( ) . Be ( resource . SomeTimeSpan ) ) ;
557569 }
558570
571+ [ Theory ]
572+ [ InlineData ( IsoDateOnlyLowerBound , IsoDateOnlyUpperBound , ComparisonOperator . LessThan , IsoDateOnlyInTheRange ) ]
573+ [ InlineData ( IsoDateOnlyLowerBound , IsoDateOnlyUpperBound , ComparisonOperator . LessThan , IsoDateOnlyUpperBound ) ]
574+ [ InlineData ( IsoDateOnlyLowerBound , IsoDateOnlyUpperBound , ComparisonOperator . LessOrEqual , IsoDateOnlyInTheRange ) ]
575+ [ InlineData ( IsoDateOnlyLowerBound , IsoDateOnlyUpperBound , ComparisonOperator . LessOrEqual , IsoDateOnlyLowerBound ) ]
576+ [ InlineData ( IsoDateOnlyUpperBound , IsoDateOnlyLowerBound , ComparisonOperator . GreaterThan , IsoDateOnlyInTheRange ) ]
577+ [ InlineData ( IsoDateOnlyUpperBound , IsoDateOnlyLowerBound , ComparisonOperator . GreaterThan , IsoDateOnlyLowerBound ) ]
578+ [ InlineData ( IsoDateOnlyUpperBound , IsoDateOnlyLowerBound , ComparisonOperator . GreaterOrEqual , IsoDateOnlyInTheRange ) ]
579+ [ InlineData ( IsoDateOnlyUpperBound , IsoDateOnlyLowerBound , ComparisonOperator . GreaterOrEqual , IsoDateOnlyUpperBound ) ]
580+ [ InlineData ( InvariantDateOnlyLowerBound , InvariantDateOnlyUpperBound , ComparisonOperator . LessThan , InvariantDateOnlyInTheRange ) ]
581+ [ InlineData ( InvariantDateOnlyLowerBound , InvariantDateOnlyUpperBound , ComparisonOperator . LessThan , InvariantDateOnlyUpperBound ) ]
582+ [ InlineData ( InvariantDateOnlyLowerBound , InvariantDateOnlyUpperBound , ComparisonOperator . LessOrEqual , InvariantDateOnlyInTheRange ) ]
583+ [ InlineData ( InvariantDateOnlyLowerBound , InvariantDateOnlyUpperBound , ComparisonOperator . LessOrEqual , InvariantDateOnlyLowerBound ) ]
584+ [ InlineData ( InvariantDateOnlyUpperBound , InvariantDateOnlyLowerBound , ComparisonOperator . GreaterThan , InvariantDateOnlyInTheRange ) ]
585+ [ InlineData ( InvariantDateOnlyUpperBound , InvariantDateOnlyLowerBound , ComparisonOperator . GreaterThan , InvariantDateOnlyLowerBound ) ]
586+ [ InlineData ( InvariantDateOnlyUpperBound , InvariantDateOnlyLowerBound , ComparisonOperator . GreaterOrEqual , InvariantDateOnlyInTheRange ) ]
587+ [ InlineData ( InvariantDateOnlyUpperBound , InvariantDateOnlyLowerBound , ComparisonOperator . GreaterOrEqual , InvariantDateOnlyUpperBound ) ]
588+ public async Task Can_filter_comparison_on_DateOnly ( string matchingValue , string nonMatchingValue , ComparisonOperator filterOperator , string filterValue )
589+ {
590+ // Arrange
591+ var resource = new FilterableResource
592+ {
593+ SomeDateOnly = DateOnly . Parse ( matchingValue , CultureInfo . InvariantCulture )
594+ } ;
595+
596+ var otherResource = new FilterableResource
597+ {
598+ SomeDateOnly = DateOnly . Parse ( nonMatchingValue , CultureInfo . InvariantCulture )
599+ } ;
600+
601+ await _testContext . RunOnDatabaseAsync ( async dbContext =>
602+ {
603+ await dbContext . ClearTableAsync < FilterableResource > ( ) ;
604+ dbContext . FilterableResources . AddRange ( resource , otherResource ) ;
605+ await dbContext . SaveChangesAsync ( ) ;
606+ } ) ;
607+
608+ string route = $ "/filterableResources?filter={ filterOperator . ToString ( ) . Camelize ( ) } (someDateOnly,'{ filterValue } ')";
609+
610+ // Act
611+ ( HttpResponseMessage httpResponse , Document responseDocument ) = await _testContext . ExecuteGetAsync < Document > ( route ) ;
612+
613+ // Assert
614+ httpResponse . ShouldHaveStatusCode ( HttpStatusCode . OK ) ;
615+
616+ responseDocument . Data . ManyValue . ShouldHaveCount ( 1 ) ;
617+ responseDocument . Data . ManyValue [ 0 ] . Attributes . ShouldContainKey ( "someDateOnly" ) . With ( value => value . Should ( ) . Be ( resource . SomeDateOnly ) ) ;
618+ }
619+
620+ [ Theory ]
621+ [ InlineData ( TimeOnlyLowerBound , TimeOnlyUpperBound , ComparisonOperator . LessThan , TimeOnlyInTheRange ) ]
622+ [ InlineData ( TimeOnlyLowerBound , TimeOnlyUpperBound , ComparisonOperator . LessThan , TimeOnlyUpperBound ) ]
623+ [ InlineData ( TimeOnlyLowerBound , TimeOnlyUpperBound , ComparisonOperator . LessOrEqual , TimeOnlyInTheRange ) ]
624+ [ InlineData ( TimeOnlyLowerBound , TimeOnlyUpperBound , ComparisonOperator . LessOrEqual , TimeOnlyLowerBound ) ]
625+ [ InlineData ( TimeOnlyUpperBound , TimeOnlyLowerBound , ComparisonOperator . GreaterThan , TimeOnlyInTheRange ) ]
626+ [ InlineData ( TimeOnlyUpperBound , TimeOnlyLowerBound , ComparisonOperator . GreaterThan , TimeOnlyLowerBound ) ]
627+ [ InlineData ( TimeOnlyUpperBound , TimeOnlyLowerBound , ComparisonOperator . GreaterOrEqual , TimeOnlyInTheRange ) ]
628+ [ InlineData ( TimeOnlyUpperBound , TimeOnlyLowerBound , ComparisonOperator . GreaterOrEqual , TimeOnlyUpperBound ) ]
629+ public async Task Can_filter_comparison_on_TimeOnly ( string matchingValue , string nonMatchingValue , ComparisonOperator filterOperator , string filterValue )
630+ {
631+ // Arrange
632+ var resource = new FilterableResource
633+ {
634+ SomeTimeOnly = TimeOnly . Parse ( matchingValue , CultureInfo . InvariantCulture )
635+ } ;
636+
637+ var otherResource = new FilterableResource
638+ {
639+ SomeTimeOnly = TimeOnly . Parse ( nonMatchingValue , CultureInfo . InvariantCulture )
640+ } ;
641+
642+ await _testContext . RunOnDatabaseAsync ( async dbContext =>
643+ {
644+ await dbContext . ClearTableAsync < FilterableResource > ( ) ;
645+ dbContext . FilterableResources . AddRange ( resource , otherResource ) ;
646+ await dbContext . SaveChangesAsync ( ) ;
647+ } ) ;
648+
649+ string route = $ "/filterableResources?filter={ filterOperator . ToString ( ) . Camelize ( ) } (someTimeOnly,'{ filterValue } ')";
650+
651+ // Act
652+ ( HttpResponseMessage httpResponse , Document responseDocument ) = await _testContext . ExecuteGetAsync < Document > ( route ) ;
653+
654+ // Assert
655+ httpResponse . ShouldHaveStatusCode ( HttpStatusCode . OK ) ;
656+
657+ responseDocument . Data . ManyValue . ShouldHaveCount ( 1 ) ;
658+ responseDocument . Data . ManyValue [ 0 ] . Attributes . ShouldContainKey ( "someTimeOnly" ) . With ( value => value . Should ( ) . Be ( resource . SomeTimeOnly ) ) ;
659+ }
660+
559661 [ Theory ]
560662 [ InlineData ( "The fox jumped over the lazy dog" , "Other" , TextMatchKind . Contains , "jumped" ) ]
561663 [ InlineData ( "The fox jumped over the lazy dog" , "the fox..." , TextMatchKind . Contains , "The" ) ]
0 commit comments