2019-11-27 21:08:51 -05:00
|
|
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
|
using PoweredSoft.Data;
|
2019-03-22 16:27:04 -04:00
|
|
|
|
using PoweredSoft.Data.EntityFrameworkCore;
|
|
|
|
|
using PoweredSoft.DynamicQuery.Core;
|
|
|
|
|
using PoweredSoft.DynamicQuery.Extensions;
|
|
|
|
|
using PoweredSoft.DynamicQuery.Test.Mock;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Xunit;
|
2019-11-27 21:08:51 -05:00
|
|
|
|
using static PoweredSoft.DynamicQuery.Test.GroupInterceptorTests;
|
2018-12-07 00:08:16 -05:00
|
|
|
|
|
2019-03-22 16:27:04 -04:00
|
|
|
|
namespace PoweredSoft.DynamicQuery.Test
|
|
|
|
|
{
|
|
|
|
|
public class AsyncTests
|
|
|
|
|
{
|
|
|
|
|
[Fact]
|
|
|
|
|
public void TestEmptyCriteria()
|
|
|
|
|
{
|
|
|
|
|
MockContextFactory.SeedAndTestContextFor("AsyncTests_TestEmptyCriteria", TestSeeders.SimpleSeedScenario, async ctx =>
|
|
|
|
|
{
|
|
|
|
|
var resultShouldMatch = ctx.Items.ToList();
|
|
|
|
|
var queryable = ctx.Items.AsQueryable();
|
2018-12-07 00:08:16 -05:00
|
|
|
|
|
2019-03-22 16:27:04 -04:00
|
|
|
|
// query handler that is empty should be the same as running to list.
|
|
|
|
|
var aqf = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() });
|
|
|
|
|
var criteria = new QueryCriteria();
|
2019-12-12 18:37:32 -05:00
|
|
|
|
var queryHandler = new QueryHandlerAsync(aqf, Enumerable.Empty<IQueryInterceptorProvider>());
|
2019-03-22 16:27:04 -04:00
|
|
|
|
var result = await queryHandler.ExecuteAsync(queryable, criteria);
|
|
|
|
|
Assert.Equal(resultShouldMatch, result.Data);
|
|
|
|
|
});
|
|
|
|
|
}
|
2018-12-07 00:08:16 -05:00
|
|
|
|
|
2019-03-22 16:27:04 -04:00
|
|
|
|
[Fact]
|
|
|
|
|
public void WithGrouping()
|
|
|
|
|
{
|
|
|
|
|
MockContextFactory.SeedAndTestContextFor("AsyncTests_WithGrouping", TestSeeders.SimpleSeedScenario, async ctx =>
|
|
|
|
|
{
|
|
|
|
|
var shouldResults = ctx.OrderItems
|
|
|
|
|
.GroupBy(t => t.Order.CustomerId)
|
|
|
|
|
.Select(t => new
|
|
|
|
|
{
|
|
|
|
|
GroupValue = t.Key,
|
|
|
|
|
Count = t.Count(),
|
|
|
|
|
ItemQuantityAverage = t.Average(t2 => t2.Quantity),
|
|
|
|
|
ItemQuantitySum = t.Sum(t2 => t2.Quantity),
|
|
|
|
|
AvgOfPrice = t.Average(t2 => t2.PriceAtTheTime)
|
|
|
|
|
})
|
|
|
|
|
.ToList();
|
2018-12-07 00:08:16 -05:00
|
|
|
|
|
2019-03-22 16:27:04 -04:00
|
|
|
|
// query handler that is empty should be the same as running to list.
|
|
|
|
|
var criteria = new QueryCriteria()
|
|
|
|
|
{
|
|
|
|
|
Groups = new List<IGroup>
|
|
|
|
|
{
|
|
|
|
|
new Group { Path = "Order.CustomerId" }
|
|
|
|
|
},
|
|
|
|
|
Aggregates = new List<Core.IAggregate>
|
|
|
|
|
{
|
|
|
|
|
new Aggregate { Type = AggregateType.Count },
|
|
|
|
|
new Aggregate { Type = AggregateType.Avg, Path = "Quantity" },
|
|
|
|
|
new Aggregate { Type = AggregateType.Sum, Path = "Quantity" },
|
|
|
|
|
new Aggregate { Type = AggregateType.Avg, Path = "PriceAtTheTime"}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() });
|
2019-12-12 18:37:32 -05:00
|
|
|
|
var queryHandler = new QueryHandlerAsync(asyncService, Enumerable.Empty<IQueryInterceptorProvider>());
|
2019-11-27 21:08:51 -05:00
|
|
|
|
var result = await queryHandler.ExecuteAsync(ctx.OrderItems.Include(t => t.Order.Customer), criteria, new QueryExecutionOptions
|
|
|
|
|
{
|
|
|
|
|
GroupByInMemory = true
|
|
|
|
|
});
|
|
|
|
|
|
2019-03-22 16:27:04 -04:00
|
|
|
|
var groups = result.GroupedResult().Groups;
|
2018-12-07 00:08:16 -05:00
|
|
|
|
|
2019-03-22 16:27:04 -04:00
|
|
|
|
// validate group and aggregates of groups.
|
|
|
|
|
Assert.Equal(groups.Count, shouldResults.Count);
|
|
|
|
|
Assert.All(groups, g =>
|
|
|
|
|
{
|
|
|
|
|
var index = groups.IndexOf(g);
|
|
|
|
|
var shouldResult = shouldResults[index];
|
2018-12-07 00:08:16 -05:00
|
|
|
|
|
2019-03-22 16:27:04 -04:00
|
|
|
|
// validate the group value.
|
|
|
|
|
Assert.Equal(g.GroupValue, shouldResult.GroupValue);
|
2018-12-07 00:08:16 -05:00
|
|
|
|
|
2019-03-22 16:27:04 -04:00
|
|
|
|
// validate the group aggregates.
|
|
|
|
|
var aggCount = g.Aggregates.First(t => t.Type == AggregateType.Count);
|
|
|
|
|
var aggItemQuantityAverage = g.Aggregates.First(t => t.Type == AggregateType.Avg && t.Path == "Quantity");
|
|
|
|
|
var aggItemQuantitySum = g.Aggregates.First(t => t.Type == AggregateType.Sum && t.Path == "Quantity");
|
|
|
|
|
var aggAvgOfPrice = g.Aggregates.First(t => t.Type == AggregateType.Avg && t.Path == "PriceAtTheTime");
|
|
|
|
|
Assert.Equal(shouldResult.Count, aggCount.Value);
|
|
|
|
|
Assert.Equal(shouldResult.ItemQuantityAverage, aggItemQuantityAverage.Value);
|
|
|
|
|
Assert.Equal(shouldResult.ItemQuantitySum, aggItemQuantitySum.Value);
|
|
|
|
|
Assert.Equal(shouldResult.AvgOfPrice, aggAvgOfPrice.Value);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
2018-12-07 00:08:16 -05:00
|
|
|
|
|
2019-03-22 16:27:04 -04:00
|
|
|
|
[Fact]
|
|
|
|
|
public void SimpleFilter()
|
|
|
|
|
{
|
|
|
|
|
MockContextFactory.SeedAndTestContextFor("AsyncTests_SimpleFilter", TestSeeders.SimpleSeedScenario, async ctx =>
|
|
|
|
|
{
|
|
|
|
|
var resultShouldMatch = ctx.Items.Where(t => t.Name.EndsWith("Cables")).ToList();
|
2018-12-07 00:08:16 -05:00
|
|
|
|
|
2019-03-22 16:27:04 -04:00
|
|
|
|
var criteria = new QueryCriteria()
|
|
|
|
|
{
|
|
|
|
|
Filters = new List<IFilter>
|
|
|
|
|
{
|
|
|
|
|
new SimpleFilter
|
|
|
|
|
{
|
|
|
|
|
Path = "Name",
|
|
|
|
|
Type = FilterType.EndsWith,
|
|
|
|
|
Value = "Cables"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
2018-12-07 00:08:16 -05:00
|
|
|
|
|
2019-03-22 16:27:04 -04:00
|
|
|
|
var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() });
|
2019-12-12 18:37:32 -05:00
|
|
|
|
var queryHandler = new QueryHandlerAsync(asyncService, Enumerable.Empty<IQueryInterceptorProvider>());
|
2019-03-22 16:27:04 -04:00
|
|
|
|
var result = await queryHandler.ExecuteAsync(ctx.Items, criteria);
|
2019-10-13 15:11:57 -04:00
|
|
|
|
Assert.Equal(resultShouldMatch, result.Data);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void SimpleFilterWithNot()
|
|
|
|
|
{
|
|
|
|
|
MockContextFactory.SeedAndTestContextFor("AsyncTests_SimpleFilter2", TestSeeders.SimpleSeedScenario, async ctx =>
|
|
|
|
|
{
|
|
|
|
|
var resultShouldMatch = ctx.Items.Where(t => !t.Name.EndsWith("Cables")).ToList();
|
|
|
|
|
|
|
|
|
|
var criteria = new QueryCriteria()
|
|
|
|
|
{
|
|
|
|
|
Filters = new List<IFilter>
|
|
|
|
|
{
|
|
|
|
|
new SimpleFilter
|
|
|
|
|
{
|
|
|
|
|
Path = "Name",
|
|
|
|
|
Type = FilterType.EndsWith,
|
|
|
|
|
Value = "Cables",
|
|
|
|
|
Not = true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() });
|
2019-12-12 18:37:32 -05:00
|
|
|
|
var queryHandler = new QueryHandlerAsync(asyncService, Enumerable.Empty<IQueryInterceptorProvider>());
|
2019-10-13 15:11:57 -04:00
|
|
|
|
var result = await queryHandler.ExecuteAsync(ctx.Items, criteria);
|
2019-03-22 16:27:04 -04:00
|
|
|
|
Assert.Equal(resultShouldMatch, result.Data);
|
|
|
|
|
});
|
|
|
|
|
}
|
2018-12-07 00:08:16 -05:00
|
|
|
|
|
2019-03-22 16:27:04 -04:00
|
|
|
|
[Fact]
|
|
|
|
|
public void TestPaging()
|
|
|
|
|
{
|
|
|
|
|
MockContextFactory.SeedAndTestContextFor("AsyncTests_TestPagging", TestSeeders.SimpleSeedScenario, async ctx =>
|
|
|
|
|
{
|
|
|
|
|
var resultShouldMatch = ctx.OrderItems.OrderBy(t => t.Id).Skip(5).Take(5).ToList();
|
2018-12-07 00:08:16 -05:00
|
|
|
|
|
2019-03-22 16:27:04 -04:00
|
|
|
|
// query handler that is empty should be the same as running to list.
|
|
|
|
|
var criteria = new QueryCriteria();
|
|
|
|
|
criteria.Sorts.Add(new Sort("Id"));
|
|
|
|
|
criteria.Page = 2;
|
|
|
|
|
criteria.PageSize = 5;
|
2018-12-07 00:08:16 -05:00
|
|
|
|
|
2019-03-22 16:27:04 -04:00
|
|
|
|
var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() });
|
2019-12-12 18:37:32 -05:00
|
|
|
|
var queryHandler = new QueryHandlerAsync(asyncService, Enumerable.Empty<IQueryInterceptorProvider>());
|
2019-03-22 16:27:04 -04:00
|
|
|
|
var result = await queryHandler.ExecuteAsync(ctx.OrderItems, criteria);
|
|
|
|
|
Assert.Equal(resultShouldMatch, result.Data);
|
|
|
|
|
});
|
|
|
|
|
}
|
2019-11-27 21:08:51 -05:00
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void WithGroupingInterceptorOptions()
|
|
|
|
|
{
|
|
|
|
|
MockContextFactory.SeedAndTestContextFor("AsyncTests_WithGroupingInterceptorOptions", TestSeeders.SimpleSeedScenario, async ctx =>
|
|
|
|
|
{
|
|
|
|
|
var shouldResults = ctx.OrderItems
|
|
|
|
|
.GroupBy(t => t.Order.CustomerId)
|
|
|
|
|
.Select(t => new
|
|
|
|
|
{
|
|
|
|
|
GroupValue = t.Key,
|
|
|
|
|
Count = t.Count(),
|
|
|
|
|
ItemQuantityAverage = t.Average(t2 => t2.Quantity),
|
|
|
|
|
ItemQuantitySum = t.Sum(t2 => t2.Quantity),
|
|
|
|
|
AvgOfPrice = t.Average(t2 => t2.PriceAtTheTime)
|
|
|
|
|
})
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
// query handler that is empty should be the same as running to list.
|
|
|
|
|
var criteria = new QueryCriteria()
|
|
|
|
|
{
|
|
|
|
|
Groups = new List<IGroup>
|
|
|
|
|
{
|
|
|
|
|
new Group { Path = "Order.CustomerId" }
|
|
|
|
|
},
|
|
|
|
|
Aggregates = new List<Core.IAggregate>
|
|
|
|
|
{
|
|
|
|
|
new Aggregate { Type = AggregateType.Count },
|
|
|
|
|
new Aggregate { Type = AggregateType.Avg, Path = "Quantity" },
|
|
|
|
|
new Aggregate { Type = AggregateType.Sum, Path = "Quantity" },
|
|
|
|
|
new Aggregate { Type = AggregateType.Avg, Path = "PriceAtTheTime"}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() });
|
2019-12-12 18:37:32 -05:00
|
|
|
|
var queryHandler = new QueryHandlerAsync(asyncService, Enumerable.Empty<IQueryInterceptorProvider>());
|
2019-11-27 21:08:51 -05:00
|
|
|
|
queryHandler.AddInterceptor(new MockQueryExecutionOptionsInterceptor());
|
|
|
|
|
var result = await queryHandler.ExecuteAsync(ctx.OrderItems.Include(t => t.Order.Customer), criteria);
|
|
|
|
|
|
|
|
|
|
var groups = result.GroupedResult().Groups;
|
|
|
|
|
|
|
|
|
|
// validate group and aggregates of groups.
|
|
|
|
|
Assert.Equal(groups.Count, shouldResults.Count);
|
|
|
|
|
Assert.All(groups, g =>
|
|
|
|
|
{
|
|
|
|
|
var index = groups.IndexOf(g);
|
|
|
|
|
var shouldResult = shouldResults[index];
|
|
|
|
|
|
|
|
|
|
// validate the group value.
|
|
|
|
|
Assert.Equal(g.GroupValue, shouldResult.GroupValue);
|
|
|
|
|
|
|
|
|
|
// validate the group aggregates.
|
|
|
|
|
var aggCount = g.Aggregates.First(t => t.Type == AggregateType.Count);
|
|
|
|
|
var aggItemQuantityAverage = g.Aggregates.First(t => t.Type == AggregateType.Avg && t.Path == "Quantity");
|
|
|
|
|
var aggItemQuantitySum = g.Aggregates.First(t => t.Type == AggregateType.Sum && t.Path == "Quantity");
|
|
|
|
|
var aggAvgOfPrice = g.Aggregates.First(t => t.Type == AggregateType.Avg && t.Path == "PriceAtTheTime");
|
|
|
|
|
Assert.Equal(shouldResult.Count, aggCount.Value);
|
|
|
|
|
Assert.Equal(shouldResult.ItemQuantityAverage, aggItemQuantityAverage.Value);
|
|
|
|
|
Assert.Equal(shouldResult.ItemQuantitySum, aggItemQuantitySum.Value);
|
|
|
|
|
Assert.Equal(shouldResult.AvgOfPrice, aggAvgOfPrice.Value);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
2019-03-22 16:27:04 -04:00
|
|
|
|
}
|
2018-12-07 00:08:16 -05:00
|
|
|
|
|
2019-03-22 16:27:04 -04:00
|
|
|
|
}
|