Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 70 additions & 12 deletions JsonApiToolkit.Tests/Extensions/IncludeFilterParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public void SeparateIncludeFilters_WithOnlyMainFilters_ReturnsMainFilters()
[Fact]
public void SeparateIncludeFilters_WithSimpleIncludeFilter_SeparatesCorrectly()
{
// Arrange
// Arrange - Include filters must have IsIncludeFilter=true (set by parser for bracket syntax)
var filters = new FilterGroup
{
Filters = new List<FilterParameter>
Expand All @@ -80,6 +80,7 @@ public void SeparateIncludeFilters_WithSimpleIncludeFilter_SeparatesCorrectly()
Field = "comments.status",
Operator = FilterOperator.Eq,
Value = "approved",
IsIncludeFilter = true, // Bracket syntax: filter[comments][status][eq]=approved
},
},
};
Expand All @@ -103,10 +104,51 @@ public void SeparateIncludeFilters_WithSimpleIncludeFilter_SeparatesCorrectly()
Assert.Equal("approved", includeFilters[0].FilterGroup.Filters[0].Value);
}

[Fact]
public void SeparateIncludeFilters_WithDotNotation_TreatedAsPrimaryFilter()
{
// Arrange - Dot notation filters are primary filters (filter main resource through relationship)
var filters = new FilterGroup
{
Filters = new List<FilterParameter>
{
new()
{
Field = "title",
Operator = FilterOperator.Eq,
Value = "Test",
},
new()
{
Field = "comments.status", // Dot notation without IsIncludeFilter = primary filter
Operator = FilterOperator.Eq,
Value = "approved",
IsIncludeFilter = false,
},
},
};
var includePaths = new List<string> { "comments" };

// Act
var (mainFilters, includeFilters) = IncludeFilterParser.SeparateIncludeFilters(
filters,
includePaths
);

// Assert - Both filters should be main filters (dot notation = primary filter)
Assert.NotNull(mainFilters);
Assert.Equal(2, mainFilters.Filters.Count);
Assert.Contains(mainFilters.Filters, f => f.Field == "title");
Assert.Contains(mainFilters.Filters, f => f.Field == "comments.status");

// No include filters - dot notation is now primary filter
Assert.Empty(includeFilters);
}

[Fact]
public void SeparateIncludeFilters_WithKebabCaseInclude_HandlesCorrectly()
{
// Arrange
// Arrange - Include filters must have IsIncludeFilter=true
var filters = new FilterGroup
{
Filters = new List<FilterParameter>
Expand All @@ -116,6 +158,7 @@ public void SeparateIncludeFilters_WithKebabCaseInclude_HandlesCorrectly()
Field = "cveComments.companyCode",
Operator = FilterOperator.Eq,
Value = "AA",
IsIncludeFilter = true, // Bracket syntax: filter[cveComments][companyCode][eq]=AA
},
},
};
Expand All @@ -137,7 +180,7 @@ public void SeparateIncludeFilters_WithKebabCaseInclude_HandlesCorrectly()
[Fact]
public void SeparateIncludeFilters_WithNestedIncludeFilter_SeparatesCorrectly()
{
// Arrange
// Arrange - Include filters must have IsIncludeFilter=true
var filters = new FilterGroup
{
Filters = new List<FilterParameter>
Expand All @@ -147,6 +190,7 @@ public void SeparateIncludeFilters_WithNestedIncludeFilter_SeparatesCorrectly()
Field = "comments.author.department",
Operator = FilterOperator.Eq,
Value = "Security",
IsIncludeFilter = true, // Bracket syntax for nested: filter[comments.author][department][eq]=Security
},
},
};
Expand All @@ -168,7 +212,7 @@ public void SeparateIncludeFilters_WithNestedIncludeFilter_SeparatesCorrectly()
[Fact]
public void SeparateIncludeFilters_WithComplexOrFilter_HandlesCorrectly()
{
// Arrange
// Arrange - Include filters must have IsIncludeFilter=true
var filters = new FilterGroup
{
LogicalOperator = LogicalOperator.Or,
Expand All @@ -179,12 +223,14 @@ public void SeparateIncludeFilters_WithComplexOrFilter_HandlesCorrectly()
Field = "comments.companyCode",
Operator = FilterOperator.Eq,
Value = "AA",
IsIncludeFilter = true,
},
new()
{
Field = "comments.companyCode",
Operator = FilterOperator.IsNull,
Value = "true",
IsIncludeFilter = true,
},
},
};
Expand All @@ -201,13 +247,16 @@ public void SeparateIncludeFilters_WithComplexOrFilter_HandlesCorrectly()
Assert.Equal("comments", includeFilters[0].RelationshipPath);
Assert.Equal(LogicalOperator.Or, includeFilters[0].FilterGroup.LogicalOperator);
Assert.Equal(2, includeFilters[0].FilterGroup.Filters.Count);
Assert.All(includeFilters[0].FilterGroup.Filters, f => Assert.Equal("companyCode", f.Field));
Assert.All(
includeFilters[0].FilterGroup.Filters,
f => Assert.Equal("companyCode", f.Field)
);
}

