From c81fd2ff5398c2b7ad72ca94f243775370beaf8e Mon Sep 17 00:00:00 2001 From: Alex Jackson Date: Tue, 11 Jan 2022 16:15:56 +0000 Subject: [PATCH 1/7] HEEDLS-711 Filter resources where delegate answers lie outside required result range --- .../RecommendedLearningServiceTests.cs | 309 ++++++++++++------ .../CompetencyLearningResourcesDataService.cs | 4 +- ...encyResourceAssessmentQuestionParameter.cs | 4 + .../Services/RecommendedLearningService.cs | 115 +++++-- 4 files changed, 310 insertions(+), 122 deletions(-) diff --git a/DigitalLearningSolutions.Data.Tests/Services/RecommendedLearningServiceTests.cs b/DigitalLearningSolutions.Data.Tests/Services/RecommendedLearningServiceTests.cs index fa4c83746f..9033a797ac 100644 --- a/DigitalLearningSolutions.Data.Tests/Services/RecommendedLearningServiceTests.cs +++ b/DigitalLearningSolutions.Data.Tests/Services/RecommendedLearningServiceTests.cs @@ -61,10 +61,13 @@ public async Task { // Given GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); + GivenQuestionParametersAreReturned(true, true, 1, 10); + GivenSelfAssessmentHasResults(5, 5); + A.CallTo(() => learningLogItemsDataService.GetLearningLogItems(DelegateId)) .Returns(new List()); - var expectedResource = GetExpectedResource(false, false, null); + var expectedResource = GetExpectedResource(false, false, null, 175); // When var result = @@ -82,6 +85,8 @@ public async Task { // Given GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); + GivenQuestionParametersAreReturned(true, true, 1, 10); + GivenSelfAssessmentHasResults(5, 5); var learningLogItems = Builder.CreateListOfSize(5).All() .With(i => i.LearningHubResourceReferenceId = LearningHubResourceReferenceId + 1) @@ -89,7 +94,7 @@ public async Task A.CallTo(() => learningLogItemsDataService.GetLearningLogItems(DelegateId)) .Returns(learningLogItems); - var expectedResource = GetExpectedResource(false, false, null); + var expectedResource = GetExpectedResource(false, false, null, 175); // When var result = @@ -107,6 +112,8 @@ public async Task { // Given GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); + GivenQuestionParametersAreReturned(true, true, 1, 10); + GivenSelfAssessmentHasResults(5, 5); var learningLogItem = Builder.CreateNew() .With(i => i.LearningHubResourceReferenceId = LearningHubResourceReferenceId) @@ -116,7 +123,7 @@ public async Task A.CallTo(() => learningLogItemsDataService.GetLearningLogItems(DelegateId)) .Returns(new List { learningLogItem }); - var expectedResource = GetExpectedResource(false, true, null); + var expectedResource = GetExpectedResource(false, true, null, 175); // When var result = @@ -134,6 +141,8 @@ public async Task { // Given GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); + GivenQuestionParametersAreReturned(true, true, 1, 10); + GivenSelfAssessmentHasResults(5, 5); var learningLogItem = Builder.CreateNew() .With(i => i.LearningHubResourceReferenceId = LearningHubResourceReferenceId) @@ -143,7 +152,7 @@ public async Task A.CallTo(() => learningLogItemsDataService.GetLearningLogItems(DelegateId)) .Returns(new List { learningLogItem }); - var expectedResource = GetExpectedResource(true, false, LearningLogId); + var expectedResource = GetExpectedResource(true, false, LearningLogId, 175); // When var result = @@ -161,21 +170,23 @@ public async Task { // Given GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); + GivenQuestionParametersAreReturned(true, true, 1, 10); + GivenSelfAssessmentHasResults(5, 5); - var completeLearningLogItem = Builder.CreateNew() - .With(i => i.LearningHubResourceReferenceId = LearningHubResourceReferenceId) - .And(i => i.CompletedDate = DateTime.UtcNow) - .And(i => i.LearningLogItemId = LearningLogId) - .And(i => i.ArchivedDate = null).Build(); - var incompleteLearningLogItem = Builder.CreateNew() + var learningLogItems = Builder.CreateListOfSize(2) + .All() .With(i => i.LearningHubResourceReferenceId = LearningHubResourceReferenceId) - .And(i => i.CompletedDate = null) .And(i => i.LearningLogItemId = LearningLogId) - .And(i => i.ArchivedDate = null).Build(); + .And(i => i.ArchivedDate = null) + .TheFirst(1) + .With(i => i.CompletedDate = DateTime.UtcNow) + .TheRest() + .With(i => i.CompletedDate = null) + .Build(); A.CallTo(() => learningLogItemsDataService.GetLearningLogItems(DelegateId)) - .Returns(new List { completeLearningLogItem, incompleteLearningLogItem }); + .Returns(learningLogItems); - var expectedResource = GetExpectedResource(true, true, LearningLogId); + var expectedResource = GetExpectedResource(true, true, LearningLogId, 175); // When var result = @@ -201,26 +212,7 @@ public async Task GetRecommendedLearningForSelfAssessment_calls_learning_hub_api () => competencyLearningResourcesDataService.GetCompetencyLearningResourcesByCompetencyId(A._) ).Returns(competencyLearningResources); - var clientResponse = new BulkResourceReferences - { - ResourceReferences = new List - { - new ResourceReferenceWithResourceDetails - { - ResourceId = 0, - RefId = LearningHubResourceReferenceId, - Title = ResourceName, - Description = ResourceDescription, - Catalogue = new Catalogue { Name = ResourceCatalogue }, - ResourceType = ResourceType, - Rating = 0, - Link = ResourceLink, - }, - }, - }; - - A.CallTo(() => learningHubApiClient.GetBulkResourcesByReferenceIds(A>._)) - .Returns(clientResponse); + GivenLearningUpApiReturnsResources(0); // When await recommendedLearningService.GetRecommendedLearningForSelfAssessment(SelfAssessmentId, DelegateId); @@ -235,12 +227,10 @@ public async Task GetRecommendedLearningForSelfAssessment_calls_learning_hub_api } [Test] - [TestCase(1, true, 100)] - [TestCase(1, false, 30)] - [TestCase(0, true, 0)] + [TestCase(true, 175)] + [TestCase(false, 105)] public async Task - GetRecommendedLearningForSelfAssessment_returns_correct_recommendation_score_for_resource_with_essential_question_parameters_only( - int numberOfQuestionParameters, + GetRecommendedLearningForSelfAssessment_returns_correct_recommendation_score_for_resource_with_essential_question_parameters( bool essential, decimal expectedScore ) @@ -248,19 +238,8 @@ decimal expectedScore // Given GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); GivenGetLearningLogItemsReturnsAnItem(); - - var questionParameters = - numberOfQuestionParameters == 0 - ? new List() - : Builder - .CreateListOfSize(numberOfQuestionParameters).All() - .With(qp => qp.Essential = essential).Build(); - - A.CallTo( - () => competencyLearningResourcesDataService.GetCompetencyResourceAssessmentQuestionParameters( - A>._ - ) - ).Returns(questionParameters); + GivenQuestionParametersAreReturned(essential, true, 1, 10); + GivenSelfAssessmentHasResults(5, 5); var expectedResource = GetExpectedResource(true, false, LearningLogId, expectedScore); @@ -276,17 +255,26 @@ decimal expectedScore [Test] public async Task - GetRecommendedLearningForSelfAssessment_returns_correct_recommendation_score_for_resource_with__multiple_essential_question_parameters_of_different_value() + GetRecommendedLearningForSelfAssessment_returns_correct_recommendation_score_for_resource_with_multiple_competencies_with_essential_question_parameters_of_different_value() { // Given - GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); + GivenResourceHasTwoCompetencies(); + GivenLearningUpApiReturnsResources(0); GivenGetLearningLogItemsReturnsAnItem(); + GivenSelfAssessmentHasResults(5, 5); var questionParameters = Builder - .CreateListOfSize(5).TheFirst(2) - .With(qp => qp.Essential = true) - .TheRest() - .With(qp => qp.Essential = false).Build(); + .CreateListOfSize(2) + .All() + .With(qp => qp.MinResultMatch = 1) + .And(qp => qp.MaxResultMatch = 10) + .TheFirst(1) + .With(qp => qp.Essential = true) + .And(qp => qp.CompetencyLearningResourceId = CompetencyLearningResourceId) + .TheRest() + .With(qp => qp.Essential = false) + .And(qp => qp.CompetencyLearningResourceId = 2) + .Build(); A.CallTo( () => competencyLearningResourcesDataService.GetCompetencyResourceAssessmentQuestionParameters( @@ -294,7 +282,7 @@ public async Task ) ).Returns(questionParameters); - var expectedResource = GetExpectedResource(true, false, LearningLogId, 100); + var expectedResource = GetExpectedResource(true, false, LearningLogId, 175); // When var result = @@ -307,10 +295,10 @@ public async Task } [Test] - [TestCase(0, 0)] - [TestCase(1, 4)] - [TestCase(2.4, 9.6)] - [TestCase(5, 20)] + [TestCase(0, 175)] + [TestCase(1, 179)] + [TestCase(2.4, 184.6)] + [TestCase(5, 195)] public async Task GetRecommendedLearningForSelfAssessment_returns_correct_recommendation_score_for_resource_with_learning_hub_ratings_only( decimal learningHubRating, @@ -320,6 +308,8 @@ decimal expectedScore // Given GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(learningHubRating); GivenGetLearningLogItemsReturnsAnItem(); + GivenQuestionParametersAreReturned(true, true, 1, 10); + GivenSelfAssessmentHasResults(5, 5); var expectedResource = GetExpectedResource(true, false, LearningLogId, expectedScore); @@ -347,16 +337,8 @@ decimal expectedScore // Given GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); GivenGetLearningLogItemsReturnsAnItem(); - - var questionParameters = Builder - .CreateListOfSize(1).All() - .With(qp => qp.Essential = true) - .And(qp => qp.CompareToRoleRequirements = true).Build(); - A.CallTo( - () => competencyLearningResourcesDataService.GetCompetencyResourceAssessmentQuestionParameters( - A>._ - ) - ).Returns(questionParameters); + GivenQuestionParametersAreReturned(true, true, 1, 10); + GivenSelfAssessmentHasResults(5, 5); var roleRequirement = Builder.CreateNew() .With(rr => rr.LevelRag = levelRag).Build(); @@ -400,26 +382,7 @@ decimal expectedScore GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); GivenGetLearningLogItemsReturnsAnItem(); GivenNotComparingToRoleRequirements(); - - var assessmentResults = Builder.CreateListOfSize(2) - .All() - .With(r => r.SelfAssessmentId = SelfAssessmentId) - .And(r => r.CandidateId = DelegateId) - .And(r => r.CompetencyId = CompetencyId) - .TheFirst(1) - .With(r => r.AssessmentQuestionId = CompetencyAssessmentQuestionId) - .And(r => r.Result = confidenceResult) - .TheRest() - .With(r => r.AssessmentQuestionId = RelevanceAssessmentQuestionId) - .And(r => r.Result = relevanceResult) - .Build(); - A.CallTo( - () => selfAssessmentDataService.GetSelfAssessmentResultsForDelegateSelfAssessmentCompetency( - DelegateId, - SelfAssessmentId, - CompetencyId - ) - ).Returns(assessmentResults); + GivenSelfAssessmentHasResults(relevanceResult, confidenceResult); var expectedResource = GetExpectedResource(true, false, LearningLogId, expectedScore); @@ -441,7 +404,7 @@ decimal expectedScore [Test] public async Task - GetRecommendedLearningForSelfAssessment_returns_correct_recommendation_score_for_resource_with_missing_self_assessment_results() + GetRecommendedLearningForSelfAssessment_does_not_return_resources_relating_to_unanswered_optional_competencies() { // Given GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); @@ -456,16 +419,13 @@ public async Task ) ).Returns(new List()); - var expectedResource = GetExpectedResource(true, false, LearningLogId, 100); - // When var result = (await recommendedLearningService.GetRecommendedLearningForSelfAssessment(SelfAssessmentId, DelegateId)) .ToList(); // Then - result.Should().HaveCount(1); - result.Single().Should().BeEquivalentTo(expectedResource); + result.Should().BeEmpty(); A.CallTo( () => selfAssessmentDataService.GetCompetencyAssessmentQuestionRoleRequirements( A._, @@ -474,7 +434,83 @@ public async Task ).MustNotHaveHappened(); } + [Test] + public async Task + GetRecommendedLearningForSelfAssessment_does_return_resources_with_some_unanswered_optional_competencies() + { + // Given + GivenResourceHasTwoCompetencies(); + GivenLearningUpApiReturnsResources(0); + GivenGetLearningLogItemsReturnsAnItem(); + GivenSelfAssessmentHasResults(5, 5); + + var questionParameters = Builder + .CreateListOfSize(2) + .All() + .With(qp => qp.MinResultMatch = 1) + .And(qp => qp.MaxResultMatch = 10) + .TheFirst(1) + .With(qp => qp.Essential = true) + .And(qp => qp.CompetencyLearningResourceId = CompetencyLearningResourceId) + .TheRest() + .With(qp => qp.Essential = false) + .And(qp => qp.CompetencyLearningResourceId = 2) + .Build(); + + A.CallTo( + () => competencyLearningResourcesDataService.GetCompetencyResourceAssessmentQuestionParameters( + A>._ + ) + ).Returns(questionParameters); + + var expectedResource = GetExpectedResource(true, false, LearningLogId, 175); + + // When + var result = + (await recommendedLearningService.GetRecommendedLearningForSelfAssessment(SelfAssessmentId, DelegateId)) + .ToList(); + + // Then + result.Should().HaveCount(1); + result.Single().Should().BeEquivalentTo(expectedResource); + } + + [Test] + [TestCase(1, 10, 5, 1)] + [TestCase(5, 10, 4, 0)] + [TestCase(1, 5, 6, 0)] + [TestCase(3, 7, 3, 1)] + [TestCase(3, 7, 7, 1)] + public async Task + GetRecommendedLearningForSelfAssessment_returns_expected_number_of_resources_for_answers_in_and_out_of_range( + int minScore, + int maxScore, + int confidenceResult, + int expectedResultCount + ) + { + // Given + GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); + GivenGetLearningLogItemsReturnsAnItem(); + GivenQuestionParametersAreReturned(true, true, minScore, maxScore); + GivenSelfAssessmentHasResults(5, confidenceResult); + + // When + var result = + (await recommendedLearningService.GetRecommendedLearningForSelfAssessment(SelfAssessmentId, DelegateId)) + .ToList(); + + // Then + result.Should().HaveCount(expectedResultCount); + } + private void GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(decimal rating = 0) + { + GivenSingleCompetencyExistsForResource(); + GivenLearningUpApiReturnsResources(rating); + } + + private void GivenSingleCompetencyExistsForResource() { A.CallTo(() => selfAssessmentDataService.GetCompetencyIdsForSelfAssessment(SelfAssessmentId)) .Returns(new[] { CompetencyId }); @@ -491,7 +527,33 @@ private void GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(decimal ra A.CallTo( () => competencyLearningResourcesDataService.GetCompetencyLearningResourcesByCompetencyId(CompetencyId) ).Returns(new List { competencyLearningResource }); + } + + private void GivenResourceHasTwoCompetencies() + { + A.CallTo(() => selfAssessmentDataService.GetCompetencyIdsForSelfAssessment(SelfAssessmentId)) + .Returns(new[] { CompetencyId, 3 }); + + var competencyLearningResources = Builder.CreateListOfSize(2) + .All() + .With(clr => clr.LearningResourceReferenceId = LearningResourceReferenceId) + .And(clr => clr.LearningHubResourceReferenceId = LearningHubResourceReferenceId) + .And(clr => clr.AdminId = 7) + .TheFirst(1) + .With(clr => clr.Id = CompetencyLearningResourceId) + .And(clr => clr.CompetencyId = CompetencyId) + .TheRest() + .With(clr => clr.Id = 2) + .And(clr => clr.CompetencyId = 3) + .Build(); + A.CallTo( + () => competencyLearningResourcesDataService.GetCompetencyLearningResourcesByCompetencyId(CompetencyId) + ).Returns(competencyLearningResources); + } + + private void GivenLearningUpApiReturnsResources(decimal rating) + { var clientResponse = new BulkResourceReferences { ResourceReferences = new List @@ -531,8 +593,34 @@ private void GivenNotComparingToRoleRequirements() .CreateListOfSize(1).All() .With(qp => qp.Essential = true) .And(qp => qp.CompareToRoleRequirements = false) + .And(qp => qp.CompetencyLearningResourceId = CompetencyLearningResourceId) .And(qp => qp.AssessmentQuestionId = CompetencyAssessmentQuestionId) - .And(qp => qp.RelevanceAssessmentQuestionId = RelevanceAssessmentQuestionId).Build(); + .And(qp => qp.RelevanceAssessmentQuestionId = RelevanceAssessmentQuestionId) + .And(qp => qp.MinResultMatch = 1) + .And(qp => qp.MaxResultMatch = 10) + .Build(); + A.CallTo( + () => competencyLearningResourcesDataService.GetCompetencyResourceAssessmentQuestionParameters( + A>._ + ) + ).Returns(questionParameters); + } + + private void GivenQuestionParametersAreReturned( + bool essential, + bool compareToRoleRequirements, + int minMatch, + int maxMatch + ) + { + var questionParameters = Builder + .CreateListOfSize(1).All() + .With(qp => qp.Essential = essential) + .And(qp => qp.CompareToRoleRequirements = compareToRoleRequirements) + .And(qp => qp.MinResultMatch = minMatch) + .And(qp => qp.MaxResultMatch = maxMatch) + .And(qp => qp.CompetencyLearningResourceId = CompetencyLearningResourceId) + .Build(); A.CallTo( () => competencyLearningResourcesDataService.GetCompetencyResourceAssessmentQuestionParameters( A>._ @@ -540,6 +628,29 @@ private void GivenNotComparingToRoleRequirements() ).Returns(questionParameters); } + private void GivenSelfAssessmentHasResults(int relevanceResult, int confidenceResult) + { + var assessmentResults = Builder.CreateListOfSize(2) + .All() + .With(r => r.SelfAssessmentId = SelfAssessmentId) + .And(r => r.CandidateId = DelegateId) + .And(r => r.CompetencyId = CompetencyId) + .TheFirst(1) + .With(r => r.AssessmentQuestionId = CompetencyAssessmentQuestionId) + .And(r => r.Result = confidenceResult) + .TheRest() + .With(r => r.AssessmentQuestionId = RelevanceAssessmentQuestionId) + .And(r => r.Result = relevanceResult) + .Build(); + A.CallTo( + () => selfAssessmentDataService.GetSelfAssessmentResultsForDelegateSelfAssessmentCompetency( + DelegateId, + SelfAssessmentId, + CompetencyId + ) + ).Returns(assessmentResults); + } + private RecommendedResource GetExpectedResource( bool isInActionPlan, bool isCompleted, diff --git a/DigitalLearningSolutions.Data/DataServices/CompetencyLearningResourcesDataService.cs b/DigitalLearningSolutions.Data/DataServices/CompetencyLearningResourcesDataService.cs index e594c73092..b280331c58 100644 --- a/DigitalLearningSolutions.Data/DataServices/CompetencyLearningResourcesDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/CompetencyLearningResourcesDataService.cs @@ -96,7 +96,9 @@ public IEnumerable AssessmentQuestionID, Essential, RelevanceAssessmentQuestionID, - CompareToRoleRequirements + CompareToRoleRequirements, + MinResultMatch, + MaxResultMatch FROM CompetencyResourceAssessmentQuestionParameters WHERE CompetencyLearningResourceId IN @competencyLearningResourceIds", new { competencyLearningResourceIds } diff --git a/DigitalLearningSolutions.Data/Models/SelfAssessments/CompetencyResourceAssessmentQuestionParameter.cs b/DigitalLearningSolutions.Data/Models/SelfAssessments/CompetencyResourceAssessmentQuestionParameter.cs index 915c6fb33a..c0dc1ae4f7 100644 --- a/DigitalLearningSolutions.Data/Models/SelfAssessments/CompetencyResourceAssessmentQuestionParameter.cs +++ b/DigitalLearningSolutions.Data/Models/SelfAssessments/CompetencyResourceAssessmentQuestionParameter.cs @@ -11,5 +11,9 @@ public class CompetencyResourceAssessmentQuestionParameter public int? RelevanceAssessmentQuestionId { get; set; } public bool CompareToRoleRequirements { get; set; } + + public int MinResultMatch { get; set; } + + public int MaxResultMatch { get; set; } } } diff --git a/DigitalLearningSolutions.Data/Services/RecommendedLearningService.cs b/DigitalLearningSolutions.Data/Services/RecommendedLearningService.cs index 17aebe527f..bf689915cc 100644 --- a/DigitalLearningSolutions.Data/Services/RecommendedLearningService.cs +++ b/DigitalLearningSolutions.Data/Services/RecommendedLearningService.cs @@ -67,40 +67,111 @@ int delegateId var delegateLearningLogItems = learningLogItemsDataService.GetLearningLogItems(delegateId); var recommendedResources = resources.ResourceReferences.Select( - rr => - { - var learningLogItemsForResource = delegateLearningLogItems.Where( - ll => ll.ArchivedDate == null && ll.LearningHubResourceReferenceId == rr.RefId - ).ToList(); - var incompleteLearningLogItem = - learningLogItemsForResource.SingleOrDefault(ll => ll.CompletedDate == null); - return new RecommendedResource( - resourceReferences[rr.RefId], - rr, - incompleteLearningLogItem, - learningLogItemsForResource.Any(ll => ll.CompletedDate != null), - CalculateRecommendedLearningScore(rr, competencyLearningResources, selfAssessmentId, delegateId) - ); - } + rr => PopulatedRecommendedResource( + selfAssessmentId, + delegateId, + resourceReferences[rr.RefId], + delegateLearningLogItems, + rr, + competencyLearningResources + ) ); - return recommendedResources; + return recommendedResources.Where(r => r != null).Select(r => r!); } - private decimal CalculateRecommendedLearningScore( - ResourceReferenceWithResourceDetails resource, - List competencyLearningResources, + private RecommendedResource? PopulatedRecommendedResource( int selfAssessmentId, - int delegateId + int delegateId, + int learningHubResourceReferenceId, + IEnumerable delegateLearningLogItems, + ResourceReferenceWithResourceDetails rr, + List competencyLearningResources ) { + var learningLogItemsForResource = delegateLearningLogItems.Where( + ll => ll.ArchivedDate == null && ll.LearningHubResourceReferenceId == rr.RefId + ).ToList(); + var incompleteLearningLogItem = + learningLogItemsForResource.SingleOrDefault(ll => ll.CompletedDate == null); + var clrsForResource = - competencyLearningResources.Where(clr => clr.LearningHubResourceReferenceId == resource.RefId).ToList(); + competencyLearningResources.Where(clr => clr.LearningHubResourceReferenceId == rr.RefId) + .ToList(); var competencyResourceAssessmentQuestionParameters = competencyLearningResourcesDataService - .GetCompetencyResourceAssessmentQuestionParameters(clrsForResource.Select(clr => clr.Id)).ToList(); + .GetCompetencyResourceAssessmentQuestionParameters(clrsForResource.Select(clr => clr.Id)) + .ToList(); + + return AreDelegateAnswersWithinRangeToDisplayResource( + clrsForResource, + competencyResourceAssessmentQuestionParameters, + selfAssessmentId, + delegateId + ) + ? new RecommendedResource( + learningHubResourceReferenceId, + rr, + incompleteLearningLogItem, + learningLogItemsForResource.Any(ll => ll.CompletedDate != null), + CalculateRecommendedLearningScore( + rr, + clrsForResource, + competencyResourceAssessmentQuestionParameters, + selfAssessmentId, + delegateId + ) + ) + : null; + } + + private bool AreDelegateAnswersWithinRangeToDisplayResource( + List clrsForResource, + List competencyResourceAssessmentQuestionParameters, + int selfAssessmentId, + int delegateId + ) + { + foreach (var competencyLearningResource in clrsForResource) + { + var delegateResults = selfAssessmentDataService + .GetSelfAssessmentResultsForDelegateSelfAssessmentCompetency( + delegateId, + selfAssessmentId, + competencyLearningResource.CompetencyId + ).ToList(); + + var competencyResourceAssessmentQuestionParameter = + competencyResourceAssessmentQuestionParameters.Single( + qp => qp.CompetencyLearningResourceId == competencyLearningResource.Id + ); + var latestConfidenceResult = delegateResults + .Where( + dr => dr.AssessmentQuestionId == + competencyResourceAssessmentQuestionParameter.AssessmentQuestionId + ) + .OrderByDescending(dr => dr.DateTime).FirstOrDefault(); + + if (competencyResourceAssessmentQuestionParameter.MinResultMatch <= latestConfidenceResult?.Result && + latestConfidenceResult?.Result <= competencyResourceAssessmentQuestionParameter.MaxResultMatch) + { + return true; + } + } + + return false; + } + + private decimal CalculateRecommendedLearningScore( + ResourceReferenceWithResourceDetails resource, + List clrsForResource, + List competencyResourceAssessmentQuestionParameters, + int selfAssessmentId, + int delegateId + ) + { var essentialnessValue = CalculateEssentialnessValue(competencyResourceAssessmentQuestionParameters); var learningHubRating = resource.Rating; From 96dcc48b648fc0d2b23871ca8bb4ff3b12e8a898 Mon Sep 17 00:00:00 2001 From: Alex Jackson Date: Tue, 11 Jan 2022 16:20:58 +0000 Subject: [PATCH 2/7] HEEDLS-711 Add new column to unit test --- .../CompetencyLearningResourcesDataServiceTests.cs | 4 +++- .../CompetencyLearningResourcesTestHelper.cs | 12 +++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/DigitalLearningSolutions.Data.Tests/DataServices/CompetencyLearningResourcesDataServiceTests.cs b/DigitalLearningSolutions.Data.Tests/DataServices/CompetencyLearningResourcesDataServiceTests.cs index cab3b825a6..7604bfd4ff 100644 --- a/DigitalLearningSolutions.Data.Tests/DataServices/CompetencyLearningResourcesDataServiceTests.cs +++ b/DigitalLearningSolutions.Data.Tests/DataServices/CompetencyLearningResourcesDataServiceTests.cs @@ -78,7 +78,7 @@ public void GetCompetencyResourceAssessmentQuestionParameters_returns_expected_r testHelper.InsertLearningResourceReference(2, 2, adminId, "Resource 2"); testHelper.InsertCompetencyLearningResource(1, 1, 2, adminId); - testHelper.InsertCompetencyResourceAssessmentQuestionParameters(1, 1, true, 2, false); + testHelper.InsertCompetencyResourceAssessmentQuestionParameters(1, 1, true, 2, false, 1, 10); var expectedItem = new CompetencyResourceAssessmentQuestionParameter { CompetencyLearningResourceId = 1, @@ -86,6 +86,8 @@ public void GetCompetencyResourceAssessmentQuestionParameters_returns_expected_r Essential = true, RelevanceAssessmentQuestionId = 2, CompareToRoleRequirements = false, + MinResultMatch = 1, + MaxResultMatch = 10, }; // When diff --git a/DigitalLearningSolutions.Data.Tests/TestHelpers/CompetencyLearningResourcesTestHelper.cs b/DigitalLearningSolutions.Data.Tests/TestHelpers/CompetencyLearningResourcesTestHelper.cs index 94280a115a..b71410cb21 100644 --- a/DigitalLearningSolutions.Data.Tests/TestHelpers/CompetencyLearningResourcesTestHelper.cs +++ b/DigitalLearningSolutions.Data.Tests/TestHelpers/CompetencyLearningResourcesTestHelper.cs @@ -47,14 +47,20 @@ public void InsertCompetencyResourceAssessmentQuestionParameters( int assessmentQuestionId, bool essential, int? relevanceQuestionId, - bool compareToRoleRequirements + bool compareToRoleRequirements, + int minMatchResult, + int maxMatchResult ) { connection.Execute( @"INSERT INTO CompetencyResourceAssessmentQuestionParameters (CompetencyLearningResourceId, AssessmentQuestionID, Essential, RelevanceAssessmentQuestionID, CompareToRoleRequirements, MinResultMatch, MaxResultMatch) - VALUES (@competencyLearningResourceId, @assessmentQuestionId, @essential, @relevanceQuestionId, @compareToRoleRequirements, 0, 0)", - new { competencyLearningResourceId, assessmentQuestionId, essential, relevanceQuestionId, compareToRoleRequirements } + VALUES (@competencyLearningResourceId, @assessmentQuestionId, @essential, @relevanceQuestionId, @compareToRoleRequirements, @minMatchResult, @maxMatchResult)", + new + { + competencyLearningResourceId, assessmentQuestionId, essential, relevanceQuestionId, + compareToRoleRequirements, minMatchResult, maxMatchResult, + } ); } } From d93748a7a5d9f25f62e798463e7177abee4123bc Mon Sep 17 00:00:00 2001 From: Alex Jackson Date: Wed, 12 Jan 2022 17:16:02 +0000 Subject: [PATCH 3/7] HEEDLS-711 Review markups --- .../RecommendedLearningServiceTests.cs | 55 +++++++++--------- .../Services/RecommendedLearningService.cs | 58 +++++++++++-------- 2 files changed, 61 insertions(+), 52 deletions(-) diff --git a/DigitalLearningSolutions.Data.Tests/Services/RecommendedLearningServiceTests.cs b/DigitalLearningSolutions.Data.Tests/Services/RecommendedLearningServiceTests.cs index 9033a797ac..47e048b385 100644 --- a/DigitalLearningSolutions.Data.Tests/Services/RecommendedLearningServiceTests.cs +++ b/DigitalLearningSolutions.Data.Tests/Services/RecommendedLearningServiceTests.cs @@ -20,11 +20,13 @@ public class RecommendedLearningServiceTests { private const int SelfAssessmentId = 1; private const int CompetencyId = 2; + private const int SecondCompetencyId = 3; private const int LearningResourceReferenceId = 3; private const int LearningHubResourceReferenceId = 4; private const int DelegateId = 5; private const int LearningLogId = 6; private const int CompetencyLearningResourceId = 1; + private const int SecondCompetencyLearningResourceId = 2; private const int CompetencyAssessmentQuestionId = 1; private const int RelevanceAssessmentQuestionId = 2; private const string ResourceName = "Resource"; @@ -62,7 +64,7 @@ public async Task // Given GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); GivenQuestionParametersAreReturned(true, true, 1, 10); - GivenSelfAssessmentHasResults(5, 5); + GivenSelfAssessmentHasResultsForFirstCompetency(5, 5); A.CallTo(() => learningLogItemsDataService.GetLearningLogItems(DelegateId)) .Returns(new List()); @@ -86,7 +88,7 @@ public async Task // Given GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); GivenQuestionParametersAreReturned(true, true, 1, 10); - GivenSelfAssessmentHasResults(5, 5); + GivenSelfAssessmentHasResultsForFirstCompetency(5, 5); var learningLogItems = Builder.CreateListOfSize(5).All() .With(i => i.LearningHubResourceReferenceId = LearningHubResourceReferenceId + 1) @@ -113,7 +115,7 @@ public async Task // Given GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); GivenQuestionParametersAreReturned(true, true, 1, 10); - GivenSelfAssessmentHasResults(5, 5); + GivenSelfAssessmentHasResultsForFirstCompetency(5, 5); var learningLogItem = Builder.CreateNew() .With(i => i.LearningHubResourceReferenceId = LearningHubResourceReferenceId) @@ -142,7 +144,7 @@ public async Task // Given GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); GivenQuestionParametersAreReturned(true, true, 1, 10); - GivenSelfAssessmentHasResults(5, 5); + GivenSelfAssessmentHasResultsForFirstCompetency(5, 5); var learningLogItem = Builder.CreateNew() .With(i => i.LearningHubResourceReferenceId = LearningHubResourceReferenceId) @@ -171,7 +173,7 @@ public async Task // Given GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); GivenQuestionParametersAreReturned(true, true, 1, 10); - GivenSelfAssessmentHasResults(5, 5); + GivenSelfAssessmentHasResultsForFirstCompetency(5, 5); var learningLogItems = Builder.CreateListOfSize(2) .All() @@ -212,7 +214,7 @@ public async Task GetRecommendedLearningForSelfAssessment_calls_learning_hub_api () => competencyLearningResourcesDataService.GetCompetencyLearningResourcesByCompetencyId(A._) ).Returns(competencyLearningResources); - GivenLearningUpApiReturnsResources(0); + GivenLearningHubApiReturnsResources(0); // When await recommendedLearningService.GetRecommendedLearningForSelfAssessment(SelfAssessmentId, DelegateId); @@ -239,7 +241,7 @@ decimal expectedScore GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); GivenGetLearningLogItemsReturnsAnItem(); GivenQuestionParametersAreReturned(essential, true, 1, 10); - GivenSelfAssessmentHasResults(5, 5); + GivenSelfAssessmentHasResultsForFirstCompetency(5, 5); var expectedResource = GetExpectedResource(true, false, LearningLogId, expectedScore); @@ -259,9 +261,9 @@ public async Task { // Given GivenResourceHasTwoCompetencies(); - GivenLearningUpApiReturnsResources(0); + GivenLearningHubApiReturnsResources(0); GivenGetLearningLogItemsReturnsAnItem(); - GivenSelfAssessmentHasResults(5, 5); + GivenSelfAssessmentHasResultsForFirstCompetency(5, 5); var questionParameters = Builder .CreateListOfSize(2) @@ -295,10 +297,10 @@ public async Task } [Test] - [TestCase(0, 175)] - [TestCase(1, 179)] - [TestCase(2.4, 184.6)] - [TestCase(5, 195)] + [TestCase(0, 0)] + [TestCase(1, 4)] + [TestCase(2.4, 9.6)] + [TestCase(5, 20)] public async Task GetRecommendedLearningForSelfAssessment_returns_correct_recommendation_score_for_resource_with_learning_hub_ratings_only( decimal learningHubRating, @@ -308,8 +310,7 @@ decimal expectedScore // Given GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(learningHubRating); GivenGetLearningLogItemsReturnsAnItem(); - GivenQuestionParametersAreReturned(true, true, 1, 10); - GivenSelfAssessmentHasResults(5, 5); + GivenSelfAssessmentHasResultsForFirstCompetency(5, 5); var expectedResource = GetExpectedResource(true, false, LearningLogId, expectedScore); @@ -338,7 +339,7 @@ decimal expectedScore GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); GivenGetLearningLogItemsReturnsAnItem(); GivenQuestionParametersAreReturned(true, true, 1, 10); - GivenSelfAssessmentHasResults(5, 5); + GivenSelfAssessmentHasResultsForFirstCompetency(5, 5); var roleRequirement = Builder.CreateNew() .With(rr => rr.LevelRag = levelRag).Build(); @@ -382,7 +383,7 @@ decimal expectedScore GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); GivenGetLearningLogItemsReturnsAnItem(); GivenNotComparingToRoleRequirements(); - GivenSelfAssessmentHasResults(relevanceResult, confidenceResult); + GivenSelfAssessmentHasResultsForFirstCompetency(relevanceResult, confidenceResult); var expectedResource = GetExpectedResource(true, false, LearningLogId, expectedScore); @@ -440,9 +441,9 @@ public async Task { // Given GivenResourceHasTwoCompetencies(); - GivenLearningUpApiReturnsResources(0); + GivenLearningHubApiReturnsResources(0); GivenGetLearningLogItemsReturnsAnItem(); - GivenSelfAssessmentHasResults(5, 5); + GivenSelfAssessmentHasResultsForFirstCompetency(5, 5); var questionParameters = Builder .CreateListOfSize(2) @@ -454,7 +455,7 @@ public async Task .And(qp => qp.CompetencyLearningResourceId = CompetencyLearningResourceId) .TheRest() .With(qp => qp.Essential = false) - .And(qp => qp.CompetencyLearningResourceId = 2) + .And(qp => qp.CompetencyLearningResourceId = SecondCompetencyLearningResourceId) .Build(); A.CallTo( @@ -493,7 +494,7 @@ int expectedResultCount GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(); GivenGetLearningLogItemsReturnsAnItem(); GivenQuestionParametersAreReturned(true, true, minScore, maxScore); - GivenSelfAssessmentHasResults(5, confidenceResult); + GivenSelfAssessmentHasResultsForFirstCompetency(5, confidenceResult); // When var result = @@ -507,7 +508,7 @@ int expectedResultCount private void GivenResourceForSelfAssessmentIsReturnedByLearningHubApi(decimal rating = 0) { GivenSingleCompetencyExistsForResource(); - GivenLearningUpApiReturnsResources(rating); + GivenLearningHubApiReturnsResources(rating); } private void GivenSingleCompetencyExistsForResource() @@ -532,7 +533,7 @@ private void GivenSingleCompetencyExistsForResource() private void GivenResourceHasTwoCompetencies() { A.CallTo(() => selfAssessmentDataService.GetCompetencyIdsForSelfAssessment(SelfAssessmentId)) - .Returns(new[] { CompetencyId, 3 }); + .Returns(new[] { CompetencyId, SecondCompetencyId }); var competencyLearningResources = Builder.CreateListOfSize(2) .All() @@ -543,8 +544,8 @@ private void GivenResourceHasTwoCompetencies() .With(clr => clr.Id = CompetencyLearningResourceId) .And(clr => clr.CompetencyId = CompetencyId) .TheRest() - .With(clr => clr.Id = 2) - .And(clr => clr.CompetencyId = 3) + .With(clr => clr.Id = SecondCompetencyLearningResourceId) + .And(clr => clr.CompetencyId = SecondCompetencyId) .Build(); A.CallTo( @@ -552,7 +553,7 @@ private void GivenResourceHasTwoCompetencies() ).Returns(competencyLearningResources); } - private void GivenLearningUpApiReturnsResources(decimal rating) + private void GivenLearningHubApiReturnsResources(decimal rating) { var clientResponse = new BulkResourceReferences { @@ -628,7 +629,7 @@ int maxMatch ).Returns(questionParameters); } - private void GivenSelfAssessmentHasResults(int relevanceResult, int confidenceResult) + private void GivenSelfAssessmentHasResultsForFirstCompetency(int relevanceResult, int confidenceResult) { var assessmentResults = Builder.CreateListOfSize(2) .All() diff --git a/DigitalLearningSolutions.Data/Services/RecommendedLearningService.cs b/DigitalLearningSolutions.Data/Services/RecommendedLearningService.cs index bf689915cc..f7137578c8 100644 --- a/DigitalLearningSolutions.Data/Services/RecommendedLearningService.cs +++ b/DigitalLearningSolutions.Data/Services/RecommendedLearningService.cs @@ -67,7 +67,7 @@ int delegateId var delegateLearningLogItems = learningLogItemsDataService.GetLearningLogItems(delegateId); var recommendedResources = resources.ResourceReferences.Select( - rr => PopulatedRecommendedResource( + rr => GetPopulatedRecommendedResource( selfAssessmentId, delegateId, resourceReferences[rr.RefId], @@ -80,7 +80,7 @@ int delegateId return recommendedResources.Where(r => r != null).Select(r => r!); } - private RecommendedResource? PopulatedRecommendedResource( + private RecommendedResource? GetPopulatedRecommendedResource( int selfAssessmentId, int delegateId, int learningHubResourceReferenceId, @@ -104,26 +104,29 @@ List competencyLearningResources .GetCompetencyResourceAssessmentQuestionParameters(clrsForResource.Select(clr => clr.Id)) .ToList(); - return AreDelegateAnswersWithinRangeToDisplayResource( + if (!AreDelegateAnswersWithinRangeToDisplayResource( clrsForResource, competencyResourceAssessmentQuestionParameters, selfAssessmentId, delegateId - ) - ? new RecommendedResource( - learningHubResourceReferenceId, + )) + { + return null; + } + + return new RecommendedResource( + learningHubResourceReferenceId, + rr, + incompleteLearningLogItem, + learningLogItemsForResource.Any(ll => ll.CompletedDate != null), + CalculateRecommendedLearningScore( rr, - incompleteLearningLogItem, - learningLogItemsForResource.Any(ll => ll.CompletedDate != null), - CalculateRecommendedLearningScore( - rr, - clrsForResource, - competencyResourceAssessmentQuestionParameters, - selfAssessmentId, - delegateId - ) + clrsForResource, + competencyResourceAssessmentQuestionParameters, + selfAssessmentId, + delegateId ) - : null; + ); } private bool AreDelegateAnswersWithinRangeToDisplayResource( @@ -142,20 +145,25 @@ int delegateId competencyLearningResource.CompetencyId ).ToList(); - var competencyResourceAssessmentQuestionParameter = - competencyResourceAssessmentQuestionParameters.Single( + var competencyResourceAssessmentQuestionParametersForClr = + competencyResourceAssessmentQuestionParameters.SingleOrDefault( qp => qp.CompetencyLearningResourceId == competencyLearningResource.Id ); + if (competencyResourceAssessmentQuestionParametersForClr == null) + { + return true; + } + var latestConfidenceResult = delegateResults .Where( dr => dr.AssessmentQuestionId == - competencyResourceAssessmentQuestionParameter.AssessmentQuestionId + competencyResourceAssessmentQuestionParametersForClr.AssessmentQuestionId ) .OrderByDescending(dr => dr.DateTime).FirstOrDefault(); - if (competencyResourceAssessmentQuestionParameter.MinResultMatch <= latestConfidenceResult?.Result && - latestConfidenceResult?.Result <= competencyResourceAssessmentQuestionParameter.MaxResultMatch) + if (competencyResourceAssessmentQuestionParametersForClr.MinResultMatch <= latestConfidenceResult?.Result && + latestConfidenceResult.Result <= competencyResourceAssessmentQuestionParametersForClr.MaxResultMatch) { return true; } @@ -205,17 +213,17 @@ int delegateId foreach (var competencyLearningResource in competencyLearningResources) { - var competencyResourceAssessmentQuestionParameterForClr = + var competencyResourceAssessmentQuestionParametersForClr = competencyResourceAssessmentQuestionParameters.SingleOrDefault( c => c.CompetencyLearningResourceId == competencyLearningResource.Id ); - if (competencyResourceAssessmentQuestionParameterForClr == null) + if (competencyResourceAssessmentQuestionParametersForClr == null) { break; } - if (competencyResourceAssessmentQuestionParameterForClr.CompareToRoleRequirements) + if (competencyResourceAssessmentQuestionParametersForClr.CompareToRoleRequirements) { requirementAdjusters.Add( CalculateRoleRequirementValue(competencyLearningResource.CompetencyId, selfAssessmentId) @@ -229,7 +237,7 @@ int delegateId .CompetencyId, selfAssessmentId, delegateId, - competencyResourceAssessmentQuestionParameterForClr + competencyResourceAssessmentQuestionParametersForClr ) ); } From 878b89801e14220327f71c596be6d030e0457280 Mon Sep 17 00:00:00 2001 From: Alex Jackson Date: Fri, 14 Jan 2022 10:22:52 +0000 Subject: [PATCH 4/7] HEEDLS-711 Rename unit test --- .../Services/RecommendedLearningServiceTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DigitalLearningSolutions.Data.Tests/Services/RecommendedLearningServiceTests.cs b/DigitalLearningSolutions.Data.Tests/Services/RecommendedLearningServiceTests.cs index 47e048b385..6788d0f3dc 100644 --- a/DigitalLearningSolutions.Data.Tests/Services/RecommendedLearningServiceTests.cs +++ b/DigitalLearningSolutions.Data.Tests/Services/RecommendedLearningServiceTests.cs @@ -302,7 +302,7 @@ public async Task [TestCase(2.4, 9.6)] [TestCase(5, 20)] public async Task - GetRecommendedLearningForSelfAssessment_returns_correct_recommendation_score_for_resource_with_learning_hub_ratings_only( + GetRecommendedLearningForSelfAssessment_returns_correct_recommendation_score_for_resource_with_learning_hub_ratings_and_no_question_parameters( decimal learningHubRating, decimal expectedScore ) From d3609c5d10c70c46698bae825852576e0ef9c060 Mon Sep 17 00:00:00 2001 From: Alex Jackson Date: Fri, 14 Jan 2022 14:24:54 +0000 Subject: [PATCH 5/7] HEEDLS-711 Add WhereNotNull extension that filters null items out of a list --- ...DigitalLearningSolutions.Data.Tests.csproj | 1 + .../Extensions/EnumerableExtensionsTests.cs | 24 +++++++++++++++++++ .../Extensions/EnumerableExtensions.cs | 13 ++++++++++ .../Services/RecommendedLearningService.cs | 3 ++- 4 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 DigitalLearningSolutions.Data.Tests/Extensions/EnumerableExtensionsTests.cs create mode 100644 DigitalLearningSolutions.Data/Extensions/EnumerableExtensions.cs diff --git a/DigitalLearningSolutions.Data.Tests/DigitalLearningSolutions.Data.Tests.csproj b/DigitalLearningSolutions.Data.Tests/DigitalLearningSolutions.Data.Tests.csproj index 426bc90d5a..1e96c40bbc 100644 --- a/DigitalLearningSolutions.Data.Tests/DigitalLearningSolutions.Data.Tests.csproj +++ b/DigitalLearningSolutions.Data.Tests/DigitalLearningSolutions.Data.Tests.csproj @@ -42,6 +42,7 @@ + diff --git a/DigitalLearningSolutions.Data.Tests/Extensions/EnumerableExtensionsTests.cs b/DigitalLearningSolutions.Data.Tests/Extensions/EnumerableExtensionsTests.cs new file mode 100644 index 0000000000..4b98221418 --- /dev/null +++ b/DigitalLearningSolutions.Data.Tests/Extensions/EnumerableExtensionsTests.cs @@ -0,0 +1,24 @@ +namespace DigitalLearningSolutions.Data.Tests.Extensions +{ + using System.Collections.Generic; + using DigitalLearningSolutions.Data.Extensions; + using FluentAssertions; + using NUnit.Framework; + + public class EnumerableExtensionsTests + { + [Test] + public void WhereNotNull_filters_items_correctly() + { + // Given + var list = new List { "1", "2", null, "3", null, "4" }; + var expectedResult = new List { "1", "2", "3", "4" }; + + // When + var result = list.WhereNotNull(); + + // Then + result.Should().BeEquivalentTo(expectedResult); + } + } +} diff --git a/DigitalLearningSolutions.Data/Extensions/EnumerableExtensions.cs b/DigitalLearningSolutions.Data/Extensions/EnumerableExtensions.cs new file mode 100644 index 0000000000..00ab26d727 --- /dev/null +++ b/DigitalLearningSolutions.Data/Extensions/EnumerableExtensions.cs @@ -0,0 +1,13 @@ +namespace DigitalLearningSolutions.Data.Extensions +{ + using System.Collections.Generic; + using System.Linq; + + public static class EnumerableExtensions + { + public static IEnumerable WhereNotNull(this IEnumerable enumerable) where T : class + { + return enumerable.Where(e => e != null).Select(e => e!); + } + } +} diff --git a/DigitalLearningSolutions.Data/Services/RecommendedLearningService.cs b/DigitalLearningSolutions.Data/Services/RecommendedLearningService.cs index f7137578c8..2294aced17 100644 --- a/DigitalLearningSolutions.Data/Services/RecommendedLearningService.cs +++ b/DigitalLearningSolutions.Data/Services/RecommendedLearningService.cs @@ -6,6 +6,7 @@ using DigitalLearningSolutions.Data.ApiClients; using DigitalLearningSolutions.Data.DataServices; using DigitalLearningSolutions.Data.DataServices.SelfAssessmentDataService; + using DigitalLearningSolutions.Data.Extensions; using DigitalLearningSolutions.Data.Models.External.LearningHubApiClient; using DigitalLearningSolutions.Data.Models.LearningResources; using DigitalLearningSolutions.Data.Models.SelfAssessments; @@ -77,7 +78,7 @@ int delegateId ) ); - return recommendedResources.Where(r => r != null).Select(r => r!); + return recommendedResources.WhereNotNull(); } private RecommendedResource? GetPopulatedRecommendedResource( From 14d2b62e97e9ed0b3724fb2573af0053b3004691 Mon Sep 17 00:00:00 2001 From: Alex Jackson Date: Mon, 17 Jan 2022 16:44:19 +0000 Subject: [PATCH 6/7] HEEDLS-711 Refactor unit test --- .../Extensions/EnumerableExtensionsTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DigitalLearningSolutions.Data.Tests/Extensions/EnumerableExtensionsTests.cs b/DigitalLearningSolutions.Data.Tests/Extensions/EnumerableExtensionsTests.cs index 4b98221418..6f3f39933d 100644 --- a/DigitalLearningSolutions.Data.Tests/Extensions/EnumerableExtensionsTests.cs +++ b/DigitalLearningSolutions.Data.Tests/Extensions/EnumerableExtensionsTests.cs @@ -12,12 +12,12 @@ public void WhereNotNull_filters_items_correctly() { // Given var list = new List { "1", "2", null, "3", null, "4" }; - var expectedResult = new List { "1", "2", "3", "4" }; // When var result = list.WhereNotNull(); // Then + var expectedResult = new List { "1", "2", "3", "4" }; result.Should().BeEquivalentTo(expectedResult); } } From e01a4b380fb73053a5652031bbbfde6a27ccc0f5 Mon Sep 17 00:00:00 2001 From: Alex Jackson Date: Mon, 17 Jan 2022 17:20:46 +0000 Subject: [PATCH 7/7] HEEDLS-711 Inline expected result in test --- .../Extensions/EnumerableExtensionsTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/DigitalLearningSolutions.Data.Tests/Extensions/EnumerableExtensionsTests.cs b/DigitalLearningSolutions.Data.Tests/Extensions/EnumerableExtensionsTests.cs index 6f3f39933d..e5b7ad9c65 100644 --- a/DigitalLearningSolutions.Data.Tests/Extensions/EnumerableExtensionsTests.cs +++ b/DigitalLearningSolutions.Data.Tests/Extensions/EnumerableExtensionsTests.cs @@ -17,8 +17,7 @@ public void WhereNotNull_filters_items_correctly() var result = list.WhereNotNull(); // Then - var expectedResult = new List { "1", "2", "3", "4" }; - result.Should().BeEquivalentTo(expectedResult); + result.Should().BeEquivalentTo(new List { "1", "2", "3", "4" }); } } }