Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void GetGroupsForCentre_returns_expected_groups()
ShouldAddNewRegistrantsToGroup = true,
ChangesToRegistrationDetailsShouldChangeGroupMembership = true
};

// When
var result = groupsDataService.GetGroupsForCentre(101).ToList();

Expand All @@ -48,5 +48,33 @@ public void GetGroupsForCentre_returns_expected_groups()
result.First(x => x.GroupId == 34).Should().BeEquivalentTo(expectedFirstGroup);
}
}

[Test]
public void GetGroupDelegates_returns_expected_delegates()
{
// Given
var expectedFirstGroupDelegate = GroupTestHelper.GetDefaultGroupDelegate();

// When
var result = groupsDataService.GetGroupDelegates(5).ToList();

// Then
using (new AssertionScope())
{
result.Count.Should().Be(24);
result.First(x => x.GroupDelegateId == expectedFirstGroupDelegate.GroupDelegateId).Should()
.BeEquivalentTo(expectedFirstGroupDelegate);
}
}

[Test]
public void GetGroupNameForGroupId_returns_expected_name()
{
// When
var result = groupsDataService.GetGroupNameForGroupId(5);

// Then
result.Should().BeEquivalentTo("Activities worker or coordinator");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
namespace DigitalLearningSolutions.Data.Tests.NBuilderHelpers
{
using System;
using NUnit.Framework;

public static class NBuilderAlphabeticalPropertyNamingHelper
{
public static string IndexToAlphabeticalString(int index)
{
if (index < 0)
{
throw new ArgumentOutOfRangeException(nameof(index) , @"Index must be greater than or equal to zero");
}

var remainder = index % 26;
var place = index / 26;

var s = new string('Z', place);
s += GetNthLetterOfAlphabet(remainder);

return s;
}

private static char GetNthLetterOfAlphabet(int n)
{
return (char)(n + 65);
}
}

public class NBuilderAlphabeticalPropertyNamingHelperTests
{
[Test]
[TestCase(0, ExpectedResult = "A")]
[TestCase(25, ExpectedResult = "Z")]
[TestCase(26, ExpectedResult = "ZA")]
[TestCase(51, ExpectedResult = "ZZ")]
[TestCase(52, ExpectedResult = "ZZA")]
[TestCase(77, ExpectedResult = "ZZZ")]
[TestCase(78, ExpectedResult = "ZZZA")]
[TestCase(103, ExpectedResult = "ZZZZ")]
public string IndexToAlphabeticalString_returns_expected_string(int inputIndex)
{
return NBuilderAlphabeticalPropertyNamingHelper.IndexToAlphabeticalString(inputIndex);
}
}

}
29 changes: 29 additions & 0 deletions DigitalLearningSolutions.Data.Tests/TestHelpers/GroupTestHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
namespace DigitalLearningSolutions.Data.Tests.TestHelpers
{
using DigitalLearningSolutions.Data.Models.DelegateGroups;

public static class GroupTestHelper
{
public static GroupDelegate GetDefaultGroupDelegate(
int groupDelegateId = 62,
int groupId = 5,
int delegateId = 245969,
string? firstName = "xxxxx",
string lastName = "xxxx",
string? emailAddress = "gslectik.m@vao",
string candidateNumber = "KT553"
)
{
return new GroupDelegate
{
GroupDelegateId = groupDelegateId,
GroupId = groupId,
DelegateId = delegateId,
FirstName = firstName,
LastName = lastName,
EmailAddress = emailAddress,
CandidateNumber = candidateNumber
};
}
}
}
34 changes: 34 additions & 0 deletions DigitalLearningSolutions.Data/DataServices/GroupsDataService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@
{
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Dapper;
using DigitalLearningSolutions.Data.Models.DelegateGroups;

public interface IGroupsDataService
{
IEnumerable<Group> GetGroupsForCentre(int centreId);

IEnumerable<GroupDelegate> GetGroupDelegates(int groupId);

string GetGroupNameForGroupId(int groupId);
}

public class GroupsDataService : IGroupsDataService
Expand Down Expand Up @@ -50,5 +55,34 @@ FROM Groups AS g
new { centreId }
);
}

