Skip to content

Commit 1e4d3ba

Browse files
committed
Fix nullable boolean handling in LINQ filters and add IsFamilyFriendly test
- ProcessEqualityExpression now handles Convert expressions for nullable types (bool?) - Added explicit boolean-to-lowercase string conversion for Bing API compatibility - Added test for IsFamilyFriendly == true filter (validates safeSearch query parameter) - Achieves 100% coverage of all 10 LINQ filter operations - Note: CA1308 warning acceptable - Bing API requires lowercase boolean strings
1 parent 2607c18 commit 1e4d3ba

2 files changed

Lines changed: 44 additions & 3 deletions

File tree

dotnet/src/Plugins/Plugins.UnitTests/Web/Bing/BingTextSearchTests.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,30 @@ public async Task GenericSearchAsyncWithNoFilterReturnsResultsSuccessfullyAsync(
462462
Assert.Equal(10, resultList.Count);
463463
}
464464

465+
[Fact]
466+
public async Task GenericSearchAsyncWithIsFamilyFriendlyFilterProducesCorrectBingQueryAsync()
467+
{
468+
// Arrange
469+
this._messageHandlerStub.AddJsonResponse(File.ReadAllText(WhatIsTheSKResponseJson));
470+
ITextSearch<BingWebPage> textSearch = new BingTextSearch(apiKey: "ApiKey", options: new() { HttpClient = this._httpClient });
471+
472+
// Act
473+
var searchOptions = new TextSearchOptions<BingWebPage>
474+
{
475+
Top = 4,
476+
Skip = 0,
477+
Filter = page => page.IsFamilyFriendly == true
478+
};
479+
KernelSearchResults<string> result = await textSearch.SearchAsync("What is the Semantic Kernel?", searchOptions);
480+
481+
// Assert - Verify LINQ IsFamilyFriendly equality converted to Bing's safeSearch query parameter
482+
var requestUris = this._messageHandlerStub.RequestUris;
483+
Assert.Single(requestUris);
484+
Assert.NotNull(requestUris[0]);
485+
// safeSearch is a query parameter, not an advanced search operator
486+
Assert.Contains("safeSearch=true", requestUris[0]!.AbsoluteUri);
487+
}
488+
465489
#endregion
466490

467491
/// <inheritdoc/>

dotnet/src/Plugins/Plugins.Web/Bing/BingTextSearch.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,24 +204,41 @@ private static void ProcessExpression(Expression expression, TextSearchFilter fi
204204
/// <param name="isNegated">True if this is an inequality (!=) expression.</param>
205205
private static void ProcessEqualityExpression(BinaryExpression binaryExpr, TextSearchFilter filter, bool isNegated)
206206
{
207-
if (binaryExpr.Left is MemberExpression memberExpr && binaryExpr.Right is ConstantExpression constExpr)
207+
// Handle nullable properties with conversions (e.g., bool? == bool becomes Convert(property) == value)
208+
MemberExpression? memberExpr = binaryExpr.Left as MemberExpression;
209+
if (memberExpr == null && binaryExpr.Left is UnaryExpression unaryExpr && unaryExpr.NodeType == ExpressionType.Convert)
210+
{
211+
memberExpr = unaryExpr.Operand as MemberExpression;
212+
}
213+
214+
// Handle conversions on the right side too
215+
ConstantExpression? constExpr = binaryExpr.Right as ConstantExpression;
216+
if (constExpr == null && binaryExpr.Right is UnaryExpression rightUnaryExpr && rightUnaryExpr.NodeType == ExpressionType.Convert)
217+
{
218+
constExpr = rightUnaryExpr.Operand as ConstantExpression;
219+
}
220+
221+
if (memberExpr != null && constExpr != null)
208222
{
209223
string propertyName = memberExpr.Member.Name;
210224
object? value = constExpr.Value;
211225

212226
string? bingFilterName = MapPropertyToBingFilter(propertyName);
213227
if (bingFilterName != null && value != null)
214228
{
229+
// Convert boolean values to lowercase strings for Bing API compatibility
230+
string stringValue = value is bool boolValue ? boolValue.ToString().ToLowerInvariant() : value.ToString() ?? string.Empty;
231+
215232
if (isNegated)
216233
{
217234
// For inequality, wrap the value with a negation marker
218235
// This will be processed in BuildQuery to prepend '-' to the advanced search operator
219236
// Example: language:en becomes -language:en (excludes pages in English)
220-
filter.Equality(bingFilterName, $"-{value}");
237+
filter.Equality(bingFilterName, $"-{stringValue}");
221238
}
222239
else
223240
{
224-
filter.Equality(bingFilterName, value);
241+
filter.Equality(bingFilterName, stringValue);
225242
}
226243
}
227244
else if (value == null)

0 commit comments

Comments
 (0)