Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
public 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();
}

public 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>
<GlobalUsings Include="Xunit" />
</ItemGroup>

</Project>
Loading