[CDX-496] Add PreFilterExpressionPerSection support to Autocomplete requests - #104
Conversation
There was a problem hiding this comment.
Pull request overview
Adds support for pre_filter_expression on Autocomplete requests, including a per-section variant that uses bracket notation (pre_filter_expression[Section]=...) consistent with Constructor.io’s documented query param shape.
Changes:
- Added
PreFilterExpressionandPreFilterExpressionPerSectionsupport toAutocompleteRequestrequest-parameter generation. - Implemented URL querystring serialization for per-section pre-filter expressions in
Helpers.MakeUrl. - Added unit/integration tests validating parameter generation and request serialization behavior.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/Constructorio_NET.Tests/utils/HelpersTest.cs | Adds a URL-formation test for bracketed per-section pre_filter_expression in autocomplete URLs. |
| src/Constructorio_NET.Tests/models/Autocomplete/AutocompleteRequestTest.cs | Adds request-parameter unit tests for global and per-section pre-filter expressions. |
| src/Constructorio_NET.Tests/client/modules/AutocompleteTests.cs | Adds integration tests asserting pre_filter_expression is included (global and per-section) in Autocomplete requests. |
| src/constructor.io/utils/Helpers.cs | Serializes PRE_FILTER_EXPRESSION_PER_SECTION into bracket-notation query params (pre_filter_expression[Section]=...). |
| src/constructor.io/utils/Constants.cs | Introduces PRE_FILTER_EXPRESSION_PER_SECTION constant. |
| src/constructor.io/models/common/PreFilterExpressionPerSection.cs | Adds a model to associate a PreFilterExpression with a specific autocomplete section. |
| src/constructor.io/models/Autocomplete/AutocompleteRequest.cs | Adds new request properties and includes them in GetRequestParameters(). |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Alexey-Pavlov
left a comment
There was a problem hiding this comment.
LGTM! Left a few comments, could you please take a look?
| parameters.Add(Constants.PRE_FILTER_EXPRESSION, this.PreFilterExpression.GetExpression()); | ||
| } | ||
|
|
||
| if (this.PreFilterExpressionPerSection != null && this.PreFilterExpressionPerSection.Count > 0) |
There was a problem hiding this comment.
If we would set together pre_filter_expression= and pre_filter_expression[Section]=- it will throw
{
"message": "Both dictionary and non dictionary value is supplied for pre_filter_expression key."
}
Can we throw here, or at least say "mutually exclusive" in the doc?
| /// Gets or sets per-section filter expressions used to scope results for specific sections. | ||
| /// Serialized as pre_filter_expression[Section]={...}. | ||
| /// </summary> | ||
| public List<PreFilterExpressionPerSection> PreFilterExpressionPerSection { get; set; } |
There was a problem hiding this comment.
| public List<PreFilterExpressionPerSection> PreFilterExpressionPerSection { get; set; } | |
| public Dictionary<string, PreFilterExpression> PreFilterExpressionPerSection { get; set; } |
List<> lets you pass the same section twice:
{
"message": "pre_filter_expression: Products: Invalid JSON string"
}
|
|
||
| foreach (var sectionExpression in preFilterExpressionPerSection) | ||
| { | ||
| if (sectionExpression?.Section == null || sectionExpression.Expression == null) |
There was a problem hiding this comment.
Section == null lets "" and " " through, so we send pre_filter_expression[ ]=..., the API accepts it, but should we validate it?
| bool hasProductsKey = Regex.Match(url, "&pre_filter_expression%5BProducts%5D=").Success; | ||
| bool hasSuggestionsKey = Regex.Match(url, "&pre_filter_expression%5BSearch%20Suggestions%5D=").Success; | ||
| bool hasBrandExpression = url.Contains(OurEscapeDataString("XYZ")); | ||
| bool hasGroupExpression = url.Contains(OurEscapeDataString("All")); | ||
| Assert.That(hasProductsKey && hasSuggestionsKey && hasBrandExpression && hasGroupExpression, "url should have bracketed per-section pre_filter_expression"); |
There was a problem hiding this comment.
It passes even if we emit the JSON unescaped
Also, there is one `Assert. ', it hides which part failed, maybe we can make a few asserts as the fmt_options test above?
| bool hasProductsKey = Regex.Match(url, "&pre_filter_expression%5BProducts%5D=").Success; | |
| bool hasSuggestionsKey = Regex.Match(url, "&pre_filter_expression%5BSearch%20Suggestions%5D=").Success; | |
| bool hasBrandExpression = url.Contains(OurEscapeDataString("XYZ")); | |
| bool hasGroupExpression = url.Contains(OurEscapeDataString("All")); | |
| Assert.That(hasProductsKey && hasSuggestionsKey && hasBrandExpression && hasGroupExpression, "url should have bracketed per-section pre_filter_expression"); | |
| string productsParameter = "&pre_filter_expression%5BProducts%5D=" + OurEscapeDataString(filterProducts.GetExpression()); | |
| string suggestionsParameter = "&pre_filter_expression%5BSearch%20Suggestions%5D=" + OurEscapeDataString(filterSuggestions.GetExpression()); | |
| Assert.That(url, Does.Contain(productsParameter), "url should have the escaped Products expression"); | |
| Assert.That(url, Does.Contain(suggestionsParameter), "url should have the escaped Search Suggestions expression"); | |
| Assert.That(url, Does.Not.Contain("{"), "url should not contain unescaped json"); | |
| Assert.That(url, Does.Not.Contain("&pre_filter_expression="), "url should not have the non per-section form"); |
No description provided.