[Fact]
public void SeparateIncludeFilters_WithFilterOnNonIncludedRelationship_ReturnsAsMainFilter()
{
// Arrange
// Arrange - Even with IsIncludeFilter=true, if relationship is not included, it becomes main filter
var filters = new FilterGroup
{
Filters = new List<FilterParameter>
Expand All @@ -217,6 +266,7 @@ public void SeparateIncludeFilters_WithFilterOnNonIncludedRelationship_ReturnsAs
Field = "comments.status",
Operator = FilterOperator.Eq,
Value = "approved",
IsIncludeFilter = true, // Marked as include filter but relationship not in includes
},
},
};
Expand All @@ -229,7 +279,7 @@ public void SeparateIncludeFilters_WithFilterOnNonIncludedRelationship_ReturnsAs
);

// Assert
// When the relationship is not included, the filter should be treated as a main filter with dot notation
// When the relationship is not included, the filter should be treated as a main filter
Assert.NotNull(mainFilters);
Assert.Single(mainFilters.Filters);
Assert.Equal("comments.status", mainFilters.Filters[0].Field);
Expand All @@ -239,7 +289,7 @@ public void SeparateIncludeFilters_WithFilterOnNonIncludedRelationship_ReturnsAs
[Fact]
public void SeparateIncludeFilters_WithTooDeepNesting_ThrowsException()
{
// Arrange
// Arrange - Include filters must have IsIncludeFilter=true for depth checking
var filters = new FilterGroup
{
Filters = new List<FilterParameter>
Expand All @@ -249,7 +299,8 @@ public void SeparateIncludeFilters_WithTooDeepNesting_ThrowsException()
Field = "a.b.c.d.e",
Operator = FilterOperator.Eq,
Value = "test",
}, // 5 levels deep
IsIncludeFilter = true, // 5 levels deep
},
},
};
var includePaths = new List<string> { "a.b.c.d" };
Expand All @@ -265,7 +316,7 @@ public void SeparateIncludeFilters_WithTooDeepNesting_ThrowsException()
[Fact]
public void SeparateIncludeFilters_WithMixedMainAndIncludeFilters_SeparatesCorrectly()
{
// Arrange
// Arrange - Include filters must have IsIncludeFilter=true
var filters = new FilterGroup
{
Filters = new List<FilterParameter>
Expand All @@ -281,6 +332,7 @@ public void SeparateIncludeFilters_WithMixedMainAndIncludeFilters_SeparatesCorre
Field = "comments.approved",
Operator = FilterOperator.Eq,
Value = "true",
IsIncludeFilter = true, // Bracket syntax: filter[comments][approved][eq]=true
},
new()
{
Expand Down Expand Up @@ -313,7 +365,7 @@ public void SeparateIncludeFilters_WithMixedMainAndIncludeFilters_SeparatesCorre
[Fact]
public void SeparateIncludeFilters_WithNestedGroups_HandlesCorrectly()
{
// Arrange
// Arrange - Include filters must have IsIncludeFilter=true
var filters = new FilterGroup
{
LogicalOperator = LogicalOperator.And,
Expand All @@ -338,12 +390,14 @@ public void SeparateIncludeFilters_WithNestedGroups_HandlesCorrectly()
Field = "comments.status",
Operator = FilterOperator.Eq,
Value = "approved",
IsIncludeFilter = true,
},
new()
{
Field = "comments.status",
Operator = FilterOperator.Eq,
Value = "pending",
IsIncludeFilter = true,
},
},
},
Expand Down Expand Up @@ -373,7 +427,7 @@ public void SeparateIncludeFilters_WithNestedGroups_HandlesCorrectly()
[Fact]
public void SeparateIncludeFilters_WithDeepNestedIncludeFilterUsingLeafName_SeparatesCorrectly()
{
// Arrange - This tests the scenario: include=cve,cve.cvecomments&filter[cvecomments.companyCode][eq]=AA
// Arrange - This tests the scenario: include=cve,cve.cvecomments&filter[cvecomments][companyCode][eq]=AA
var filters = new FilterGroup
{
Filters = new List<FilterParameter>
Expand All @@ -383,6 +437,7 @@ public void SeparateIncludeFilters_WithDeepNestedIncludeFilterUsingLeafName_Sepa
Field = "cvecomments.companyCode",
Operator = FilterOperator.Eq,
Value = "AA",
IsIncludeFilter = true, // Bracket syntax: filter[cvecomments][companyCode][eq]=AA
},
},
};
Expand Down Expand Up @@ -416,6 +471,7 @@ public void SeparateIncludeFilters_WithDeepNestedIncludeFilterUsingKebabCase_Sep
Field = "cveComments.companyCode",
Operator = FilterOperator.Eq,
Value = "AA",
IsIncludeFilter = true, // Bracket syntax: filter[cveComments][companyCode][eq]=AA
},
},
};
Expand Down Expand Up @@ -449,12 +505,14 @@ public void SeparateIncludeFilters_WithMultipleDeepNestedFilters_SeparatesCorrec
Field = "author.name",
Operator = FilterOperator.Eq,
Value = "John",
IsIncludeFilter = true, // Bracket syntax
},
new()
{
Field = "comments.status",
Operator = FilterOperator.Eq,
Value = "approved",
IsIncludeFilter = true, // Bracket syntax
},
},
};
Expand Down
Loading