From 9c8427871e9bf9fdefb9fecdab05dcdcae924c6c Mon Sep 17 00:00:00 2001 From: Sven Hansen <76601644+SyntaxSven@users.noreply.github.com> Date: Tue, 28 Mar 2023 09:56:18 +0200 Subject: [PATCH] Feat/58 unit testing poc (#73) * Release v1.0.0 (#41) * Change formats type to `string` and split with comma separator * Use root configuration instead of configuration section * Fix exceptions not properly displaying in the console * Add all module item types according to documentation * Update application demo GIF * Create code-analysis.yml * Remove comments and enable additional queries * Removed push from code-analysis.yml workflow * Typo code-analysis.yml * Added support for a Word export option * Added footer Epsilon Credits * Created helper class with reformat functions * Reformat code * Improved helper functions, Found that they can be added to records :-) * Reformat files * string interpolation * Feature/cleanup (#40) * Remove obsolete Epsilon.Http.Abstractions project * Fix invalid serializable implementation * Disable unused method return value hint * Change exception to more appropriate one * Update Grade score description * Prevent null grades from exporting * Reduce cognitive complexity to acceptable level * Move logging call * Reduce nesting * Move project name and repository uri to constants * Fix nullability warnings * Remove unused class * Use ?: operator and move constants to top level of class * Reduce loop complexity * Use project name constant in output name export option * Update README.md application demo gif * Add supported formats to README.md Co-authored-by: Jelle Maas * POC Open XML SDK * Update * Add KPI format and structure * Added module names to document * Testing the build and structure of exel files. * Testing release deployment script. * Delete file * POC for excel export * Code reformat * Abstracted format logic from exporters to main logic * Remove typo * Remove unused variable * Headers added * Code cleanup * Merge * Removal nullability warnings * Removal nullability warnings * Removal tasks/awaits because they dont have nay use atm. * Removal tasks/awaits because they dont have nay use atm. * Add exporters return type * Added memoryStream return type for ConsoleModuleExporter * Remove unused ExportOptions from ConsoleModuleExporter * Clean up old merge files * Update continuous-integration.yml * Add tests for HttpService, Exporter and ExportDataPackager * Update continuous-integration.yml * 'Var' is everything * Update continuous-integration.yml * Created unit test for CanvasModuleCollectionFetcher GetAll method * Renamed unit test * Bugfix * Merged feat/42 into feat/58 * Refactored ExcelModuleExporter tests to WordModuleExporter tests --------- Co-authored-by: Neal Geilen Co-authored-by: Jelle Maas Co-authored-by: Sven Hansen <76601644+1SvenHansen@users.noreply.github.com> --- .github/workflows/continuous-integration.yml | 30 ++++- Epsilon.Abstractions/Export/IExporter.cs | 2 - Epsilon.Abstractions/Model/CourseModule.cs | 2 +- .../CanvasModuleCollectionFetcherTests.cs | 126 ++++++++++++++++++ .../Epsilon.Canvas.Tests.csproj | 8 +- .../Services/AssignmentHttpServiceTests.cs | 52 ++++++++ Epsilon.Cli/Startup.cs | 1 + Epsilon.Tests/Epsilon.Tests.csproj | 30 +++++ Epsilon.Tests/ExportDataPackagerTests.cs | 94 +++++++++++++ .../Exporters/WordModuleExporterTests.cs | 55 ++++++++ Epsilon.Tests/Usings.cs | 1 + Epsilon.sln | 27 +++- Epsilon/Export/ExportDataPackager.cs | 13 +- .../Export/Exporters/ConsoleModuleExporter.cs | 6 +- Epsilon/Export/Exporters/CsvModuleExporter.cs | 2 +- .../Export/Exporters/ExcelModuleExporter.cs | 6 +- .../Export/Exporters/WordModuleExporter.cs | 2 +- 17 files changed, 427 insertions(+), 30 deletions(-) create mode 100644 Epsilon.Canvas.Tests/CanvasModuleCollectionFetcherTests.cs create mode 100644 Epsilon.Canvas.Tests/Services/AssignmentHttpServiceTests.cs create mode 100644 Epsilon.Tests/Epsilon.Tests.csproj create mode 100644 Epsilon.Tests/ExportDataPackagerTests.cs create mode 100644 Epsilon.Tests/Exporters/WordModuleExporterTests.cs create mode 100644 Epsilon.Tests/Usings.cs diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 2b9bb230..64a46248 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -2,16 +2,36 @@ on: [ pull_request ] jobs: - build: - name: Build + setup: + name: Setup runs-on: ubuntu-20.04 - steps: - uses: actions/checkout@v2 - - uses: actions/setup-dotnet@v1.7.2 + + - name: Setup .NET + uses: actions/setup-dotnet@v1.7.2 with: dotnet-version: '6.0.x' + + build: + name: Build + needs: [ setup ] + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - name: Restore dependencies run: dotnet restore + - name: Build - run: dotnet build --no-restore \ No newline at end of file + run: dotnet build --no-restore + + test: + name: Test + needs: [ setup, build ] + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + + - name: Test + run: dotnet test --no-build --verbosity normal diff --git a/Epsilon.Abstractions/Export/IExporter.cs b/Epsilon.Abstractions/Export/IExporter.cs index d36f4aea..5f049fff 100644 --- a/Epsilon.Abstractions/Export/IExporter.cs +++ b/Epsilon.Abstractions/Export/IExporter.cs @@ -3,8 +3,6 @@ public interface IExporter { public IEnumerable Formats { get; } - public string FileExtension { get; } - Task Export(T data, string format); } \ No newline at end of file diff --git a/Epsilon.Abstractions/Model/CourseModule.cs b/Epsilon.Abstractions/Model/CourseModule.cs index c31dfb65..a9a113ac 100644 --- a/Epsilon.Abstractions/Model/CourseModule.cs +++ b/Epsilon.Abstractions/Model/CourseModule.cs @@ -3,6 +3,6 @@ public class CourseModule { public string Name { get; set; } = String.Empty; - public IEnumerable Kpis { get; set; } = Enumerable.Empty(); + public IEnumerable Outcomes { get; set; } = Enumerable.Empty(); } } diff --git a/Epsilon.Canvas.Tests/CanvasModuleCollectionFetcherTests.cs b/Epsilon.Canvas.Tests/CanvasModuleCollectionFetcherTests.cs new file mode 100644 index 00000000..1206d886 --- /dev/null +++ b/Epsilon.Canvas.Tests/CanvasModuleCollectionFetcherTests.cs @@ -0,0 +1,126 @@ +using Epsilon.Abstractions.Model; +using Epsilon.Canvas.Abstractions.Model; +using Epsilon.Canvas.Abstractions.Service; +using Microsoft.Extensions.Logging; +using Moq; +using System.Text.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; +using Epsilon.Canvas.Abstractions; + +namespace Epsilon.Canvas.Tests +{ + public class CanvasModuleCollectionFetcherTests + { + [Fact] + public async Task GivenAllowedModulesAndCourseId_WhenModuleAndOutcomeServiceAreMocked_ThenReturnsExpectedModuleOutcomeResultCollection() + { + // Arrange + var courseId = 123; + var allowedModules = new[] { "Module 1", "Module 3" }; + var outcomeServiceMock = new Mock(); + var moduleServiceMock = new Mock(); + + var expectedResults = new List + { + new ModuleOutcomeResultCollection( + new Module(1, "Module 1", 3, new List + { + new ModuleItem(1, "Module 1 Item 1", ModuleItemType.Page, 1), + new ModuleItem(2, "Module 1 Item 2", ModuleItemType.Assignment, 2), + new ModuleItem(3, "Module 1 Item 3", ModuleItemType.Quiz, 3) + }), + new OutcomeResultCollection( + new List { }, + new OutcomeResultCollectionLink( + new List + { + new Outcome(1, "Outcome 1", "Outcome 1 EN Short Description NL Long Description"), + new Outcome(2, "Outcome 2", "Outcome 2 EN Short Description NL Long Description") + }, + new List { } + ) + ) + ), + new ModuleOutcomeResultCollection( + new Module(3, "Module 3", 2, new List + { + new ModuleItem(4, "Module 3 Item 1", ModuleItemType.Assignment, 4), + new ModuleItem(5, "Module 3 Item 2", ModuleItemType.Assignment, 5) + }), + new OutcomeResultCollection( + new List { }, + new OutcomeResultCollectionLink( + new List + { + new Outcome(1, "Outcome 1", "Outcome 1 EN Short Description NL Long Description"), + new Outcome(2, "Outcome 2", "Outcome 2 EN Short Description NL Long Description") + }, + new List { } + ) + ) + ) + }; + + outcomeServiceMock + .Setup(s => s.GetResults(It.IsAny(), It.IsAny())) + .ReturnsAsync(new OutcomeResultCollection( + new List + { + new OutcomeResult(false, 3, new OutcomeResultLink("user1", "1", "1", "2")), + new OutcomeResult(true, 4.5, new OutcomeResultLink("user2", "2", "2", "3")), + new OutcomeResult(false, null, new OutcomeResultLink("user1", "1", "1", "3")), + }, + new OutcomeResultCollectionLink( + new List + { + new Outcome(1, "Outcome 1", "Outcome 1 EN Short Description NL Long Description"), + new Outcome(2, "Outcome 2", "Outcome 2 EN Short Description NL Long Description"), + }, + new List + { + new Alignment("1", "Alignment 1", new Uri("https://alignment1.com")), + new Alignment("2", "Alignment 2", new Uri("https://alignment2.com")), + new Alignment("3", "Alignment 3", new Uri("https://alignment3.com")), + } + ) + )); + + moduleServiceMock + .Setup(s => s.GetAll(It.IsAny(), It.IsAny())) + .ReturnsAsync(new List + { + new Module(1, "Module 1", 3, new List + { + new ModuleItem(1, "Module 1 Item 1", ModuleItemType.Page, 1), + new ModuleItem(2, "Module 1 Item 2", ModuleItemType.Assignment, 2), + new ModuleItem(3, "Module 1 Item 3", ModuleItemType.Quiz, 3) + }), + new Module(2, "Module 2", 0, new List()), + new Module(3, "Module 3", 2, new List + { + new ModuleItem(4, "Module 3 Item 1", ModuleItemType.Assignment, 4), + new ModuleItem(5, "Module 3 Item 2", ModuleItemType.Assignment, 5) + }), + }); + + var canvasModuleCollectionFetcher = new CanvasModuleCollectionFetcher( + Mock.Of>(), moduleServiceMock.Object, outcomeServiceMock.Object + ); + + // Act + var result = new List(); + await foreach (var item in canvasModuleCollectionFetcher.GetAll(courseId, allowedModules)) + { + result.Add(item); + } + + // Assert + Assert.Equal(JsonSerializer.Serialize(expectedResults), JsonSerializer.Serialize(result)); + } + } +} diff --git a/Epsilon.Canvas.Tests/Epsilon.Canvas.Tests.csproj b/Epsilon.Canvas.Tests/Epsilon.Canvas.Tests.csproj index a4f2013f..93db85e6 100644 --- a/Epsilon.Canvas.Tests/Epsilon.Canvas.Tests.csproj +++ b/Epsilon.Canvas.Tests/Epsilon.Canvas.Tests.csproj @@ -9,9 +9,13 @@ - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Epsilon.Canvas.Tests/Services/AssignmentHttpServiceTests.cs b/Epsilon.Canvas.Tests/Services/AssignmentHttpServiceTests.cs new file mode 100644 index 00000000..c5b276f7 --- /dev/null +++ b/Epsilon.Canvas.Tests/Services/AssignmentHttpServiceTests.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Net.Http.Json; +using System.Threading; +using System.Threading.Tasks; +using Epsilon.Abstractions.Http; +using Epsilon.Canvas.Abstractions.Model; +using Epsilon.Canvas.Abstractions.Service; +using Moq; +using Moq.Protected; +using Xunit; + +namespace Epsilon.Canvas.Service.Tests +{ + public class AssignmentHttpServiceTests + { + private readonly HttpClient _httpClient; + private readonly Mock _paginatorHttpServiceMock; + private readonly AssignmentHttpService _assignmentHttpService; + + public AssignmentHttpServiceTests() + { + _httpClient = new HttpClient(); + _paginatorHttpServiceMock = new Mock(); + _assignmentHttpService = new AssignmentHttpService(_httpClient, _paginatorHttpServiceMock.Object); + } + + [Fact] + public async Task GivenCourseIdAndIncludeSubmissionAndRubricAssessment_WhenCanvasAssignmentsAreRetrieved_ThenAssignmentsAreReturned() + { + // Arrange + var courseId = 123; + var include = new[] { "submission", "rubric_assessment" }; + var assignments = new[] + { + new Assignment(1, "Assignment 1", new("https://example.com/1"), null), + new Assignment(2, "Assignment 2", new("https://example.com/2"), new Submission(null, null, null, null)), + new Assignment(3, "Assignment 3", new("https://example.com/3"), new Submission(null, null, new RubricAssessment(8.5, 1, Enumerable.Empty()), null)), + }; + _paginatorHttpServiceMock.Setup(x => x.GetAllPages>(HttpMethod.Get, $"v1/courses/{courseId}/assignments?include[]=submission&include[]=rubric_assessment")) + .ReturnsAsync(new[] { assignments }); + + // Act + var result = await _assignmentHttpService.GetAll(courseId, include); + + // Assert + Assert.Equal(assignments, result); + } + } +} diff --git a/Epsilon.Cli/Startup.cs b/Epsilon.Cli/Startup.cs index e026bc23..b9195422 100644 --- a/Epsilon.Cli/Startup.cs +++ b/Epsilon.Cli/Startup.cs @@ -80,6 +80,7 @@ private async Task ExecuteAsync() foreach (var (format, exporter) in exporters) { _logger.LogInformation("Exporting to {Format} using {Exporter}...", format, exporter.GetType().Name); + var stream = await exporter.Export(formattedItems, format); await using var fileStream = new FileStream($"{_exportOptions.FormattedOutputName}.{exporter.FileExtension}", FileMode.Create, FileAccess.Write); diff --git a/Epsilon.Tests/Epsilon.Tests.csproj b/Epsilon.Tests/Epsilon.Tests.csproj new file mode 100644 index 00000000..8f3b7519 --- /dev/null +++ b/Epsilon.Tests/Epsilon.Tests.csproj @@ -0,0 +1,30 @@ + + + + net6.0 + enable + enable + + false + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + diff --git a/Epsilon.Tests/ExportDataPackagerTests.cs b/Epsilon.Tests/ExportDataPackagerTests.cs new file mode 100644 index 00000000..27b86dc6 --- /dev/null +++ b/Epsilon.Tests/ExportDataPackagerTests.cs @@ -0,0 +1,94 @@ +using Epsilon.Abstractions.Model; +using Epsilon.Canvas.Abstractions.Model; +using Epsilon.Export; +using Moq; +using System.Text.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Epsilon.Tests +{ + public class ExportDataPackagerTests + { + [Fact] + public async Task GivenListOfModuleOutcomeResultCollection_WhenRequiringOpenLearningOutcomeStructure_ThenOutcomeStructureShouldBeTransformed() + { + // Arrange + var module = new Module(1, "Module 1", 3, new List + { + new ModuleItem(1, "Module 1 Item 1", ModuleItemType.Page, 1), + new ModuleItem(2, "Module 1 Item 2", ModuleItemType.Assignment, 2), + new ModuleItem(3, "Module 1 Item 3", ModuleItemType.Quiz, 3) + }); + + var outcomes = new List + { + new Outcome(1, "Outcome 1", "Outcome 1 EN Short Description NL Long Description"), + new Outcome(2, "Outcome 2", "Outcome 2 EN Short Description NL Long Description"), + }; + + var alignments = new List + { + new Alignment("1", "Alignment 1", new Uri("https://alignment1.com")), + new Alignment("2", "Alignment 2", new Uri("https://alignment2.com")), + }; + + var outcomeResults = new List + { + new OutcomeResult(false, 3, new OutcomeResultLink("user1", "1", "1", "2")), + new OutcomeResult(true, 4.5, new OutcomeResultLink("user2", "2", "2", "3")), + new OutcomeResult(false, null, new OutcomeResultLink("user1", "1", "1", "3")), + }; + + var links = new OutcomeResultCollectionLink(outcomes, alignments); + + var collection = new OutcomeResultCollection(outcomeResults, links); + + var moduleOutcomeResultCollection = new ModuleOutcomeResultCollection(module, collection); + + var data = new List + { + moduleOutcomeResultCollection + }.ToAsyncEnumerable(); + + var expectedData = new ExportData + { + CourseModules = new List + { + new CourseModule + { + Name = "Module 1", + Outcomes = new List + { + new CourseOutcome + { + Name = "Outcome 1", + Description = "Short Description", + Assignments = new List + { + new CourseAssignment + { + Name = "Alignment 2", + Url = "https://alignment2.com/", + Score = "Satisfactory" + } + } + } + } + } + } + }; + + var exportDataPackager = new ExportDataPackager(); + + // Act + var result = await exportDataPackager.GetExportData(data); + + // Assert + Assert.Equal(JsonSerializer.Serialize(expectedData), JsonSerializer.Serialize(result)); + } + } +} diff --git a/Epsilon.Tests/Exporters/WordModuleExporterTests.cs b/Epsilon.Tests/Exporters/WordModuleExporterTests.cs new file mode 100644 index 00000000..b63843a6 --- /dev/null +++ b/Epsilon.Tests/Exporters/WordModuleExporterTests.cs @@ -0,0 +1,55 @@ +using Epsilon.Abstractions.Model; +using Epsilon.Export; +using Epsilon.Export.Exporters; +using Microsoft.Extensions.Options; +using DocumentFormat.OpenXml.Packaging; + +namespace Epsilon.Tests.Exporters +{ + public class WordModuleExporterTests + { + [Fact] + public async Task GivenExportData_WhenExportToWord_ThenFileShouldContainExportData() + { + // Arrange + var data = new ExportData + { + CourseModules = new List + { + new CourseModule + { + Name = "Module 1", + Outcomes = new List + { + new CourseOutcome + { + Name = "Outcome 1", + Description = "Short Description", + Assignments = new List + { + new CourseAssignment { Name = "Assignment 1", Url = "https://assignment1.com/", Score = "Good" }, + new CourseAssignment { Name = "Assignment 2", Url = "https://assignment2.com/", Score = "Outstanding" }, + } + } + } + } + } + }; + + var moduleExporter = new WordModuleExporter(); + + // Act + using var stream = await moduleExporter.Export(data, "word"); + using var document = WordprocessingDocument.Open(stream, false); + + var content = document?.MainDocumentPart?.Document?.Body?.InnerText; + + // Assert + Assert.Contains("Module 1", content); + Assert.Contains("Outcome 1", content); + Assert.Contains("Short Description", content); + Assert.Contains("Assignment 1", content); + Assert.Contains("Assignment 2", content); + } + } +} diff --git a/Epsilon.Tests/Usings.cs b/Epsilon.Tests/Usings.cs new file mode 100644 index 00000000..8c927eb7 --- /dev/null +++ b/Epsilon.Tests/Usings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/Epsilon.sln b/Epsilon.sln index 7bb4b9c2..45b12d06 100644 --- a/Epsilon.sln +++ b/Epsilon.sln @@ -1,16 +1,21 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Epsilon.Cli", "Epsilon.Cli\Epsilon.Cli.csproj", "{358E6BB1-E2A2-4397-A831-A2194604D532}" +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33414.496 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Epsilon.Cli", "Epsilon.Cli\Epsilon.Cli.csproj", "{358E6BB1-E2A2-4397-A831-A2194604D532}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Epsilon.Canvas", "Epsilon.Canvas\Epsilon.Canvas.csproj", "{AD6AB75F-D71B-4FDD-8B37-1FB547AAC753}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Epsilon.Canvas", "Epsilon.Canvas\Epsilon.Canvas.csproj", "{AD6AB75F-D71B-4FDD-8B37-1FB547AAC753}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Epsilon.Canvas.Abstractions", "Epsilon.Canvas.Abstractions\Epsilon.Canvas.Abstractions.csproj", "{A8301F2C-F889-464F-9385-862BFB447435}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Epsilon.Canvas.Abstractions", "Epsilon.Canvas.Abstractions\Epsilon.Canvas.Abstractions.csproj", "{A8301F2C-F889-464F-9385-862BFB447435}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Epsilon.Canvas.Tests", "Epsilon.Canvas.Tests\Epsilon.Canvas.Tests.csproj", "{9DF6EB90-439D-4372-9912-0B82B84D1C36}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Epsilon.Canvas.Tests", "Epsilon.Canvas.Tests\Epsilon.Canvas.Tests.csproj", "{9DF6EB90-439D-4372-9912-0B82B84D1C36}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Epsilon", "Epsilon\Epsilon.csproj", "{30C8913E-6FAF-42AF-A3AE-0CF0E5A3DC88}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Epsilon", "Epsilon\Epsilon.csproj", "{30C8913E-6FAF-42AF-A3AE-0CF0E5A3DC88}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Epsilon.Abstractions", "Epsilon.Abstractions\Epsilon.Abstractions.csproj", "{4AEA96B5-B30A-49C7-8871-29D18587936F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Epsilon.Abstractions", "Epsilon.Abstractions\Epsilon.Abstractions.csproj", "{4AEA96B5-B30A-49C7-8871-29D18587936F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Epsilon.Tests", "Epsilon.Tests\Epsilon.Tests.csproj", "{4F5E4A10-5D0E-4C7D-B24C-33C9B6FA52CF}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -42,5 +47,15 @@ Global {4AEA96B5-B30A-49C7-8871-29D18587936F}.Debug|Any CPU.Build.0 = Debug|Any CPU {4AEA96B5-B30A-49C7-8871-29D18587936F}.Release|Any CPU.ActiveCfg = Release|Any CPU {4AEA96B5-B30A-49C7-8871-29D18587936F}.Release|Any CPU.Build.0 = Release|Any CPU + {4F5E4A10-5D0E-4C7D-B24C-33C9B6FA52CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F5E4A10-5D0E-4C7D-B24C-33C9B6FA52CF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F5E4A10-5D0E-4C7D-B24C-33C9B6FA52CF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F5E4A10-5D0E-4C7D-B24C-33C9B6FA52CF}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {63F9A5D2-3979-4C37-9A45-C0AF94B7FEE9} EndGlobalSection EndGlobal diff --git a/Epsilon/Export/ExportDataPackager.cs b/Epsilon/Export/ExportDataPackager.cs index a9f94d7d..7b125bb2 100644 --- a/Epsilon/Export/ExportDataPackager.cs +++ b/Epsilon/Export/ExportDataPackager.cs @@ -2,17 +2,18 @@ using Epsilon.Abstractions.Export; using Epsilon.Abstractions.Model; using Epsilon.Canvas.Abstractions.Model; +using System.Text.Json; namespace Epsilon.Export; public class ExportDataPackager : IExportDataPackager { public async Task GetExportData(IAsyncEnumerable data) - { + { var output = new List(); await foreach (var item in data.Where(m => m.Collection.OutcomeResults.Any())) - { + { var module = new CourseModule { Name = item.Module.Name }; var links = item.Collection.Links; @@ -21,7 +22,7 @@ public async Task GetExportData(IAsyncEnumerable(); + var moduleOutcomes = new List(); foreach (var (outcomeId, outcome) in outcomes) { @@ -42,7 +43,7 @@ public async Task GetExportData(IAsyncEnumerable GetExportData(IAsyncEnumerable Export(ExportData data, string format) await WriteLineAndLog(writer, "--------------------------------"); await WriteLineAndLog(writer, $"Module: {module.Name}"); - foreach (var kpi in module.Kpis) + foreach (var outcome in module.Outcomes) { await WriteLineAndLog(writer, ""); - await WriteLineAndLog(writer, $"KPI: {kpi.Name}"); + await WriteLineAndLog(writer, $"KPI: {outcome.Name}"); - foreach (var assignment in kpi.Assignments) + foreach (var assignment in outcome.Assignments) { await WriteLineAndLog(writer, $"- Assignment: {assignment.Name}"); await WriteLineAndLog(writer, $" Score: {assignment.Score}"); diff --git a/Epsilon/Export/Exporters/CsvModuleExporter.cs b/Epsilon/Export/Exporters/CsvModuleExporter.cs index eb1d560e..975ac274 100644 --- a/Epsilon/Export/Exporters/CsvModuleExporter.cs +++ b/Epsilon/Export/Exporters/CsvModuleExporter.cs @@ -35,7 +35,7 @@ private static DataTable CreateDataTable(IEnumerable data) foreach (var module in data) { - foreach (var kpi in module.Kpis) + foreach (var kpi in module.Outcomes) { foreach (var assignment in kpi.Assignments) { diff --git a/Epsilon/Export/Exporters/ExcelModuleExporter.cs b/Epsilon/Export/Exporters/ExcelModuleExporter.cs index 76d9174e..61758886 100644 --- a/Epsilon/Export/Exporters/ExcelModuleExporter.cs +++ b/Epsilon/Export/Exporters/ExcelModuleExporter.cs @@ -46,9 +46,9 @@ public async Task Export(ExportData data, string format) ); uint count = 2; - foreach (var kpi in module.Kpis) + foreach (var outcome in module.Outcomes) { - foreach (var assignment in kpi.Assignments) + foreach (var assignment in outcome.Assignments) { cellValueBuilder.AppendLine($"{assignment.Name} {assignment.Url}"); cellValueOutComeResultsBuilder.AppendLine(assignment.Score); @@ -57,7 +57,7 @@ public async Task Export(ExportData data, string format) InsertCellsInWorksheet( worksheetPart, count, - CreateTextCell($"{kpi.Name} {kpi.Description}", "A", count), + CreateTextCell($"{outcome.Name} {outcome.Description}", "A", count), CreateTextCell(cellValueBuilder.ToString(), "B", count), CreateTextCell(cellValueOutComeResultsBuilder.ToString(), "C", count) ); diff --git a/Epsilon/Export/Exporters/WordModuleExporter.cs b/Epsilon/Export/Exporters/WordModuleExporter.cs index f9a36be3..d87e669a 100644 --- a/Epsilon/Export/Exporters/WordModuleExporter.cs +++ b/Epsilon/Export/Exporters/WordModuleExporter.cs @@ -51,7 +51,7 @@ public async Task Export(ExportData data, string format) table.AppendChild(s_defaultTableProperties.CloneNode(true)); table.Append(s_defaultHeader.CloneNode(true)); - var rows = module.Kpis.Select(kpi => + var rows = module.Outcomes.Select(kpi => { foreach (var assignment in kpi.Assignments) {