From 8193693a46a370af74f920a9bde7c145c8f78a33 Mon Sep 17 00:00:00 2001 From: CodeTile <43536260+CodeTile@users.noreply.github.com> Date: Thu, 27 Feb 2025 14:44:28 +0000 Subject: [PATCH 01/12] Inital API produced --- .../Controllers/ReportsController.cs | 27 + .../ProductCategoryServiceAddTests.feature.cs | 194 +++---- ...oductCategoryServiceDeleteTests.feature.cs | 70 +-- ...ProductCategoryServiceFindTests.feature.cs | 476 +++++++++--------- ...oductCategoryServiceUpdateTests.feature.cs | 184 +++---- .../Models/Reports/SalesSummaryByYear.cs | 9 + .../Repository/ReportingRepository.cs | 27 + .../Services/ReportService.cs | 15 + .../StartUp/IOCData.cs | 3 + 9 files changed, 543 insertions(+), 462 deletions(-) create mode 100644 src/API/AdventureWorksDemo.API/Controllers/ReportsController.cs create mode 100644 src/API/AdventureWorksDemo.Data/Models/Reports/SalesSummaryByYear.cs create mode 100644 src/API/AdventureWorksDemo.Data/Repository/ReportingRepository.cs create mode 100644 src/API/AdventureWorksDemo.Data/Services/ReportService.cs diff --git a/src/API/AdventureWorksDemo.API/Controllers/ReportsController.cs b/src/API/AdventureWorksDemo.API/Controllers/ReportsController.cs new file mode 100644 index 0000000..3977330 --- /dev/null +++ b/src/API/AdventureWorksDemo.API/Controllers/ReportsController.cs @@ -0,0 +1,27 @@ +using AdventureWorksDemo.Data.Entities; +using AdventureWorksDemo.Data.Services; + +using Microsoft.AspNetCore.Mvc; + +namespace AdventureWorksDemo.API.Controllers +{ + [ApiController] + [Route("api/[controller]")] + public class ReportsController(ILogger logger, IReportService service) : Controller + { + internal readonly ILogger _logger = logger; + internal readonly IReportService _service = service; + + [ProducesResponseType(StatusCodes.Status200OK)] + public virtual async Task ReportOnlineVsOffLine() + { + return Ok(await Task.Run(() => _service.ReportOnlineVsOffLine())); + } + + internal void WriteToTraceLog(string namespaceName, string methodName, string parmeterNames = "") + { + string Message = $"{namespaceName}.{methodName}({parmeterNames})"; + _logger.LogTrace("{Message}", Message); + } + } +} \ No newline at end of file diff --git a/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ProductCategoryService/ProductCategoryServiceAddTests.feature.cs b/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ProductCategoryService/ProductCategoryServiceAddTests.feature.cs index 8476ddc..3a29133 100644 --- a/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ProductCategoryService/ProductCategoryServiceAddTests.feature.cs +++ b/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ProductCategoryService/ProductCategoryServiceAddTests.feature.cs @@ -128,76 +128,76 @@ public async System.Threading.Tasks.Task AddAsyncShortName() #line 8 await this.FeatureBackgroundAsync(); #line hidden - global::Reqnroll.Table table397 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table389 = new global::Reqnroll.Table(new string[] { "Name", "Rowguid"}); - table397.AddRow(new string[] { + table389.AddRow(new string[] { "Hi", "00000000-1111-0000-0000-000000000002"}); #line 13 - await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Models.ProductCategoryModel\'", ((string)(null)), table397, "When "); + await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Models.ProductCategoryModel\'", ((string)(null)), table389, "When "); #line hidden - global::Reqnroll.Table table398 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table390 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table398.AddRow(new string[] { + table390.AddRow(new string[] { "model", "{{model}}", "AdventureWorksDemo.Data.Models.ProductCategoryModel"}); #line 16 - await testRunner.AndAsync("I call the method \'AddAsync\' with the parameter values", ((string)(null)), table398, "And "); + await testRunner.AndAsync("I call the method \'AddAsync\' with the parameter values", ((string)(null)), table390, "And "); #line hidden - global::Reqnroll.Table table399 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table391 = new global::Reqnroll.Table(new string[] { "Expected"}); - table399.AddRow(new string[] { + table391.AddRow(new string[] { "AdventureWorksDemo.Data.Models.ServiceResult"}); #line 19 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table399, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table391, "Then "); #line hidden - global::Reqnroll.Table table400 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table392 = new global::Reqnroll.Table(new string[] { "IsFailure", "IsSuccess", "Message"}); - table400.AddRow(new string[] { + table392.AddRow(new string[] { "True", "False", "\'Name\' must be between 3 and 50 characters. You entered 2 characters."}); #line 22 - await testRunner.AndAsync("the result is", ((string)(null)), table400, "And "); + await testRunner.AndAsync("the result is", ((string)(null)), table392, "And "); #line hidden - global::Reqnroll.Table table401 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table393 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "Name", "ModifiedDate", "Rowguid"}); - table401.AddRow(new string[] { + table393.AddRow(new string[] { "0", "Hi", "1/1/0001 12:00:00 AM", "00000000-1111-0000-0000-000000000002"}); #line 26 - await testRunner.AndAsync("the results property \'Value\' contains", ((string)(null)), table401, "And "); + await testRunner.AndAsync("the results property \'Value\' contains", ((string)(null)), table393, "And "); #line hidden - global::Reqnroll.Table table402 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table394 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "Name", "ModifiedDate", "Rowguid"}); - table402.AddRow(new string[] { + table394.AddRow(new string[] { "6", "Road Bikes", "6/1/2002 12:00:00 AM", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table402.AddRow(new string[] { + table394.AddRow(new string[] { "7", "For Delete Tests Only", "6/1/2002 12:00:00 AM", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 30 await testRunner.AndAsync("the table \'Production.ProductCategory\' filtered by \'ProductCategoryId > 5\' contai" + - "ns", ((string)(null)), table402, "And "); + "ns", ((string)(null)), table394, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -227,81 +227,81 @@ public async System.Threading.Tasks.Task AddAsync() #line 36 await testRunner.GivenAsync("I reset the database after the scenario", ((string)(null)), ((global::Reqnroll.Table)(null)), "Given "); #line hidden - global::Reqnroll.Table table403 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table395 = new global::Reqnroll.Table(new string[] { "Name", "Rowguid"}); - table403.AddRow(new string[] { + table395.AddRow(new string[] { "PingPong", "00000000-1111-0000-0000-000000000002"}); #line 37 - await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Models.ProductCategoryModel\'", ((string)(null)), table403, "When "); + await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Models.ProductCategoryModel\'", ((string)(null)), table395, "When "); #line hidden - global::Reqnroll.Table table404 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table396 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table404.AddRow(new string[] { + table396.AddRow(new string[] { "model", "{{model}}", "AdventureWorksDemo.Data.Models.ProductCategoryModel"}); #line 40 - await testRunner.AndAsync("I call the method \'AddAsync\' with the parameter values", ((string)(null)), table404, "And "); + await testRunner.AndAsync("I call the method \'AddAsync\' with the parameter values", ((string)(null)), table396, "And "); #line hidden - global::Reqnroll.Table table405 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table397 = new global::Reqnroll.Table(new string[] { "Expected"}); - table405.AddRow(new string[] { + table397.AddRow(new string[] { "AdventureWorksDemo.Data.Models.ServiceResult"}); #line 43 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table405, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table397, "Then "); #line hidden - global::Reqnroll.Table table406 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table398 = new global::Reqnroll.Table(new string[] { "IsFailure", "IsSuccess", "Message"}); - table406.AddRow(new string[] { + table398.AddRow(new string[] { "False", "True", ""}); #line 46 - await testRunner.AndAsync("the result is", ((string)(null)), table406, "And "); + await testRunner.AndAsync("the result is", ((string)(null)), table398, "And "); #line hidden - global::Reqnroll.Table table407 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table399 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "Name", "ModifiedDate", "Rowguid"}); - table407.AddRow(new string[] { + table399.AddRow(new string[] { "5001", "PingPong", "5/24/2024 12:34:56 PM", "00000000-1111-0000-0000-000000000002"}); #line 49 - await testRunner.AndAsync("the results property \'Value\' contains", ((string)(null)), table407, "And "); + await testRunner.AndAsync("the results property \'Value\' contains", ((string)(null)), table399, "And "); #line hidden - global::Reqnroll.Table table408 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table400 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "Name", "ModifiedDate", "Rowguid"}); - table408.AddRow(new string[] { + table400.AddRow(new string[] { "6", "Road Bikes", "6/1/2002 12:00:00 AM", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table408.AddRow(new string[] { + table400.AddRow(new string[] { "7", "For Delete Tests Only", "6/1/2002 12:00:00 AM", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); - table408.AddRow(new string[] { + table400.AddRow(new string[] { "5001", "PingPong", "5/24/2024 12:34:56 PM", "00000000-1111-0000-0000-000000000002"}); #line 52 await testRunner.AndAsync("the table \'Production.ProductCategory\' filtered by \'ProductCategoryId > 5\' contai" + - "ns", ((string)(null)), table408, "And "); + "ns", ((string)(null)), table400, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -331,122 +331,122 @@ public async System.Threading.Tasks.Task AddBatchAsync() #line 59 await testRunner.GivenAsync("I reset the database after the scenario", ((string)(null)), ((global::Reqnroll.Table)(null)), "Given "); #line hidden - global::Reqnroll.Table table409 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table401 = new global::Reqnroll.Table(new string[] { "Name", "Rowguid"}); - table409.AddRow(new string[] { + table401.AddRow(new string[] { "How", "00000000-1111-1111-0000-000000000001"}); - table409.AddRow(new string[] { + table401.AddRow(new string[] { "Now", "00000000-1111-1111-0000-000000000002"}); - table409.AddRow(new string[] { + table401.AddRow(new string[] { "Brown", "00000000-1111-1111-0000-000000000003"}); - table409.AddRow(new string[] { + table401.AddRow(new string[] { "Cow", "00000000-1111-1111-0000-000000000004"}); #line 60 await testRunner.WhenAsync("I populate a list of the model \'AdventureWorksDemo.Data.Models.ProductCategoryMod" + - "el\'", ((string)(null)), table409, "When "); + "el\'", ((string)(null)), table401, "When "); #line hidden - global::Reqnroll.Table table410 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table402 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table410.AddRow(new string[] { + table402.AddRow(new string[] { "model", "{{ListOfObjects}}", "System.Collections.Generic.IEnumerable"}); #line 66 - await testRunner.AndAsync("I call the method \'AddBatchAsync\' with the parameter values", ((string)(null)), table410, "And "); + await testRunner.AndAsync("I call the method \'AddBatchAsync\' with the parameter values", ((string)(null)), table402, "And "); #line hidden - global::Reqnroll.Table table411 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table403 = new global::Reqnroll.Table(new string[] { "Expected"}); - table411.AddRow(new string[] { + table403.AddRow(new string[] { "AdventureWorksDemo.Data.Models.ServiceResult"}); #line 69 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table411, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table403, "Then "); #line hidden - global::Reqnroll.Table table412 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table404 = new global::Reqnroll.Table(new string[] { "IsFailure", "IsSuccess", "Message"}); - table412.AddRow(new string[] { + table404.AddRow(new string[] { "false", "true", ""}); #line 72 - await testRunner.AndAsync("the result is", ((string)(null)), table412, "And "); + await testRunner.AndAsync("the result is", ((string)(null)), table404, "And "); #line hidden - global::Reqnroll.Table table413 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table405 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "Name", "ModifiedDate", "Rowguid"}); - table413.AddRow(new string[] { + table405.AddRow(new string[] { "5001", "How", "5/24/2024 12:34:56 PM", "00000000-1111-1111-0000-000000000001"}); - table413.AddRow(new string[] { + table405.AddRow(new string[] { "5002", "Now", "5/24/2024 12:34:56 PM", "00000000-1111-1111-0000-000000000002"}); - table413.AddRow(new string[] { + table405.AddRow(new string[] { "5003", "Brown", "5/24/2024 12:34:56 PM", "00000000-1111-1111-0000-000000000003"}); - table413.AddRow(new string[] { + table405.AddRow(new string[] { "5004", "Cow", "5/24/2024 12:34:56 PM", "00000000-1111-1111-0000-000000000004"}); #line 76 - await testRunner.AndAsync("the results property \'Value\' contains", ((string)(null)), table413, "And "); + await testRunner.AndAsync("the results property \'Value\' contains", ((string)(null)), table405, "And "); #line hidden - global::Reqnroll.Table table414 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table406 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "Name", "ModifiedDate", "Rowguid"}); - table414.AddRow(new string[] { + table406.AddRow(new string[] { "6", "Road Bikes", "6/1/2002 12:00:00 AM", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table414.AddRow(new string[] { + table406.AddRow(new string[] { "7", "For Delete Tests Only", "6/1/2002 12:00:00 AM", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); - table414.AddRow(new string[] { + table406.AddRow(new string[] { "5001", "How", "5/24/2024 12:34:56 PM", "00000000-1111-1111-0000-000000000001"}); - table414.AddRow(new string[] { + table406.AddRow(new string[] { "5002", "Now", "5/24/2024 12:34:56 PM", "00000000-1111-1111-0000-000000000002"}); - table414.AddRow(new string[] { + table406.AddRow(new string[] { "5003", "Brown", "5/24/2024 12:34:56 PM", "00000000-1111-1111-0000-000000000003"}); - table414.AddRow(new string[] { + table406.AddRow(new string[] { "5004", "Cow", "5/24/2024 12:34:56 PM", "00000000-1111-1111-0000-000000000004"}); #line 83 await testRunner.AndAsync("the table \'Production.ProductCategory\' filtered by \'ProductCategoryId > 5\' contai" + - "ns", ((string)(null)), table414, "And "); + "ns", ((string)(null)), table406, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -473,109 +473,109 @@ public async System.Threading.Tasks.Task AddBatchAsync2ShortName() #line 8 await this.FeatureBackgroundAsync(); #line hidden - global::Reqnroll.Table table415 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table407 = new global::Reqnroll.Table(new string[] { "Name", "Rowguid"}); - table415.AddRow(new string[] { + table407.AddRow(new string[] { "Hi", "00000000-1111-1111-0000-000000000001"}); - table415.AddRow(new string[] { + table407.AddRow(new string[] { "Now", "00000000-1111-1111-0000-000000000002"}); - table415.AddRow(new string[] { + table407.AddRow(new string[] { "Brown", "00000000-1111-1111-0000-000000000003"}); - table415.AddRow(new string[] { + table407.AddRow(new string[] { "It", "00000000-1111-1111-0000-000000000004"}); #line 93 await testRunner.WhenAsync("I populate a list of the model \'AdventureWorksDemo.Data.Models.ProductCategoryMod" + - "el\'", ((string)(null)), table415, "When "); + "el\'", ((string)(null)), table407, "When "); #line hidden - global::Reqnroll.Table table416 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table408 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table416.AddRow(new string[] { + table408.AddRow(new string[] { "model", "{{ListOfObjects}}", "System.Collections.Generic.IEnumerable"}); #line 99 - await testRunner.AndAsync("I call the method \'AddBatchAsync\' with the parameter values", ((string)(null)), table416, "And "); + await testRunner.AndAsync("I call the method \'AddBatchAsync\' with the parameter values", ((string)(null)), table408, "And "); #line hidden - global::Reqnroll.Table table417 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table409 = new global::Reqnroll.Table(new string[] { "Expected"}); - table417.AddRow(new string[] { + table409.AddRow(new string[] { "AdventureWorksDemo.Data.Models.ServiceResult"}); #line 102 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table417, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table409, "Then "); #line hidden - global::Reqnroll.Table table418 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table410 = new global::Reqnroll.Table(new string[] { "IsFailure", "IsSuccess"}); - table418.AddRow(new string[] { + table410.AddRow(new string[] { "True", "False"}); #line 105 - await testRunner.AndAsync("the result is", ((string)(null)), table418, "And "); + await testRunner.AndAsync("the result is", ((string)(null)), table410, "And "); #line hidden - global::Reqnroll.Table table419 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table411 = new global::Reqnroll.Table(new string[] { "Expected"}); - table419.AddRow(new string[] { + table411.AddRow(new string[] { "\'Name\' must be between 3 and 50 characters. You entered 2 characters."}); - table419.AddRow(new string[] { + table411.AddRow(new string[] { "\'Name\' must be between 3 and 50 characters. You entered 2 characters."}); #line 108 - await testRunner.AndAsync("the results property \'Message\' contains", ((string)(null)), table419, "And "); + await testRunner.AndAsync("the results property \'Message\' contains", ((string)(null)), table411, "And "); #line hidden - global::Reqnroll.Table table420 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table412 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "Name", "ModifiedDate", "Rowguid"}); - table420.AddRow(new string[] { + table412.AddRow(new string[] { "0", "Hi", "1/1/0001 12:00:00 AM", "00000000-1111-1111-0000-000000000001"}); - table420.AddRow(new string[] { + table412.AddRow(new string[] { "0", "Now", "1/1/0001 12:00:00 AM", "00000000-1111-1111-0000-000000000002"}); - table420.AddRow(new string[] { + table412.AddRow(new string[] { "0", "Brown", "1/1/0001 12:00:00 AM", "00000000-1111-1111-0000-000000000003"}); - table420.AddRow(new string[] { + table412.AddRow(new string[] { "0", "It", "1/1/0001 12:00:00 AM", "00000000-1111-1111-0000-000000000004"}); #line 112 - await testRunner.AndAsync("the results property \'Value\' contains", ((string)(null)), table420, "And "); + await testRunner.AndAsync("the results property \'Value\' contains", ((string)(null)), table412, "And "); #line hidden - global::Reqnroll.Table table421 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table413 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "Name", "ModifiedDate", "Rowguid"}); - table421.AddRow(new string[] { + table413.AddRow(new string[] { "6", "Road Bikes", "6/1/2002 12:00:00 AM", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table421.AddRow(new string[] { + table413.AddRow(new string[] { "7", "For Delete Tests Only", "6/1/2002 12:00:00 AM", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 119 await testRunner.AndAsync("the table \'Production.ProductCategory\' filtered by \'ProductCategoryId > 5\' contai" + - "ns", ((string)(null)), table421, "And "); + "ns", ((string)(null)), table413, "And "); #line hidden } await this.ScenarioCleanupAsync(); diff --git a/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ProductCategoryService/ProductCategoryServiceDeleteTests.feature.cs b/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ProductCategoryService/ProductCategoryServiceDeleteTests.feature.cs index 7d9be85..e1c1eee 100644 --- a/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ProductCategoryService/ProductCategoryServiceDeleteTests.feature.cs +++ b/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ProductCategoryService/ProductCategoryServiceDeleteTests.feature.cs @@ -128,79 +128,79 @@ public async System.Threading.Tasks.Task DeleteAsync1234() #line 7 await this.FeatureBackgroundAsync(); #line hidden - global::Reqnroll.Table table422 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table414 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName", "ModifiedDate"}); - table422.AddRow(new string[] { + table414.AddRow(new string[] { "productCategoryId", "1234", "int", "21 Apr 2024 12:34:56"}); #line 13 - await testRunner.WhenAsync("I call the method \'DeleteAsync\' with the parameter values", ((string)(null)), table422, "When "); + await testRunner.WhenAsync("I call the method \'DeleteAsync\' with the parameter values", ((string)(null)), table414, "When "); #line hidden - global::Reqnroll.Table table423 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table415 = new global::Reqnroll.Table(new string[] { "Expected"}); - table423.AddRow(new string[] { + table415.AddRow(new string[] { "AdventureWorksDemo.Data.Models.ServiceResult"}); #line 16 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table423, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table415, "Then "); #line hidden - global::Reqnroll.Table table424 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table416 = new global::Reqnroll.Table(new string[] { "IsFailure", "IsSuccess", "Message"}); - table424.AddRow(new string[] { + table416.AddRow(new string[] { "True", "False", "Unable to find record to delete!"}); #line 19 - await testRunner.AndAsync("the result is", ((string)(null)), table424, "And "); + await testRunner.AndAsync("the result is", ((string)(null)), table416, "And "); #line hidden - global::Reqnroll.Table table425 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table417 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "Name", "ModifiedDate", "Rowguid"}); - table425.AddRow(new string[] { + table417.AddRow(new string[] { "1", "Bikes", "6/1/2002 12:00:00 AM", "cfbda25c-df71-47a7-b81b-64ee161aa37c"}); - table425.AddRow(new string[] { + table417.AddRow(new string[] { "2", "Components", "6/1/2002 12:00:00 AM", "c657828d-d808-4aba-91a3-af2ce02300e9"}); - table425.AddRow(new string[] { + table417.AddRow(new string[] { "3", "Clothing", "6/1/2002 12:00:00 AM", "10a7c342-ca82-48d4-8a38-46a2eb089b74"}); - table425.AddRow(new string[] { + table417.AddRow(new string[] { "4", "Accessories", "6/1/2002 12:00:00 AM", "2be3be36-d9a2-4eee-b593-ed895d97c2a6"}); - table425.AddRow(new string[] { + table417.AddRow(new string[] { "5", "Mountain Bikes", "6/1/2002 12:00:00 AM", "2d364ade-264a-433c-b092-4fcbf3804e01"}); - table425.AddRow(new string[] { + table417.AddRow(new string[] { "6", "Road Bikes", "6/1/2002 12:00:00 AM", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table425.AddRow(new string[] { + table417.AddRow(new string[] { "7", "For Delete Tests Only", "6/1/2002 12:00:00 AM", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 23 - await testRunner.AndAsync("the table \'Production.ProductCategory\' contains", ((string)(null)), table425, "And "); + await testRunner.AndAsync("the table \'Production.ProductCategory\' contains", ((string)(null)), table417, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -230,72 +230,72 @@ public async System.Threading.Tasks.Task DeleteAsync7() #line 34 await testRunner.GivenAsync("I reset the database after the scenario", ((string)(null)), ((global::Reqnroll.Table)(null)), "Given "); #line hidden - global::Reqnroll.Table table426 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table418 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table426.AddRow(new string[] { + table418.AddRow(new string[] { "productCategoryId", "7", "int"}); #line 35 - await testRunner.WhenAsync("I call the method \'DeleteAsync\' with the parameter values", ((string)(null)), table426, "When "); + await testRunner.WhenAsync("I call the method \'DeleteAsync\' with the parameter values", ((string)(null)), table418, "When "); #line hidden - global::Reqnroll.Table table427 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table419 = new global::Reqnroll.Table(new string[] { "Expected"}); - table427.AddRow(new string[] { + table419.AddRow(new string[] { "AdventureWorksDemo.Data.Models.ServiceResult"}); #line 38 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table427, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table419, "Then "); #line hidden - global::Reqnroll.Table table428 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table420 = new global::Reqnroll.Table(new string[] { "IsFailure", "IsSuccess", "Message"}); - table428.AddRow(new string[] { + table420.AddRow(new string[] { "False", "True", ""}); #line 41 - await testRunner.AndAsync("the result is", ((string)(null)), table428, "And "); + await testRunner.AndAsync("the result is", ((string)(null)), table420, "And "); #line hidden - global::Reqnroll.Table table429 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table421 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "Name", "ModifiedDate", "Rowguid"}); - table429.AddRow(new string[] { + table421.AddRow(new string[] { "1", "Bikes", "6/1/2002 12:00:00 AM", "cfbda25c-df71-47a7-b81b-64ee161aa37c"}); - table429.AddRow(new string[] { + table421.AddRow(new string[] { "2", "Components", "6/1/2002 12:00:00 AM", "c657828d-d808-4aba-91a3-af2ce02300e9"}); - table429.AddRow(new string[] { + table421.AddRow(new string[] { "3", "Clothing", "6/1/2002 12:00:00 AM", "10a7c342-ca82-48d4-8a38-46a2eb089b74"}); - table429.AddRow(new string[] { + table421.AddRow(new string[] { "4", "Accessories", "6/1/2002 12:00:00 AM", "2be3be36-d9a2-4eee-b593-ed895d97c2a6"}); - table429.AddRow(new string[] { + table421.AddRow(new string[] { "5", "Mountain Bikes", "6/1/2002 12:00:00 AM", "2d364ade-264a-433c-b092-4fcbf3804e01"}); - table429.AddRow(new string[] { + table421.AddRow(new string[] { "6", "Road Bikes", "6/1/2002 12:00:00 AM", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); #line 44 - await testRunner.ThenAsync("the table \'Production.ProductCategory\' contains", ((string)(null)), table429, "Then "); + await testRunner.ThenAsync("the table \'Production.ProductCategory\' contains", ((string)(null)), table421, "Then "); #line hidden } await this.ScenarioCleanupAsync(); diff --git a/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ProductCategoryService/ProductCategoryServiceFindTests.feature.cs b/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ProductCategoryService/ProductCategoryServiceFindTests.feature.cs index 1a5b272..5be61e7 100644 --- a/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ProductCategoryService/ProductCategoryServiceFindTests.feature.cs +++ b/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ProductCategoryService/ProductCategoryServiceFindTests.feature.cs @@ -126,36 +126,36 @@ public async System.Threading.Tasks.Task FindAsync01() #line 7 await this.FeatureBackgroundAsync(); #line hidden - global::Reqnroll.Table table430 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table422 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table430.AddRow(new string[] { + table422.AddRow(new string[] { "productCategoryId", "1", "int"}); #line 11 - await testRunner.WhenAsync("I call the method \'FindAsync\' with the parameter values", ((string)(null)), table430, "When "); + await testRunner.WhenAsync("I call the method \'FindAsync\' with the parameter values", ((string)(null)), table422, "When "); #line hidden - global::Reqnroll.Table table431 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table423 = new global::Reqnroll.Table(new string[] { "Expected"}); - table431.AddRow(new string[] { + table423.AddRow(new string[] { "AdventureWorksDemo.Data.Models.ProductCategoryModel"}); #line 14 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table431, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table423, "Then "); #line hidden - global::Reqnroll.Table table432 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table424 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table432.AddRow(new string[] { + table424.AddRow(new string[] { "1", "6/1/2002 12:00:00 AM", "Bikes", "cfbda25c-df71-47a7-b81b-64ee161aa37c"}); #line 17 - await testRunner.AndAsync("the result is", ((string)(null)), table432, "And "); + await testRunner.AndAsync("the result is", ((string)(null)), table424, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -182,36 +182,36 @@ public async System.Threading.Tasks.Task FindAsync04() #line 7 await this.FeatureBackgroundAsync(); #line hidden - global::Reqnroll.Table table433 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table425 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table433.AddRow(new string[] { + table425.AddRow(new string[] { "productCategoryId", "4", "int"}); #line 22 - await testRunner.WhenAsync("I call the method \'FindAsync\' with the parameter values", ((string)(null)), table433, "When "); + await testRunner.WhenAsync("I call the method \'FindAsync\' with the parameter values", ((string)(null)), table425, "When "); #line hidden - global::Reqnroll.Table table434 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table426 = new global::Reqnroll.Table(new string[] { "Expected"}); - table434.AddRow(new string[] { + table426.AddRow(new string[] { "AdventureWorksDemo.Data.Models.ProductCategoryModel"}); #line 25 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table434, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table426, "Then "); #line hidden - global::Reqnroll.Table table435 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table427 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table435.AddRow(new string[] { + table427.AddRow(new string[] { "4", "6/1/2002 12:00:00 AM", "Accessories", "2be3be36-d9a2-4eee-b593-ed895d97c2a6"}); #line 28 - await testRunner.AndAsync("the result is", ((string)(null)), table435, "And "); + await testRunner.AndAsync("the result is", ((string)(null)), table427, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -238,79 +238,79 @@ public async System.Threading.Tasks.Task FindAllAsync_0_5() #line 7 await this.FeatureBackgroundAsync(); #line hidden - global::Reqnroll.Table table436 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table428 = new global::Reqnroll.Table(new string[] { "PageNumber", "PageSize"}); - table436.AddRow(new string[] { + table428.AddRow(new string[] { "0", "5"}); #line 33 - await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table436, "When "); + await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table428, "When "); #line hidden - global::Reqnroll.Table table437 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table429 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table437.AddRow(new string[] { + table429.AddRow(new string[] { "pageingFilter", "{{model}}", "AdventureWorksDemo.Data.Paging.PagingFilter"}); #line 36 - await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table437, "And "); + await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table429, "And "); #line hidden - global::Reqnroll.Table table438 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table430 = new global::Reqnroll.Table(new string[] { "Expected"}); - table438.AddRow(new string[] { + table430.AddRow(new string[] { "AdventureWorksDemo.Data.Paging.PagedList"}); #line 39 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table438, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table430, "Then "); #line hidden - global::Reqnroll.Table table439 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table431 = new global::Reqnroll.Table(new string[] { "TotalPages", "TotalCount", "PageSize", "CurrentPage"}); - table439.AddRow(new string[] { + table431.AddRow(new string[] { "2", "7", "5", "0"}); #line 43 - await testRunner.AndAsync("the PagedList values are", ((string)(null)), table439, "And "); + await testRunner.AndAsync("the PagedList values are", ((string)(null)), table431, "And "); #line hidden - global::Reqnroll.Table table440 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table432 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table440.AddRow(new string[] { + table432.AddRow(new string[] { "1", "6/1/2002 12:00:00 AM", "Bikes", "cfbda25c-df71-47a7-b81b-64ee161aa37c"}); - table440.AddRow(new string[] { + table432.AddRow(new string[] { "2", "6/1/2002 12:00:00 AM", "Components", "c657828d-d808-4aba-91a3-af2ce02300e9"}); - table440.AddRow(new string[] { + table432.AddRow(new string[] { "3", "6/1/2002 12:00:00 AM", "Clothing", "10a7c342-ca82-48d4-8a38-46a2eb089b74"}); - table440.AddRow(new string[] { + table432.AddRow(new string[] { "4", "6/1/2002 12:00:00 AM", "Accessories", "2be3be36-d9a2-4eee-b593-ed895d97c2a6"}); - table440.AddRow(new string[] { + table432.AddRow(new string[] { "5", "6/1/2002 12:00:00 AM", "Mountain Bikes", "2d364ade-264a-433c-b092-4fcbf3804e01"}); #line 46 - await testRunner.AndAsync("the sorted results are", ((string)(null)), table440, "And "); + await testRunner.AndAsync("the sorted results are", ((string)(null)), table432, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -337,89 +337,89 @@ public async System.Threading.Tasks.Task FindAllAsync_0_0() #line 7 await this.FeatureBackgroundAsync(); #line hidden - global::Reqnroll.Table table441 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table433 = new global::Reqnroll.Table(new string[] { "PageNumber", "PageSize"}); - table441.AddRow(new string[] { + table433.AddRow(new string[] { "0", "0"}); #line 55 - await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table441, "When "); + await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table433, "When "); #line hidden - global::Reqnroll.Table table442 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table434 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table442.AddRow(new string[] { + table434.AddRow(new string[] { "pageingFilter", "{{model}}", "AdventureWorksDemo.Data.Paging.PagingFilter"}); #line 58 - await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table442, "And "); + await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table434, "And "); #line hidden - global::Reqnroll.Table table443 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table435 = new global::Reqnroll.Table(new string[] { "Expected"}); - table443.AddRow(new string[] { + table435.AddRow(new string[] { "AdventureWorksDemo.Data.Paging.PagedList"}); #line 61 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table443, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table435, "Then "); #line hidden - global::Reqnroll.Table table444 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table436 = new global::Reqnroll.Table(new string[] { "TotalPages", "TotalCount", "PageSize", "CurrentPage"}); - table444.AddRow(new string[] { + table436.AddRow(new string[] { "1", "7", "25", "0"}); #line 65 - await testRunner.AndAsync("the PagedList values are", ((string)(null)), table444, "And "); + await testRunner.AndAsync("the PagedList values are", ((string)(null)), table436, "And "); #line hidden - global::Reqnroll.Table table445 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table437 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table445.AddRow(new string[] { + table437.AddRow(new string[] { "1", "6/1/2002 12:00:00 AM", "Bikes", "cfbda25c-df71-47a7-b81b-64ee161aa37c"}); - table445.AddRow(new string[] { + table437.AddRow(new string[] { "2", "6/1/2002 12:00:00 AM", "Components", "c657828d-d808-4aba-91a3-af2ce02300e9"}); - table445.AddRow(new string[] { + table437.AddRow(new string[] { "3", "6/1/2002 12:00:00 AM", "Clothing", "10a7c342-ca82-48d4-8a38-46a2eb089b74"}); - table445.AddRow(new string[] { + table437.AddRow(new string[] { "4", "6/1/2002 12:00:00 AM", "Accessories", "2be3be36-d9a2-4eee-b593-ed895d97c2a6"}); - table445.AddRow(new string[] { + table437.AddRow(new string[] { "5", "6/1/2002 12:00:00 AM", "Mountain Bikes", "2d364ade-264a-433c-b092-4fcbf3804e01"}); - table445.AddRow(new string[] { + table437.AddRow(new string[] { "6", "6/1/2002 12:00:00 AM", "Road Bikes", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table445.AddRow(new string[] { + table437.AddRow(new string[] { "7", "6/1/2002 12:00:00 AM", "For Delete Tests Only", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 68 - await testRunner.AndAsync("the sorted results are", ((string)(null)), table445, "And "); + await testRunner.AndAsync("the sorted results are", ((string)(null)), table437, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -446,89 +446,89 @@ public async System.Threading.Tasks.Task FindAllAsync_0_500() #line 7 await this.FeatureBackgroundAsync(); #line hidden - global::Reqnroll.Table table446 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table438 = new global::Reqnroll.Table(new string[] { "PageNumber", "PageSize"}); - table446.AddRow(new string[] { + table438.AddRow(new string[] { "0", "500"}); #line 80 - await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table446, "When "); + await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table438, "When "); #line hidden - global::Reqnroll.Table table447 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table439 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table447.AddRow(new string[] { + table439.AddRow(new string[] { "pageingFilter", "{{model}}", "AdventureWorksDemo.Data.Paging.PagingFilter"}); #line 83 - await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table447, "And "); + await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table439, "And "); #line hidden - global::Reqnroll.Table table448 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table440 = new global::Reqnroll.Table(new string[] { "Expected"}); - table448.AddRow(new string[] { + table440.AddRow(new string[] { "AdventureWorksDemo.Data.Paging.PagedList"}); #line 86 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table448, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table440, "Then "); #line hidden - global::Reqnroll.Table table449 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table441 = new global::Reqnroll.Table(new string[] { "TotalPages", "TotalCount", "PageSize", "CurrentPage"}); - table449.AddRow(new string[] { + table441.AddRow(new string[] { "1", "7", "100", "0"}); #line 89 - await testRunner.AndAsync("the PagedList values are", ((string)(null)), table449, "And "); + await testRunner.AndAsync("the PagedList values are", ((string)(null)), table441, "And "); #line hidden - global::Reqnroll.Table table450 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table442 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table450.AddRow(new string[] { + table442.AddRow(new string[] { "1", "6/1/2002 12:00:00 AM", "Bikes", "cfbda25c-df71-47a7-b81b-64ee161aa37c"}); - table450.AddRow(new string[] { + table442.AddRow(new string[] { "2", "6/1/2002 12:00:00 AM", "Components", "c657828d-d808-4aba-91a3-af2ce02300e9"}); - table450.AddRow(new string[] { + table442.AddRow(new string[] { "3", "6/1/2002 12:00:00 AM", "Clothing", "10a7c342-ca82-48d4-8a38-46a2eb089b74"}); - table450.AddRow(new string[] { + table442.AddRow(new string[] { "4", "6/1/2002 12:00:00 AM", "Accessories", "2be3be36-d9a2-4eee-b593-ed895d97c2a6"}); - table450.AddRow(new string[] { + table442.AddRow(new string[] { "5", "6/1/2002 12:00:00 AM", "Mountain Bikes", "2d364ade-264a-433c-b092-4fcbf3804e01"}); - table450.AddRow(new string[] { + table442.AddRow(new string[] { "6", "6/1/2002 12:00:00 AM", "Road Bikes", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table450.AddRow(new string[] { + table442.AddRow(new string[] { "7", "6/1/2002 12:00:00 AM", "For Delete Tests Only", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 92 - await testRunner.AndAsync("the sorted results are", ((string)(null)), table450, "And "); + await testRunner.AndAsync("the sorted results are", ((string)(null)), table442, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -555,91 +555,91 @@ public async System.Threading.Tasks.Task FindAllAsync_0_500_Sort_ProductCategory #line 7 await this.FeatureBackgroundAsync(); #line hidden - global::Reqnroll.Table table451 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table443 = new global::Reqnroll.Table(new string[] { "PageNumber", "PageSize", "Sorting"}); - table451.AddRow(new string[] { + table443.AddRow(new string[] { "0", "500", "ProductCategoryId"}); #line 104 - await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table451, "When "); + await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table443, "When "); #line hidden - global::Reqnroll.Table table452 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table444 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table452.AddRow(new string[] { + table444.AddRow(new string[] { "pageingFilter", "{{model}}", "AdventureWorksDemo.Data.Paging.PagingFilter"}); #line 107 - await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table452, "And "); + await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table444, "And "); #line hidden - global::Reqnroll.Table table453 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table445 = new global::Reqnroll.Table(new string[] { "Expected"}); - table453.AddRow(new string[] { + table445.AddRow(new string[] { "AdventureWorksDemo.Data.Paging.PagedList"}); #line 110 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table453, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table445, "Then "); #line hidden - global::Reqnroll.Table table454 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table446 = new global::Reqnroll.Table(new string[] { "TotalPages", "TotalCount", "PageSize", "CurrentPage"}); - table454.AddRow(new string[] { + table446.AddRow(new string[] { "1", "7", "100", "0"}); #line 113 - await testRunner.AndAsync("the PagedList values are", ((string)(null)), table454, "And "); + await testRunner.AndAsync("the PagedList values are", ((string)(null)), table446, "And "); #line hidden - global::Reqnroll.Table table455 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table447 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table455.AddRow(new string[] { + table447.AddRow(new string[] { "1", "6/1/2002 12:00:00 AM", "Bikes", "cfbda25c-df71-47a7-b81b-64ee161aa37c"}); - table455.AddRow(new string[] { + table447.AddRow(new string[] { "2", "6/1/2002 12:00:00 AM", "Components", "c657828d-d808-4aba-91a3-af2ce02300e9"}); - table455.AddRow(new string[] { + table447.AddRow(new string[] { "3", "6/1/2002 12:00:00 AM", "Clothing", "10a7c342-ca82-48d4-8a38-46a2eb089b74"}); - table455.AddRow(new string[] { + table447.AddRow(new string[] { "4", "6/1/2002 12:00:00 AM", "Accessories", "2be3be36-d9a2-4eee-b593-ed895d97c2a6"}); - table455.AddRow(new string[] { + table447.AddRow(new string[] { "5", "6/1/2002 12:00:00 AM", "Mountain Bikes", "2d364ade-264a-433c-b092-4fcbf3804e01"}); - table455.AddRow(new string[] { + table447.AddRow(new string[] { "6", "6/1/2002 12:00:00 AM", "Road Bikes", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table455.AddRow(new string[] { + table447.AddRow(new string[] { "7", "6/1/2002 12:00:00 AM", "For Delete Tests Only", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 116 - await testRunner.AndAsync("the sorted results are", ((string)(null)), table455, "And "); + await testRunner.AndAsync("the sorted results are", ((string)(null)), table447, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -666,91 +666,91 @@ public async System.Threading.Tasks.Task FindAllAsync_0_500_Sort_ProductCategory #line 7 await this.FeatureBackgroundAsync(); #line hidden - global::Reqnroll.Table table456 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table448 = new global::Reqnroll.Table(new string[] { "PageNumber", "PageSize", "Sorting"}); - table456.AddRow(new string[] { + table448.AddRow(new string[] { "0", "500", "ProductCategoryId DESC"}); #line 128 - await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table456, "When "); + await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table448, "When "); #line hidden - global::Reqnroll.Table table457 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table449 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table457.AddRow(new string[] { + table449.AddRow(new string[] { "pageingFilter", "{{model}}", "AdventureWorksDemo.Data.Paging.PagingFilter"}); #line 131 - await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table457, "And "); + await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table449, "And "); #line hidden - global::Reqnroll.Table table458 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table450 = new global::Reqnroll.Table(new string[] { "Expected"}); - table458.AddRow(new string[] { + table450.AddRow(new string[] { "AdventureWorksDemo.Data.Paging.PagedList"}); #line 134 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table458, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table450, "Then "); #line hidden - global::Reqnroll.Table table459 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table451 = new global::Reqnroll.Table(new string[] { "TotalPages", "TotalCount", "PageSize", "CurrentPage"}); - table459.AddRow(new string[] { + table451.AddRow(new string[] { "1", "7", "100", "0"}); #line 137 - await testRunner.AndAsync("the PagedList values are", ((string)(null)), table459, "And "); + await testRunner.AndAsync("the PagedList values are", ((string)(null)), table451, "And "); #line hidden - global::Reqnroll.Table table460 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table452 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table460.AddRow(new string[] { + table452.AddRow(new string[] { "7", "6/1/2002 12:00:00 AM", "For Delete Tests Only", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); - table460.AddRow(new string[] { + table452.AddRow(new string[] { "6", "6/1/2002 12:00:00 AM", "Road Bikes", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table460.AddRow(new string[] { + table452.AddRow(new string[] { "5", "6/1/2002 12:00:00 AM", "Mountain Bikes", "2d364ade-264a-433c-b092-4fcbf3804e01"}); - table460.AddRow(new string[] { + table452.AddRow(new string[] { "4", "6/1/2002 12:00:00 AM", "Accessories", "2be3be36-d9a2-4eee-b593-ed895d97c2a6"}); - table460.AddRow(new string[] { + table452.AddRow(new string[] { "3", "6/1/2002 12:00:00 AM", "Clothing", "10a7c342-ca82-48d4-8a38-46a2eb089b74"}); - table460.AddRow(new string[] { + table452.AddRow(new string[] { "2", "6/1/2002 12:00:00 AM", "Components", "c657828d-d808-4aba-91a3-af2ce02300e9"}); - table460.AddRow(new string[] { + table452.AddRow(new string[] { "1", "6/1/2002 12:00:00 AM", "Bikes", "cfbda25c-df71-47a7-b81b-64ee161aa37c"}); #line 140 - await testRunner.AndAsync("the sorted results are", ((string)(null)), table460, "And "); + await testRunner.AndAsync("the sorted results are", ((string)(null)), table452, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -777,91 +777,91 @@ public async System.Threading.Tasks.Task FindAllAsync_0_500_Sort_ProductCategory #line 7 await this.FeatureBackgroundAsync(); #line hidden - global::Reqnroll.Table table461 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table453 = new global::Reqnroll.Table(new string[] { "PageNumber", "PageSize", "Sorting"}); - table461.AddRow(new string[] { + table453.AddRow(new string[] { "0", "500", "ProductCategoryId ASC"}); #line 152 - await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table461, "When "); + await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table453, "When "); #line hidden - global::Reqnroll.Table table462 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table454 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table462.AddRow(new string[] { + table454.AddRow(new string[] { "pageingFilter", "{{model}}", "AdventureWorksDemo.Data.Paging.PagingFilter"}); #line 155 - await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table462, "And "); + await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table454, "And "); #line hidden - global::Reqnroll.Table table463 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table455 = new global::Reqnroll.Table(new string[] { "Expected"}); - table463.AddRow(new string[] { + table455.AddRow(new string[] { "AdventureWorksDemo.Data.Paging.PagedList"}); #line 158 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table463, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table455, "Then "); #line hidden - global::Reqnroll.Table table464 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table456 = new global::Reqnroll.Table(new string[] { "TotalPages", "TotalCount", "PageSize", "CurrentPage"}); - table464.AddRow(new string[] { + table456.AddRow(new string[] { "1", "7", "100", "0"}); #line 161 - await testRunner.AndAsync("the PagedList values are", ((string)(null)), table464, "And "); + await testRunner.AndAsync("the PagedList values are", ((string)(null)), table456, "And "); #line hidden - global::Reqnroll.Table table465 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table457 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table465.AddRow(new string[] { + table457.AddRow(new string[] { "1", "6/1/2002 12:00:00 AM", "Bikes", "cfbda25c-df71-47a7-b81b-64ee161aa37c"}); - table465.AddRow(new string[] { + table457.AddRow(new string[] { "2", "6/1/2002 12:00:00 AM", "Components", "c657828d-d808-4aba-91a3-af2ce02300e9"}); - table465.AddRow(new string[] { + table457.AddRow(new string[] { "3", "6/1/2002 12:00:00 AM", "Clothing", "10a7c342-ca82-48d4-8a38-46a2eb089b74"}); - table465.AddRow(new string[] { + table457.AddRow(new string[] { "4", "6/1/2002 12:00:00 AM", "Accessories", "2be3be36-d9a2-4eee-b593-ed895d97c2a6"}); - table465.AddRow(new string[] { + table457.AddRow(new string[] { "5", "6/1/2002 12:00:00 AM", "Mountain Bikes", "2d364ade-264a-433c-b092-4fcbf3804e01"}); - table465.AddRow(new string[] { + table457.AddRow(new string[] { "6", "6/1/2002 12:00:00 AM", "Road Bikes", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table465.AddRow(new string[] { + table457.AddRow(new string[] { "7", "6/1/2002 12:00:00 AM", "For Delete Tests Only", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 164 - await testRunner.AndAsync("the sorted results are", ((string)(null)), table465, "And "); + await testRunner.AndAsync("the sorted results are", ((string)(null)), table457, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -888,23 +888,23 @@ public async System.Threading.Tasks.Task FindAsync1234() #line 7 await this.FeatureBackgroundAsync(); #line hidden - global::Reqnroll.Table table466 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table458 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table466.AddRow(new string[] { + table458.AddRow(new string[] { "productCategoryId", "1234", "int"}); #line 175 - await testRunner.WhenAsync("I call the method \'FindAsync\' with the parameter values", ((string)(null)), table466, "When "); + await testRunner.WhenAsync("I call the method \'FindAsync\' with the parameter values", ((string)(null)), table458, "When "); #line hidden - global::Reqnroll.Table table467 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table459 = new global::Reqnroll.Table(new string[] { "Expected"}); - table467.AddRow(new string[] { + table459.AddRow(new string[] { "AdventureWorksDemo.Data.Models.ProductCategoryModel"}); #line 179 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table467, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table459, "Then "); #line hidden #line 182 await testRunner.AndAsync("the result is null", ((string)(null)), ((global::Reqnroll.Table)(null)), "And "); @@ -934,64 +934,64 @@ public async System.Threading.Tasks.Task FindAllAsync_1_5() #line 7 await this.FeatureBackgroundAsync(); #line hidden - global::Reqnroll.Table table468 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table460 = new global::Reqnroll.Table(new string[] { "PageNumber", "PageSize"}); - table468.AddRow(new string[] { + table460.AddRow(new string[] { "1", "5"}); #line 185 - await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table468, "When "); + await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table460, "When "); #line hidden - global::Reqnroll.Table table469 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table461 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table469.AddRow(new string[] { + table461.AddRow(new string[] { "pageingFilter", "{{model}}", "AdventureWorksDemo.Data.Paging.PagingFilter"}); #line 188 - await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table469, "And "); + await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table461, "And "); #line hidden - global::Reqnroll.Table table470 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table462 = new global::Reqnroll.Table(new string[] { "Expected"}); - table470.AddRow(new string[] { + table462.AddRow(new string[] { "AdventureWorksDemo.Data.Paging.PagedList"}); #line 191 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table470, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table462, "Then "); #line hidden - global::Reqnroll.Table table471 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table463 = new global::Reqnroll.Table(new string[] { "TotalPages", "TotalCount", "PageSize", "CurrentPage"}); - table471.AddRow(new string[] { + table463.AddRow(new string[] { "2", "7", "5", "1"}); #line 194 - await testRunner.AndAsync("the PagedList values are", ((string)(null)), table471, "And "); + await testRunner.AndAsync("the PagedList values are", ((string)(null)), table463, "And "); #line hidden - global::Reqnroll.Table table472 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table464 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table472.AddRow(new string[] { + table464.AddRow(new string[] { "6", "6/1/2002 12:00:00 AM", "Road Bikes", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table472.AddRow(new string[] { + table464.AddRow(new string[] { "7", "6/1/2002 12:00:00 AM", "For Delete Tests Only", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 197 - await testRunner.AndAsync("the sorted results are", ((string)(null)), table472, "And "); + await testRunner.AndAsync("the sorted results are", ((string)(null)), table464, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -1018,64 +1018,64 @@ public async System.Threading.Tasks.Task FindAllAsync_2_5() #line 7 await this.FeatureBackgroundAsync(); #line hidden - global::Reqnroll.Table table473 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table465 = new global::Reqnroll.Table(new string[] { "PageNumber", "PageSize"}); - table473.AddRow(new string[] { + table465.AddRow(new string[] { "2", "5"}); #line 203 - await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table473, "When "); + await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table465, "When "); #line hidden - global::Reqnroll.Table table474 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table466 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table474.AddRow(new string[] { + table466.AddRow(new string[] { "pageingFilter", "{{model}}", "AdventureWorksDemo.Data.Paging.PagingFilter"}); #line 206 - await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table474, "And "); + await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table466, "And "); #line hidden - global::Reqnroll.Table table475 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table467 = new global::Reqnroll.Table(new string[] { "Expected"}); - table475.AddRow(new string[] { + table467.AddRow(new string[] { "AdventureWorksDemo.Data.Paging.PagedList"}); #line 209 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table475, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table467, "Then "); #line hidden - global::Reqnroll.Table table476 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table468 = new global::Reqnroll.Table(new string[] { "TotalPages", "TotalCount", "PageSize", "CurrentPage"}); - table476.AddRow(new string[] { + table468.AddRow(new string[] { "2", "7", "5", "1"}); #line 212 - await testRunner.AndAsync("the PagedList values are", ((string)(null)), table476, "And "); + await testRunner.AndAsync("the PagedList values are", ((string)(null)), table468, "And "); #line hidden - global::Reqnroll.Table table477 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table469 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table477.AddRow(new string[] { + table469.AddRow(new string[] { "6", "6/1/2002 12:00:00 AM", "Road Bikes", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table477.AddRow(new string[] { + table469.AddRow(new string[] { "7", "6/1/2002 12:00:00 AM", "For Delete Tests Only", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 215 - await testRunner.AndAsync("the sorted results are", ((string)(null)), table477, "And "); + await testRunner.AndAsync("the sorted results are", ((string)(null)), table469, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -1102,89 +1102,89 @@ public async System.Threading.Tasks.Task FindAllAsync_2_8() #line 7 await this.FeatureBackgroundAsync(); #line hidden - global::Reqnroll.Table table478 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table470 = new global::Reqnroll.Table(new string[] { "PageNumber", "PageSize"}); - table478.AddRow(new string[] { + table470.AddRow(new string[] { "2", "8"}); #line 221 - await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table478, "When "); + await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table470, "When "); #line hidden - global::Reqnroll.Table table479 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table471 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table479.AddRow(new string[] { + table471.AddRow(new string[] { "pageingFilter", "{{model}}", "AdventureWorksDemo.Data.Paging.PagingFilter"}); #line 224 - await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table479, "And "); + await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table471, "And "); #line hidden - global::Reqnroll.Table table480 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table472 = new global::Reqnroll.Table(new string[] { "Expected"}); - table480.AddRow(new string[] { + table472.AddRow(new string[] { "AdventureWorksDemo.Data.Paging.PagedList"}); #line 227 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table480, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table472, "Then "); #line hidden - global::Reqnroll.Table table481 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table473 = new global::Reqnroll.Table(new string[] { "TotalPages", "TotalCount", "PageSize", "CurrentPage"}); - table481.AddRow(new string[] { + table473.AddRow(new string[] { "1", "7", "8", "0"}); #line 230 - await testRunner.AndAsync("the PagedList values are", ((string)(null)), table481, "And "); + await testRunner.AndAsync("the PagedList values are", ((string)(null)), table473, "And "); #line hidden - global::Reqnroll.Table table482 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table474 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table482.AddRow(new string[] { + table474.AddRow(new string[] { "1", "6/1/2002 12:00:00 AM", "Bikes", "cfbda25c-df71-47a7-b81b-64ee161aa37c"}); - table482.AddRow(new string[] { + table474.AddRow(new string[] { "2", "6/1/2002 12:00:00 AM", "Components", "c657828d-d808-4aba-91a3-af2ce02300e9"}); - table482.AddRow(new string[] { + table474.AddRow(new string[] { "3", "6/1/2002 12:00:00 AM", "Clothing", "10a7c342-ca82-48d4-8a38-46a2eb089b74"}); - table482.AddRow(new string[] { + table474.AddRow(new string[] { "4", "6/1/2002 12:00:00 AM", "Accessories", "2be3be36-d9a2-4eee-b593-ed895d97c2a6"}); - table482.AddRow(new string[] { + table474.AddRow(new string[] { "5", "6/1/2002 12:00:00 AM", "Mountain Bikes", "2d364ade-264a-433c-b092-4fcbf3804e01"}); - table482.AddRow(new string[] { + table474.AddRow(new string[] { "6", "6/1/2002 12:00:00 AM", "Road Bikes", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table482.AddRow(new string[] { + table474.AddRow(new string[] { "7", "6/1/2002 12:00:00 AM", "For Delete Tests Only", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 233 - await testRunner.AndAsync("the sorted results are", ((string)(null)), table482, "And "); + await testRunner.AndAsync("the sorted results are", ((string)(null)), table474, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -1211,64 +1211,64 @@ public async System.Threading.Tasks.Task FindAllAsync_1234_5() #line 7 await this.FeatureBackgroundAsync(); #line hidden - global::Reqnroll.Table table483 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table475 = new global::Reqnroll.Table(new string[] { "PageNumber", "PageSize"}); - table483.AddRow(new string[] { + table475.AddRow(new string[] { "1234", "5"}); #line 244 - await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table483, "When "); + await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table475, "When "); #line hidden - global::Reqnroll.Table table484 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table476 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table484.AddRow(new string[] { + table476.AddRow(new string[] { "pageingFilter", "{{model}}", "AdventureWorksDemo.Data.Paging.PagingFilter"}); #line 247 - await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table484, "And "); + await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table476, "And "); #line hidden - global::Reqnroll.Table table485 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table477 = new global::Reqnroll.Table(new string[] { "Expected"}); - table485.AddRow(new string[] { + table477.AddRow(new string[] { "AdventureWorksDemo.Data.Paging.PagedList"}); #line 250 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table485, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table477, "Then "); #line hidden - global::Reqnroll.Table table486 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table478 = new global::Reqnroll.Table(new string[] { "TotalPages", "TotalCount", "PageSize", "CurrentPage"}); - table486.AddRow(new string[] { + table478.AddRow(new string[] { "2", "7", "5", "1"}); #line 253 - await testRunner.AndAsync("the PagedList values are", ((string)(null)), table486, "And "); + await testRunner.AndAsync("the PagedList values are", ((string)(null)), table478, "And "); #line hidden - global::Reqnroll.Table table487 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table479 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table487.AddRow(new string[] { + table479.AddRow(new string[] { "6", "6/1/2002 12:00:00 AM", "Road Bikes", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table487.AddRow(new string[] { + table479.AddRow(new string[] { "7", "6/1/2002 12:00:00 AM", "For Delete Tests Only", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 256 - await testRunner.AndAsync("the sorted results are", ((string)(null)), table487, "And "); + await testRunner.AndAsync("the sorted results are", ((string)(null)), table479, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -1295,89 +1295,89 @@ public async System.Threading.Tasks.Task FindAllAsync_5_0() #line 7 await this.FeatureBackgroundAsync(); #line hidden - global::Reqnroll.Table table488 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table480 = new global::Reqnroll.Table(new string[] { "PageNumber", "PageSize"}); - table488.AddRow(new string[] { + table480.AddRow(new string[] { "5", "0"}); #line 262 - await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table488, "When "); + await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Paging.PagingFilter\'", ((string)(null)), table480, "When "); #line hidden - global::Reqnroll.Table table489 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table481 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table489.AddRow(new string[] { + table481.AddRow(new string[] { "pageingFilter", "{{model}}", "AdventureWorksDemo.Data.Paging.PagingFilter"}); #line 265 - await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table489, "And "); + await testRunner.AndAsync("I call the method \'FindAllAsync\' with the parameter values", ((string)(null)), table481, "And "); #line hidden - global::Reqnroll.Table table490 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table482 = new global::Reqnroll.Table(new string[] { "Expected"}); - table490.AddRow(new string[] { + table482.AddRow(new string[] { "AdventureWorksDemo.Data.Paging.PagedList"}); #line 268 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table490, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table482, "Then "); #line hidden - global::Reqnroll.Table table491 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table483 = new global::Reqnroll.Table(new string[] { "TotalPages", "TotalCount", "PageSize", "CurrentPage"}); - table491.AddRow(new string[] { + table483.AddRow(new string[] { "1", "7", "25", "0"}); #line 272 - await testRunner.AndAsync("the PagedList values are", ((string)(null)), table491, "And "); + await testRunner.AndAsync("the PagedList values are", ((string)(null)), table483, "And "); #line hidden - global::Reqnroll.Table table492 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table484 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table492.AddRow(new string[] { + table484.AddRow(new string[] { "1", "6/1/2002 12:00:00 AM", "Bikes", "cfbda25c-df71-47a7-b81b-64ee161aa37c"}); - table492.AddRow(new string[] { + table484.AddRow(new string[] { "2", "6/1/2002 12:00:00 AM", "Components", "c657828d-d808-4aba-91a3-af2ce02300e9"}); - table492.AddRow(new string[] { + table484.AddRow(new string[] { "3", "6/1/2002 12:00:00 AM", "Clothing", "10a7c342-ca82-48d4-8a38-46a2eb089b74"}); - table492.AddRow(new string[] { + table484.AddRow(new string[] { "4", "6/1/2002 12:00:00 AM", "Accessories", "2be3be36-d9a2-4eee-b593-ed895d97c2a6"}); - table492.AddRow(new string[] { + table484.AddRow(new string[] { "5", "6/1/2002 12:00:00 AM", "Mountain Bikes", "2d364ade-264a-433c-b092-4fcbf3804e01"}); - table492.AddRow(new string[] { + table484.AddRow(new string[] { "6", "6/1/2002 12:00:00 AM", "Road Bikes", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table492.AddRow(new string[] { + table484.AddRow(new string[] { "7", "6/1/2002 12:00:00 AM", "For Delete Tests Only", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 275 - await testRunner.AndAsync("the sorted results are", ((string)(null)), table492, "And "); + await testRunner.AndAsync("the sorted results are", ((string)(null)), table484, "And "); #line hidden } await this.ScenarioCleanupAsync(); diff --git a/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ProductCategoryService/ProductCategoryServiceUpdateTests.feature.cs b/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ProductCategoryService/ProductCategoryServiceUpdateTests.feature.cs index 624c257..82bd7bf 100644 --- a/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ProductCategoryService/ProductCategoryServiceUpdateTests.feature.cs +++ b/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ProductCategoryService/ProductCategoryServiceUpdateTests.feature.cs @@ -128,95 +128,95 @@ public async System.Threading.Tasks.Task UpdateAsync() #line 7 await this.FeatureBackgroundAsync(); #line hidden - global::Reqnroll.Table table506 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table498 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table506.AddRow(new string[] { + table498.AddRow(new string[] { "6", "6/1/2002 12:00:00 AM", "Road Bikes", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table506.AddRow(new string[] { + table498.AddRow(new string[] { "7", "6/1/2002 12:00:00 AM", "For Delete Tests Only", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 12 await testRunner.GivenAsync("the table \'Production.ProductCategory\' filtered by \'ProductCategoryId > 5\' contai" + - "ns", ((string)(null)), table506, "Given "); + "ns", ((string)(null)), table498, "Given "); #line hidden - global::Reqnroll.Table table507 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table499 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "Name"}); - table507.AddRow(new string[] { + table499.AddRow(new string[] { "6", "How Now Brown Cow"}); #line 16 - await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Models.ProductCategoryModel\'", ((string)(null)), table507, "When "); + await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Models.ProductCategoryModel\'", ((string)(null)), table499, "When "); #line hidden - global::Reqnroll.Table table508 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table500 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table508.AddRow(new string[] { + table500.AddRow(new string[] { "model", "{{model}}", "AdventureWorksDemo.Data.Models.ProductCategoryModel"}); #line 19 - await testRunner.AndAsync("I call the method \'UpdateAsync\' with the parameter values", ((string)(null)), table508, "And "); + await testRunner.AndAsync("I call the method \'UpdateAsync\' with the parameter values", ((string)(null)), table500, "And "); #line hidden - global::Reqnroll.Table table509 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table501 = new global::Reqnroll.Table(new string[] { "Expected"}); - table509.AddRow(new string[] { + table501.AddRow(new string[] { "AdventureWorksDemo.Data.Models.ServiceResult"}); #line 22 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table509, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table501, "Then "); #line hidden - global::Reqnroll.Table table510 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table502 = new global::Reqnroll.Table(new string[] { "IsFailure", "IsSuccess", "Message"}); - table510.AddRow(new string[] { + table502.AddRow(new string[] { "False", "True", ""}); #line 25 - await testRunner.AndAsync("the result is", ((string)(null)), table510, "And "); + await testRunner.AndAsync("the result is", ((string)(null)), table502, "And "); #line hidden - global::Reqnroll.Table table511 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table503 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table511.AddRow(new string[] { + table503.AddRow(new string[] { "6", "5/24/2024 12:34:56 PM", "How Now Brown Cow", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); #line 28 - await testRunner.AndAsync("the results property \'Value\' contains", ((string)(null)), table511, "And "); + await testRunner.AndAsync("the results property \'Value\' contains", ((string)(null)), table503, "And "); #line hidden - global::Reqnroll.Table table512 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table504 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table512.AddRow(new string[] { + table504.AddRow(new string[] { "6", "5/24/2024 12:34:56 PM", "How Now Brown Cow", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table512.AddRow(new string[] { + table504.AddRow(new string[] { "7", "6/1/2002 12:00:00 AM", "For Delete Tests Only", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 32 await testRunner.AndAsync("the table \'Production.ProductCategory\' filtered by \'ProductCategoryId > 5\' contai" + - "ns", ((string)(null)), table512, "And "); + "ns", ((string)(null)), table504, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -246,80 +246,80 @@ public async System.Threading.Tasks.Task UpdateNoChange() #line 38 await testRunner.GivenAsync("I don\'t reset the database after the scenario", ((string)(null)), ((global::Reqnroll.Table)(null)), "Given "); #line hidden - global::Reqnroll.Table table513 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table505 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table513.AddRow(new string[] { + table505.AddRow(new string[] { "7", "6/1/2002 12:00:00 AM", "For Delete Tests Only", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 39 - await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Models.ProductCategoryModel\'", ((string)(null)), table513, "When "); + await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Models.ProductCategoryModel\'", ((string)(null)), table505, "When "); #line hidden - global::Reqnroll.Table table514 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table506 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table514.AddRow(new string[] { + table506.AddRow(new string[] { "model", "{{model}}", "AdventureWorksDemo.Data.Models.ProductCategoryModel"}); #line 42 - await testRunner.AndAsync("I call the method \'UpdateAsync\' with the parameter values", ((string)(null)), table514, "And "); + await testRunner.AndAsync("I call the method \'UpdateAsync\' with the parameter values", ((string)(null)), table506, "And "); #line hidden - global::Reqnroll.Table table515 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table507 = new global::Reqnroll.Table(new string[] { "Expected"}); - table515.AddRow(new string[] { + table507.AddRow(new string[] { "AdventureWorksDemo.Data.Models.ServiceResult"}); #line 45 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table515, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table507, "Then "); #line hidden - global::Reqnroll.Table table516 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table508 = new global::Reqnroll.Table(new string[] { "IsFailure", "IsSuccess", "Message"}); - table516.AddRow(new string[] { + table508.AddRow(new string[] { "False", "True", "Record is already up to date!"}); #line 48 - await testRunner.AndAsync("the result is", ((string)(null)), table516, "And "); + await testRunner.AndAsync("the result is", ((string)(null)), table508, "And "); #line hidden - global::Reqnroll.Table table517 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table509 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table517.AddRow(new string[] { + table509.AddRow(new string[] { "7", "6/1/2002 12:00:00 AM", "For Delete Tests Only", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 51 - await testRunner.AndAsync("the results property \'Value\' contains", ((string)(null)), table517, "And "); + await testRunner.AndAsync("the results property \'Value\' contains", ((string)(null)), table509, "And "); #line hidden - global::Reqnroll.Table table518 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table510 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table518.AddRow(new string[] { + table510.AddRow(new string[] { "6", "6/1/2002 12:00:00 AM", "Road Bikes", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table518.AddRow(new string[] { + table510.AddRow(new string[] { "7", "6/1/2002 12:00:00 AM", "For Delete Tests Only", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 54 await testRunner.AndAsync("the table \'Production.ProductCategory\' filtered by \'ProductCategoryId > 5\' contai" + - "ns", ((string)(null)), table518, "And "); + "ns", ((string)(null)), table510, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -349,100 +349,100 @@ public async System.Threading.Tasks.Task UpdateShortName() #line 60 await testRunner.GivenAsync("I don\'t reset the database after the scenario", ((string)(null)), ((global::Reqnroll.Table)(null)), "Given "); #line hidden - global::Reqnroll.Table table519 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table511 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table519.AddRow(new string[] { + table511.AddRow(new string[] { "6", "6/1/2002 12:00:00 AM", "Road Bikes", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table519.AddRow(new string[] { + table511.AddRow(new string[] { "7", "6/1/2002 12:00:00 AM", "For Delete Tests Only", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 61 await testRunner.AndAsync("the table \'Production.ProductCategory\' filtered by \'ProductCategoryId > 5\' contai" + - "ns", ((string)(null)), table519, "And "); + "ns", ((string)(null)), table511, "And "); #line hidden - global::Reqnroll.Table table520 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table512 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "Name"}); - table520.AddRow(new string[] { + table512.AddRow(new string[] { "6", "Hi"}); #line 65 - await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Models.ProductCategoryModel\'", ((string)(null)), table520, "When "); + await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Models.ProductCategoryModel\'", ((string)(null)), table512, "When "); #line hidden - global::Reqnroll.Table table521 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table513 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table521.AddRow(new string[] { + table513.AddRow(new string[] { "model", "{{model}}", "AdventureWorksDemo.Data.Models.ProductCategoryModel"}); #line 68 - await testRunner.AndAsync("I call the method \'UpdateAsync\' with the parameter values", ((string)(null)), table521, "And "); + await testRunner.AndAsync("I call the method \'UpdateAsync\' with the parameter values", ((string)(null)), table513, "And "); #line hidden - global::Reqnroll.Table table522 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table514 = new global::Reqnroll.Table(new string[] { "Expected"}); - table522.AddRow(new string[] { + table514.AddRow(new string[] { "AdventureWorksDemo.Data.Models.ServiceResult"}); #line 71 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table522, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table514, "Then "); #line hidden - global::Reqnroll.Table table523 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table515 = new global::Reqnroll.Table(new string[] { "IsFailure", "IsSuccess"}); - table523.AddRow(new string[] { + table515.AddRow(new string[] { "True", "False"}); #line 74 - await testRunner.AndAsync("the result is", ((string)(null)), table523, "And "); + await testRunner.AndAsync("the result is", ((string)(null)), table515, "And "); #line hidden - global::Reqnroll.Table table524 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table516 = new global::Reqnroll.Table(new string[] { "Expected"}); - table524.AddRow(new string[] { + table516.AddRow(new string[] { "\'Name\' must be between 3 and 50 characters. You entered 2 characters."}); #line 77 - await testRunner.AndAsync("the results property \'Message\' contains", ((string)(null)), table524, "And "); + await testRunner.AndAsync("the results property \'Message\' contains", ((string)(null)), table516, "And "); #line hidden - global::Reqnroll.Table table525 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table517 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "Name", "ModifiedDate", "Rowguid"}); - table525.AddRow(new string[] { + table517.AddRow(new string[] { "6", "Hi", "6/1/2002 12:00:00 AM", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); #line 80 - await testRunner.AndAsync("the results property \'Value\' contains", ((string)(null)), table525, "And "); + await testRunner.AndAsync("the results property \'Value\' contains", ((string)(null)), table517, "And "); #line hidden - global::Reqnroll.Table table526 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table518 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table526.AddRow(new string[] { + table518.AddRow(new string[] { "6", "6/1/2002 12:00:00 AM", "Road Bikes", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table526.AddRow(new string[] { + table518.AddRow(new string[] { "7", "6/1/2002 12:00:00 AM", "For Delete Tests Only", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 84 await testRunner.AndAsync("the table \'Production.ProductCategory\' filtered by \'ProductCategoryId > 5\' contai" + - "ns", ((string)(null)), table526, "And "); + "ns", ((string)(null)), table518, "And "); #line hidden } await this.ScenarioCleanupAsync(); @@ -472,100 +472,100 @@ public async System.Threading.Tasks.Task UpdateUnknownRecord() #line 90 await testRunner.GivenAsync("I don\'t reset the database after the scenario", ((string)(null)), ((global::Reqnroll.Table)(null)), "Given "); #line hidden - global::Reqnroll.Table table527 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table519 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "Name"}); - table527.AddRow(new string[] { + table519.AddRow(new string[] { "1234", "UpdateUnknownRecord"}); #line 91 - await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Models.ProductCategoryModel\'", ((string)(null)), table527, "When "); + await testRunner.WhenAsync("I populate the model \'AdventureWorksDemo.Data.Models.ProductCategoryModel\'", ((string)(null)), table519, "When "); #line hidden - global::Reqnroll.Table table528 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table520 = new global::Reqnroll.Table(new string[] { "Key", "Value", "TypeName"}); - table528.AddRow(new string[] { + table520.AddRow(new string[] { "model", "{{model}}", "AdventureWorksDemo.Data.Models.ProductCategoryModel"}); #line 94 - await testRunner.AndAsync("I call the method \'UpdateAsync\' with the parameter values", ((string)(null)), table528, "And "); + await testRunner.AndAsync("I call the method \'UpdateAsync\' with the parameter values", ((string)(null)), table520, "And "); #line hidden - global::Reqnroll.Table table529 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table521 = new global::Reqnroll.Table(new string[] { "Expected"}); - table529.AddRow(new string[] { + table521.AddRow(new string[] { "AdventureWorksDemo.Data.Models.ServiceResult"}); #line 97 - await testRunner.ThenAsync("the result is of type", ((string)(null)), table529, "Then "); + await testRunner.ThenAsync("the result is of type", ((string)(null)), table521, "Then "); #line hidden - global::Reqnroll.Table table530 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table522 = new global::Reqnroll.Table(new string[] { "IsFailure", "IsSuccess", "Message"}); - table530.AddRow(new string[] { + table522.AddRow(new string[] { "True", "False", "Unable to locate record to update!"}); #line 101 - await testRunner.AndAsync("the result is", ((string)(null)), table530, "And "); + await testRunner.AndAsync("the result is", ((string)(null)), table522, "And "); #line hidden - global::Reqnroll.Table table531 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table523 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table531.AddRow(new string[] { + table523.AddRow(new string[] { "1234", "1/1/0001 12:00:00 AM", "UpdateUnknownRecord", "00000000-0000-0000-0000-000000000000"}); #line 105 - await testRunner.AndAsync("the results property \'Value\' contains", ((string)(null)), table531, "And "); + await testRunner.AndAsync("the results property \'Value\' contains", ((string)(null)), table523, "And "); #line hidden - global::Reqnroll.Table table532 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table524 = new global::Reqnroll.Table(new string[] { "ProductCategoryId", "ModifiedDate", "Name", "Rowguid"}); - table532.AddRow(new string[] { + table524.AddRow(new string[] { "1", "6/1/2002 12:00:00 AM", "Bikes", "cfbda25c-df71-47a7-b81b-64ee161aa37c"}); - table532.AddRow(new string[] { + table524.AddRow(new string[] { "2", "6/1/2002 12:00:00 AM", "Components", "c657828d-d808-4aba-91a3-af2ce02300e9"}); - table532.AddRow(new string[] { + table524.AddRow(new string[] { "3", "6/1/2002 12:00:00 AM", "Clothing", "10a7c342-ca82-48d4-8a38-46a2eb089b74"}); - table532.AddRow(new string[] { + table524.AddRow(new string[] { "4", "6/1/2002 12:00:00 AM", "Accessories", "2be3be36-d9a2-4eee-b593-ed895d97c2a6"}); - table532.AddRow(new string[] { + table524.AddRow(new string[] { "5", "6/1/2002 12:00:00 AM", "Mountain Bikes", "2d364ade-264a-433c-b092-4fcbf3804e01"}); - table532.AddRow(new string[] { + table524.AddRow(new string[] { "6", "6/1/2002 12:00:00 AM", "Road Bikes", "000310c0-bcc8-42c4-b0c3-45ae611af06b"}); - table532.AddRow(new string[] { + table524.AddRow(new string[] { "7", "6/1/2002 12:00:00 AM", "For Delete Tests Only", "02c5061d-ecdc-4274-b5f1-e91d76bc3f37"}); #line 109 - await testRunner.AndAsync("the table \'Production.ProductCategory\' contains", ((string)(null)), table532, "And "); + await testRunner.AndAsync("the table \'Production.ProductCategory\' contains", ((string)(null)), table524, "And "); #line hidden } await this.ScenarioCleanupAsync(); diff --git a/src/API/AdventureWorksDemo.Data/Models/Reports/SalesSummaryByYear.cs b/src/API/AdventureWorksDemo.Data/Models/Reports/SalesSummaryByYear.cs new file mode 100644 index 0000000..17db621 --- /dev/null +++ b/src/API/AdventureWorksDemo.Data/Models/Reports/SalesSummaryByYear.cs @@ -0,0 +1,9 @@ +namespace AdventureWorksDemo.Data.Models.Reports +{ + public record SalesSummaryByYear + { + public int OrderYear { get; set; } + public bool OnlineOrderFlag { get; set; } + public int SalesCount { get; set; } + } +} \ No newline at end of file diff --git a/src/API/AdventureWorksDemo.Data/Repository/ReportingRepository.cs b/src/API/AdventureWorksDemo.Data/Repository/ReportingRepository.cs new file mode 100644 index 0000000..1734bcd --- /dev/null +++ b/src/API/AdventureWorksDemo.Data/Repository/ReportingRepository.cs @@ -0,0 +1,27 @@ +using AdventureWorksDemo.Data.DbContexts; +using AdventureWorksDemo.Data.Models.Reports; + +namespace AdventureWorksDemo.Data.Repository +{ + public interface IReportingRepository + { + IQueryable ReportOnLineVsOffLine(); + } + + public class ReportingRepository(AdventureWorksContext _context) : IReportingRepository + { + public IQueryable ReportOnLineVsOffLine() + { + return _context.SalesOrderHeaders + .GroupBy(o => new { OrderYear = o.OrderDate.Year, o.OnlineOrderFlag }) + .Select(g => new SalesSummaryByYear + { + OrderYear = g.Key.OrderYear, + OnlineOrderFlag = g.Key.OnlineOrderFlag, + SalesCount = g.Count() + }) + .OrderByDescending(x => x.OrderYear) + .ThenBy(x => x.OnlineOrderFlag); + } + } +} \ No newline at end of file diff --git a/src/API/AdventureWorksDemo.Data/Services/ReportService.cs b/src/API/AdventureWorksDemo.Data/Services/ReportService.cs new file mode 100644 index 0000000..301aa5d --- /dev/null +++ b/src/API/AdventureWorksDemo.Data/Services/ReportService.cs @@ -0,0 +1,15 @@ +using AdventureWorksDemo.Data.Models.Reports; +using AdventureWorksDemo.Data.Repository; + +namespace AdventureWorksDemo.Data.Services +{ + public interface IReportService + { + IQueryable ReportOnlineVsOffLine(); + } + + public class ReportService(IReportingRepository _repository) : IReportService + { + public IQueryable ReportOnlineVsOffLine() => _repository.ReportOnLineVsOffLine(); + } +} \ No newline at end of file diff --git a/src/API/AdventureWorksDemo.Data/StartUp/IOCData.cs b/src/API/AdventureWorksDemo.Data/StartUp/IOCData.cs index 0b384e9..569206d 100644 --- a/src/API/AdventureWorksDemo.Data/StartUp/IOCData.cs +++ b/src/API/AdventureWorksDemo.Data/StartUp/IOCData.cs @@ -36,6 +36,9 @@ public void ConfigureServices(IServiceCollection services) services.AddScoped, GenericCrudRepository
>(); services.AddScoped, GenericCrudRepository>(); services.AddScoped, GenericCrudRepository>(); + + services.AddTransient(); + services.AddTransient(); // Add Singleton's services.AddSingleton(TimeProvider.System); // Add validators From 5f838b7b690d77a6373906ea981e4b6a8647004e Mon Sep 17 00:00:00 2001 From: CodeTile <43536260+CodeTile@users.noreply.github.com> Date: Fri, 28 Feb 2025 17:06:07 +0000 Subject: [PATCH 02/12] Fix API endpoint issue --- .../AdventureWorksDemo.API.csproj | 1 + .../Controllers/GenericControllerBase.cs | 8 -- .../Controllers/ReportsController.cs | 9 +- src/API/AdventureWorksDemo.API/Program.cs | 21 ++-- ...{SalesSummaryByYear.cs => SalesSummary.cs} | 5 +- .../Repository/ReportingRepository.cs | 18 ++- .../Services/ReportService.cs | 4 +- .../Common/CommonResponse.cs | 7 ++ .../Common/Url.cs | 10 +- .../Components/Pages/Home.razor | 107 ++++++++++-------- .../appsettings.Development.json | 6 +- 11 files changed, 113 insertions(+), 83 deletions(-) rename src/API/AdventureWorksDemo.Data/Models/Reports/{SalesSummaryByYear.cs => SalesSummary.cs} (60%) diff --git a/src/API/AdventureWorksDemo.API/AdventureWorksDemo.API.csproj b/src/API/AdventureWorksDemo.API/AdventureWorksDemo.API.csproj index 9f9a280..22c57bf 100644 --- a/src/API/AdventureWorksDemo.API/AdventureWorksDemo.API.csproj +++ b/src/API/AdventureWorksDemo.API/AdventureWorksDemo.API.csproj @@ -9,6 +9,7 @@ + diff --git a/src/API/AdventureWorksDemo.API/Controllers/GenericControllerBase.cs b/src/API/AdventureWorksDemo.API/Controllers/GenericControllerBase.cs index ce5c4c4..af6c4c4 100644 --- a/src/API/AdventureWorksDemo.API/Controllers/GenericControllerBase.cs +++ b/src/API/AdventureWorksDemo.API/Controllers/GenericControllerBase.cs @@ -18,8 +18,6 @@ public abstract class GenericControllerBase(ILogger logger, internal readonly IService _service = service; [HttpPost()] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status400BadRequest)] public virtual async Task AddAsync([FromBody] TModel model) { WriteToTraceLog(nameof(GenericControllerBase), nameof(AddAsync)); @@ -31,8 +29,6 @@ public virtual async Task AddAsync([FromBody] TModel model) } [HttpDelete("id")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status400BadRequest)] public virtual async Task DeleteAsync(int id) { WriteToTraceLog(nameof(GenericControllerBase), nameof(DeleteAsync)); @@ -43,8 +39,6 @@ public virtual async Task DeleteAsync(int id) } [HttpGet()] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status404NotFound)] public virtual async Task FindAllAsync([FromBody] PageingFilter pageingFilter) { WriteToTraceLog(nameof(GenericControllerBase), nameof(FindAllAsync), "pageingFilter"); @@ -58,7 +52,6 @@ public virtual async Task FindAllAsync([FromBody] PageingFilter p } [HttpGet("id")] - [ProducesResponseType(StatusCodes.Status200OK)] public virtual async Task FindAsync(int id) { WriteToTraceLog(nameof(GenericControllerBase), nameof(FindAllAsync)); @@ -66,7 +59,6 @@ public virtual async Task FindAllAsync([FromBody] PageingFilter p } [HttpPut()] - [ProducesResponseType(StatusCodes.Status200OK)] public virtual async Task UpdateAsync([FromBody] TModel model) { WriteToTraceLog(nameof(GenericControllerBase), nameof(UpdateAsync), "model"); diff --git a/src/API/AdventureWorksDemo.API/Controllers/ReportsController.cs b/src/API/AdventureWorksDemo.API/Controllers/ReportsController.cs index 3977330..2ae9087 100644 --- a/src/API/AdventureWorksDemo.API/Controllers/ReportsController.cs +++ b/src/API/AdventureWorksDemo.API/Controllers/ReportsController.cs @@ -1,4 +1,5 @@ using AdventureWorksDemo.Data.Entities; +using AdventureWorksDemo.Data.Models.Reports; using AdventureWorksDemo.Data.Services; using Microsoft.AspNetCore.Mvc; @@ -7,15 +8,17 @@ namespace AdventureWorksDemo.API.Controllers { [ApiController] [Route("api/[controller]")] - public class ReportsController(ILogger logger, IReportService service) : Controller + public class ReportsController(ILogger logger, IReportService service) : ControllerBase { internal readonly ILogger _logger = logger; internal readonly IReportService _service = service; - [ProducesResponseType(StatusCodes.Status200OK)] + [HttpGet("onlinevsoffline")] + [ProducesResponseType(StatusCodes.Status200OK)] public virtual async Task ReportOnlineVsOffLine() { - return Ok(await Task.Run(() => _service.ReportOnlineVsOffLine())); + return Ok(await Task.Run(() => + _service.ReportOnlineVsOffLine())); } internal void WriteToTraceLog(string namespaceName, string methodName, string parmeterNames = "") diff --git a/src/API/AdventureWorksDemo.API/Program.cs b/src/API/AdventureWorksDemo.API/Program.cs index 1f7b3cd..e7c32bd 100644 --- a/src/API/AdventureWorksDemo.API/Program.cs +++ b/src/API/AdventureWorksDemo.API/Program.cs @@ -3,8 +3,6 @@ using AdventureWorksDemo.API.Exceptions; using AdventureWorksDemo.Data.StartUp; -using Microsoft.Extensions.DependencyInjection; - using Scalar.AspNetCore; namespace AdventureWorksDemo.API @@ -16,21 +14,30 @@ public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); - //Exception handling + ////Exception handling builder.Services.AddExceptionHandler(); builder.Services.AddProblemDetails(); + // Add child DI objects + new IocData(builder.Configuration).ConfigureServices(builder.Services); // Add controllers builder.Services.AddControllers(); - // Add child projects - new IocData(builder.Configuration).ConfigureServices(builder.Services); + // Add Cache Timeout + builder.Services.AddOutputCache(options => + { + options.AddBasePolicy(policy => policy.Expire(TimeSpan.FromMinutes(10))); + }); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddOpenApi(); var app = builder.Build(); + app.UseOutputCache(); + + app.UseExceptionHandler(); if (app.Environment.IsDevelopment()) { - app.MapOpenApi(); + app.MapOpenApi() + .CacheOutput(); app.MapScalarApiReference(); } @@ -40,8 +47,6 @@ public static void Main(string[] args) app.MapControllers(); - app.UseExceptionHandler(); - app.Run(); } } diff --git a/src/API/AdventureWorksDemo.Data/Models/Reports/SalesSummaryByYear.cs b/src/API/AdventureWorksDemo.Data/Models/Reports/SalesSummary.cs similarity index 60% rename from src/API/AdventureWorksDemo.Data/Models/Reports/SalesSummaryByYear.cs rename to src/API/AdventureWorksDemo.Data/Models/Reports/SalesSummary.cs index 17db621..d0b059f 100644 --- a/src/API/AdventureWorksDemo.Data/Models/Reports/SalesSummaryByYear.cs +++ b/src/API/AdventureWorksDemo.Data/Models/Reports/SalesSummary.cs @@ -1,8 +1,9 @@ namespace AdventureWorksDemo.Data.Models.Reports { - public record SalesSummaryByYear + public record SalesSummary { - public int OrderYear { get; set; } + public int Year { get; set; } + public int Month { get; set; } public bool OnlineOrderFlag { get; set; } public int SalesCount { get; set; } } diff --git a/src/API/AdventureWorksDemo.Data/Repository/ReportingRepository.cs b/src/API/AdventureWorksDemo.Data/Repository/ReportingRepository.cs index 1734bcd..fd6c5a9 100644 --- a/src/API/AdventureWorksDemo.Data/Repository/ReportingRepository.cs +++ b/src/API/AdventureWorksDemo.Data/Repository/ReportingRepository.cs @@ -5,22 +5,28 @@ namespace AdventureWorksDemo.Data.Repository { public interface IReportingRepository { - IQueryable ReportOnLineVsOffLine(); + IQueryable ReportOnLineVsOffLine(); } public class ReportingRepository(AdventureWorksContext _context) : IReportingRepository { - public IQueryable ReportOnLineVsOffLine() + public IQueryable ReportOnLineVsOffLine() { return _context.SalesOrderHeaders - .GroupBy(o => new { OrderYear = o.OrderDate.Year, o.OnlineOrderFlag }) - .Select(g => new SalesSummaryByYear + .GroupBy(o => new + { + Year = o.OrderDate.Year, + Month = o.OrderDate.Month, + o.OnlineOrderFlag + }) + .Select(g => new SalesSummary { - OrderYear = g.Key.OrderYear, + Year = g.Key.Year, + Month = g.Key.Month, OnlineOrderFlag = g.Key.OnlineOrderFlag, SalesCount = g.Count() }) - .OrderByDescending(x => x.OrderYear) + .OrderByDescending(x => x.Year) .ThenBy(x => x.OnlineOrderFlag); } } diff --git a/src/API/AdventureWorksDemo.Data/Services/ReportService.cs b/src/API/AdventureWorksDemo.Data/Services/ReportService.cs index 301aa5d..ed4439e 100644 --- a/src/API/AdventureWorksDemo.Data/Services/ReportService.cs +++ b/src/API/AdventureWorksDemo.Data/Services/ReportService.cs @@ -5,11 +5,11 @@ namespace AdventureWorksDemo.Data.Services { public interface IReportService { - IQueryable ReportOnlineVsOffLine(); + IQueryable ReportOnlineVsOffLine(); } public class ReportService(IReportingRepository _repository) : IReportService { - public IQueryable ReportOnlineVsOffLine() => _repository.ReportOnLineVsOffLine(); + public IQueryable ReportOnlineVsOffLine() => _repository.ReportOnLineVsOffLine(); } } \ No newline at end of file diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/CommonResponse.cs b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/CommonResponse.cs index d42d88d..356dce0 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/CommonResponse.cs +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/CommonResponse.cs @@ -13,6 +13,8 @@ public interface ICommonResponseGet { Task> FindAllAsync(GridState state, string defaultSorting, HttpClient httpClient); + Task ReportOnlineVsOfflineSales(HttpClient httpClient, int isOnline); + Task> UpdateAsync(T item, HttpClient httpClient); } @@ -48,6 +50,11 @@ public async Task> FindAllAsync(GridState state, string defaul }; } + public async Task ReportOnlineVsOfflineSales(HttpClient httpClient, int isOnline) + { + var url = Url.Report_OnlineVsOffLine; + } + public async Task> UpdateAsync(T item, HttpClient httpClient) { var json = System.Text.Json.JsonSerializer.Serialize(item); diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/Url.cs b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/Url.cs index 5dd3786..921ebb2 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/Url.cs +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/Url.cs @@ -1,5 +1,4 @@ - -using System.Runtime.InteropServices.Marshalling; +using System.Runtime.InteropServices.Marshalling; using AdventureWorksDemo.MudBlazor.Models; @@ -8,19 +7,22 @@ namespace AdventureWorksDemo.MudBlazor.Common public interface IUrl { string Administration_ProductDescription { get; } + string Report_OnlineVsOffLine { get; } Uri GetByModelType(Type T); } + public class Url(IConfiguration configuration) : IUrl { public string Administration_ProductDescription => $"{configuration["Api:base"]}{configuration["Api:productdescription"]}"; + public string Report_OnlineVsOffLine => $"{configuration["Api:Base"]}{configuration["Api:Reports:Base"]}{configuration["Api:Reports:OnlineVsOffLine"]}"; + public Uri GetByModelType(Type T) { if (T == typeof(ProductDescriptionModel)) return new Uri(Administration_ProductDescription); else throw new ArgumentOutOfRangeException(nameof(T), "Unknown type!"); - } } -} +} \ No newline at end of file diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Home.razor b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Home.razor index 9992eba..9e679ce 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Home.razor +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Home.razor @@ -1,59 +1,68 @@ @page "/" @using global::MudBlazor +@inject Common.ICommonResponseGet response Home -Hello, world! -Welcome to your new app, powered by MudBlazor and the .NET 8 Template! +Adventure Works - - You can find documentation and examples on our website here: - - www.mudblazor.com - - -
-Interactivity in this Template -
- - When you opt for the "Global" Interactivity Location,
- the render modes are defined in App.razor and consequently apply to all child components.
- In this case, providers are globally set in the MainLayout.
-
- On the other hand, if you choose the "Per page/component" Interactivity Location,
- it is necessary to include the
-
- <MudPopoverProvider />
- <MudDialogProvider />
- <MudSnackbarProvider />
-
- components on every interactive page.
-
- If a render mode is not specified for a page, it defaults to Server-Side Rendering (SSR),
- similar to this page. While MudBlazor allows pages to be rendered in SSR,
- please note that interactive features, such as buttons and dropdown menus, will not be functional. -

