From c457f6e5dd60a059ec003ca07127e8e935410b06 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli Date: Tue, 28 Aug 2018 14:11:06 -0400 Subject: [PATCH 1/2] failing test + document how to get started --- README.md | 38 +++++++++++++++++++ .../Models/TodoItem.cs | 6 +++ .../Acceptance/TodoItemsControllerTests.cs | 23 +++++++++++ 3 files changed, 67 insertions(+) diff --git a/README.md b/README.md index 81ebba79bf..f614dc4dbc 100644 --- a/README.md +++ b/README.md @@ -75,3 +75,41 @@ public class Startup } } ``` + +### Development + +Restore all nuget packages with: + +```bash +dotnet restore +``` + +#### Testing + +Running tests locally requires access to a postgresql database. +If you have docker installed, this can be propped up via: + +```bash +docker run --rm --name jsonapi-dotnet-core-testing \ + -e POSTGRES_DB=JsonApiDotNetCoreExample \ + -e POSTGRES_USER=postgres \ + -e POSTGRES_PASSWORD=postgres \ + -p 5432:5432 \ + postgres +``` + +And then to run the tests: + +```bash +dotnet test +``` + +#### Cleaning + +Sometimes the compiled files can be dirty / corrupt from other branches / failed builds. +If your bash prompt supports the globstar, you can recursively delete the `bin` and `obj` directories: + +```bash +shopt -s globstar +rm -rf **/bin && rm -rf **/obj +``` \ No newline at end of file diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/TodoItem.cs b/src/Examples/JsonApiDotNetCoreExample/Models/TodoItem.cs index fecd16319d..7ae957f4a5 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/TodoItem.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Models/TodoItem.cs @@ -24,6 +24,12 @@ public TodoItem() [Attr("achieved-date", isFilterable: false, isSortable: false)] public DateTime? AchievedDate { get; set; } + + + [Attr("updated-date")] + public DateTime? UpdatedDate { get; set; } + + public int? OwnerId { get; set; } public int? AssigneeId { get; set; } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs index 0600fb402b..3350fd1340 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs @@ -90,6 +90,29 @@ public async Task Can_Filter_TodoItems() Assert.Equal(todoItem.Ordinal, todoItemResult.Ordinal); } + [Fact] + public async Task Can_Filter_TodoItems_Using_NotEqual_Operator() + { + // Arrange + var todoItem = _todoItemFaker.Generate(); + todoItem.UpdatedDate = null; + _context.TodoItems.Add(todoItem); + _context.SaveChanges(); + + var httpMethod = new HttpMethod("GET"); + var route = $"/api/v1/todo-items?filter[updated-date]=ne:null"; + var request = new HttpRequestMessage(httpMethod, route); + + // Act + var response = await _fixture.Client.SendAsync(request); + var body = await response.Content.ReadAsStringAsync(); + var deserializedBody = _fixture.GetService().DeserializeList(body); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Empty(deserializedBody); + } + [Fact] public async Task Can_Filter_TodoItems_Using_Like_Operator() { From a3d9e6c0c6fb5707df5703e0ce7faf38068263d6 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli Date: Tue, 28 Aug 2018 15:17:28 -0400 Subject: [PATCH 2/2] fixed it --- .../Extensions/IQueryableExtensions.cs | 12 ++++++++++-- .../Acceptance/TodoItemsControllerTests.cs | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs index 03f74b9e59..20e6902ee9 100644 --- a/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs +++ b/src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs @@ -127,9 +127,14 @@ public static IQueryable Filter(this IQueryable sourc return source.Where(lambdaIn); } else - { // convert the incoming value to the target value type + { + var isNullabe = IsNullable(property.PropertyType); + var propertyValue = filterQuery.PropertyValue; + var value = isNullabe && propertyValue == "" ? null : propertyValue; + + // convert the incoming value to the target value type // "1" -> 1 - var convertedValue = TypeHelper.ConvertType(filterQuery.PropertyValue, property.PropertyType); + var convertedValue = TypeHelper.ConvertType(value, property.PropertyType); // {model} var parameter = Expression.Parameter(concreteType, "model"); // {model.Id} @@ -204,6 +209,9 @@ public static IQueryable Filter(this IQueryable sourc } } + private static bool IsNullable(Type type) => type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); + + private static Expression GetFilterExpressionLambda(Expression left, Expression right, FilterOperations operation) { Expression body; diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs index 3350fd1340..6044463764 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs @@ -100,7 +100,7 @@ public async Task Can_Filter_TodoItems_Using_NotEqual_Operator() _context.SaveChanges(); var httpMethod = new HttpMethod("GET"); - var route = $"/api/v1/todo-items?filter[updated-date]=ne:null"; + var route = $"/api/v1/todo-items?filter[updated-date]=ne:"; var request = new HttpRequestMessage(httpMethod, route); // Act