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
1 change: 1 addition & 0 deletions AspNetCore.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -1227,6 +1227,7 @@
<Project Path="src/Caching/perf/MicroBenchmarks/Microsoft.Extensions.Caching.MicroBenchmarks/Microsoft.Extensions.Caching.MicroBenchmarks.csproj" />
<Project Path="src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter/src/Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter.csproj" />
<Project Path="src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/Microsoft.AspNetCore.Components.QuickGrid.csproj" />
<Project Path="src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/test/Microsoft.AspNetCore.Components.QuickGrid.Tests.csproj" />
<Project Path="src/Components/WebView/test/E2ETest/Microsoft.AspNetCore.Components.WebViewE2E.Test.csproj" />
<Project Path="src/DataProtection/samples/KeyManagementSimulator/KeyManagementSimulator.csproj" />
<Project Path="src/Framework/AspNetCoreAnalyzers/samples/WebAppSample/WebAppSample.csproj" />
Expand Down
1 change: 1 addition & 0 deletions src/Components/Components.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"src\\Components\\Forms\\test\\Microsoft.AspNetCore.Components.Forms.Tests.csproj",
"src\\Components\\QuickGrid\\Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter\\src\\Microsoft.AspNetCore.Components.QuickGrid.EntityFrameworkAdapter.csproj",
"src\\Components\\QuickGrid\\Microsoft.AspNetCore.Components.QuickGrid\\src\\Microsoft.AspNetCore.Components.QuickGrid.csproj",
"src\\Components\\QuickGrid\\Microsoft.AspNetCore.Components.QuickGrid\\test\\Microsoft.AspNetCore.Components.QuickGrid.Tests.csproj",
"src\\Components\\Samples\\BlazorServerApp\\BlazorServerApp.csproj",
"src\\Components\\Samples\\BlazorUnitedApp.Client\\BlazorUnitedApp.Client.csproj",
"src\\Components\\Samples\\BlazorUnitedApp\\BlazorUnitedApp.csproj",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,16 @@ private List<SortedProperty> BuildPropertyList(bool ascending)
// Not sure we really want this level of complexity, but it converts expressions like @(c => c.Medals.Gold) to "Medals.Gold"
private static string ToPropertyName(LambdaExpression expression)
{
if (expression.Body is not MemberExpression body)
var expressionBody = expression.Body;

// Handle UnaryExpressions that can occur due to implicit conversions, such as nullable value types
if (expressionBody.NodeType == ExpressionType.Convert ||
expressionBody.NodeType == ExpressionType.ConvertChecked)
{
expressionBody = ((UnaryExpression)expressionBody).Operand;
}

if (expressionBody is not MemberExpression body)
{
throw new ArgumentException(ExpressionNotRepresentableMessage);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@
<Reference Include="Microsoft.AspNetCore.Components.Web" />
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="Microsoft.AspNetCore.Components.QuickGrid.Tests" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Globalization;
using System.Linq.Expressions;

namespace Microsoft.AspNetCore.Components.QuickGrid.Tests;

public class GridSortTest
{
// Test model classes
private class TestEntity
{
public string Name { get; set; } = string.Empty;
public int Age { get; set; }
public DateTime? NullableDate { get; set; }
public int? NullableInt { get; set; }
public TestChild Child { get; set; } = new();
}

private class TestChild
{
public string ChildName { get; set; } = string.Empty;
public DateTime? ChildNullableDate { get; set; }
}

[Fact]
public void ToPropertyName_SimpleProperty_ReturnsPropertyName()
{
// Arrange
Expression<Func<TestEntity, string>> expression = x => x.Name;

// Act
var gridSort = GridSort<TestEntity>.ByAscending(expression);
var propertyList = gridSort.ToPropertyList(ascending: true);

// Assert
Assert.Single(propertyList);
Assert.Equal("Name", propertyList.First().PropertyName);
Assert.Equal(SortDirection.Ascending, propertyList.First().Direction);
}

[Fact]
public void ToPropertyName_NullableProperty_ReturnsPropertyName()
{
// Arrange
Expression<Func<TestEntity, DateTime?>> expression = x => x.NullableDate;

// Act
var gridSort = GridSort<TestEntity>.ByAscending(expression);
var propertyList = gridSort.ToPropertyList(ascending: true);

// Assert
Assert.Single(propertyList);
Assert.Equal("NullableDate", propertyList.First().PropertyName);
Assert.Equal(SortDirection.Ascending, propertyList.First().Direction);
}

[Fact]
public void ToPropertyName_NullableInt_ReturnsPropertyName()
{
// Arrange
Expression<Func<TestEntity, int?>> expression = x => x.NullableInt;

// Act
var gridSort = GridSort<TestEntity>.ByAscending(expression);
var propertyList = gridSort.ToPropertyList(ascending: true);

// Assert
Assert.Single(propertyList);
Assert.Equal("NullableInt", propertyList.First().PropertyName);
Assert.Equal(SortDirection.Ascending, propertyList.First().Direction);
}

[Fact]
public void ToPropertyName_NestedProperty_ReturnsNestedPropertyName()
{
// Arrange
Expression<Func<TestEntity, string>> expression = x => x.Child.ChildName;

// Act
var gridSort = GridSort<TestEntity>.ByAscending(expression);
var propertyList = gridSort.ToPropertyList(ascending: true);

// Assert
Assert.Single(propertyList);
Assert.Equal("Child.ChildName", propertyList.First().PropertyName);
Assert.Equal(SortDirection.Ascending, propertyList.First().Direction);
}

[Fact]
public void ToPropertyName_NestedNullableProperty_ReturnsNestedPropertyName()
{
// Arrange
Expression<Func<TestEntity, DateTime?>> expression = x => x.Child.ChildNullableDate;

// Act
var gridSort = GridSort<TestEntity>.ByAscending(expression);
var propertyList = gridSort.ToPropertyList(ascending: true);

// Assert
Assert.Single(propertyList);
Assert.Equal("Child.ChildNullableDate", propertyList.First().PropertyName);
Assert.Equal(SortDirection.Ascending, propertyList.First().Direction);
}

[Fact]
public void ToPropertyName_DescendingSort_ReturnsCorrectDirection()
{
// Arrange
Expression<Func<TestEntity, DateTime?>> expression = x => x.NullableDate;

// Act
var gridSort = GridSort<TestEntity>.ByDescending(expression);
var propertyList = gridSort.ToPropertyList(ascending: true);

// Assert
Assert.Single(propertyList);
Assert.Equal("NullableDate", propertyList.First().PropertyName);
Assert.Equal(SortDirection.Descending, propertyList.First().Direction);
}

[Fact]
public void ToPropertyName_MultipleSort_ReturnsAllProperties()
{
// Arrange
Expression<Func<TestEntity, string>> firstExpression = x => x.Name;
Expression<Func<TestEntity, DateTime?>> secondExpression = x => x.NullableDate;

// Act
var gridSort = GridSort<TestEntity>.ByAscending(firstExpression)
.ThenDescending(secondExpression);
var propertyList = gridSort.ToPropertyList(ascending: true);

// Assert
Assert.Equal(2, propertyList.Count);

var firstProperty = propertyList.First();
Assert.Equal("Name", firstProperty.PropertyName);
Assert.Equal(SortDirection.Ascending, firstProperty.Direction);

var secondProperty = propertyList.Last();
Assert.Equal("NullableDate", secondProperty.PropertyName);
Assert.Equal(SortDirection.Descending, secondProperty.Direction);
}

[Fact]
public void ToPropertyName_InvalidExpression_ThrowsArgumentException()
{
// Arrange
Expression<Func<TestEntity, string>> invalidExpression = x => x.Name.ToUpper(CultureInfo.InvariantCulture);

// Act & Assert
var gridSort = GridSort<TestEntity>.ByAscending(invalidExpression);
var exception = Assert.Throws<ArgumentException>(() => gridSort.ToPropertyList(ascending: true));
Assert.Contains("The supplied expression can't be represented as a property name for sorting", exception.Message);
}

[Fact]
public void ToPropertyName_MethodCallExpression_ThrowsArgumentException()
{
// Arrange
Expression<Func<TestEntity, string>> invalidExpression = x => x.Name.Substring(0, 1);

// Act & Assert
var gridSort = GridSort<TestEntity>.ByAscending(invalidExpression);
var exception = Assert.Throws<ArgumentException>(() => gridSort.ToPropertyList(ascending: true));
Assert.Contains("The supplied expression can't be represented as a property name for sorting", exception.Message);
}

[Fact]
public void ToPropertyName_ConstantExpression_ThrowsArgumentException()
{
// Arrange
Expression<Func<TestEntity, string>> invalidExpression = x => "constant";

// Act & Assert
var gridSort = GridSort<TestEntity>.ByAscending(invalidExpression);
var exception = Assert.Throws<ArgumentException>(() => gridSort.ToPropertyList(ascending: true));
Assert.Contains("The supplied expression can't be represented as a property name for sorting", exception.Message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<RootNamespace>Microsoft.AspNetCore.Components.QuickGrid.Tests</RootNamespace>
</PropertyGroup>

<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Components.QuickGrid" />
</ItemGroup>



<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>

</Project>
Loading