public IEnumerable<GroupDelegate> GetGroupDelegates(int groupId)
{
return connection.Query<GroupDelegate>(
@"SELECT
GroupDelegateID,
GroupID,
DelegateID,
FirstName,
LastName,
EmailAddress,
CandidateNumber
FROM GroupDelegates AS gd
JOIN Candidates AS c ON c.CandidateID = gd.DelegateID
WHERE gd.GroupID = @groupId",
new { groupId }
);
}

public string GetGroupNameForGroupId(int groupId)
{
return connection.Query<string>(
@"SELECT
GroupLabel
FROM Groups
WHERE GroupID = @groupId",
new { groupId }
).Single();
}
}
}
2 changes: 1 addition & 1 deletion DigitalLearningSolutions.Data/Models/BaseSearchableItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public abstract class BaseSearchableItem
/// the type for the query for the FuzzySharp search parameters.
/// See GenericSearchHelper.cs in the DigitalLearningSolutions.Web project
/// </summary>
public string? SearchableNameOverrideForFuzzySharp;
protected string? SearchableNameOverrideForFuzzySharp;

public abstract string SearchableName { get; set; }
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace DigitalLearningSolutions.Data.Models.DelegateGroups
{
public class GroupDelegate : BaseSearchableItem
{
public int GroupDelegateId { get; set; }

public int GroupId { get; set; }

public int DelegateId { get; set; }

public string? FirstName { get; set; }

public string LastName { get; set; }

public string? EmailAddress { get; set; }

public string CandidateNumber { get; set; }

public override string SearchableName
{
get => SearchableNameOverrideForFuzzySharp ?? $"{FirstName} {LastName}";
set => SearchableNameOverrideForFuzzySharp = value;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public void Page_has_no_accessibility_errors(string url, string pageTitle)
[InlineData("/TrackingSystem/CourseSetup/10716/Manage", "Level 1 - Microsoft Excel 2010 - Inductions")]
[InlineData("/TrackingSystem/Delegates/All", "Delegates")]
[InlineData("/TrackingSystem/Delegates/Groups", "Groups")]
[InlineData("/TrackingSystem/Delegates/Groups/5/Delegates", "Group delegates")]
[InlineData("/TrackingSystem/Delegates/View/3", "xxxx xxxxxx")]
[InlineData("/TrackingSystem/Delegates/Approve", "Approve delegate registrations")]
[InlineData("/TrackingSystem/Delegates/BulkUpload", "Bulk upload/update delegates")]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
namespace DigitalLearningSolutions.Web.Tests.ViewModels.TrackingSystem.Delegates.DelegateGroups
{
using DigitalLearningSolutions.Data.Models.DelegateGroups;
using DigitalLearningSolutions.Data.Tests.TestHelpers;
using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Delegates.DelegateGroups;
using FizzWare.NBuilder;
using FluentAssertions;
using FluentAssertions.Execution;
using NUnit.Framework;

public class GroupDelegateViewModelTests
{
[Test]
public void GroupDelegateViewModel_populates_expected_values_with_both_names()
{
// Given
var groupDelegate = Builder<GroupDelegate>.CreateNew()
.With(gd => gd.GroupDelegateId = 62)
.With(gd => gd.FirstName = "Test")
.With(gd => gd.LastName = "Name")
.With(gd => gd.EmailAddress = "gslectik.m@vao")
.With(gd => gd.CandidateNumber = "KT553")
.Build();

// When
var result = new GroupDelegateViewModel(groupDelegate);

// Then
using (new AssertionScope())
{
result.GroupDelegateId.Should().Be(62);
result.Name.Should().Be("Test Name");
result.EmailAddress.Should().Be("gslectik.m@vao");
result.CandidateNumber.Should().Be("KT553");
}
}

[Test]
public void GroupDelegateViewModel_populates_expected_values_with_only_last_name()
{
// Given
var groupDelegate = Builder<GroupDelegate>.CreateNew()
.With(gd => gd.GroupDelegateId = 62)
.With(gd => gd.FirstName = null)
.With(gd => gd.LastName = "Name")
.With(gd => gd.EmailAddress = "gslectik.m@vao")
.With(gd => gd.CandidateNumber = "KT553")
.Build();

// When
var result = new GroupDelegateViewModel(groupDelegate);

// Then
using (new AssertionScope())
{
result.GroupDelegateId.Should().Be(62);
result.Name.Should().Be("Name");
result.EmailAddress.Should().Be("gslectik.m@vao");
result.CandidateNumber.Should().Be("KT553");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
namespace DigitalLearningSolutions.Web.Tests.ViewModels.TrackingSystem.Delegates.DelegateGroups
{
using System.Linq;
using DigitalLearningSolutions.Data.Models.DelegateGroups;
using DigitalLearningSolutions.Data.Tests.NBuilderHelpers;
using DigitalLearningSolutions.Web.Models.Enums;
using DigitalLearningSolutions.Web.ViewModels.Common.SearchablePage;
using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Delegates.DelegateGroups;
using FizzWare.NBuilder;
using FluentAssertions;
using FluentAssertions.Execution;
using NUnit.Framework;

public class GroupDelegatesViewModelTests
{
private readonly DelegateGroupsSideNavViewModel expectedNavViewModel =
new DelegateGroupsSideNavViewModel("Group name", DelegateGroupPage.Delegates);

private GroupDelegate[] groupDelegates = null!;

[SetUp]
public void SetUp()
{
BuilderSetup.DisablePropertyNamingFor<GroupDelegate, string>(g => g.SearchableName);
groupDelegates = Builder<GroupDelegate>.CreateListOfSize(15)
.All()
.With(g => g.LastName = "Surname")
.With((g, i) => g.FirstName = NBuilderAlphabeticalPropertyNamingHelper.IndexToAlphabeticalString(i))
.Build().ToArray();
}

[Test]
public void GroupDelegatesViewModel_should_return_the_first_page_worth_of_delegates()
{
var model = new GroupDelegatesViewModel(
1,
"Group name",
groupDelegates,
1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I don't properly understand this, but the test name claims it is defaulting to returning the first page, but this looks like an explicit request for the first page.

);

using (new AssertionScope())
{
model.GroupId.Should().Be(1);
model.NavViewModel.Should().BeEquivalentTo(expectedNavViewModel);
model.GroupDelegates.Count().Should().Be(BaseSearchablePageViewModel.DefaultItemsPerPage);
model.GroupDelegates.Any(groupDelegate => groupDelegate.Name == "K Surname").Should()
.BeFalse();
}
}

[Test]
public void GroupDelegatesViewModel_should_correctly_return_the_second_page_of_delegates()
{
var model = new GroupDelegatesViewModel(
1,
"Group name",
groupDelegates,
2
);
var expectedFirstGroupDelegate =
groupDelegates.Skip(BaseSearchablePageViewModel.DefaultItemsPerPage).First();

using (new AssertionScope())
{
model.GroupId.Should().Be(1);
model.NavViewModel.Should().BeEquivalentTo(expectedNavViewModel);
model.GroupDelegates.Count().Should().Be(5);
model.GroupDelegates.First().Name.Should().BeEquivalentTo($"{expectedFirstGroupDelegate.FirstName} {expectedFirstGroupDelegate.LastName}");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,16 @@ public IActionResult Index()

return View(model);
}

[Route("{groupId:int}/Delegates/{page:int=1}")]
public IActionResult GroupDelegates(int groupId, int page = 1)
{
var groupName = groupsDataService.GetGroupNameForGroupId(groupId);
var groupDelegates = groupsDataService.GetGroupDelegates(groupId);

var model = new GroupDelegatesViewModel(groupId, groupName, groupDelegates, page);

return View(model);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace DigitalLearningSolutions.Web.Models.Enums
{
public enum DelegateGroupPage
{
Delegates,
Courses
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@import 'delegateCommon';
@import '../../shared/searchableElements/searchableElements';
Loading