-What's New in Blazor with the Release of .NET 8 -
-Prerendering - - If you're exploring the features of .NET 8 Blazor,
you might be pleasantly surprised to learn that each page is prerendered on the server,
regardless of the selected render mode.

- This means that you'll need to inject all necessary services on the server,
even when opting for the wasm (WebAssembly) render mode.

- This prerendering functionality is crucial to ensuring that WebAssembly mode feels fast and responsive,
especially when it comes to initial page load times.

- For more information on how to detect prerendering and leverage the RenderContext, you can refer to the following link: - - More details - -
+
+ -InteractiveAuto - - A discussion on how to achieve this can be found here: - - More details - - \ No newline at end of file + /> + +
+ +@code { + private int Index = -1; //default value cannot be 0 -> first selectedindex is 0. + private ChartOptions _options = new ChartOptions + { + YAxisLines = false, + YAxisTicks = 500, + MaxNumYAxisTicks = 10, + YAxisRequireZeroPoint = true, + XAxisLines = false, + LineStrokeWidth = 1, + ShowLegend=true, + }; + + private TimeSeriesChartSeries _chart1 = new(); + private TimeSeriesChartSeries _chart2 = new(); + + private List _series = new(); + + private readonly Random _random = new Random(); + + protected override void OnInitialized() + { + base.OnInitialized(); + response.ReportOnlineVsOfflineSales(httpClient, 1); + var now = DateTime.Now; + + _chart1 = new TimeSeriesChartSeries + { + Index = 0, + Name = "Series 1", + Data = Enumerable.Range(-360, 360).Select(x => new TimeSeriesChartSeries.TimeValue(now.AddSeconds(x * 10), _random.Next(6000, 15000))).ToList(), + IsVisible = true, + Type = TimeSeriesDisplayType.Line + }; + + _chart2 = new TimeSeriesChartSeries + { + Index = 1, + Name = "Series 2", + Data = Enumerable.Range(-360, 360).Select(x => new TimeSeriesChartSeries.TimeValue(now.AddSeconds(x * 10), _random.Next(0, 7000))).ToList(), + IsVisible = true, + Type = TimeSeriesDisplayType.Area + }; + + _series.Add(_chart1); + _series.Add(_chart2); + + StateHasChanged(); + } +} \ No newline at end of file diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/appsettings.Development.json b/src/FrontEnd/AdventureWorksDemo.MudBlazor/appsettings.Development.json index b49edf4..2ce0e4e 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/appsettings.Development.json +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/appsettings.Development.json @@ -9,7 +9,11 @@ "Base": "https://localhost:7277/api/", "Address": "address", "ProductCategory": "productcategory", - "ProductDescription": "productdescription" + "ProductDescription": "productdescription", + "Reports": { + "Base": "reports/", + "OnlineVsOffLine": "onlinevsoffline" + } }, "Paging": { "PageCount": 25 } } \ No newline at end of file From 9c335faf78e6d7616ced41f6af9edb5f230e1a31 Mon Sep 17 00:00:00 2001 From: CodeTile <43536260+CodeTile@users.noreply.github.com> Date: Mon, 10 Mar 2025 11:53:18 +0000 Subject: [PATCH 03/12] Improve layout on home page --- .../Models/Reports/SalesSummary.cs | 5 +- .../Common/CommonResponse.cs | 35 ++++++- .../Common/JsonDataService.cs | 40 ++++++++ .../Components/Pages/Home.razor | 99 ++++++++++++------- .../Models/SalesSummary.cs | 29 ++++++ .../AdventureWorksDemo.MudBlazor/Program.cs | 6 +- 6 files changed, 174 insertions(+), 40 deletions(-) create mode 100644 src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/JsonDataService.cs create mode 100644 src/FrontEnd/AdventureWorksDemo.MudBlazor/Models/SalesSummary.cs diff --git a/src/API/AdventureWorksDemo.Data/Models/Reports/SalesSummary.cs b/src/API/AdventureWorksDemo.Data/Models/Reports/SalesSummary.cs index d0b059f..030aff9 100644 --- a/src/API/AdventureWorksDemo.Data/Models/Reports/SalesSummary.cs +++ b/src/API/AdventureWorksDemo.Data/Models/Reports/SalesSummary.cs @@ -1,4 +1,6 @@ -namespace AdventureWorksDemo.Data.Models.Reports +using Microsoft.VisualBasic; + +namespace AdventureWorksDemo.Data.Models.Reports { public record SalesSummary { @@ -6,5 +8,6 @@ public record SalesSummary public int Month { get; set; } public bool OnlineOrderFlag { get; set; } public int SalesCount { get; set; } + public DateTime Period => new(Year, Month, 1); } } \ No newline at end of file diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/CommonResponse.cs b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/CommonResponse.cs index 356dce0..67d53fc 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/CommonResponse.cs +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/CommonResponse.cs @@ -7,13 +7,16 @@ using MudBlazor; +using static System.Runtime.InteropServices.JavaScript.JSType; +using static MudBlazor.CategoryTypes; + namespace AdventureWorksDemo.MudBlazor.Common { public interface ICommonResponseGet { Task> FindAllAsync(GridState state, string defaultSorting, HttpClient httpClient); - Task ReportOnlineVsOfflineSales(HttpClient httpClient, int isOnline); + ////Task ReportOnlineVsOfflineSalesAsync(HttpClient httpClient, bool isOnline); Task> UpdateAsync(T item, HttpClient httpClient); } @@ -50,10 +53,32 @@ public async Task> FindAllAsync(GridState state, string defaul }; } - public async Task ReportOnlineVsOfflineSales(HttpClient httpClient, int isOnline) - { - var url = Url.Report_OnlineVsOffLine; - } + ////public async Task ReportOnlineVsOfflineSalesAsync(HttpClient httpClient, bool isOnline) + ////{ + //// var result = new TimeSeriesChartSeries() + //// { + //// Index = isOnline ? 0 : 1, + //// Name = isOnline ? "Online" : "Offline", + //// IsVisible = true, + //// Type = TimeSeriesDisplayType.Line, + //// }; + //// var request = new HttpRequestMessage + //// { + //// Method = HttpMethod.Get, + //// RequestUri = new Uri(Url.Report_OnlineVsOffLine), + //// }; + + //// var response = await httpClient.SendAsync(request).ConfigureAwait(false); + //// if (response.IsSuccessStatusCode) + //// { + //// var data = (await response!.Content!.ReadFromJsonAsync>()) ?? []; + //// result.Data = [.. data.Where(m => m.OnlineOrderFlag == isOnline) + //// !.OrderBy(m => m.GetHashCode()) + //// .Select(x => new TimeSeriesChartSeries.TimeValue(x.Period, x.SalesCount))]; + //// } + + //// return result; + ////} public async Task> UpdateAsync(T item, HttpClient httpClient) { diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/JsonDataService.cs b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/JsonDataService.cs new file mode 100644 index 0000000..6029c53 --- /dev/null +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/JsonDataService.cs @@ -0,0 +1,40 @@ +using Microsoft.Extensions.Caching.Memory; + +namespace AdventureWorksDemo.MudBlazor.Common +{ + public interface IJsonDataService + { + Task GetDataAsync(string url); + } + + public class JsonDataService : IJsonDataService + { + public JsonDataService(HttpClient httpClient, IMemoryCache cache) + { + _httpClient = httpClient; + _cache = cache; + } + + private readonly IMemoryCache _cache; + private readonly TimeSpan _cacheDuration = TimeSpan.FromMinutes(1); + private readonly HttpClient _httpClient; + + // Cache duration + public async Task GetDataAsync(string url) + { + if (_cache.TryGetValue(url, out T cachedData)) + { + return cachedData; // Return cached data if available + } + + T? data = await _httpClient.GetFromJsonAsync(url); + + if (data != null) + { + _cache.Set(url, data, _cacheDuration); // Cache the data + } + + return data; + } + } +} \ No newline at end of file diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Home.razor b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Home.razor index 9e679ce..60837e9 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Home.razor +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Home.razor @@ -1,22 +1,52 @@ @page "/" +@using AdventureWorksDemo.MudBlazor.Common @using global::MudBlazor @inject Common.ICommonResponseGet response - +@inject IUrl Url +@using Microsoft.Extensions.Caching.Memory; Home Adventure Works -
+@*
- - -
- + + *@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @code { + MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()); + IJsonDataService service; private int Index = -1; //default value cannot be 0 -> first selectedindex is 0. private ChartOptions _options = new ChartOptions { @@ -29,40 +59,43 @@ ShowLegend=true, }; - private TimeSeriesChartSeries _chart1 = new(); - private TimeSeriesChartSeries _chart2 = new(); + // private TimeSeriesChartSeries _chart1 = new(); + // private TimeSeriesChartSeries _chart2 = new(); private List _series = new(); private readonly Random _random = new Random(); - protected override void OnInitialized() - { - base.OnInitialized(); - response.ReportOnlineVsOfflineSales(httpClient, 1); - var now = DateTime.Now; + protected async override Task OnInitializedAsync() + { + service = new JsonDataService(httpClient, memoryCache); - _chart1 = new TimeSeriesChartSeries - { - Index = 0, - Name = "Series 1", - Data = Enumerable.Range(-360, 360).Select(x => new TimeSeriesChartSeries.TimeValue(now.AddSeconds(x * 10), _random.Next(6000, 15000))).ToList(), - IsVisible = true, - Type = TimeSeriesDisplayType.Line - }; + // _chart1 = await GetTimeSeriesAsync( true); + // _chart2 = await GetTimeSeriesAsync( false); + + _series.Add(await GetTimeSeriesAsync(true)); + _series.Add(await GetTimeSeriesAsync(false)); - _chart2 = new TimeSeriesChartSeries + StateHasChanged(); + await base.OnInitializedAsync(); + } + + private async Task GetTimeSeriesAsync (bool isOnline) + { + var result = new TimeSeriesChartSeries() { - Index = 1, - Name = "Series 2", - Data = Enumerable.Range(-360, 360).Select(x => new TimeSeriesChartSeries.TimeValue(now.AddSeconds(x * 10), _random.Next(0, 7000))).ToList(), + Index = isOnline ? 0 : 1, + Name = isOnline ? "Online" : "Offline", IsVisible = true, - Type = TimeSeriesDisplayType.Area + Type = TimeSeriesDisplayType.Line, }; - - _series.Add(_chart1); - _series.Add(_chart2); - - StateHasChanged(); + IEnumerable data = await service.GetDataAsync?>(Url.Report_OnlineVsOffLine) ?? []; + if (data != null && data.Any()) + { + result.Data = [.. data.Where(m => m.OnlineOrderFlag == isOnline) + !.OrderBy(m => m.Period.Ticks) + .Select(x => new TimeSeriesChartSeries.TimeValue(x.Period, x.SalesCount))]; + } + return result; } } \ No newline at end of file diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Models/SalesSummary.cs b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Models/SalesSummary.cs new file mode 100644 index 0000000..8a47a3e --- /dev/null +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Models/SalesSummary.cs @@ -0,0 +1,29 @@ +namespace AdventureWorksDemo.MudBlazor.Models +{ + public record SalesSummary + { + public int Year { get; set; } + public int Month { get; set; } + public bool OnlineOrderFlag { get; set; } + public int SalesCount { get; set; } + public DateTime Period => new(Year, Month, 1, 0, 0, 0, DateTimeKind.Utc); + ////public override int GetHashCode() + ////{ + //// return HashCode.Combine(Year, Month, OnlineOrderFlag); + ////} + + ////public int CompareTo(SalesSummary? other) + ////{ + //// if (other is null) return 1; + + //// // Sorting by Year, then Month, then OnlineOrderFlag, then SalesCount + //// int yearComparison = Year.CompareTo(other.Year); + //// if (yearComparison != 0) return yearComparison; + + //// int monthComparison = Month.CompareTo(other.Month); + //// if (monthComparison != 0) return monthComparison; + + //// return OnlineOrderFlag.CompareTo(other.OnlineOrderFlag); + ////} + } +} \ No newline at end of file diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Program.cs b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Program.cs index 3f72b29..d3e4727 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Program.cs +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Program.cs @@ -1,6 +1,8 @@ using AdventureWorksDemo.MudBlazor.Common; using AdventureWorksDemo.MudBlazor.Components; +using Microsoft.Extensions.Caching.Memory; + using MudBlazor.Services; namespace AdventureWorksDemo.MudBlazor @@ -24,8 +26,10 @@ public static void Main(string[] args) BaseAddress = new Uri(builder.Configuration["Api:Base"] ?? "") }); builder.Services.AddSingleton(typeof(IUrl), typeof(Url)); + builder.Services.AddScoped(typeof(IMemoryCache), typeof(MemoryCache)); + builder.Services.AddScoped(typeof(IJsonDataService), typeof(JsonDataService)); builder.Services.AddScoped(typeof(ICommonResponseGet), typeof(CommonResponse)); - + var app = builder.Build(); // Configure the HTTP request pipeline. From a2bba43bf8f1a9add61f113281416454b3adfdf5 Mon Sep 17 00:00:00 2001 From: CodeTile <43536260+CodeTile@users.noreply.github.com> Date: Tue, 11 Mar 2025 11:27:55 +0000 Subject: [PATCH 04/12] Sales by Territory chart #32 --- .../Controllers/ReportsController.cs | 16 +++- .../Models/Reports/SaleByTerritory.cs | 9 +++ .../Models/Reports/SalesSummary.cs | 4 +- .../Repository/ReportingRepository.cs | 16 +++- .../Services/ReportService.cs | 4 + .../Common/CommonResponse.cs | 35 +-------- .../Common/Url.cs | 2 + .../Pages/Charts/ChartOnlineVsOffline.razor | 60 +++++++++++++++ .../Pages/Charts/ChartSalesByTerritory.razor | 50 +++++++++++++ .../Components/Pages/Home.razor | 75 ++----------------- .../Models/SaleByTerritory.cs | 11 +++ .../Models/SalesSummary.cs | 18 ----- .../appsettings.Development.json | 3 +- 13 files changed, 174 insertions(+), 129 deletions(-) create mode 100644 src/API/AdventureWorksDemo.Data/Models/Reports/SaleByTerritory.cs create mode 100644 src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Charts/ChartOnlineVsOffline.razor create mode 100644 src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Charts/ChartSalesByTerritory.razor create mode 100644 src/FrontEnd/AdventureWorksDemo.MudBlazor/Models/SaleByTerritory.cs diff --git a/src/API/AdventureWorksDemo.API/Controllers/ReportsController.cs b/src/API/AdventureWorksDemo.API/Controllers/ReportsController.cs index 2ae9087..262cb6f 100644 --- a/src/API/AdventureWorksDemo.API/Controllers/ReportsController.cs +++ b/src/API/AdventureWorksDemo.API/Controllers/ReportsController.cs @@ -1,5 +1,5 @@ -using AdventureWorksDemo.Data.Entities; -using AdventureWorksDemo.Data.Models.Reports; +using AdventureWorksDemo.Data.Models.Reports; +using AdventureWorksDemo.Data.Repository; using AdventureWorksDemo.Data.Services; using Microsoft.AspNetCore.Mvc; @@ -17,8 +17,16 @@ public class ReportsController(ILogger logger, IReportService [ProducesResponseType(StatusCodes.Status200OK)] public virtual async Task ReportOnlineVsOffLine() { - return Ok(await Task.Run(() => - _service.ReportOnlineVsOffLine())); + WriteToTraceLog(nameof(AdventureWorksDemo.API.Controllers), nameof(ReportOnlineVsOffLine)); + return Ok(await Task.Run(() => _service.ReportOnlineVsOffLine())); + } + + [HttpGet("salesbyterritory")] + [ProducesResponseType(StatusCodes.Status200OK)] + public virtual async Task ReportSalesByTerritory() + { + WriteToTraceLog(nameof(AdventureWorksDemo.API.Controllers), nameof(ReportSalesByTerritory)); + return Ok(await Task.Run(() => _service.ReportSalesByTerritory())); } internal void WriteToTraceLog(string namespaceName, string methodName, string parmeterNames = "") diff --git a/src/API/AdventureWorksDemo.Data/Models/Reports/SaleByTerritory.cs b/src/API/AdventureWorksDemo.Data/Models/Reports/SaleByTerritory.cs new file mode 100644 index 0000000..130bfaf --- /dev/null +++ b/src/API/AdventureWorksDemo.Data/Models/Reports/SaleByTerritory.cs @@ -0,0 +1,9 @@ +namespace AdventureWorksDemo.Data.Repository +{ + public record SaleByTerritory + { + public string? CountryRegion { get; set; } + public decimal SalesLastYear { get; set; } + public decimal SalesYTD { get; set; } + } +} \ No newline at end of file diff --git a/src/API/AdventureWorksDemo.Data/Models/Reports/SalesSummary.cs b/src/API/AdventureWorksDemo.Data/Models/Reports/SalesSummary.cs index 030aff9..d8a4c30 100644 --- a/src/API/AdventureWorksDemo.Data/Models/Reports/SalesSummary.cs +++ b/src/API/AdventureWorksDemo.Data/Models/Reports/SalesSummary.cs @@ -1,6 +1,4 @@ -using Microsoft.VisualBasic; - -namespace AdventureWorksDemo.Data.Models.Reports +namespace AdventureWorksDemo.Data.Models.Reports { public record SalesSummary { diff --git a/src/API/AdventureWorksDemo.Data/Repository/ReportingRepository.cs b/src/API/AdventureWorksDemo.Data/Repository/ReportingRepository.cs index fd6c5a9..f3e8eda 100644 --- a/src/API/AdventureWorksDemo.Data/Repository/ReportingRepository.cs +++ b/src/API/AdventureWorksDemo.Data/Repository/ReportingRepository.cs @@ -6,9 +6,11 @@ namespace AdventureWorksDemo.Data.Repository public interface IReportingRepository { IQueryable ReportOnLineVsOffLine(); + + IQueryable ReportSalesByTerritory(); } - public class ReportingRepository(AdventureWorksContext _context) : IReportingRepository + public partial class ReportingRepository(AdventureWorksContext _context) : IReportingRepository { public IQueryable ReportOnLineVsOffLine() { @@ -29,5 +31,17 @@ public IQueryable ReportOnLineVsOffLine() .OrderByDescending(x => x.Year) .ThenBy(x => x.OnlineOrderFlag); } + + public IQueryable ReportSalesByTerritory() + { + return _context.SalesTerritories + .Select(m => new SaleByTerritory + { + CountryRegion = m.Name, + SalesYTD = m.SalesYtd, + SalesLastYear = m.SalesLastYear + }) + .OrderBy(m => m.CountryRegion); + } } } \ No newline at end of file diff --git a/src/API/AdventureWorksDemo.Data/Services/ReportService.cs b/src/API/AdventureWorksDemo.Data/Services/ReportService.cs index ed4439e..0d65b5c 100644 --- a/src/API/AdventureWorksDemo.Data/Services/ReportService.cs +++ b/src/API/AdventureWorksDemo.Data/Services/ReportService.cs @@ -6,10 +6,14 @@ namespace AdventureWorksDemo.Data.Services public interface IReportService { IQueryable ReportOnlineVsOffLine(); + + IQueryable ReportSalesByTerritory(); } public class ReportService(IReportingRepository _repository) : IReportService { public IQueryable ReportOnlineVsOffLine() => _repository.ReportOnLineVsOffLine(); + + public IQueryable ReportSalesByTerritory() => _repository.ReportSalesByTerritory(); } } \ No newline at end of file diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/CommonResponse.cs b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/CommonResponse.cs index 67d53fc..08f9efe 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/CommonResponse.cs +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/CommonResponse.cs @@ -1,5 +1,4 @@ -using System.Net; -using System.Net.Mime; +using System.Net.Mime; using System.Text; using System.Text.Json; @@ -7,17 +6,12 @@ using MudBlazor; -using static System.Runtime.InteropServices.JavaScript.JSType; -using static MudBlazor.CategoryTypes; - namespace AdventureWorksDemo.MudBlazor.Common { public interface ICommonResponseGet { Task> FindAllAsync(GridState state, string defaultSorting, HttpClient httpClient); - ////Task ReportOnlineVsOfflineSalesAsync(HttpClient httpClient, bool isOnline); - Task> UpdateAsync(T item, HttpClient httpClient); } @@ -53,33 +47,6 @@ public async Task> FindAllAsync(GridState state, string defaul }; } - ////public async Task ReportOnlineVsOfflineSalesAsync(HttpClient httpClient, bool isOnline) - ////{ - //// var result = new TimeSeriesChartSeries() - //// { - //// Index = isOnline ? 0 : 1, - //// Name = isOnline ? "Online" : "Offline", - //// IsVisible = true, - //// Type = TimeSeriesDisplayType.Line, - //// }; - //// var request = new HttpRequestMessage - //// { - //// Method = HttpMethod.Get, - //// RequestUri = new Uri(Url.Report_OnlineVsOffLine), - //// }; - - //// var response = await httpClient.SendAsync(request).ConfigureAwait(false); - //// if (response.IsSuccessStatusCode) - //// { - //// var data = (await response!.Content!.ReadFromJsonAsync>()) ?? []; - //// result.Data = [.. data.Where(m => m.OnlineOrderFlag == isOnline) - //// !.OrderBy(m => m.GetHashCode()) - //// .Select(x => new TimeSeriesChartSeries.TimeValue(x.Period, x.SalesCount))]; - //// } - - //// return result; - ////} - public async Task> UpdateAsync(T item, HttpClient httpClient) { var json = System.Text.Json.JsonSerializer.Serialize(item); diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/Url.cs b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/Url.cs index 921ebb2..bfe240f 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/Url.cs +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/Url.cs @@ -8,6 +8,7 @@ public interface IUrl { string Administration_ProductDescription { get; } string Report_OnlineVsOffLine { get; } + string Report_SalesByTerritory { get; } Uri GetByModelType(Type T); } @@ -16,6 +17,7 @@ public class Url(IConfiguration configuration) : IUrl { public string Administration_ProductDescription => $"{configuration["Api:base"]}{configuration["Api:productdescription"]}"; public string Report_OnlineVsOffLine => $"{configuration["Api:Base"]}{configuration["Api:Reports:Base"]}{configuration["Api:Reports:OnlineVsOffLine"]}"; + public string Report_SalesByTerritory => $"{configuration["Api:Base"]}{configuration["Api:Reports:Base"]}{configuration["Api:Reports:SalesByTerritory"]}"; public Uri GetByModelType(Type T) { diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Charts/ChartOnlineVsOffline.razor b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Charts/ChartOnlineVsOffline.razor new file mode 100644 index 0000000..6af6e1b --- /dev/null +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Charts/ChartOnlineVsOffline.razor @@ -0,0 +1,60 @@ +@page "/ChartOnlineVsOffline" +@using AdventureWorksDemo.MudBlazor.Common +@using global::MudBlazor +@inject Common.ICommonResponseGet response +@inject IUrl Url +@using Microsoft.Extensions.Caching.Memory; +Online vs Offline + + + + +@code { + MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()); + IJsonDataService service; + private int Index = -1; //default value cannot be 0 -> first selectedindex is 0. + private ChartOptions _options = new ChartOptions + { + YAxisLines = false, + YAxisTicks = 500, + MaxNumYAxisTicks = 10, + YAxisRequireZeroPoint = true, + XAxisLines = false, + LineStrokeWidth = 1, + ShowLegend = true, + }; + + + private List _series = new(); + + protected async override Task OnInitializedAsync() + { + service = new JsonDataService(httpClient, memoryCache); + + + _series.Add(await GetTimeSeriesAsync(true)); + _series.Add(await GetTimeSeriesAsync(false)); + + StateHasChanged(); + await base.OnInitializedAsync(); + } + + private async Task GetTimeSeriesAsync(bool isOnline) + { + var result = new TimeSeriesChartSeries() + { + Index = isOnline ? 0 : 1, + Name = isOnline ? "Online" : "Offline", + IsVisible = true, + Type = TimeSeriesDisplayType.Line, + }; + IEnumerable data = await service.GetDataAsync?>(Url.Report_OnlineVsOffLine) ?? []; + if (data != null && data.Any()) + { + result.Data = [.. data.Where(m => m.OnlineOrderFlag == isOnline) + !.OrderBy(m => m.Period.Ticks) + .Select(x => new TimeSeriesChartSeries.TimeValue(x.Period, x.SalesCount))]; + } + return result; + } +} \ No newline at end of file diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Charts/ChartSalesByTerritory.razor b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Charts/ChartSalesByTerritory.razor new file mode 100644 index 0000000..0a09799 --- /dev/null +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Charts/ChartSalesByTerritory.razor @@ -0,0 +1,50 @@ +@page "/ChartSalesByTerritory" +@using AdventureWorksDemo.MudBlazor.Common +@using global::MudBlazor +@inject Common.ICommonResponseGet response +@inject IUrl Url +@using Microsoft.Extensions.Caching.Memory; +Sales by Territory + + + + +@code { + MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()); + IJsonDataService service; + + private ChartOptions _options = new ChartOptions + { + YAxisLines = false, + YAxisTicks = 1, + MaxNumYAxisTicks = 10, + YAxisRequireZeroPoint = true, + XAxisLines = false, + LineStrokeWidth = 1, + ShowLegend = true, + ShowToolTips=true, + + }; + private int Index = -1; //default value cannot be 0 -> first selectedindex is 0. + private readonly List _series = new(); + + private readonly string?[] _XAxisLabels= { "Year to Date","Last Year" }; + protected async override Task OnInitializedAsync() + { + service = new JsonDataService(httpClient, memoryCache); + var rawData = await service.GetDataAsync?>(Url.Report_SalesByTerritory); + if (rawData != null && rawData.Any()) + { + foreach (SaleByTerritory item in rawData) + { + _series.Add(new ChartSeries() { Name = item.CountryRegion ?? "???", + Data = new double[] { item.SalesYTDToDisplay,item.SalesLastYearToDisplay } }); + } + } + + StateHasChanged(); + await base.OnInitializedAsync(); + } + } \ No newline at end of file diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Home.razor b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Home.razor index 60837e9..62de7c9 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Home.razor +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Home.razor @@ -1,22 +1,14 @@ @page "/" -@using AdventureWorksDemo.MudBlazor.Common @using global::MudBlazor -@inject Common.ICommonResponseGet response -@inject IUrl Url -@using Microsoft.Extensions.Caching.Memory; +@using AdventureWorksDemo.MudBlazor.Components.Pages.Charts; Home Adventure Works - -@*
-
- -
*@ - +@* @@ -24,16 +16,16 @@ - + *@ - + - + - + @* @@ -41,61 +33,8 @@ - + *@ @code { - MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()); - IJsonDataService service; - private int Index = -1; //default value cannot be 0 -> first selectedindex is 0. - private ChartOptions _options = new ChartOptions - { - YAxisLines = false, - YAxisTicks = 500, - MaxNumYAxisTicks = 10, - YAxisRequireZeroPoint = true, - XAxisLines = false, - LineStrokeWidth = 1, - ShowLegend=true, - }; - - // private TimeSeriesChartSeries _chart1 = new(); - // private TimeSeriesChartSeries _chart2 = new(); - - private List _series = new(); - - private readonly Random _random = new Random(); - - protected async override Task OnInitializedAsync() - { - service = new JsonDataService(httpClient, memoryCache); - - // _chart1 = await GetTimeSeriesAsync( true); - // _chart2 = await GetTimeSeriesAsync( false); - - _series.Add(await GetTimeSeriesAsync(true)); - _series.Add(await GetTimeSeriesAsync(false)); - - StateHasChanged(); - await base.OnInitializedAsync(); - } - - private async Task GetTimeSeriesAsync (bool isOnline) - { - var result = new TimeSeriesChartSeries() - { - Index = isOnline ? 0 : 1, - Name = isOnline ? "Online" : "Offline", - IsVisible = true, - Type = TimeSeriesDisplayType.Line, - }; - IEnumerable data = await service.GetDataAsync?>(Url.Report_OnlineVsOffLine) ?? []; - if (data != null && data.Any()) - { - result.Data = [.. data.Where(m => m.OnlineOrderFlag == isOnline) - !.OrderBy(m => m.Period.Ticks) - .Select(x => new TimeSeriesChartSeries.TimeValue(x.Period, x.SalesCount))]; - } - return result; - } } \ No newline at end of file diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Models/SaleByTerritory.cs b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Models/SaleByTerritory.cs new file mode 100644 index 0000000..d5d0dc2 --- /dev/null +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Models/SaleByTerritory.cs @@ -0,0 +1,11 @@ +namespace AdventureWorksDemo.MudBlazor.Models +{ + public record SaleByTerritory() + { + public string? CountryRegion { get; set; } + public decimal SalesLastYear { get; set; } + public decimal SalesYTD { get; set; } + public double SalesYTDToDisplay => Convert.ToDouble(SalesYTD / 1000000); + public double SalesLastYearToDisplay => Convert.ToDouble(SalesLastYear / 1000000); + } +} \ No newline at end of file diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Models/SalesSummary.cs b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Models/SalesSummary.cs index 8a47a3e..f03bc6b 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Models/SalesSummary.cs +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Models/SalesSummary.cs @@ -7,23 +7,5 @@ public record SalesSummary public bool OnlineOrderFlag { get; set; } public int SalesCount { get; set; } public DateTime Period => new(Year, Month, 1, 0, 0, 0, DateTimeKind.Utc); - ////public override int GetHashCode() - ////{ - //// return HashCode.Combine(Year, Month, OnlineOrderFlag); - ////} - - ////public int CompareTo(SalesSummary? other) - ////{ - //// if (other is null) return 1; - - //// // Sorting by Year, then Month, then OnlineOrderFlag, then SalesCount - //// int yearComparison = Year.CompareTo(other.Year); - //// if (yearComparison != 0) return yearComparison; - - //// int monthComparison = Month.CompareTo(other.Month); - //// if (monthComparison != 0) return monthComparison; - - //// return OnlineOrderFlag.CompareTo(other.OnlineOrderFlag); - ////} } } \ No newline at end of file diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/appsettings.Development.json b/src/FrontEnd/AdventureWorksDemo.MudBlazor/appsettings.Development.json index 2ce0e4e..0460573 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/appsettings.Development.json +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/appsettings.Development.json @@ -12,7 +12,8 @@ "ProductDescription": "productdescription", "Reports": { "Base": "reports/", - "OnlineVsOffLine": "onlinevsoffline" + "OnlineVsOffLine": "onlinevsoffline", + "SalesByTerritory": "salesbyterritory" } }, "Paging": { "PageCount": 25 } From 2051aba09332feb33ed67d3ce54c9a1861dac778 Mon Sep 17 00:00:00 2001 From: CodeTile <43536260+CodeTile@users.noreply.github.com> Date: Tue, 11 Mar 2025 17:05:43 +0000 Subject: [PATCH 05/12] Report Tests 1. ReportSalesByTerritoryTests 2. ReportOnLineVsOffLineTests #32 --- .../Controllers/ReportsController.cs | 1 - .../ReportOnLineVsOffLine.feature | 15 +++ .../ReportSalesByTerritory.feature | 22 ++++ .../StepDefinitions/StepDefinitions.cs | 105 +++++++++++------- .../Models/Reports/SaleByTerritory.cs | 2 +- .../Services/ReportService.cs | 4 +- 6 files changed, 107 insertions(+), 42 deletions(-) create mode 100644 src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ReportService/ReportOnLineVsOffLine.feature create mode 100644 src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ReportService/ReportSalesByTerritory.feature diff --git a/src/API/AdventureWorksDemo.API/Controllers/ReportsController.cs b/src/API/AdventureWorksDemo.API/Controllers/ReportsController.cs index 262cb6f..54f554e 100644 --- a/src/API/AdventureWorksDemo.API/Controllers/ReportsController.cs +++ b/src/API/AdventureWorksDemo.API/Controllers/ReportsController.cs @@ -1,5 +1,4 @@ using AdventureWorksDemo.Data.Models.Reports; -using AdventureWorksDemo.Data.Repository; using AdventureWorksDemo.Data.Services; using Microsoft.AspNetCore.Mvc; diff --git a/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ReportService/ReportOnLineVsOffLine.feature b/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ReportService/ReportOnLineVsOffLine.feature new file mode 100644 index 0000000..b7b02d2 --- /dev/null +++ b/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ReportService/ReportOnLineVsOffLine.feature @@ -0,0 +1,15 @@ +Feature:ReportOnLineVsOffLineTests + +Tests for the report ReportOnLineVsOffLine + +Background: + Given The service to test is 'AdventureWorksDemo.Data.Services.IReportService' + And I don't reset the database after the scenario + + Scenario: debug + When I call the method 'ReportOnlineVsOffLine' + Then the result is of type + | Expected | + | Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable | + And the results are + | Year | Month | OnlineOrderFlag | SalesCount | Period | diff --git a/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ReportService/ReportSalesByTerritory.feature b/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ReportService/ReportSalesByTerritory.feature new file mode 100644 index 0000000..b25286d --- /dev/null +++ b/src/API/AdventureWorksDemo.Data.Tests.reqnroll/Features/Services/ReportService/ReportSalesByTerritory.feature @@ -0,0 +1,22 @@ +Feature: ReportSalesByTerritoryTests + +Tests for the report ReportOnLineVsOffLine + +Background: + Given The service to test is 'AdventureWorksDemo.Data.Services.IReportService' + And I don't reset the database after the scenario + +Scenario: debug + When I call the method 'ReportSalesByTerritory' + Then the result is of type + | Expected | + | Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable | + And the results are + | CountryRegion | SalesLastYear | SalesYTD | + | Australia | 2278548.9800 | 5977814.9200 | + | Canada | 5693988.8600 | 6771829.1400 | + | Delete Orphan | 0.0000 | 0.0000 | + | France | 2396539.7600 | 4772398.3100 | + | Germany | 1307949.7900 | 3805202.3500 | + | Tokelau | 2344344.4000 | 4325344.3700 | + | United Kingdom | 1635823.4000 | 5012905.3700 | diff --git a/src/API/AdventureWorksDemo.Data.Tests.reqnroll/StepDefinitions/StepDefinitions.cs b/src/API/AdventureWorksDemo.Data.Tests.reqnroll/StepDefinitions/StepDefinitions.cs index b522f29..9f58721 100644 --- a/src/API/AdventureWorksDemo.Data.Tests.reqnroll/StepDefinitions/StepDefinitions.cs +++ b/src/API/AdventureWorksDemo.Data.Tests.reqnroll/StepDefinitions/StepDefinitions.cs @@ -5,6 +5,7 @@ using AdventureWorksDemo.Common.Tests.Extensions; using AdventureWorksDemo.Data.Models; +using AdventureWorksDemo.Data.Models.Reports; using AdventureWorksDemo.Data.Paging; using AdventureWorksDemo.Data.Services; using AdventureWorksDemo.Data.Tests.reqnroll.Helpers; @@ -38,6 +39,11 @@ public void GivenTheServiceToTestIs(string uotName) Helper.ScenarioContexts.AddToContext(ScenarioContextKey.UOT, Helper.Ioc.ResolveObject()); break; + case "AdventureWorksDemo.Data.Services.IReportService": + case "AdventureWorksDemo.Data.Services.ReportService": + Helper.ScenarioContexts.AddToContext(ScenarioContextKey.UOT, Helper.Ioc.ResolveObject()); + break; + case "AdventureWorksDemo.Data.Services.IProductCategoryService": case "AdventureWorksDemo.Data.Services.ProductCategoryService": Helper.ScenarioContexts.AddToContext(ScenarioContextKey.UOT, Helper.Ioc.ResolveObject()); @@ -69,7 +75,7 @@ public void ThenTheExceptionMessageIs(DataTable dataTable) public void ThenThePagedListValuesAre(DataTable expected) { IPagedList actual = (IPagedList)Helper.ScenarioContexts.GetResult; - List actualAsList = new() { actual }; + List actualAsList = [actual]; expected.CompareToSet(actualAsList); } @@ -80,15 +86,14 @@ public void ThenTheResultIs(DataTable table) var contextResult = Helper.ScenarioContexts.GetResult; string? resultTypeName = contextResult.GetType().FullNameReadable(); - switch (contextResult) { case bool: - table.CompareToSet(new List() { new ValueExpectedResult() { Expected = ((bool)contextResult).ToString() } }); + table.CompareToSet([new ValueExpectedResult() { Expected = ((bool)contextResult).ToString() }]); break; case Exception: - table.CompareToSet(new List() { resultTypeName }); + table.CompareToSet([resultTypeName]); break; case AdventureWorksDemo.Data.Models.AddressModel: @@ -123,7 +128,9 @@ public void ThenTheResultIs(DataTable table) break; default: + //table.CompareToSet(contextResult); throw new NotImplementedException($"Type [{resultTypeName}] is not handled in step {nameof(ThenTheResultIs)}!"); + break; } } @@ -190,19 +197,29 @@ public void ThenTheSortedResultsAre(DataTable table) CompareResults(table, true); } + [When("I call the method {string}")] + public async Task WhenICallTheMethodAsync(string methodName) + { + await WhenICallTheMethodWithTheParameterValuesAsync(methodName, null); + } + [When("I call the method {string} with the parameter values")] - public async Task WhenICallTheMethodWithTheParameterValuesAsync(string methodName, DataTable table) + public async Task WhenICallTheMethodWithTheParameterValuesAsync(string methodName, DataTable? table) { - if (table.Rows.Count == 0) + if (table?.Rows.Count == 0) { throw new Exception("Table is empty"); } - var methodParameters = GetParametersFromDataTable(table); + KeyValueTypeName[] methodParameters = []; + if (table != null) + { + methodParameters = GetParametersFromDataTable(table); + } var uot = Helper.ScenarioContexts.GetUot; var result = await GetMethodValueForObjectAsync(uot, - methodName, - methodParameters); + methodName, + methodParameters); if (result.Item1.FullName.Contains("Task")) { var t = result.Item1.GenericTypeArguments.FirstOrDefault(); @@ -221,16 +238,6 @@ public void WhenIPopulateAListOfTheModel(string modelTypeName, DataTable table) Helper.ScenarioContexts.AddToContext(ScenarioContextKey.ListOfObjects, models); } - //[When("I populate a list of type {string}")] - //public void WhenIPopulateAListOfStrings(string typeName, DataTable dataTable) - //{ - // var list = Helper.Types.CreateListByTypeName(typeName); - // for (int i = 0; i < dataTable.Rows.Count; i++) - // { - // list.Add(dataTable.Rows[i][0]); - // } - // Helper.ScenarioContexts.AddToContext(ScenarioContextKey.ListOfObjects, list); - //} [When("I populate the model {string}")] public void WhenIPopulateTheModel(string modelTypeName, DataTable dataTable) { @@ -285,6 +292,8 @@ private void CompareResults(DataTable table, bool compareSorted) { case "System.Exception": table.CompareToSet([resultTypeName]); break; case "AdventureWorksDemo.Data.Models.AddressModel": table.CompareToSet((IEnumerable)actual, compareSorted); break; + case "AdventureWorksDemo.Data.Models.Reports.SalesSummary": table.CompareToSet((IEnumerable)actual, compareSorted); break; + case "AdventureWorksDemo.Data.Models.Reports.SaleByTerritory": table.CompareToSet((IEnumerable)actual, compareSorted); break; case "AdventureWorksDemo.Data.Models.ProductCategoryModel": table.CompareToSet((IEnumerable)actual, compareSorted); break; case "AdventureWorksDemo.Data.Models.ProductDescriptionModel": table.CompareToSet((IEnumerable)actual, compareSorted); break; default: throw new NotImplementedException($"Type [{resultTypeName}] is not implemented!"); @@ -334,9 +343,9 @@ private IList CreateList(Type myType) private async Task> GetMethodValueForObjectAsync(dynamic target, string methodName, - KeyValueTypeName[] arguments) + KeyValueTypeName[]? arguments) { - if (target == null) throw new ArgumentNullException("target"); + ArgumentNullException.ThrowIfNull(target); Tuple retval = null; await Task.Delay(0); Type t = target.GetType(); @@ -383,37 +392,58 @@ private KeyValueTypeName[] GetParametersFromDataTable(DataTable table) return args.ToArray(); } - private async Task InvokeMethod(object target, object[] args, dynamic method) + private async Task InvokeMethod(object target, object[] args, MethodInfo method) { - dynamic actionResult; - if (await IsMethodAsync(method)) - { - actionResult = await method.Invoke(target, args); - } - else + if (method == null) throw new ArgumentNullException(nameof(method)); + if (target == null) throw new ArgumentNullException(nameof(target)); + + object actionResult; + + try { - var nonAsyncResult = method.Invoke(target, args); - try + if (IsMethodAsynchronous(method)) { - if (!typeof(IEnumerable).IsAssignableFrom(nonAsyncResult)) + var result = method.Invoke(target, args); + if (result is Task task) { - actionResult = nonAsyncResult; + await task.ConfigureAwait(false); + actionResult = task.GetType().IsGenericType ? ((dynamic)task).Result : null; } else { - actionResult = nonAsyncResult.Expression.Value; + actionResult = result; } } - catch (Exception) + else { - actionResult = nonAsyncResult; + var nonAsyncResult = method.Invoke(target, args); + actionResult = nonAsyncResult is IEnumerable enumerable ? enumerable : nonAsyncResult; } } + catch (Exception ex) + { + // Log exception (if needed) + throw new InvalidOperationException($"Error invoking method {method.Name}.", ex); + } return actionResult; } - private async Task> InvokeMethodReturnValue(object target, object[] args, dynamic method) + //private async Task InvokeMethod(object target, object[] args, dynamic method) + //{ + // ArgumentNullException.ThrowIfNull(method); + // ArgumentNullException.ThrowIfNull(target); + + // dynamic actionResult; if (IsMethodAsynchronous(method)) { actionResult = await + // method.Invoke(target, args); } else { var nonAsyncResult = method.Invoke(target, args); + // try { if (!typeof(IEnumerable).IsAssignableFrom(nonAsyncResult)) { actionResult = + // nonAsyncResult; } else { actionResult = nonAsyncResult.Expression.Value; } } catch + // (Exception) { actionResult = nonAsyncResult; } } + + // return actionResult; + //} + + private async Task> InvokeMethodReturnValue(object target, object[]? args, dynamic method) { dynamic actionResult = await InvokeMethod(target, args, method); @@ -428,9 +458,8 @@ private async Task> InvokeMethodReturnValue(object target, o } } - private async Task IsMethodAsync(dynamic method) + private bool IsMethodAsynchronous(dynamic method) { - await Task.Delay(0); IReadOnlyCollection r = method.CustomAttributes; return r.Any(w => w.AttributeType?.Name == "AsyncStateMachineAttribute"); } diff --git a/src/API/AdventureWorksDemo.Data/Models/Reports/SaleByTerritory.cs b/src/API/AdventureWorksDemo.Data/Models/Reports/SaleByTerritory.cs index 130bfaf..affa3cb 100644 --- a/src/API/AdventureWorksDemo.Data/Models/Reports/SaleByTerritory.cs +++ b/src/API/AdventureWorksDemo.Data/Models/Reports/SaleByTerritory.cs @@ -1,4 +1,4 @@ -namespace AdventureWorksDemo.Data.Repository +namespace AdventureWorksDemo.Data.Models.Reports { public record SaleByTerritory { diff --git a/src/API/AdventureWorksDemo.Data/Services/ReportService.cs b/src/API/AdventureWorksDemo.Data/Services/ReportService.cs index 0d65b5c..66a62d0 100644 --- a/src/API/AdventureWorksDemo.Data/Services/ReportService.cs +++ b/src/API/AdventureWorksDemo.Data/Services/ReportService.cs @@ -12,8 +12,8 @@ public interface IReportService public class ReportService(IReportingRepository _repository) : IReportService { - public IQueryable ReportOnlineVsOffLine() => _repository.ReportOnLineVsOffLine(); + public IQueryable ReportOnlineVsOffLine() => _repository.ReportOnLineVsOffLine().AsQueryable(); - public IQueryable ReportSalesByTerritory() => _repository.ReportSalesByTerritory(); + public IQueryable ReportSalesByTerritory() => _repository.ReportSalesByTerritory().AsQueryable(); } } \ No newline at end of file From 654d5bd34a8b713561f1d87e7a4ff75bb8b96917 Mon Sep 17 00:00:00 2001 From: CodeTile <43536260+CodeTile@users.noreply.github.com> Date: Wed, 12 Mar 2025 17:04:29 +0000 Subject: [PATCH 06/12] Fix issue with cache not being used --- .../Common/JsonDataService.cs | 16 ++++------------ .../Pages/Charts/ChartOnlineVsOffline.razor | 7 ++----- .../Pages/Charts/ChartSalesByTerritory.razor | 18 ++++++++---------- .../AdventureWorksDemo.MudBlazor/Program.cs | 1 + 4 files changed, 15 insertions(+), 27 deletions(-) diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/JsonDataService.cs b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/JsonDataService.cs index 6029c53..5282a7e 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/JsonDataService.cs +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/JsonDataService.cs @@ -4,30 +4,22 @@ namespace AdventureWorksDemo.MudBlazor.Common { public interface IJsonDataService { - Task GetDataAsync(string url); + Task GetDataAsync(string url, HttpClient httpClient); } - public class JsonDataService : IJsonDataService + public class JsonDataService(IMemoryCache _cache) : IJsonDataService { - public JsonDataService(HttpClient httpClient, IMemoryCache cache) - { - _httpClient = httpClient; - _cache = cache; - } - - private readonly IMemoryCache _cache; private readonly TimeSpan _cacheDuration = TimeSpan.FromMinutes(1); - private readonly HttpClient _httpClient; // Cache duration - public async Task GetDataAsync(string url) + public async Task GetDataAsync(string url, HttpClient httpClient) { if (_cache.TryGetValue(url, out T cachedData)) { return cachedData; // Return cached data if available } - T? data = await _httpClient.GetFromJsonAsync(url); + T? data = await httpClient.GetFromJsonAsync(url); if (data != null) { diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Charts/ChartOnlineVsOffline.razor b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Charts/ChartOnlineVsOffline.razor index 6af6e1b..1e3caaf 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Charts/ChartOnlineVsOffline.razor +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Charts/ChartOnlineVsOffline.razor @@ -3,15 +3,13 @@ @using global::MudBlazor @inject Common.ICommonResponseGet response @inject IUrl Url -@using Microsoft.Extensions.Caching.Memory; +@inject IJsonDataService _jsonDataService Online vs Offline @code { - MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()); - IJsonDataService service; private int Index = -1; //default value cannot be 0 -> first selectedindex is 0. private ChartOptions _options = new ChartOptions { @@ -29,7 +27,6 @@ protected async override Task OnInitializedAsync() { - service = new JsonDataService(httpClient, memoryCache); _series.Add(await GetTimeSeriesAsync(true)); @@ -48,7 +45,7 @@ IsVisible = true, Type = TimeSeriesDisplayType.Line, }; - IEnumerable data = await service.GetDataAsync?>(Url.Report_OnlineVsOffLine) ?? []; + IEnumerable data = await _jsonDataService.GetDataAsync?>(Url.Report_OnlineVsOffLine,httpClient) ?? []; if (data != null && data.Any()) { result.Data = [.. data.Where(m => m.OnlineOrderFlag == isOnline) diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Charts/ChartSalesByTerritory.razor b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Charts/ChartSalesByTerritory.razor index 0a09799..6b2b292 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Charts/ChartSalesByTerritory.razor +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Components/Pages/Charts/ChartSalesByTerritory.razor @@ -3,7 +3,7 @@ @using global::MudBlazor @inject Common.ICommonResponseGet response @inject IUrl Url -@using Microsoft.Extensions.Caching.Memory; +@inject IJsonDataService _jsonDataService Sales by Territory @@ -12,35 +12,33 @@ ChartOptions="@_options" > @code { - MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()); - IJsonDataService service; + IJsonDataService? service; private ChartOptions _options = new ChartOptions { YAxisLines = false, YAxisTicks = 1, MaxNumYAxisTicks = 10, - YAxisRequireZeroPoint = true, + YAxisRequireZeroPoint = false, XAxisLines = false, - LineStrokeWidth = 1, + LineStrokeWidth = 3, ShowLegend = true, ShowToolTips=true, - + ShowLabels= true, }; private int Index = -1; //default value cannot be 0 -> first selectedindex is 0. private readonly List _series = new(); - private readonly string?[] _XAxisLabels= { "Year to Date","Last Year" }; + private readonly string?[] _XAxisLabels= { "","Year to Date","Last Year",""}; protected async override Task OnInitializedAsync() { - service = new JsonDataService(httpClient, memoryCache); - var rawData = await service.GetDataAsync?>(Url.Report_SalesByTerritory); + var rawData = await _jsonDataService.GetDataAsync?>(Url.Report_SalesByTerritory,httpClient); if (rawData != null && rawData.Any()) { foreach (SaleByTerritory item in rawData) { _series.Add(new ChartSeries() { Name = item.CountryRegion ?? "???", - Data = new double[] { item.SalesYTDToDisplay,item.SalesLastYearToDisplay } }); + Data = new double[] {0,item.SalesYTDToDisplay,item.SalesLastYearToDisplay,0 } }); } } diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Program.cs b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Program.cs index d3e4727..277ea02 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Program.cs +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Program.cs @@ -25,6 +25,7 @@ public static void Main(string[] args) { BaseAddress = new Uri(builder.Configuration["Api:Base"] ?? "") }); + // add singleton's builder.Services.AddSingleton(typeof(IUrl), typeof(Url)); builder.Services.AddScoped(typeof(IMemoryCache), typeof(MemoryCache)); builder.Services.AddScoped(typeof(IJsonDataService), typeof(JsonDataService)); From aa780c42d8722919ebb7d3d5754fc8023e435cf9 Mon Sep 17 00:00:00 2001 From: CodeTile <43536260+CodeTile@users.noreply.github.com> Date: Thu, 13 Mar 2025 09:21:20 +0000 Subject: [PATCH 07/12] Tests for Url building class #32 --- .../Common/UrlTests.cs | 81 +++++++++++++++++++ .../Common/Url.cs | 4 +- 2 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 src/AdventureWorksDemo.MudBlazor.Tests/Common/UrlTests.cs diff --git a/src/AdventureWorksDemo.MudBlazor.Tests/Common/UrlTests.cs b/src/AdventureWorksDemo.MudBlazor.Tests/Common/UrlTests.cs new file mode 100644 index 0000000..57377cb --- /dev/null +++ b/src/AdventureWorksDemo.MudBlazor.Tests/Common/UrlTests.cs @@ -0,0 +1,81 @@ +using System; + +using AdventureWorksDemo.MudBlazor.Common; + +using Microsoft.Extensions.Configuration; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using AdventureWorksDemo.MudBlazor.Models; +using Moq; + +namespace AdventureWorksDemo.MudBlazor.Tests.Common +{ + [TestClass] + public class UrlTests + { + private Mock _configurationMock; + private IUrl _url; + + [TestMethod] + public void Administration_ProductDescription_ShouldReturnCorrectUrl() + { + // Act + var result = _url.Administration_ProductDescription; + + // Assert + Assert.AreEqual("https://api.example.com/product/description", result); + } + + [TestMethod] + public void GetByModelType_WithProductDescriptionModel_ShouldReturnCorrectUri() + { + // Act + var result = _url.GetByModelType(typeof(ProductDescriptionModel)); + + // Assert + Assert.AreEqual(new Uri("https://api.example.com/product/description"), result); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentOutOfRangeException))] + public void GetByModelType_WithUnknownType_ShouldThrowArgumentOutOfRangeException() + { + // Act + _url.GetByModelType(typeof(string)); + } + + [TestMethod] + public void Report_OnlineVsOffLine_ShouldReturnCorrectUrl() + { + // Act + var result = _url.Report_OnlineVsOffLine; + + // Assert + Assert.AreEqual("https://api.example.com/reports/online-vs-offline", result); + } + + [TestMethod] + public void Report_SalesByTerritory_ShouldReturnCorrectUrl() + { + // Act + var result = _url.Report_SalesByTerritory; + + // Assert + Assert.AreEqual("https://api.example.com/reports/sales-by-territory", result); + } + + [TestInitialize] + public void Setup() + { + _configurationMock = new Mock(); + + _configurationMock.Setup(x => x["Api:base"]).Returns("https://api.example.com/"); + _configurationMock.Setup(x => x["Api:productdescription"]).Returns("product/description"); + _configurationMock.Setup(x => x["Api:Reports:Base"]).Returns("reports/"); + _configurationMock.Setup(x => x["Api:Reports:OnlineVsOffLine"]).Returns("online-vs-offline"); + _configurationMock.Setup(x => x["Api:Reports:SalesByTerritory"]).Returns("sales-by-territory"); + + _url = new Url(_configurationMock.Object); + } + } +} \ No newline at end of file diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/Url.cs b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/Url.cs index bfe240f..5207d6a 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/Url.cs +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/Url.cs @@ -16,8 +16,8 @@ public interface IUrl public class Url(IConfiguration configuration) : IUrl { public string Administration_ProductDescription => $"{configuration["Api:base"]}{configuration["Api:productdescription"]}"; - public string Report_OnlineVsOffLine => $"{configuration["Api:Base"]}{configuration["Api:Reports:Base"]}{configuration["Api:Reports:OnlineVsOffLine"]}"; - public string Report_SalesByTerritory => $"{configuration["Api:Base"]}{configuration["Api:Reports:Base"]}{configuration["Api:Reports:SalesByTerritory"]}"; + public string Report_OnlineVsOffLine => $"{configuration["Api:base"]}{configuration["Api:Reports:Base"]}{configuration["Api:Reports:OnlineVsOffLine"]}"; + public string Report_SalesByTerritory => $"{configuration["Api:base"]}{configuration["Api:Reports:Base"]}{configuration["Api:Reports:SalesByTerritory"]}"; public Uri GetByModelType(Type T) { From 03dbe90950a7e9faff2c8db333131f1f83f182f9 Mon Sep 17 00:00:00 2001 From: CodeTile <43536260+CodeTile@users.noreply.github.com> Date: Thu, 13 Mar 2025 09:34:36 +0000 Subject: [PATCH 08/12] Tests fir JsonDataService.GetDataAsync(...) #32 --- .../Common/JsonDataServiceTests.cs | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 src/AdventureWorksDemo.MudBlazor.Tests/Common/JsonDataServiceTests.cs diff --git a/src/AdventureWorksDemo.MudBlazor.Tests/Common/JsonDataServiceTests.cs b/src/AdventureWorksDemo.MudBlazor.Tests/Common/JsonDataServiceTests.cs new file mode 100644 index 0000000..db84b68 --- /dev/null +++ b/src/AdventureWorksDemo.MudBlazor.Tests/Common/JsonDataServiceTests.cs @@ -0,0 +1,117 @@ +using System.Net; +using System.Net.Http.Json; + +using AdventureWorksDemo.MudBlazor.Common; + +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Primitives; + +using Moq; + +namespace AdventureWorksDemo.MudBlazor.Tests.Common +{ + [TestClass] + public class JsonDataServiceTests + { + private HttpClient _httpClient; + private JsonDataService _jsonDataService; + private Mock _mockCache; + private MockCacheEntry _mockCacheEntry; + private MockHttpMessageHandler _mockHttpMessageHandler; + + [TestMethod] + public async Task GetDataAsync_CallsHttpClient_WhenDataNotInCache() + { + // Arrange + string url = "https://api.example.com/data"; + var expectedData = new TestData { Id = 1, Name = "New Item" }; + + var responseMessage = new HttpResponseMessage(HttpStatusCode.OK) + { + Content = JsonContent.Create(expectedData) + }; + + _mockHttpMessageHandler.SetResponse(responseMessage); + + object cacheEntry; + _mockCache.Setup(x => x.TryGetValue(url, out cacheEntry)).Returns(false); + _mockCache.Setup(x => x.CreateEntry(It.IsAny())).Returns(_mockCacheEntry); + + // Act + var result = await _jsonDataService.GetDataAsync(url, _httpClient); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(expectedData.Id, result.Id); + Assert.AreEqual(expectedData.Name, result.Name); + } + + [TestMethod] + public async Task GetDataAsync_ReturnsCachedData_WhenAvailable() + { + // Arrange + string url = "https://api.example.com/data"; + var expectedData = new TestData { Id = 1, Name = "Cached Item" }; + object cacheEntry = expectedData; + + _mockCache.Setup(x => x.TryGetValue(url, out cacheEntry)).Returns(true); + + // Act + var result = await _jsonDataService.GetDataAsync(url, _httpClient); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(expectedData.Id, result.Id); + Assert.AreEqual(expectedData.Name, result.Name); + } + + [TestInitialize] + public void Setup() + { + _mockCache = new Mock(); + _mockCacheEntry = new MockCacheEntry(); + _mockHttpMessageHandler = new MockHttpMessageHandler(); + _httpClient = new HttpClient(_mockHttpMessageHandler); + _jsonDataService = new JsonDataService(_mockCache.Object); + } + + // Custom class to mock CacheEntry + public class MockCacheEntry : ICacheEntry + { + public DateTimeOffset? AbsoluteExpiration { get; set; } + public TimeSpan? AbsoluteExpirationRelativeToNow { get; set; } + public IList ExpirationTokens { get; } = new List(); + public object Key { get; set; } + public IList PostEvictionCallbacks { get; } = new List(); + public CacheItemPriority Priority { get; set; } + public long? Size { get; set; } + public TimeSpan? SlidingExpiration { get; set; } + public object Value { get; set; } + + public void Dispose() + { } + } + + // Custom class to mock HttpMessageHandler + public class MockHttpMessageHandler : HttpMessageHandler + { + private HttpResponseMessage _response; + + public void SetResponse(HttpResponseMessage response) + { + _response = response; + } + + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + return Task.FromResult(_response); + } + } + + public class TestData + { + public int Id { get; set; } + public string Name { get; set; } + } + } +} \ No newline at end of file From a5b3123308bfb4780df0e839103c73282b38f991 Mon Sep 17 00:00:00 2001 From: CodeTile <43536260+CodeTile@users.noreply.github.com> Date: Thu, 13 Mar 2025 13:04:33 +0000 Subject: [PATCH 09/12] Tests for CommonResponse.FindAllAsync #32 --- .../Common/CommonResponseTests.cs | 87 +++++++++++++++++++ .../Common/MockHttpMessageHandler.cs | 17 ++++ .../Common/CommonResponse.cs | 2 +- 3 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 src/AdventureWorksDemo.MudBlazor.Tests/Common/CommonResponseTests.cs create mode 100644 src/AdventureWorksDemo.MudBlazor.Tests/Common/MockHttpMessageHandler.cs diff --git a/src/AdventureWorksDemo.MudBlazor.Tests/Common/CommonResponseTests.cs b/src/AdventureWorksDemo.MudBlazor.Tests/Common/CommonResponseTests.cs new file mode 100644 index 0000000..a1b3991 --- /dev/null +++ b/src/AdventureWorksDemo.MudBlazor.Tests/Common/CommonResponseTests.cs @@ -0,0 +1,87 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using AdventureWorksDemo.MudBlazor.Common; +using AdventureWorksDemo.MudBlazor.Models; +using MudBlazor; + +namespace AdventureWorksDemo.MudBlazor.Tests.Common +{ + [TestClass] + public class CommonResponseTests + { + private CommonResponse _commonResponse; + private HttpClient _httpClient; + private Mock _mockUrl; + + [TestMethod] + public async Task FindAllAsync_ReturnsGridData_WhenResponseIsSuccessful() + { + // Arrange + var gridState = new GridState(); + var mockData = new List { new() { ProductDescriptionId = 1, Description = "Test", ModifiedDate = DateTime.UtcNow } }; + var jsonResponse = JsonSerializer.Serialize(mockData); + var mockResponse = new HttpResponseMessage + { + StatusCode = HttpStatusCode.OK, + Content = new StringContent(jsonResponse, Encoding.UTF8, "application/json") + }; + mockResponse.Headers.Add("X-Pagination", "{\"TotalCount\":1}"); + + _mockUrl.Setup(u => u.Administration_ProductDescription).Returns("https://api.test.com/products"); + + var handler = new MockHttpMessageHandler(_ => Task.FromResult(mockResponse)); + _httpClient = new HttpClient(handler); + _commonResponse = new CommonResponse(_mockUrl.Object); + + // Act + var result = await _commonResponse.FindAllAsync(gridState, "Default", _httpClient); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(1, result.TotalItems); + Assert.AreEqual(1, result.Items.Count()); + } + + [TestInitialize] + public void Setup() + { + _mockUrl = new Mock(); + } + + [TestMethod] + public async Task UpdateAsync_ReturnsServiceResult_WhenUpdateFails() + { + // Arrange + var product = new ProductDescriptionModel { ProductDescriptionId = 1, Description = "Updated", ModifiedDate = DateTime.UtcNow }; + var errorJson = JsonSerializer.Serialize(new ServiceResult { IsSuccess = false, IsFailure = true, Message = "Update failed" }); + var mockResponse = new HttpResponseMessage + { + StatusCode = HttpStatusCode.BadRequest, + Content = new StringContent(errorJson, Encoding.UTF8, "application/json") + }; + + _mockUrl.Setup(u => u.GetByModelType(typeof(ProductDescriptionModel))).Returns(new Uri("https://api.test.com/products")); + + var handler = new MockHttpMessageHandler(_ => Task.FromResult(mockResponse)); + _httpClient = new HttpClient(handler); + _commonResponse = new CommonResponse(_mockUrl.Object); + + // Act + var result = await _commonResponse.UpdateAsync(product, _httpClient); + + // Assert + Assert.IsFalse(result.IsSuccess); + Assert.IsTrue(result.IsFailure); + Assert.AreEqual("System error!", result.Message); + } + } +} \ No newline at end of file diff --git a/src/AdventureWorksDemo.MudBlazor.Tests/Common/MockHttpMessageHandler.cs b/src/AdventureWorksDemo.MudBlazor.Tests/Common/MockHttpMessageHandler.cs new file mode 100644 index 0000000..05aefdd --- /dev/null +++ b/src/AdventureWorksDemo.MudBlazor.Tests/Common/MockHttpMessageHandler.cs @@ -0,0 +1,17 @@ +namespace AdventureWorksDemo.MudBlazor.Tests.Common +{ + public class MockHttpMessageHandler : HttpMessageHandler + { + public MockHttpMessageHandler(Func> sendAsyncFunc) + { + _sendAsyncFunc = sendAsyncFunc; + } + + private readonly Func> _sendAsyncFunc; + + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + return _sendAsyncFunc(request); + } + } +} \ No newline at end of file diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/CommonResponse.cs b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/CommonResponse.cs index 08f9efe..c59627a 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/CommonResponse.cs +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/CommonResponse.cs @@ -72,7 +72,7 @@ public async Task> UpdateAsync(T item, HttpClient httpClien private static JsonSerializerOptions DeserialiseOptions() => new() { - PropertyNameCaseInsensitive = true // ✅ Allows matching lowercase JSON keys + PropertyNameCaseInsensitive = true // Allows matching lowercase JSON keys }; } } \ No newline at end of file From 27be2ba1643955e4939d78f040e8b5cf348f0045 Mon Sep 17 00:00:00 2001 From: CodeTile <43536260+CodeTile@users.noreply.github.com> Date: Wed, 19 Mar 2025 17:09:00 +0000 Subject: [PATCH 10/12] Tests for SalesSummary --- .../{ => Common}/CommonResponseGetTests.cs | 0 .../Common/CommonResponseTests.cs | 6 +- .../Models/SalesSummaryTests.cs | 98 +++++++++++++++++++ .../Models/SalesSummary.cs | 31 +++++- 4 files changed, 129 insertions(+), 6 deletions(-) rename src/AdventureWorksDemo.MudBlazor.Tests/{ => Common}/CommonResponseGetTests.cs (100%) create mode 100644 src/AdventureWorksDemo.MudBlazor.Tests/Models/SalesSummaryTests.cs diff --git a/src/AdventureWorksDemo.MudBlazor.Tests/CommonResponseGetTests.cs b/src/AdventureWorksDemo.MudBlazor.Tests/Common/CommonResponseGetTests.cs similarity index 100% rename from src/AdventureWorksDemo.MudBlazor.Tests/CommonResponseGetTests.cs rename to src/AdventureWorksDemo.MudBlazor.Tests/Common/CommonResponseGetTests.cs diff --git a/src/AdventureWorksDemo.MudBlazor.Tests/Common/CommonResponseTests.cs b/src/AdventureWorksDemo.MudBlazor.Tests/Common/CommonResponseTests.cs index a1b3991..a18a61c 100644 --- a/src/AdventureWorksDemo.MudBlazor.Tests/Common/CommonResponseTests.cs +++ b/src/AdventureWorksDemo.MudBlazor.Tests/Common/CommonResponseTests.cs @@ -18,9 +18,9 @@ namespace AdventureWorksDemo.MudBlazor.Tests.Common [TestClass] public class CommonResponseTests { - private CommonResponse _commonResponse; - private HttpClient _httpClient; - private Mock _mockUrl; + private CommonResponse? _commonResponse; + private HttpClient? _httpClient; + private Mock? _mockUrl; [TestMethod] public async Task FindAllAsync_ReturnsGridData_WhenResponseIsSuccessful() diff --git a/src/AdventureWorksDemo.MudBlazor.Tests/Models/SalesSummaryTests.cs b/src/AdventureWorksDemo.MudBlazor.Tests/Models/SalesSummaryTests.cs new file mode 100644 index 0000000..371a06f --- /dev/null +++ b/src/AdventureWorksDemo.MudBlazor.Tests/Models/SalesSummaryTests.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using AdventureWorksDemo.MudBlazor.Models; + +namespace AdventureWorksDemo.MudBlazor.Tests.Models +{ + [TestClass] + public class SalesSummaryTests + { + public SalesSummaryTests() + { + } + + [TestMethod] + public void SalesSummary_ChangingMonth_ShouldResetPeriod() + { + // Arrange + var salesSummary = new SalesSummary { Year = 2023, Month = 5 }; + DateTime initialPeriod = salesSummary.Period; + + // Act + salesSummary.Month = 6; + DateTime updatedPeriod = salesSummary.Period; + + // Assert + Assert.AreNotEqual(initialPeriod, updatedPeriod); + Assert.AreEqual(new DateTime(2023, 6, 1, 0, 0, 0, DateTimeKind.Utc), updatedPeriod); + } + + [DataTestMethod] + [DataRow(2023, 0)] + [DataRow(2022, 1234)] + [DataRow(2020, 13)] + [DataRow(0, 3)] + [DataRow(-1234, 4)] + [ExpectedException(typeof(ArgumentOutOfRangeException))] + public void SalesSummary_Period_ShouldHandleBadMonth(int year, int month) + { + // Arrange & act + var salesSummary = new SalesSummary + { + Year = year, + Month = month, + OnlineOrderFlag = true, + SalesCount = 100 + }; + // cause error + Console.WriteLine(salesSummary.Period); + } + + [DataTestMethod] + [DataRow(2023, 1)] + [DataRow(2022, 5)] + [DataRow(2020, 12)] + [DataRow(2019, 7)] + public void SalesSummary_Period_ShouldReturnCorrectDate(int year, int month) + { + // Arrange + var salesSummary = new SalesSummary + { + Year = year, + Month = month, + OnlineOrderFlag = true, + SalesCount = 100 + }; + + // Act + DateTime expectedDate = new(year, month, 1, 0, 0, 0, DateTimeKind.Utc); + DateTime actualDate = salesSummary.Period; + + // Assert + Assert.AreEqual(expectedDate, actualDate); + } + + [TestMethod] + public void SalesSummary_Properties_ShouldStoreValuesCorrectly() + { + // Arrange + var salesSummary = new SalesSummary + { + Year = 2022, + Month = 12, + OnlineOrderFlag = false, + SalesCount = 50 + }; + + // Act & Assert + Assert.AreEqual(2022, salesSummary.Year); + Assert.AreEqual(12, salesSummary.Month); + Assert.IsFalse(salesSummary.OnlineOrderFlag); + Assert.AreEqual(50, salesSummary.SalesCount); + } + } +} \ No newline at end of file diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Models/SalesSummary.cs b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Models/SalesSummary.cs index f03bc6b..feef198 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Models/SalesSummary.cs +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Models/SalesSummary.cs @@ -2,10 +2,35 @@ { public record SalesSummary { - public int Year { get; set; } - public int Month { get; set; } + private int _month; + private int _year; + private DateTime? _cachedPeriod; + + public int Year + { + get => _year; + set + { + _year = value; + _cachedPeriod = null; // Reset cached period + } + } + + public int Month + { + get => _month; + set + { + if (value is < 1 or > 12) + throw new ArgumentOutOfRangeException(nameof(Month), "Month must be between 1 and 12."); + _month = value; + _cachedPeriod = null; // Reset cached period + } + } + public bool OnlineOrderFlag { get; set; } public int SalesCount { get; set; } - public DateTime Period => new(Year, Month, 1, 0, 0, 0, DateTimeKind.Utc); + + public DateTime Period => _cachedPeriod ??= new DateTime(Year, Month, 1, 0, 0, 0, DateTimeKind.Utc); } } \ No newline at end of file From 892d7aca578c468ca7d957ff6c7f9a9fb7fc4e4d Mon Sep 17 00:00:00 2001 From: CodeTile <43536260+CodeTile@users.noreply.github.com> Date: Wed, 19 Mar 2025 17:13:23 +0000 Subject: [PATCH 11/12] SaleByTerritoryTests --- .../Models/SaleByTerritoryTests.cs | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 src/AdventureWorksDemo.MudBlazor.Tests/Models/SaleByTerritoryTests.cs diff --git a/src/AdventureWorksDemo.MudBlazor.Tests/Models/SaleByTerritoryTests.cs b/src/AdventureWorksDemo.MudBlazor.Tests/Models/SaleByTerritoryTests.cs new file mode 100644 index 0000000..10398f2 --- /dev/null +++ b/src/AdventureWorksDemo.MudBlazor.Tests/Models/SaleByTerritoryTests.cs @@ -0,0 +1,97 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using System; + +namespace AdventureWorksDemo.MudBlazor.Tests.Models +{ + public record SaleByTerritory + { + public string? CountryRegion { get; set; } + public decimal SalesLastYear { get; set; } + public decimal SalesYTD { get; set; } + public double SalesYTDToDisplay => Convert.ToDouble(SalesYTD / 1000000); + public double SalesLastYearToDisplay => Convert.ToDouble(SalesLastYear / 1000000); + } + + [TestClass] + public class SaleByTerritoryTests + { + [TestMethod] + public void SalesYTDToDisplay_ShouldReturnCorrectValue() + { + // Arrange + var sale = new SaleByTerritory { SalesYTD = 5000000m }; + + // Act + double result = sale.SalesYTDToDisplay; + + // Assert + Assert.AreEqual(5.0, result, 0.0001, "SalesYTDToDisplay calculation is incorrect"); + } + + [TestMethod] + public void SalesLastYearToDisplay_ShouldReturnCorrectValue() + { + // Arrange + var sale = new SaleByTerritory { SalesLastYear = 3000000m }; + + // Act + double result = sale.SalesLastYearToDisplay; + + // Assert + Assert.AreEqual(3.0, result, 0.0001, "SalesLastYearToDisplay calculation is incorrect"); + } + + [TestMethod] + public void SalesYTDToDisplay_ShouldHandleZeroValue() + { + // Arrange + var sale = new SaleByTerritory { SalesYTD = 0m }; + + // Act + double result = sale.SalesYTDToDisplay; + + // Assert + Assert.AreEqual(0.0, result, 0.0001, "SalesYTDToDisplay should return 0 for zero sales"); + } + + [TestMethod] + public void SalesLastYearToDisplay_ShouldHandleZeroValue() + { + // Arrange + var sale = new SaleByTerritory { SalesLastYear = 0m }; + + // Act + double result = sale.SalesLastYearToDisplay; + + // Assert + Assert.AreEqual(0.0, result, 0.0001, "SalesLastYearToDisplay should return 0 for zero sales"); + } + + [TestMethod] + public void SalesYTDToDisplay_ShouldHandleNegativeValue() + { + // Arrange + var sale = new SaleByTerritory { SalesYTD = -1000000m }; + + // Act + double result = sale.SalesYTDToDisplay; + + // Assert + Assert.AreEqual(-1.0, result, 0.0001, "SalesYTDToDisplay should return correct value for negative sales"); + } + + [TestMethod] + public void SalesLastYearToDisplay_ShouldHandleNegativeValue() + { + // Arrange + var sale = new SaleByTerritory { SalesLastYear = -2000000m }; + + // Act + double result = sale.SalesLastYearToDisplay; + + // Assert + Assert.AreEqual(-2.0, result, 0.0001, "SalesLastYearToDisplay should return correct value for negative sales"); + } + } +} \ No newline at end of file From 1ecdeb5e4b1b4ac1885a6c66e389a2ca9391fc25 Mon Sep 17 00:00:00 2001 From: CodeTile <43536260+CodeTile@users.noreply.github.com> Date: Mon, 24 Mar 2025 09:52:44 +0000 Subject: [PATCH 12/12] Fix Sonar cloud issues --- .../Common/JsonDataServiceTests.cs | 6 ++-- .../Common/JsonDataService.cs | 35 +++++++++++++++---- .../AdventureWorksDemo.MudBlazor/Program.cs | 2 +- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/AdventureWorksDemo.MudBlazor.Tests/Common/JsonDataServiceTests.cs b/src/AdventureWorksDemo.MudBlazor.Tests/Common/JsonDataServiceTests.cs index db84b68..4bbddb4 100644 --- a/src/AdventureWorksDemo.MudBlazor.Tests/Common/JsonDataServiceTests.cs +++ b/src/AdventureWorksDemo.MudBlazor.Tests/Common/JsonDataServiceTests.cs @@ -72,7 +72,7 @@ public void Setup() _mockCacheEntry = new MockCacheEntry(); _mockHttpMessageHandler = new MockHttpMessageHandler(); _httpClient = new HttpClient(_mockHttpMessageHandler); - _jsonDataService = new JsonDataService(_mockCache.Object); + _jsonDataService = new JsonDataService(_mockCache.Object, null); } // Custom class to mock CacheEntry @@ -80,9 +80,9 @@ public class MockCacheEntry : ICacheEntry { public DateTimeOffset? AbsoluteExpiration { get; set; } public TimeSpan? AbsoluteExpirationRelativeToNow { get; set; } - public IList ExpirationTokens { get; } = new List(); + public IList ExpirationTokens { get; } = []; public object Key { get; set; } - public IList PostEvictionCallbacks { get; } = new List(); + public IList PostEvictionCallbacks { get; } = []; public CacheItemPriority Priority { get; set; } public long? Size { get; set; } public TimeSpan? SlidingExpiration { get; set; } diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/JsonDataService.cs b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/JsonDataService.cs index 5282a7e..709e749 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/JsonDataService.cs +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Common/JsonDataService.cs @@ -7,26 +7,47 @@ public interface IJsonDataService Task GetDataAsync(string url, HttpClient httpClient); } - public class JsonDataService(IMemoryCache _cache) : IJsonDataService + public class JsonDataService(IMemoryCache _cache, ILogger? _logger) : IJsonDataService { private readonly TimeSpan _cacheDuration = TimeSpan.FromMinutes(1); // Cache duration public async Task GetDataAsync(string url, HttpClient httpClient) { - if (_cache.TryGetValue(url, out T cachedData)) + if (string.IsNullOrWhiteSpace(url)) + throw new ArgumentException("URL cannot be null or empty.", nameof(url)); + + if (_cache.TryGetValue(url, out T? cachedData)) { + _logger?.LogInformation("Cache hit for {Url}", url); return cachedData; // Return cached data if available } - T? data = await httpClient.GetFromJsonAsync(url); + try + { + _logger?.LogInformation("Fetching data from {Url}", url); + T? data = await httpClient.GetFromJsonAsync(url); + + if (!EqualityComparer.Default.Equals(data, default)) // Compare using EqualityComparer + + { + _cache.Set(url, data, _cacheDuration); + } - if (data != null) + return data; + } +#pragma warning disable S2139 // Either log this exception and handle it, or rethrow it with some contextual information + catch (HttpRequestException ex) { - _cache.Set(url, data, _cacheDuration); // Cache the data + _logger?.LogError(ex, "HTTP request failed for {Url}", url); + throw; } - - return data; + catch (Exception ex) + { + _logger?.LogError(ex, "Unexpected error fetching data from {Url}", url); + throw; + } +#pragma warning restore S2139 // Re-enable warning } } } \ No newline at end of file diff --git a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Program.cs b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Program.cs index 277ea02..4fd6f80 100644 --- a/src/FrontEnd/AdventureWorksDemo.MudBlazor/Program.cs +++ b/src/FrontEnd/AdventureWorksDemo.MudBlazor/Program.cs @@ -7,7 +7,7 @@ namespace AdventureWorksDemo.MudBlazor { - public class Program + public static class Program { public static void Main(string[] args) {